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:
@@ -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,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import { prisma, queryRaw } from "@/lib/db";
|
||||
import { assignTransactionsToTrip } from "@/lib/queries";
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const body = await req.json();
|
||||
@@ -77,5 +78,11 @@ export async function POST(req: NextRequest) {
|
||||
return NextResponse.json({ updated: ids.length });
|
||||
}
|
||||
|
||||
if (action === "assign_trip") {
|
||||
const { trip_id } = body as { ids: number[]; trip_id: number | null };
|
||||
await assignTransactionsToTrip(trip_id, ids);
|
||||
return NextResponse.json({ updated: ids.length });
|
||||
}
|
||||
|
||||
return NextResponse.json({ error: "Invalid action" }, { status: 400 });
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ export async function GET(req: NextRequest) {
|
||||
amount_min: sp.get("amount_min") ? Number(sp.get("amount_min")) : undefined,
|
||||
amount_max: sp.get("amount_max") ? Number(sp.get("amount_max")) : undefined,
|
||||
has_split: sp.get("has_split") || undefined,
|
||||
trip_id: sp.get("trip_id") || undefined,
|
||||
});
|
||||
|
||||
return NextResponse.json(result);
|
||||
|
||||
Reference in New Issue
Block a user