import { NextRequest, NextResponse } from "next/server"; import { queryRow } from "@/lib/db"; import { getCurrentUser } from "@/lib/auth"; import { canAccessTransactions } from "@/lib/queries"; /** * Order provenance for one transaction. * * `expense_metadata` has held the itemised receipt since ingestion started and * nothing in the UI ever read it — a transaction that came from a DoorDash or * Uber Eats receipt showed a merchant and an amount, with the item list and the * delivery addresses sitting unread in the row behind it (user, 2026-07-27). * * Read-only. The receipt is a record of what a provider sent; editing it here * would make provenance mean nothing. */ export async function GET( req: NextRequest, { params }: { params: Promise<{ id: string }> } ) { const user = await getCurrentUser(req); if (!user) return NextResponse.json({ error: "Unauthorized" }, { status: 403 }); const { id } = await params; if (!(await canAccessTransactions(user.id, [Number(id)]))) { return NextResponse.json({ error: "Forbidden" }, { status: 403 }); } const row = await queryRow( `SELECT source, platform, order_reference, line_items, route, subtotal, amount, currency, card_last4, flags, source_email_subject, transaction_date FROM expense_metadata -- A card-settled order creates no transaction of its own (I5): the -- statement line is the transaction, and the receipt points at it -- through matched_transaction_id. Both directions have to resolve or the -- detail is missing on exactly the orders that were paid by card. WHERE transaction_id = $1 OR matched_transaction_id = $1 LIMIT 1`, [Number(id)] ); // Phase 2 (board 205). A BNPL leg has NO expense_metadata row of its own — // the plan is four transactions against one order — so without this the four // Afterpay debits behind the A$1,599 DJI drone stay four bare "Afterpay // $399.75" rows naming nothing. That is the surface where this was noticed. const link = await queryRow<{ entity_key: string; leg_kind: string; leg_index: number | null; leg_count: number | null; canonical_name: string | null; platform: string | null; order_total: string | null; currency: string | null; }>( `SELECT l.entity_key, l.leg_kind, l.leg_index::int, l.leg_count::int, e.canonical_name, o.platform, o.order_total, o.currency FROM order_transaction_links l LEFT JOIN entities e ON e.entity_key = l.entity_key LEFT JOIN entity_orders o ON o.entity_id = e.id WHERE l.transaction_id = $1 LIMIT 1`, [Number(id)] ); // Not an order — most transactions aren't. Null, not 404: the caller is // asking "is there a receipt behind this?", and "no" is a normal answer. if (!row && !link) return NextResponse.json(null); // expense_metadata carries the itemised receipt and stays primary; the link // adds what it cannot express — which order this is a leg OF, and which leg. return NextResponse.json({ ...(row ?? {}), order_link: link ?? null }); }