WFDASH-WEBAPP/src/lib
Dave 3b926570c7 fix(quotes): delivery-note quotes skip approvals; company follows customer
Two quote-flow defects found while auditing Q202610315.

1. Delivery-note quotes were being dumped into the rep approval queue.

   A DN quote is never sent on its own — it goes out with the note, via
   the note's "Send the delivery note and quote to the customer" button.
   But `generateQuotePdf` auto-flipped every non-terminal quote to
   `approval_pending`, which overwrote the DN status before the
   skip-approval branch in `sendQuoteEmail` could ever run. Ten DN
   quotes were sitting in Pending Approval as a result.

   - `createQuoteFromDeliveryNote` now creates the quote `approved`
     rather than `delivery_note`.
   - The PDF render no longer flips DN quotes at all, as a backstop.
   - The quote page gets a non-sending action row pointing back at the
     note. No "send" button — a second way to email a customer the same
     invoice is a liability, not a feature.

   Also fixes a latent duplicate-invoice bug: the duplicate guard
   pinned `status = "delivery_note"`, so once the quote had been sent
   it fell through and a second quote could be raised for the same
   note. Verified by test — the old guard silently minted a duplicate.

2. `quotes.company` never followed a customer change.

   `quotes.company` is a denormalised copy of `customer.company` and
   PB does not re-cascade relations, so swapping the customer left the
   old company behind forever (Q202610315 read "Mre" while its
   customer sat at Harmony — two contradictory companies on one row).

   The customer swap ran as a raw client-side PB PATCH that wrote only
   `customer`, which also bypassed the server's placeholder guard. It
   now goes through `PATCH /api/v1/quotes/[id]/pdf`, which cascades
   both relations atomically.

   The customer-facing PDF already read `customer.expand.company`,
   which is why this never reached a customer — but every consumer of
   the quote's own `company` got the wrong answer. A read-only audit
   (`scripts/audit-quote-company-drift.mjs`) puts it at 2,591 of 9,950
   quotes. That data is NOT backfilled here.

Also drops the duplicate standalone "COMPANY" column on the quote
detail page, and the stale-company fallback in approvals, so this
class of bug can't hide in the UI again.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-10-16 00:44:45 +02:00
..
pdf fix(delivery-note): signed copy invisible, and a bigger QR in the corner 2026-10-04 17:00:30 +02:00
reports feat(audit): implement audit trail for delivery notes and orders 2026-09-30 01:48:44 +02:00
scan fix(scan): speed up QR recognition and keep scanning 2026-10-05 09:43:53 +02:00
server fix(quotes): delivery-note quotes skip approvals; company follows customer 2026-10-16 00:44:45 +02:00
audit-fetch.test.ts feat(audit): implement audit trail for delivery notes and orders 2026-09-30 01:48:44 +02:00
audit-fetch.ts feat(audit): implement audit trail for delivery notes and orders 2026-09-30 01:48:44 +02:00
audit-format.test.ts feat(audit): implement audit trail for delivery notes and orders 2026-09-30 01:48:44 +02:00
audit-format.ts feat(audit): implement audit trail for delivery notes and orders 2026-09-30 01:48:44 +02:00
delivery-note-stage.test.ts fix(delivery-notes): merge cancelled into completed, and fix the search 2026-10-04 23:29:48 +02:00
delivery-note-stage.ts fix(delivery-notes): merge cancelled into completed, and fix the search 2026-10-04 23:29:48 +02:00
dev-identity.test.ts
dev-identity.ts
file-fields.test.ts fix(delivery-note): signed copy invisible, and a bigger QR in the corner 2026-10-04 17:00:30 +02:00
file-fields.ts fix(delivery-note): signed copy invisible, and a bigger QR in the corner 2026-10-04 17:00:30 +02:00
geo.test.ts feat(visits): batch pin tool — tag every customer on a shaft at once 2026-09-07 08:30:23 +02:00
geo.ts feat(visits): batch pin tool — tag every customer on a shaft at once 2026-09-07 08:30:23 +02:00
giellie-image.ts feat(giellie): chat UI, approval card, photo/file composer, sidebar rename 2026-10-01 00:06:50 +02:00
giellie-sse.test.ts fix(giellie): stale-tab approval guard, size guard, SSE heartbeat, shared in-flight set 2026-10-01 00:36:55 +02:00
giellie-sse.ts feat(giellie): shared types and SSE codec 2026-09-30 23:34:53 +02:00
giellie-types.ts fix(giellie): args-aware tool policy, deny quotes.re_run_ai, harden bridge and agent 2026-10-01 00:36:54 +02:00
item-status-ui.test.ts
item-status-ui.ts Revert "feat(orders): add Duplicates tab surfacing flagged duplicate orders" 2026-08-31 16:34:37 +02:00
letterhead.test.ts
letterhead.ts fix(pdf): render through renderToBuffer, not pdf().toString() 2026-10-04 13:14:59 +02:00
order-age.test.ts feat(orders): add order-age util with bucket thresholds 2026-09-01 01:58:46 +02:00
order-age.ts feat(orders): add order-age util with bucket thresholds 2026-09-01 01:58:46 +02:00
order-color.test.ts
order-color.ts
order-invoices.test.ts feat(audit): implement audit trail for delivery notes and orders 2026-09-30 01:48:44 +02:00
order-invoices.ts feat(audit): implement audit trail for delivery notes and orders 2026-09-30 01:48:44 +02:00
order-item-qty.test.ts
order-item-qty.ts
order-rep.test.ts
order-rep.ts
pb-helpers-duplicate.test.ts
pb-helpers.ts feat(delivery-notes): one linear flow control, and fix the quote lookup 2026-10-05 18:21:19 +02:00
pin-model.test.ts
placeholder-customers.ts
pocketbase.ts
pos-cart-quantity.test.ts fix(pos): dead discount toggle + stale discount figure, lift dark palette 2026-10-12 23:17:57 +02:00
pos-inline-handlers.test.ts fix(pos): revive the dead "Print cash-up" button, add 20c/10c denominations 2026-09-19 07:30:11 +02:00
pos-search.test.ts feat(pos): tiered catalog search — word order, plurals, glued SKUs 2026-10-06 23:36:12 +02:00
price-list-search.ts
quote-pricing.test.ts feat(delivery-notes): lock the cost price, markup stays the only input 2026-10-15 15:44:24 +02:00
quote-pricing.ts feat(delivery-notes): lock the cost price, markup stays the only input 2026-10-15 15:44:24 +02:00
quote-status.test.ts
quote-status.ts feat(quotes): allow resubmit from any post-submit status, not just rejected 2026-09-07 16:51:55 +02:00
rep-visibility.test.ts feat: add isRepUser helper for rep-scoped list filtering 2026-08-31 23:24:25 +02:00
rep-visibility.ts feat: add isRepUser helper for rep-scoped list filtering 2026-08-31 23:24:25 +02:00
repair-document-stage.test.ts feat(stock): update pricing logic and transform script for fasteners 2026-09-21 12:32:44 +02:00
repair-document-stage.ts feat(stock): update pricing logic and transform script for fasteners 2026-09-21 12:32:44 +02:00
safe-next-path.ts fix: preserve destination through the login redirect 2026-09-01 15:47:27 +02:00
sops.ts feat: implement discount functionality in POS system 2026-09-03 12:19:21 +02:00
stock-fulfillment.test.ts
stock-fulfillment.ts
stock-low-stock.ts
stock-match.ts
stock-status.test.ts
stock-status.ts
supplier-color.test.ts
supplier-color.ts
theme-types.ts
themes.ts
tracker-parsing.test.ts feat(rep-visits): FleetAI tracker adapter, nearby-customer matching, stop detection 2026-09-06 14:22:28 +02:00
tracker-parsing.ts feat(rep-visits): FleetAI tracker adapter, nearby-customer matching, stop detection 2026-09-06 14:22:28 +02:00
types.ts feat(pos): ex-VAT totals, ad-hoc custom lines, fixed discount tiers 2026-10-12 22:54:09 +02:00
use-boolean-preference.ts
use-split-ratio.test.ts
use-split-ratio.ts
use-theme-id.ts
user-color.ts
utils.test.ts
utils.ts
visit-matching.test.ts feat(rep-visits): FleetAI tracker adapter, nearby-customer matching, stop detection 2026-09-06 14:22:28 +02:00
visit-matching.ts feat(rep-visits): FleetAI tracker adapter, nearby-customer matching, stop detection 2026-09-06 14:22:28 +02:00
visit-stops.test.ts feat(rep-visits): FleetAI tracker adapter, nearby-customer matching, stop detection 2026-09-06 14:22:28 +02:00
visit-stops.ts feat(rep-visits): FleetAI tracker adapter, nearby-customer matching, stop detection 2026-09-06 14:22:28 +02:00
working-days.ts