1. Purpose

An Adjudication is a persistent comparison object that imports competing supplier/subcontractor prices, normalises them for like-for-like comparison, and on award updates the Estimate with the winning pricing. Two structurally identical flavours exist — differing only in scope and output.

  • Price Book Adjudication: scopes over Resources selected from the Estimate. Supports multiple rounds. On award, winning rates replace the existing Resources (BR-062).
  • Subcontract Package Adjudication: scopes over an Item bundle. Supports multiple rounds. On award, creates/updates a system-generated Price Book with Subcontract Resources (BR-063).

Both follow the shared six-step workflow (BR-068): Generate → Export → Import → Compare → Normalise → Transfer.


2. Attributes

Shared (both flavours)

AttributeTypeRequiredDefaultNotes
idUUIDgeneratedSystem-managed
namestringE.g., “Labour rates Q2 2026” or “Electrical subcontract round 1”
statusenumDraftDraft · Adjudicated. See §5
created_at / updated_attimestampsystemAudit
created_by / updated_byUser refsystemAudit

Price Book Adjudication specific

AttributeTypeRequiredDefaultNotes
adjudication_typeenumDiscriminator: price_book
estimate_idEstimate refParent Estimate (M:1)
scoped_resource_idsarray of UUID[]Resources being adjudicated (M:M join)
round_numberinteger1Sequential round within the same resource set (BR-062)

Subcontract Package Adjudication specific

AttributeTypeRequiredDefaultNotes
adjudication_typeenumDiscriminator: subcontract_package
estimate_idEstimate refParent Estimate (M:1)
subcontract_package_idSubcontract Package refPackage being adjudicated (M:1)
round_numberinteger1Sequential round within the Package (BR-065)
system_generated_price_book_idPrice Book refnullProduced on award; system-generated (BR-063). Null until Adjudicated status

3. Supplier/Subcontractor Returns (M:M join)

Both flavours track competing returns via a join table: Adjudication Return (one per participating Company).

AttributeTypeNotes
idUUIDReturn record ID
adjudication_idUUID refParent Adjudication
company_idCompany refSupplier or Subcontractor (Company Role validated)
return_received_datetimestampWhen this return was imported
return_data (JSON)objectPriced line items: [{ item_id, resource_id, quoted_rate, unit, notes }, ...] (Price Book Adj) or [{ item_id, quoted_rate, variances: {...} }, ...] (Subcontract Adj)
selectedbooleanTrue if this return’s pricing was awarded (BR-068 Transfer step)
awarded_attimestampWhen selection occurred

4. The Six-Step Workflow (BR-068, shared for both flavours)

Step 1: Generate

Purpose: Assemble the comparison package.

  • Price Book Adjudication: Estimator selects Resources from the Estimate’s active Price Books (e.g., 8 labour rates across 3 suppliers). System creates a scoped list with current rates as baseline.
  • Subcontract Package Adjudication: Estimator references the Subcontract Package (pre-existing; persistent). System snapshots the Package’s Items (names, quantities, units) as the scope.

Stored: scoped_resource_ids (PBA) or subcontract_package_id (SPA). Status = Draft.

Step 2: Export/Send

Purpose: Package the scope for distribution to competing suppliers.

  • Format: Excel or PDF with:
    • Baseline rates (PBA: current Resource rates; SPA: item descriptions, quantities, units)
    • Instructions for return (add your quoted rates)
    • Variances template (optional inclusions, exclusions, cost notes)
  • Distribution: manual email or system integration (future; out of scope v1)
  • Tracking: return_received_date on each Return once imported

Step 3: Import

Purpose: Ingest competing returns.

For each supplier:

  • Estimator uploads an Excel return file via Import Wizard.
  • Import Wizard: smart column mapping (auto-detect or manual override), preview validation, error detection.
  • System parses and stores in the Return record (return_data JSON).
  • Validation: quantities match scope; units align; rates are numeric.

Stored: Return records in adjudication_return join table.

Step 4: Compare

Purpose: Side-by-side view of competing quotes with variances.

  • Display: table or card view showing baseline vs each supplier’s return, +/- variance per item.
  • Variance logic: if supplier says “includes waste factor” but baseline doesn’t, estimator marks as +$X (inclusion). System tracks these notes.
  • Variance/inclusion notes: captured as Content Block instances on the affected Item Worksheets. Notes persist on Items after award, independent of the Adjudication.
  • No change to data: this is a read-only exploration step.

Step 5: Normalise (BR-068a)

Purpose: Add missed items for like-for-like comparison.

  • If Supplier A quoted everything but Supplier B omitted one rate, estimator can add a normalisation row to B’s return (e.g., “use Supplier A’s rate for that item, or a manual estimate”).
  • Critical: Normalisation items exist transiently in the Adjudication only. They are not written back to the Estimate’s Resources or Items.
  • Usage: only the selected winner’s pricing (including any normalisations that apply to them) is transferred on award.

Stored: Normalisation rows live in the Adjudication’s comparison state, not persisted to Resources.

Step 6: Transfer to Buildup (BR-068)

Purpose: Apply the award.

  • Price Book Adjudication (BR-062):

    • Estimator selects one Supplier’s return.
    • System updates the scoped Resources: replaces rate with the awarded supplier’s quoted rates.
    • Estimate immediately reflects the new rates.
    • Workflow complete: Adjudication status = Adjudicated. Resources updated in place.
  • Subcontract Package Adjudication (BR-063):

    • Estimator selects one Subcontractor’s return.
    • System creates or updates the system-generated Price Book (one per Package, reused across rounds).
    • For each Item in the Package, creates a Subcontract Resource with the awarded rate.
    • Each Item’s Worksheet gets a Worksheet Resource linking to its corresponding Resource.
    • Workflow complete: Adjudication status = Adjudicated. System-generated Price Book populated. Items now reference the awarded Resources.

5. Lifecycle States

StateMeaningWho can transition
DraftInitial state. Scope assembled, returns imported, under comparison/normalisationEstimator, Lead Estimator, Admin
AdjudicatedAward applied. Resources updated (PBA) or system-generated Price Book created (SPA)Automatic on Transfer step completion

State transitions:

Draft ──normalise & transfer──> Adjudicated
Adjudicated ──re-open──> Draft (BR-064; constrained by Estimate state)

Re-open constraints (BR-064): Adjudications can be re-opened (Adjudicated → Draft) only while the parent Estimate is in an editable state (In Progress / Reviewed). Once the Estimate transitions to Submitted (or beyond — Won / Lost / Archived), the Estimate is locked (BR-094) and its Adjudications are frozen.

Re-open semantics (BR-067): When Adjudicated → Draft, the Resources persist unchanged in the system-generated Price Book (SPA) or remain updated in the Resources (PBA). Re-opening does not undo the award; it allows a new round of adjudication. For SPA, the same system-generated Price Book is carried forward and updated on the next award.


6. Relationships

Inbound (things referring to Adjudication)

FromCardinalityNotes
EstimateAdjudication M:1 EstimateBoth flavours belong to one Estimate
Subcontract PackageSP 1:M SPA AdjudicationOnly SPA; one Package can have multiple rounds (BR-065)
Price Book (system-generated)PB 1:0..1 SPALineage is 1-to-1: each SPA produces at most one system-generated Price Book, and each system-generated Price Book points back to exactly one SPA

Outbound (things Adjudication references)

Price Book Adjudication:

ToCardinalityRequiredNotes
EstimatePBA M:1 EstimateParent
ResourcePBA M:M ResourceScope (selected for adjudication)
Company (Supplier)PBA M:M CompanyVia Adjudication Return (competing suppliers)

Subcontract Package Adjudication:

ToCardinalityRequiredNotes
EstimateSPA M:1 EstimateParent
Subcontract PackageSPA M:1 SPPackage being adjudicated (M:1 per round)
Company (Subcontractor)SPA M:M CompanyVia Adjudication Return (competing subs)
Price Book (system-generated)SPA 1:0..1 PBOutput of award; null until Adjudicated (BR-063)

7. Validation / Invariants

Rules that must hold at all times:

  1. Adjudication belongs to one Estimate. estimate_id cannot be null.
  2. Status enum. status must be Draft or Adjudicated.
  3. Price Book Adjudication scope required. If adjudication_type = price_book, scoped_resource_ids must be non-empty.
  4. Subcontract Package Adjudication scope required. If adjudication_type = subcontract_package, subcontract_package_id must be non-null.
  5. Round number increments. For both PBA and SPA, round_number must be sequential starting at 1 (enforced on create).
  6. System-generated Price Book on SPA award. After Transfer step on SPA, system_generated_price_book_id must be non-null and status = Adjudicated.
  7. Supplier/Subcontractor role enforcement at first gate (BR-069). Companies in Adjudication Returns must have the appropriate Role (Supplier for PBA; Subcontractor for SPA). Validation occurs at whichever comes first: adding the Company to the Adjudication, or importing the Company’s priced return.
  8. Return data consistency. Return JSON structures must match the adjudication type (scoped resource format for PBA; item format for SPA).
  9. No circular lineage. System-generated Price Books must not reference themselves.
  10. Re-open constraint. Adjudications locked in Adjudicated state cannot be re-opened if the parent Estimate is Submitted or beyond (BR-064).
  11. Item-membership freeze on SPA (BR-065). For Subcontract Package Adjudications: Items in the parent Subcontract Package can be added or removed while the current round is in Draft. Once the round transitions to Adjudicated, the Package’s Item set is frozen until the Adjudication is re-opened (creating a new Draft round).

8. Derived / Computed Attributes

AttributeDerivationNotes
current_status_labelHuman-friendly status”Draft” or “Adjudicated” + awarded supplier/subcontractor name if applicable
is_awardedstatus == AdjudicatedBoolean convenience flag
winning_company_idFrom Return where selected = trueNull if Draft; populated on award
is_re-openablestatus == Adjudicated AND parent Estimate is in editable state (In Progress / Reviewed)Per BR-064: re-open is gated on Estimate state in v1. Once the Estimate transitions to Submitted (or Won / Lost / Archived), Adjudications are frozen and this is false

9. Revised attributes: round_number for PBA

Both Price Book Adjudication and Subcontract Package Adjudication now track round_number to support multiple rounds. For PBA, round_number increments when the same resource set is re-adjudicated (e.g., after a market re-check or cost review). This mirrors SPA’s existing round semantics and provides consistency across both flavours.


10. Worked Examples

Example 1 — Price Book Adjudication (8 labour rates, 3 suppliers)

Context: Estimate for office fitout. Estimator has baseline rates for Carpenters, Electricians, Plumbers (2–3 variants each = 8 total Resources) sourced from an old Price Book. Decides to seek fresh quotes.

Generate: Adjudication created; 8 Resources (all Labour type) selected as scope.

Export: Excel sent to 3 labour-hire suppliers (A, B, C) showing baseline rates, asking for updated day rates.

Import:

  • Supplier A returns: all 8 rates, slightly above baseline (5–10% uplift)
  • Supplier B returns: 7 rates (missed one Electrician variant); lower overall (3–8% discount)
  • Supplier C returns: all 8 rates, highly competitive (10–15% discount on most)

Compare: Side-by-side table shows each supplier’s quote vs baseline. Estimator notes:

  • B’s missing Electrician (variant 3) — a gap
  • C is cheapest but markup language on “liability” differs from A & B

Normalise: Estimator adds normalisation row to B: “Use A’s Electrician variant 3 rate for B’s comparison” ($65/day). Now all three are directly comparable.

Transfer: Estimator selects Supplier C (best value despite markup language; risk accepted). System replaces the 8 Resource rates in the Estimate with C’s quoted rates:

  • Carpenter day rate: $78 → $68
  • Electrician day rate: $92 → $79
  • Plumber day rate: $85 → $72
  • (etc., all 8)

Result: Estimate immediately recalculates with lower labour costs. Adjudication status = Adjudicated. Adjudication remains attached to Estimate for audit trail and re-opening.


Example 2 — Subcontract Package Adjudication (electrical, 3 subs, creates system-generated Price Book)

Context: Estimate for construction project. Estimator groups electrical Items (12 items: panel install, wiring, testing, etc., totalling ~2800 labour hours) into a “Electrical subcontract” Package for pricing.

Generate: Adjudication created for the Electrical Package. Scope = 12 Items (descriptions, quantities, units captured as baseline).

Export: PDF/Excel sent to 3 electrical subcontractors showing 12 line items; each sub to quote a total or per-item rates.

Import:

  • Sub A (ABC Electric): quotes fixed price per item (rates vary by item complexity)
  • Sub B (XYZ Electrical): quotes a lump sum for the whole package ($285,000) + notes on variations
  • Sub C (Local Sparks): quotes unit rates ($/hour) per item type

Compare: Estimator reviews returns. Sub B’s lump sum needs decomposition to compare fairly.

Normalise: Estimator decomposes B’s lump sum across the 12 items proportionally, adding normalisation notes. Now C’s hourly rates and A’s item rates are both visible in the comparison.

Transfer: Estimator selects Sub A (best value after normalisation, clear item breakdown, local). System:

  1. Creates a system-generated Price Book (e.g., “SPA Adjudication #42 — Electrical Round 1”, hidden from default list)
  2. Creates 12 Subcontract Resources (one per Item), each with Sub A’s quoted rate:
    • Resource “Panel install” (Type: Subcontract): $12,500 LS
    • Resource “Wall wiring 100m” (Type: Subcontract): $3.50/m
    • (etc., one per Item in the Package)
  3. For each Item in the Package, creates a Worksheet Resource linking to its corresponding Resource in the system-generated Price Book

Result:

  • Adjudication status = Adjudicated
  • System-generated Price Book contains 12 Subcontract Resources (Sub A rates)
  • Estimate’s 12 Items now pull their costs from this Price Book
  • Lineage: estimator can trace each cost back to the adjudication that awarded it

Example 3 — Re-open after scope change (Subcontract Package Adjudication)

Context: Continuing from Example 2. One week after awarding to Sub A, the client changes scope: adds 2 new electrical items, removes 1 item. Estimator must re-adjudicate.

Before re-open:

  • Adjudication #42 status = Adjudicated
  • System-generated Price Book contains 12 Resources (A’s rates)
  • Items 1–12 reference these Resources

Re-open: Estimator clicks “Re-open Adjudication #42”. Status reverts to Draft. The system-generated Price Book is preserved (BR-067): all 12 Resources remain with Sub A’s awarded rates. New Items (13, 14) and the removed Item (say #7) are scoped for re-adjudication.

New Generate: Adjudication now scopes over:

  • Keep: Items 1–6, 8–12 (existing scope)
  • Add: Items 13, 14 (new scope)
  • Remove: Item 7 (marked out-of-scope)

Re-export, Re-import, Re-compare, Re-normalise, Re-transfer: Estimator repeats the workflow with 3 subs (or same Sub A + others). Selects winner (assume Sub A again).

On re-transfer: System updates the system-generated Price Book in place (BR-063, “creates or updates”):

  • Items 1–6, 8–12: Resources remain unchanged (Sub A’s original rates)
  • Items 13, 14: new Resources created with the re-adjudicated rates
  • Item 7: Resource remains but is no longer referenced (orphaned or marked inactive in the Price Book)

Result: Estimate’s cost now reflects scope change + new adjudication. Audit trail shows two rounds: original award to A (12 items), then re-award after scope change (adds 2, retains 11 of original). No loss of history.