The name on an invoice means two different things. On an internal invoice it is a
SITE, transcribed from the invoice's own description. On an external invoice it is
the SUPPLIER - and the PDF does not print the supplier's company name at all, so
there is nothing to transcribe and a human has to type it.
`invoices.site` stays the single field; the column header follows the page (Site on
Internal, Supplier on External) and only the external one is editable, via
components/SupplierCell.tsx and PATCH /api/invoices/:id/site. It saves on blur or
Enter, never per keystroke, and an empty value clears the name so a stray
description fragment can be removed rather than displayed as a supplier.
Sites stop taking their names from external invoices, in both places:
- syncSitesFromInvoices only creates sites from internal invoices, so a job
description can never be registered as a yard.
- buildSiteSummaries only counts internal invoice lines towards a site, which is
what /sites and the dashboard's per-site chart read.
This is the "Move containers" case. PHI 192's description is "Crane Truck Hire 17
September 2026 Move containers", which had registered a site literally called
"Move containers" - a job, not a yard - on /sites, on the dashboard's per-site
chart and in the plant register's site filter. The record stays in the collection
(sites are never deleted) but is no longer surfaced; the count went 13 -> 12.
External income is not lost by this - it is booked to a machine and still appears on
/income and /charts. It is simply not a site.
The intake route stops resolving an external invoice's text against the site list,
which would have invented a site out of a description, and reports needsSupplier so
the import toast says the name is outstanding.
npm run seed now captures existing invoice names before it wipes the collection and
re-applies them where data/source does not specify one - the same data-loss trap the
uploaded PDFs already had. A JSON name always wins, so internal sites are unchanged.
Verified: typecheck clean, 45 tests pass (4 new, covering the "Move containers" case
directly), production build green, the new PATCH route 401s when anonymous, and
/sites plus both invoice pages pass the mobile checklist at 375x812 and 768x1024. The
supplier edit was exercised end to end and the test value reverted.
Still open: the three external invoices (PHI 178/186/192) have no supplier name yet
and none can be derived from the data. They show "Set supplier" until the client
supplies them.
Note: lib/rows.ts, lib/server-data.ts and the running/insurance feature are
someone else's in-flight work and were deliberately left uncommitted here.