New /delivery-pool page, a clone of the Collection Pool for deliveries with no pending stage. Invoiced lines are grouped per company, one card per customer invoice; a card expands to its lines. Assign a driver and day per invoice (or bulk per company); uploading the signed copy adds it to every line, marks the lines completed + delivered_at, and closes a delivery note once none of its lines is still open. - Driver lives in new order_items.delivery_driver / delivery_assigned_at (npm run pb:migrate:delivery-pool), never drv_id (collection driver). - Pool starts at DELIVERY_POOL_START (2026-10-30); lines whose DN is already completed/cancelled (POS counter sales) are left out. - Service + /api/v1/delivery-pool routes (browser session); the service 503s until the migration has run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.9 KiB
Delivery Pool — design
Date: 2026-10-30 · Status: draft for Dave's approval
Why
The current /deliveries page tracks paper (To Load → Back from Driver →
Checked In) but never says which driver has a delivery or when it
goes out, and the signed copy is left to an n8n job. The office wants
deliveries to work like the Collection Pool: one list of everything that
must go out, assign it to a driver for a day, and close it when the signed
copy comes back.
What it is (Dave's words)
- A clone of the Collection Pool for deliveries, without the pending stage — everything in the pool is ready to go.
- Grouped per company, and under each company one card per invoice number. Expanding a card shows the lines on that invoice.
- Assign a card to a driver; the driver delivers; when the paper comes back
the office uploads the signed copy and every line on that invoice
becomes
completed.
Goals
- New page
/delivery-pool("Delivery Pool" in the sidebar). - Company sections (collapsible, count + total value), invoice cards inside.
- Card shows: invoice number, DN number(s) if any, order number, line count, value ex VAT, driver + date badge (Unassigned / Today / future date).
- Card actions: Assign / Reschedule driver (same dialog as the Collection Pool), Unassign, Upload signed copy, open invoice PDF.
- Bulk select cards in a company section → assign them all to one driver/date.
- Filter box (company / invoice / DN / order / item text) and a driver filter ("All / Unassigned / ").
Non-goals
- The driver app (
WFDASHDRIVER-APP) — drivers do not see deliveries there yet. Assigning is office-side. Separate follow-up. - Map / nearby sort (the Collection Pool's supplier map). Not in v1.
- The old
/deliveriespage and itswith_driver/checked_inrows stay as they are until the new pool is trusted; then it is retired.
Anti-goals
- Must not overwrite the collection driver (
order_items.drv_id,drv_collected_at) — that history feeds Collection Confirm and stats. - Must not drop un-invoiced lines off the Invoicing page.
- Must not flood the pool with months of already-delivered invoices.
Rules
What is in the pool — an order_items line where all hold:
item_status = "invoiced"customer_invoice_number != ""(the customer's QB invoice — NOTorder_item_details.invoice.number, which Collection Confirm also uses for the supplier invoice)invoiced_date >= DELIVERY_POOL_START(constant, set to go-live day)delivered_at = ""(not yet delivered)- not
exclude_from_invoice - its delivery note (if any) is not
completed/cancelled— this drops POS counter sales, which close their DN with a signed copy at the till.
Card key = customer_invoice_number, normalised (30352 and
INV30352 are the same invoice; shown as INV30352).
Company = the order's company; for lines without an order (POS) the
DN's company; else order_item_details.invoice.invoiceCompany; else
"Unknown company".
Lines on a DN but not yet invoiced (item_status = "delivery_note")
are not in the pool — the card is per invoice. They join the pool when
they are invoiced. (My call, from "per invoice number" — say if a DN-only
delivery must go out before invoicing.)
Data
Two new fields on order_items (migration script
npm run pb:migrate:delivery-pool, manual live step):
delivery_driver— relation → users, singledelivery_assigned_at— date
Existing fields reused: delivered_at (stamped when the signed copy is
uploaded; currently set on only 2 rows), item_status → completed.
Item status does not change on assign — the line stays invoiced
until the signed copy is in. Both new fields go in nothing noisy, so the
audit hook records who assigned what.
Server
src/lib/server/delivery-pool-service.ts:
listDeliveryPool()→{ companies: [{ id, name, invoices: [{ invoiceNumber, dnNumbers, orderNumbers, driverId, assignedAt, lines[], total }] }] }assignInvoice({ invoiceNumber, driverId, date })— writes both fields on every pool line of that invoice; empty driverId = unassign.completeInvoice({ invoiceNumber, file })— adds the file to each line'sorder_item_attachements(withaddAttachmentForm, ADD never replace), stores it assigned_copyon each linked DN that has none and sets that DNcompleted, stampsdelivered_at, sets linescompleted.
Routes (browser-session auth, like the other office pages):
GET /api/v1/delivery-poolPATCH /api/v1/delivery-pool/{invoice}/assignPOST /api/v1/delivery-pool/{invoice}/signed-copy(multipart)
Page
src/app/(app)/delivery-pool/ — page.tsx, components.tsx,
view-model.ts (grouping, badges, filters — pure + tested), reusing
AssignDriverDialog and /api/v1/users/lookup from the Collection Pool.
Left to the builder
Styling details, empty states, toasts, test layout.