feat: add order ack detail/PDF, BOL detail/PDF, coil activity usage & receipts
Some checks failed
Build and Deploy / build (push) Successful in 10m53s
Build and Deploy / deploy (push) Failing after 2s

C-005: Order Acknowledgement Detail + PDF
- Order detail page with full line items, releases, addresses, paint codes
- PDF export via Puppeteer matching legacy format
- Clickable order # links and PDF icons in orders table

C-007: BOL Detail + PDF
- BOL detail page with ship-from/to, line items, weights
- PDF export matching legacy BOL format
- PDF icon column in shipments table

C-008: Coil Activity - Usage Report
- Date range picker (max 31 days, default last 10 days)
- Reusable UI: Popover, Calendar (react-day-picker v9), DateRangePicker
- SQL from legacy portal_CoilActivityUsage.sql with OnHandQty dedup
- 11-column sortable table with search and CSV export

C-009: Coil Activity - Receipts Report
- VGL customer exception (special SQL vs portal view)
- 10-column sortable table with search and CSV export
- Shared date range picker component

Also: dashboard API route, shipments API route, HDC→HDM mapping,
Puppeteer PDF infrastructure, improved error handling.

Progress: 9/16 Phase 2 tasks complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lorentz Hinrichsen 2026-02-17 09:14:52 -05:00
parent cd95bc4218
commit 53c35cc273
39 changed files with 3894 additions and 355 deletions

View file

@ -142,14 +142,12 @@ quest-vorteq/
### Not Yet Created (Planned)
```
src/app/(portal)/shipments/
src/app/(portal)/coil-activity/
src/app/(portal)/invoices/
src/app/(portal)/shipment-requests/
src/app/(portal)/allocation-requests/
src/app/(portal)/jobs/
src/app/(portal)/admin/
src/services/shipments.ts # Shipment data access
src/services/coil-activity.ts # Coil activity data access
src/services/ship-requests.ts # Shipment request business logic
src/services/alloc-requests.ts # Allocation request business logic
@ -251,6 +249,22 @@ export function ShipmentRequestCart() { ... }
- Standard view: `dbo.portal_Orders WHERE CustomerID = @CustID`
- HDC exception: uses `dbo.portal_OrdersHDC` view and maps CustID `HDC``HDM`
### RSC Serialization — Critical Pattern for Epicor Data
**Problem:** Next.js RSC (React Server Components) dev mode serializes ALL server-side data and console output to forward to the browser. The `mssql` package returns `recordset` objects with circular references, metadata, and prototype chains that blow up RSC serialization (`RangeError: Maximum call stack size exceeded` at `Set.add` or `Map.set`). This is especially severe for large result sets (e.g., ACM has 7,633 shipment rows).
**Solution:** For Epicor data displayed in the UI, use a **client-side fetch → API route** pattern instead of RSC server components:
1. Create an API route (e.g., `/api/shipments/route.ts`) that calls the service and returns `NextResponse.json(data)`
2. Make the page a `'use client'` component that fetches from the API route via `useEffect` + `fetch()`
3. The API route handles auth/session checks and returns plain JSON — no RSC serialization involved
**When RSC works fine:** Small result sets (< ~500 rows) through `execStoredProc` generally work. The `[...result.recordset]` spread in `execStoredProc` detaches the array-level prototype. For safety, services should still `JSON.parse(JSON.stringify(...))` their return values if passing to RSC.
**When RSC breaks:** Large result sets (1000+ rows), or any scenario where mssql objects remain in scope during server component rendering. Even with `JSON.parse(JSON.stringify())`, Next.js dev mode console forwarding can serialize the function's closure scope including mssql objects.
**Rule of thumb:** If an Epicor query can return > 500 rows for any customer, use the API route pattern.
### Column Mapping
Epicor SP results use PascalCase column names. Services map them to snake_case:
```typescript