The prior .gitignore only covered `scripts/_import_one_off_*.py`,
`scripts/_smoke_*.py`, and `tsconfig.tsbuildinfo`. This session
created scripts with other prefixes (_import_splits_, _patch_) and
a tsconfig.tsbuildinfo.bak that leaked through.
Added:
- scripts/_import_splits_*.py
- scripts/_patch_*.py
- tsconfig.tsbuildinfo.bak
Now all session-local helpers stay out of git.
Following the 472ae5c pattern of tracking renamed invoice PDFs:
- invoices/157925.pdf [page 1 of JEI Supplier Invoice222.pdf]
- invoices/157926.pdf [page 2 of JEI Supplier Invoice222.pdf]
- invoices/GBP JEI Invoice - with bank details.pdf
- invoices/JEI Supplier Invoice222.pdf [2-page original, both invoices on it]
- invoices/Supplier Invoice162326.pdf [invoice 162154 - filename typo]
- invoices/161453.pdf [corrected/re-uploaded version]
The 161453.pdf replacement was driven by PATCH of the existing PB
record id o797ahy6sw175to (carriage 0 -> 280, total 844 -> 1124,
notes 'Drill serial #: 3105', pdf_file replaced).
Quick order-builder for the user. Pick a stock code, set a qty, hit Add.
Default unit price is the HIGHEST price ever paid for each code (worst-
case budget), with the reference invoice [no + date] shown in the table
so the price source is auditable. Ties broken by most-recent date so
the source reflects current market, not an old historical peak.
UI:
- Stock code dropdown shows code, description, default price, ref inv
- Inline-editable qty + unit price per row
- Running grand total at bottom
- Clear button (with confirm) wipes the list
- Export PDF button calls window.print() — browser "Save as PDF" gives
a clean table with no chrome (header/nav/controls hidden via @media
print stylesheet)
Persistence:
- List kept in localStorage key 'jei:order-list' across reloads
Files:
- app/order/page.tsx [server: fetches stock codes + lines, builds highest-price map]
- app/order/OrderClient.tsx [client: UI, state, print stylesheet]
- app/layout.tsx [nav: added Order link]
PB query note: when using `fields=...` to limit the response, you must
also include 'expand.invoice.invoice_no' and 'expand.invoice.invoice_date'
in the field selector, otherwise PB drops the expand data entirely.
- 22 files renamed to <invoice_no>.pdf (154923.pdf, 151778.pdf, etc.)
- 5 duplicate files moved to invoices/_non_jei/
- 7 files left as-is (multi-invoice PDFs or unscannable:
1.Invoice_29.05.pdf, Invoice.pdf, JEI Drilling Invoices.pdf,
JEI SA Invoice 147842.pdf, JEI SA Proforma 148931.pdf,
newdoc10018920260413143327_001.pdf, Supplier Invoice.pdf,
Supplier Invoices.pdf)
- Installed Tesseract OCR via winget
- Added scripts/ocr_invoices.py to OCR all PDFs via PyMuPDF
- Updated extract_invoices.py to fall back to OCR text for scanned pages
- Fixed stock-code regex to match "qty + code" pairs only (avoids spurious
matches like bare TCT in invoice headers)
- Added merge step to combine multi-page proformas into single invoice records
- All 11 previously-missing codes now in PB:
JEITCS12, JEITCS18, JEITCS22, JEITCL22, JEITCL92,
JEICS17, JEICS19, JEICS27, JEICS30, JEICS34, JEICS14-P1
- Only JEITCS50 remains unlisted (genuinely never ordered)
PB now: 19 invoices, 158 stock codes, 281 line items
- Removed 424 duplicate invoice lines from re-running the import
- Deleted JEISA000 stock code (it was actually your Account Ref)
- Made create_line idempotent in import_to_pb.py so re-runs skip existing
- Removed debug prints from extract_invoices.py
Next.js patches the global fetch with a cache layer that was returning
stale PB responses (showing description_goods as the code itself because
the snapshot was from before the import fixed the descriptions).
Wrap the SDK with a custom fetch using cache: no-store so every page
request gets fresh data from PocketBase.
- Two PDF layouts supported: description-before-stock-code and description-after
- Clean up trailing inch-quote artifacts and multiple-comma noise
- Importer PATCHes existing records when new description is better
- Stock codes tab now shows real goods descriptions, not just codes
The PB JS SDK serializes `filter: undefined` as the literal string
undefined in the URL, which PB rejects with 400 Bad Request.
Switched to conditionally including filter only when non-empty.