mega-plant/components
David ad4ac9173b Invoices: one line per charge, and fold an abbreviated site
PHI 179 was refused: "Machine lines total R5265 but the invoice subtotal is
R13730". Three separate faults, each of which only this invoice exposed.

1. The parser read ONE line per machine. A machine hired over more than one
   period is printed as one heading followed by a repeating block per charge,
   and PHI 179 is a single CT01 crane truck billed on 4, 16 and 18 Sep at
   R5 265 + R3 200 + R5 265. The parser only ever looked at the first block,
   so two thirds of the invoice went missing and the arithmetic check — which
   did its job — rejected it. extractLines() now walks y-banded rows and emits
   one line per money row, all carrying the machine's code. A machine billed
   once still yields exactly one line, which is what PHI 168/169 do.

   The banding matters: pdfjs splits one printed row across two y positions
   (the TOTAL sits ~2pt above the rest), so the fixed +-12pt window the old
   code used was never a row, it was a coincidence.

2. siteFromDescription required the description to START with "Hire Plant" or
   "Plant Hire". PHI 179 reads "Crane Truck Hire Sep 2026 Cosmo" — it leads
   with the machine type — so the regex returned "" and the invoice linked to
   no site at all. The month/year pair is the part every description shares,
   so that is the anchor now.

3. Even read correctly the site is "Cosmo", where every other invoice says
   "Cosmo City". Sites are DERIVED from the invoice wording, so saving the
   abbreviation would create a second "Cosmo" and split this customer across
   two rows on /sites. resolveSiteName() folds a shorter whole-word prefix
   onto a site already in the register, one direction only, so a genuinely new
   site is still recorded as new.

Also: a problem invoice stored its PDF with no way to open it. The inbox
reported the failure but not the document behind it, and /api/invoices/:id/
document only serves imported invoices — the one case you most want to inspect.
New GET /api/invoices/intake/:id/document, plus a PDF link on each inbox row.

Verified: PHI 179 reconciles in full (R13 730 + R2 059.50 VAT = R15 789.50,
three lines, each balancing). PHI 168 and PHI 169 still reproduce their hand
extraction field for field, including line count. 40 tests, typecheck clean.
2026-10-06 11:25:10 +02:00
..
auth feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
AccountMenu.tsx feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
ChartsGrid.tsx feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
DashboardCharts.tsx feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
ExpenseSectionPage.tsx feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
GlobalSearch.tsx feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
IncomeView.tsx Income: the tiles and the machine list were sharing the title's flex row 2026-10-06 11:05:37 +02:00
InvoiceIntake.tsx Invoices: one line per charge, and fold an abbreviated site 2026-10-06 11:25:10 +02:00
InvoiceList.tsx Mobile: the top tiles overflowed on /income, hugged text on /sites, and repeated on invoices 2026-10-03 16:45:23 +02:00
InvoiceTable.tsx Invoices: a machine chosen in the dropdown was never actually booked 2026-10-03 15:43:46 +02:00
InvoiceUploader.tsx Invoices: line-item extraction, booking to plant items, VAT-inclusive income 2026-10-01 15:59:30 +02:00
MachineCombobox.tsx Invoices: a machine chosen in the dropdown was never actually booked 2026-10-03 15:43:46 +02:00
MachineLineChart.tsx feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
PlantMap.tsx feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
PlantMapLoader.tsx Map: dark tiles from Esri, because CARTO retired keyless access 2026-10-03 09:20:24 +02:00
PlantRegisterTable.tsx feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
RunningView.tsx Fix: the mobile table was mislabelled and clipping its own totals 2026-10-02 15:34:19 +02:00
ScrollFade.tsx Fix: the mobile table was mislabelled and clipping its own totals 2026-10-02 15:34:19 +02:00
Sidebar.tsx Mobile: the menu button was indenting every page 2026-10-03 16:08:04 +02:00
SiteBookingSelect.tsx Invoices: fix the tablet layout and make booking an unbooked line obvious 2026-10-03 09:59:05 +02:00
SiteContainerEditor.tsx Sites: auto-allocate container lines to the container the site hires 2026-10-02 18:32:12 +02:00
SiteCoordinateEditor.tsx Sites: give every site coordinates 2026-10-02 16:33:43 +02:00
SitesView.tsx Sites: a card list that reads like the income screen 2026-10-03 09:20:20 +02:00
Sparkline.tsx Invoices: keep the PDF on the invoice, and search the invoice's own words 2026-10-02 19:09:16 +02:00
ThemeProvider.tsx Mega Plant dashboard — fix & harden (Parts 0-5) 2026-09-12 09:35:48 +02:00
ThemeToggle.tsx feat: add user access and improve plant dashboard 2026-10-06 04:02:08 +02:00
Toast.tsx Fix: toast and machine dropdown were rendering behind the page chrome 2026-10-02 18:42:29 +02:00