feat(trips): trip tracking with analytics, tag conversion, and transaction assignment

Adds trips table usage across API and UI: trip CRUD, per-trip analytics
(category/daily/merchant/tag/participant breakdowns), tag-to-trip
conversion, trip assignment via transaction overrides, and trip filter
in the transactions view. Recovered from working tree after local git
corruption; feature was already live via host-context Docker builds.
This commit is contained in:
2026-07-19 20:00:51 +10:00
parent b706973fb5
commit 48ec151c15
21 changed files with 1506 additions and 55 deletions
+6 -3
View File
@@ -23,7 +23,7 @@ export async function PATCH(
const transactionId = Number(id);
const body = await req.json();
const { category, merchant_normalized, notes, transaction_type, my_share_percent, description, amount, transaction_date } = body as {
const { category, merchant_normalized, notes, transaction_type, my_share_percent, description, amount, transaction_date, trip_id } = body as {
category?: string;
merchant_normalized?: string;
notes?: string;
@@ -32,6 +32,7 @@ export async function PATCH(
description?: string;
amount?: number;
transaction_date?: string;
trip_id?: number | null;
};
if (my_share_percent !== undefined && my_share_percent !== null) {
@@ -72,8 +73,8 @@ export async function PATCH(
);
}
// category/merchant/notes/my_share_percent go through the overrides table
const hasOverride = category !== undefined || merchant_normalized !== undefined || notes !== undefined || my_share_percent !== undefined;
// category/merchant/notes/my_share_percent/trip_id go through the overrides table
const hasOverride = category !== undefined || merchant_normalized !== undefined || notes !== undefined || my_share_percent !== undefined || trip_id !== undefined;
if (!hasOverride) {
return NextResponse.json({ ok: true });
}
@@ -83,6 +84,7 @@ export async function PATCH(
if (merchant_normalized !== undefined) data.merchant_normalized = merchant_normalized;
if (notes !== undefined) data.notes = notes;
if (my_share_percent !== undefined) data.my_share_percent = my_share_percent;
if (trip_id !== undefined) data.trip_id = trip_id;
const override = await prisma.transaction_overrides.upsert({
where: { transaction_id: transactionId },
@@ -93,6 +95,7 @@ export async function PATCH(
merchant_normalized: merchant_normalized || null,
notes: notes || null,
my_share_percent: my_share_percent != null ? String(my_share_percent) : null,
trip_id: trip_id ?? null,
},
});