40 lines
1.4 KiB
TypeScript
40 lines
1.4 KiB
TypeScript
import { NextResponse } from "next/server";
|
|
import { getSessionUser } from "@/lib/session";
|
|
import { listInvoices, syncOverdueInvoices } from "@/lib/db";
|
|
|
|
/**
|
|
* GET /api/billing/invoices
|
|
*
|
|
* Customer-scoped list of invoices for the caller's org. Returns
|
|
* a flat array of Invoice headers (no line items — those are
|
|
* fetched separately by /[invoiceNumber]).
|
|
*
|
|
* Status filter is implicit: we return every invoice the
|
|
* customer's org has, all statuses (issued/paid/overdue/void)
|
|
* because the customer wants a single billing-history view.
|
|
*
|
|
* Before returning we run syncOverdueInvoices() so the displayed
|
|
* status reflects the current date — issued invoices past their
|
|
* due_at flip to 'overdue'. Cheap, idempotent, and avoids needing
|
|
* a separate cron for this transition.
|
|
*/
|
|
export async function GET() {
|
|
const user = await getSessionUser();
|
|
if (!user) {
|
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
}
|
|
// Personal accounts have an org too — they share the same shape;
|
|
// their invoices show up under that synthetic org id.
|
|
try {
|
|
await syncOverdueInvoices();
|
|
} catch (e) {
|
|
// Non-fatal — display stale status rather than 500.
|
|
console.warn("syncOverdueInvoices failed in /api/billing/invoices:", e);
|
|
}
|
|
const invoices = await listInvoices({
|
|
zitadelOrgId: user.orgId,
|
|
limit: 200,
|
|
});
|
|
return NextResponse.json(invoices);
|
|
}
|