Materials Contracts
A docket cannot be created against a supplier until that supplier holds at least one Materials contract bound to the project, with all materials cost-allocated. This page walks the HC Project Admin through the authoring flow.
Project scoping. Contract pickers on a docket (supplier, materials, field-user, and the docket workbench cascade) list only the contracts the selected supplier holds on the current project. A supplier-link attached to several projects never bleeds another project’s contracts into the picker — the Go API enforces this server-side via
project_id(it is never trusted from, or left to, the client). The supplier-detail “rates on other jobs” view is the one intentional exception: it shows the supplier’s contracts across projects for reference.
Creating a Materials contract
The Materials contract sits inside the existing supplier-link-project relationship — same path as Labour Hire and Plant Hire, just a new value of agreement_type.
- Navigate to Admin → Contracts for the project.
- Click + New Contract and pick the supplier from the typeahead. The supplier must already be linked to the project; if not, link it via Suppliers first.
- Set Agreement type to
Materials. The editor switches to a 2-step flow:- Materials — author the rate sheet.
- Cost Allocation — map each material to a
supplier_payment_method_line.
There is no Classifications, Equipment Rates, or Allowances step — surcharges are modelled as material rows (see below).
Authoring materials
The Materials step is a flat editable table:
| Column | Required? | Notes |
|---|---|---|
| Name | Yes | Free text, case-insensitive unique within contract. Australian spelling. |
| Supplier SKU | No | Supplier’s catalogue code (e.g. BOR-N32-20-S100). Drives docket typeahead and reconciliation. |
| Description | No | Multi-line spec — slump, aggregate size, MPa class. |
| Unit | Yes | One of m3, tonne, ea, L, kg, lm, ls, load. Engine doesn’t unit-convert; pick the supplier’s billing unit. |
| Rate | Yes | Per-unit dollar rate. NUMERIC(14,4), non-negative, immutable on docket lines once created (see Dockets). |
| Min Qty | No | Billing floor. When entered_qty < minimum_qty, the pricing engine emits a top-up line so the supplier is paid the contract min. |
Realistic example for a Brisbane Metro Tunnel concrete supplier (Boral Wacol):
| Name | SKU | Unit | Rate | Min Qty |
|---|---|---|---|---|
| N20 Concrete | BOR-N20-20-S80 | m3 | 245.00 | 10 |
| N32 Concrete | BOR-N32-20-S100 | m3 | 285.00 | 10 |
| N40 Concrete | BOR-N40-20-S100 | m3 | 312.00 | 10 |
| Saturday surcharge | SUR-SAT-CONC | ea | 350.00 | |
| Pump truck hire | PMP-32M-DAY | ea | 1850.00 |
Bulk import
Supplier rate sheets are typically 30–80 rows. The Materials step ships a bulk-import drawer.
- Formats:
.csv,.xlsx. Parsed server-side; the drawer renders a per-row preview before commit. - Template: click Download template for a CSV with canonical headers (
name,supplier_sku,description,unit,rate,minimum_qty). Extra columns are ignored; missing required columns abort the parse. - Validation: required-field misses, invalid units, negative rates, and case-insensitive duplicates surface as red pills; valid rows show green.
- Errors download: failed rows can be downloaded as CSV for fix-in-place in the admin’s spreadsheet of record.
The endpoint accepts multipart form-data and returns a per-row result map — see the spec for the shape.
Modelling surcharges as material rows
Per Decision #6 in the spec, the Materials step has no Allowances tab. Surcharges — after-hours, weekend, hazmat, pump-hire, hose-extension — are modelled as material rows with unit='ea'. This keeps the editor flat and avoids a parallel allowance schema.
Saturday concrete pour example: add Saturday surcharge / SUR-SAT-CONC / ea / 350.00 / no min qty. On the docket, the supervisor adds N32 Concrete × 12 m³ and Saturday surcharge × 1 ea. The pricing engine prices both; the cost-allocation resolver routes both to the same PM line if allocated together. Same shape covers hazmat fees, pump-truck day rates, hose-extension levies.
If a surcharge needs different cost-allocation than the headline material, it gets its own PM-line mapping in the Cost Allocation step.
Cost Allocation step
After the Materials step saves, the editor advances to Cost Allocation — the same step used for labour-hire and plant-hire contracts, pivoted on contract_materials rows instead of classifications or equipment rates.
- Rows are materials; columns are
supplier_payment_method_lineentries on the supplier-link-project. - Click a cell to bind; confirm the binding to flip the status pill from Unconfirmed (amber) to Confirmed (green).
- Status pills: Unallocated (red, no row), Unconfirmed (amber,
confirmed_at IS NULL), Confirmed (green), Orphaned (red, PM line deleted). - Top-up lines inherit their parent material’s allocation via
source_entity_id— no separate row. - Non-confirmed allocations don’t block docket creation, but the docket surfaces an Unconfirmed allocation pill until closed.
A note on the AI Awards Interpreter
Materials contracts use CSV/XLSX bulk import in v1; the AI Awards Interpreter is deferred (see spec §11).