ModulesDay Works

Day Works

Day Works lets a project keep a priced catalogue of day-work items and attach one of them — with a quantity — to any docket. The line total is quantity × rate, and a new Day Works view on the docket workbench lists every docket that has a day-works entry, with a one-click CSV export.

It is a self-contained internal-reporting feature in v1: the day-works total is tracked separately from the docket grand total and is never folded into supplier-payment allocation or ERP/GRN.

How it works

  1. An admin (or manager/engineer) builds the project’s day-works catalogue in project config — a flat list of Description, Rate, Unit rows, managed by hand or by CSV.
  2. On any non-materials docket, a user picks one catalogue item and enters a quantity. The item’s description, rate and unit are snapshotted onto the docket at that moment.
  3. The Day Works workbench view reports one row per docket that has an entry; the same filters drive both the table and the CSV export.

Because the docket keeps a snapshot, re-uploading or editing the catalogue never changes day-works already attached to dockets — it only affects what can be picked next.

Catalogue manager (project config)

Open Day Works in the project sidebar (/admin/dayworks). This page is project-scoped — each project has its own catalogue.

  • Columns: Description, Rate, Unit.
    • Description is the unique key (case-insensitive) — no code column.
    • Rate is a number ≥ 0. Unit is a free-text display label only (e.g. hour, m³, each); there is no unit conversion.
  • Add / edit / delete rows inline in the table. Deleting an item removes it from future picking; dockets that already reference it keep their snapshot and are unaffected.
  • Download template gives you a Description,Rate,Unit header-only CSV to fill in.
  • Who can manage it: admins plus managers and engineers. Other roles see the catalogue read-only.

Replacing the catalogue by CSV (two-phase)

Uploading a CSV/XLSX replaces the entire catalogue. The flow is deliberately two-phase so nothing is overwritten by accident:

  1. Pick a CSV or XLSX file (Description, Rate, Unit columns; ≤ 10 MB).
  2. Validate — the file is parsed and fully checked on the server with no database write. You see how many rows were parsed, how many would be imported, and how many items the catalogue currently has.
  3. Confirm — if every row is valid you get a “Replace N current items with M?” confirmation. If any row is invalid (missing field, blank description, non-numeric or negative rate) the upload is rejected entirely — it is all-or-nothing, the catalogue is left untouched, and a per-row error table tells you what to fix.
  4. Commit — on confirm the replace is applied atomically: the old active set is retired and the new set inserted in one transaction.

In-file duplicate descriptions (case-insensitive) are collapsed silently before insert — the last occurrence wins. The previous catalogue is retained for audit/lineage, and an aggregate audit-log entry records who replaced it and the before/after counts.

Adding day works to a docket

Open any docket and find the Day Works panel.

  • Click Add day works, search the project catalogue in the typeahead, pick an item, and enter a quantity (a positive decimal — must be greater than 0).
  • The line total is shown live as quantity × rate.
  • On save, the item’s description, rate and unit are snapshotted onto the docket and never change afterward — even if the catalogue item is later edited, re-uploaded, or removed. Only the quantity stays editable.

Rules:

  • One entry per docket. A docket has at most a single day-works line.
  • Non-materials dockets only. Day works can be attached to standard, plant, combined, and labour-plant dockets — not materials dockets.
  • Draft only. You can add, change the quantity, or remove the entry while the docket is a draft. Once the docket is submitted, reviewed, or confirmed the entry is read-only (the snapshot stays frozen regardless).
  • The day-works total is the docket’s dayworks_total. It is reported separately and is never merged into the docket’s matrix grand total.

Default day works carried from a worker’s assignment

A field worker’s project assignment can store a default day-works item (Field Users → the worker → Assignment). When that worker signs on via a wet-hire prestart, the item is snapshotted onto the auto-created sign-on docket as a single day-works line — description, unit and rate frozen at sign-on, exactly like a hand-added line.

The quantity is never carried: it is always entered on the docket. The carried line therefore lands pending — no quantity, a $0 line total, and an amber “Quantity required” prompt with the quantity input live. It stays out of every total until someone enters a real quantity (the same > 0 rule as any other day-works line), so an unentered line can never quietly bill rate × 1. Pending lines read as “Quantity required” on the docket and as an amber “Required” in the day-works workbench on both web and mobile — never 0, which would read as a settled zero. A CSV export prints a blank quantity and a 0 total.

Only the item is stored on the assignment — there is no quantity field on the assignment step. A worker with no default item signs on to a docket with no day-works line.

Day Works workbench view

For every docket in a date range with its day works and sign-offs, run the Dayworks Report.

On the docket workbench (/admin/dockets) use the Day Works toggle next to Labour & Plant and Materials.

  • One row per docket that has an active day-works entry: date, docket number, supervisor, supplier, status, plus the snapshotted description, unit, quantity, rate, and line total. The docket number carries the person and date when your organisation shows them (Docket Numbers), here and in the CSV.
  • Filters: the standard workbench filters — date range, supplier, status, cost code — plus a Day Works Item filter (pick one or more catalogue items by description). Filters are encoded in the URL, so a filtered view is shareable and bookmarkable.
  • Export CSV — the button in the view header exports exactly the rows matched by the current filters, in a deterministic column order, as dayworks-export-YYYY-MM-DD.csv (the project’s today). The export honours the same filters the table is showing.

The view updates in real time: attaching, changing, or removing a docket’s day-works entry refreshes the table without a manual reload.

v1 limitations

  • Internal-reporting only. No supplier-payment allocation and no COINS ERP / GRN export for day works.
  • Web only. There is no mobile add/edit/read of day works yet.
  • One line per docket and catalogue items only (no ad-hoc free-text day-works lines). The single-entry cap is enforced by a database constraint and is designed so multi-line support is a non-breaking change later.
  • The day-works total is intentionally kept out of the docket grand total / pricing matrix.

Architecture

  • Catalogue is project-scoped data. dayworks_items holds the per-project (description, rate, unit) rows with a case-insensitive unique key on the description and soft-delete for replace lineage.
  • The docket entry snapshots at attach. docket_dayworks stores description_snapshot, unit_snapshot, rate_snapshot, quantity, and a persisted line_total = quantity × rate_snapshot. A partial unique index on docket_id enforces one entry per docket; lifting it later (multi-line) is an index drop with no data migration.
  • Replace is atomic and all-or-nothing. The dry-run path validates with no write; the commit path soft-deletes the prior active set and bulk-inserts the new set in one transaction, leaving existing docket snapshots untouched.
  • CSV export is a synchronous streamed handler with a fixed column order — it shares the workbench list’s filter parser so the export and the table always agree.
  • Real-time — dayworks_items and docket_dayworks changes flow through Postgres LISTEN/NOTIFY → WebSocket → TanStack Query invalidation; no client polling. The wide docket-detail cache is deliberately not invalidated — the day-works total renders from its own query.
  • Tenant isolation — every catalogue and docket query is scoped by org_id/project_id from the verified session.

Spec & plan

  • Spec: docs/superpowers/specs/2026-05-17-dayworks-design.md