From 438d3a6e2e931d2066274ce94cbe5c145e59487e Mon Sep 17 00:00:00 2001 From: justin Date: Mon, 27 Apr 2026 21:27:10 -0500 Subject: [PATCH] Add customer portal orders page + my-orders API - GET /api/v1/compliance-orders/my-orders?email= returns all orders grouped by batch, with USAC delegation status - /account/orders page shows order history with: - Entity name, FRN, batch ID, date, payment status - Itemized services with pricing - USAC delegation callout with confirmation button - Auth-gated (requires login) Co-Authored-By: Claude Opus 4.6 (1M context) --- api/src/routes/compliance-orders.ts | 65 +++++++ site/src/pages/account/orders.astro | 264 ++++++++++++++++++++++++++++ 2 files changed, 329 insertions(+) create mode 100644 site/src/pages/account/orders.astro diff --git a/api/src/routes/compliance-orders.ts b/api/src/routes/compliance-orders.ts index e2b7431..686909a 100644 --- a/api/src/routes/compliance-orders.ts +++ b/api/src/routes/compliance-orders.ts @@ -1453,6 +1453,71 @@ router.post( }, ); +/** + * GET /api/v1/compliance-orders/my-orders + * Returns all compliance orders for the authenticated customer (by email). + */ +router.get("/api/v1/compliance-orders/my-orders", async (req, res) => { + const email = (req.query.email as string || "").trim().toLowerCase(); + if (!email) { + res.status(400).json({ error: "email query parameter required." }); + return; + } + + try { + const result = await pool.query( + `SELECT order_number, batch_id, service_slug, service_name, service_fee_cents, + discount_cents, payment_status, payment_method, paid_at, + intake_data->>'frn' as frn, + intake_data->>'entity_name' as entity_name, + intake_data->>'usac_delegation_confirmed' as usac_delegation_confirmed, + created_at + FROM compliance_orders + WHERE customer_email = $1 + ORDER BY created_at DESC + LIMIT 100`, + [email], + ); + + // Group by batch + const batches: Record = {}; + const standalone: any[] = []; + + for (const row of result.rows) { + if (row.batch_id) { + if (!batches[row.batch_id]) { + batches[row.batch_id] = { + batch_id: row.batch_id, + entity_name: row.entity_name, + frn: row.frn, + payment_status: row.payment_status, + paid_at: row.paid_at, + created_at: row.created_at, + services: [], + needs_usac_delegation: false, + }; + } + batches[row.batch_id].services.push(row); + if ((row.service_slug || "").includes("499") && !row.usac_delegation_confirmed) { + batches[row.batch_id].needs_usac_delegation = true; + } + } else { + standalone.push(row); + } + } + + res.json({ + batches: Object.values(batches), + standalone, + total: result.rows.length, + }); + } catch (err) { + console.error("[compliance-orders] my-orders error:", err); + res.status(500).json({ error: "Could not fetch orders." }); + } +}); + + /** * POST /api/v1/compliance-orders/:id/usac-delegation * Customer confirms they've completed USAC E-File delegation. diff --git a/site/src/pages/account/orders.astro b/site/src/pages/account/orders.astro new file mode 100644 index 0000000..8670e6d --- /dev/null +++ b/site/src/pages/account/orders.astro @@ -0,0 +1,264 @@ +--- +import Base from "../../layouts/Base.astro"; +--- + + +
+ + + +

My Orders

+ + +
+
+

Loading your orders…

+
+ + + + + + + + + +
+ + + + +