# Materials — local prototype 0.12.1

Use invented customers, supplier names and prices only. Start the app with Start-Local-Prototype.command, sign in and open **Materials** in the sidebar. The normal starting databases have no materials or catalogue items. Existing saved local records are retained when this version starts.

An unchanged form closes without a warning. If you edit a value and press Cancel, choose **Keep editing** to preserve the draft or deliberately choose **Discard changes**. A failed save keeps your entered values. Equivalent valid price spellings such as 13.5 and 13.50 compare equally. See [the focused repair and verification](MATERIALS-DIRTY-STATE-CHECKPOINT.md).

## Try it

1. Add a test enquiry in Jobs. Materials need an explicit job link.
2. Open Materials → **Reusable catalogue** → **New catalogue item**. Enter an item name, supplier, optional SKU, unit and default cost. The optional charge reference is informational; it does not price a quote or invoice.
3. Return to **Job tracker** → **From catalogue**. Choose the job and item, enter a quantity and optionally override its cost. Save the snapshot. Changing the catalogue later leaves this job row and its original snapshot unchanged.
4. Use **Add material** for a one-off item. Record a supplier, SKU, private notes and up to eight supplier references, each with a manually recorded URL, price and date. No supplier page is fetched or monitored. **Look up previous price** finds the most recent positive cost for the exact material name in this business; applying the suggestion is explicit.
5. Select rows and **Mark ordered** or **Mark received**. Blank dates are filled automatically. Edit a row to adjust quantity, cost, notes, references or dates. Job links cannot be changed on an existing row.
6. Filter by stage, customer record, supplier or text. Active jobs are shown first; **Include historical jobs** adds completed/cancelled work. Visible counts and totals follow the filters. A job's own Materials panel always shows that job's materials, including historical work.
7. **Archive** a mistaken row to remove it from active totals; **Archived materials** lets you restore it. This replaces the source tracker's permanent deletion. Catalogue items can also be archived/restored. A conflicting active name must be resolved before restoration. Catalogue **History** shows changes and additions to jobs.
8. **Import CSV** accepts a local file or pasted text. Choose the header, map columns, choose the job/stage and review the preview. Name and cost columns are mandatory. Unmapped quantity defaults to 1; unmapped unit defaults to each. Blank/invalid mapped prices and quantities are errors. Previous-price suggestions are optional and require an explicit Apply. **Confirm import** saves all rows together; an error saves none. Limit: 200 rows / 250 KB.
9. **Order list** opens selected rows, or all visible rows if none are selected, in a private printable view. Filter by supplier first for a supplier-specific list. Costs, charge prices, supplier price references, customer contact details and private notes are excluded by the server. Maximum 200 rows per list. The **Print / save as PDF** button invokes browser printing; no order, email or PDF is sent automatically.
10. Sign out and choose the other business. Its jobs, catalogue, materials, history and order lists are separate.

## Cost rules

Costs use integer pence. Quantities allow up to three decimal places and must be greater than zero, up to 1,000,000. Each line rounds quantity × unit cost to the nearest penny, with half pennies rounded up. A unit price and a line total are each capped at £1,000,000. Example: 2.5 × £12.34 = **£30.85**; 1.5 × £0.01 = **£0.02**. Totals sum the rounded lines. These are stored purchase costs; this module does not calculate VAT, profitability or selling margins.

Bulk changes, imports, creates and catalogue additions use retry IDs and transactions. Edits require the current version. A stale edit or foreign/missing record rejects the entire operation; it does not partially update a list. Refresh Materials after a stale-version message and review the latest saved values. Unsaved forms are guarded during navigation; they are not durable offline drafts.

## Source parity and differences

The supplied SHS source is the reference, not a verified observation of the deployed system. Source behaviours retained: job purchasing stages, catalogue/SKU/default costs, optional charge reference, immutable catalogue snapshot, archive/restore/version history for catalogue, manual supplier links, historical job filters, bulk stages, CSV mapping/review and cost-free supplier ordering.

Intentional local changes: decimal quantities with an explicit three-decimal limit; exact-pence half-up totals instead of legacy float totals; customer-ID filtering; recoverable tracker archive instead of hard deletion; atomic CSV/bulk operations; no supplier network calls. The supplier output is private HTML with browser printing, not the source's directly generated PDF. Browser print/PDF saving itself has not been exercised.

Still deferred: invoice OCR/AI extraction and rollback, historical invoice backfill and its SHS tax-year rules, direct PDF generation, automatic quote population, accounting profit, tax/reporting integration, external supplier services and live price checking. Full Materials parity is therefore **partial**, with the manual workflow implemented locally.

The job panel now also shows manual labour and a combined cost summary. See CUSTOMERS-TIME-CALENDAR.md. Invoice and payment totals remain separate.
