WFDASH-WEBAPP/src
Dave fd3a9296c6 feat(delivery-notes): the note decides the quantity; the quote follows it
A counter note is raised when the customer takes goods off the shelf.
"They said make it five more" is edited on the NOTE. Previously that
edit changed the note and left the quote showing the old number, so
the same physical goods carried two different quantities across two
screens and the invoice was whichever screen the operator opened last.

`updateDeliveryNoteItemPricing` now pushes the note's quantity onto
the quote lines that came from it. A sync failure is logged, not
fatal — the edit already succeeded and the quote can be re-synced by
re-saving.

## Matching without a back-link

`quote_items` has no field pointing at its source `order_item`, so
the operator's call was to make the note authoritative and work around
it. Lines are paired by `sku + description`, and when a key repeats,
by ORDER OF OCCURRENCE.

That is sound because both sides derive from the same ordered list
of note lines: `createQuoteFromDeliveryNote` iterates the note's
items in query order and emits one quote line each, so the Nth of a
repeated key on the note is the Nth on the quote. On the live data
across 500 note lines there are ZERO groups sharing
(note, sku, description) — the key is unique in practice. The
occurrence counter exists so that if two identical lines are ever
added, the second still lands on the right row instead of both
writing to the first.

That is the failure the tests exist for: matching on the key alone
silently writes the wrong number onto a customer invoice. Verified by
removing the occurrence counter — exactly that test fails.

## Also carried through

- The note's COLLECTED qty is the billing qty, not the ordered qty, so
  a short pickup (10 ordered, 8 collected) puts 8 on the quote.
- A cancelled, rejected or declined quote keeps its own numbers.
  Rewriting a quote the customer has already seen is worse than a
  stale number.
- A line that cannot be matched is left alone, never guessed at.
- A note line with neither a collected nor an ordered qty is skipped,
  so this can never reintroduce the zero-quantity invoice line.

8 new tests. Full suite 3832 passing, tsc clean, no new lint errors.
2026-10-09 11:56:48 +02:00
..
app fix(invoicing): a zero-quantity line can never be sent — bill the ordered qty 2026-10-09 11:15:03 +02:00
components feat(delivery-notes): open the note document to print; surface the real QB error 2026-10-09 11:00:03 +02:00
lib feat(delivery-notes): the note decides the quantity; the quote follows it 2026-10-09 11:56:48 +02:00
styles
middleware.ts feat(tv): add TV dashboard + refine workflows 2026-08-13 20:55:22 +02:00
test-setup.ts