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>