1. Purpose

An Estimate is a priced build-up inside a Tender — the container for a submission. A Tender can have multiple Estimates (base, alternative, strategy variants) to submit different versions or strategies; only one is typically submitted at a time.

Estimate is tightly coupled to Tender: Tender state cascades to Estimates (BR-094). See tender.md §4 for cascade rules.


2. Attributes

AttributeTypeRequiredDefaultNotes
idUUIDgeneratedSystem-managed
tender_idTender refParent Tender. Exactly one per Estimate
namestring (text)Estimate name; e.g., “Base Case” or “Alternative 2”
estimate_numberstring (free text)Internal variant identifier (e.g., “rev a”, “alt”, “1”). Appears in publisher output
lead_estimator_idUser refAssigned Lead Estimator. Required (BR-093). Nominal accountability only — NOT an access-control gate (BR-095, roles-permissions.md §2)
statusenumIn ProgressIn Progress · Reviewed · Submitted · Archived. See §4
noteslong textnullEstimate-level notes
created_at / updated_attimestampsystemAudit
created_by / updated_byUser refsystemAudit

Note on Lead Estimator (BR-093): The Lead Estimator field identifies who is primarily accountable for reporting and audit trail purposes. It does not restrict who can edit, lock, submit, or publish — those capabilities are driven by Role alone. Any User with Lead Estimator Role can perform Lead Estimator actions on any Estimate.


3. Relationships

DirectionEntityCardinalityRequiredNotes
OutboundTenderEstimate M:1 TenderParent; cascade from Tender state (BR-094)
OutboundLead Estimator (User)Estimate M:1 UserAccountability; not access-control gate (BR-093)
InboundHeadingEstimate 1:M HeadingTop-level Headings; root of the work tree
InboundRuleEstimate 1:M RuleCommercials rules scoped to this Estimate
InboundPublisher OutputEstimate 1:0..1 Publisher OutputLatest submission artifact only (BR-075); absent until first publish
InboundPrice Book AdjudicationEstimate 1:M Price Book AdjudicationAdjudications scope over this Estimate’s Resources
InboundSubcontract PackageEstimate 1:M Subcontract PackageOptional subcontract packages within this Estimate

4. Lifecycle States

StateMeaningTriggerManual/AutoNotes
In ProgressInitial state. Estimate is being built and edited. Items are priced; Worksheets active.Estimate creationAutoDefault on creation
ReviewedLead Estimator has reviewed. Anomaly checks passed or accepted. Ready for submission.Automatic when ALL Items reach status = ReviewedAuto (derived)Signals readiness; no manual transition needed. Estimate Reviewed state is derived from child Item state.
SubmittedEstimate submitted to client (via Publisher). Fully locked — no fields editable (BR-094). Submit is gated — blocked if any Item status is Unpriced or Plugged (BR-019c). Estimators can navigate to Publisher preview; only final Submit action checks the gate and fires an anomaly list if items are not submission-ready. Required Item states: Priced, Reviewed, or Locked (Reviewed is optional; Priced is sufficient).Publisher publishesAuto (on publish)Once locked, only Admin can unlock (soft delete / recovery scenario)
ArchivedEstimate no longer active. Read-only; recoverable.Tender state cascade or manual transitionAuto/ManualTriggered by Tender loss/archive (auto) or manual archival (manual)

Key note: In Progress → Reviewed transition is automatic and derived — it triggers when every Item in the Estimate reaches Reviewed status. Reviewed → In Progress can occur manually (Lead Estimator reopens) or automatically (e.g., if any Item drops below Reviewed via rate-change cascade per BR-049a).

State transition diagram:

              ┌──────────────────┐
              │   In Progress    │
              │ (editing allowed)│
              └────┬───────────┬─┘
                   │           │
             (review)      (archive)
                   │           │
                   ▼           │
              ┌──────────────┐ │
              │   Reviewed   │ │
              │ (ready)      │ │
              └────┬─────────┘ │
                   │           │
             (publish)         │
                   │           │
                   ▼           ▼
        ┌──────────────────────────────┐
        │       Submitted (Locked)     │
        │ (no edits; awaiting cascade) │
        └──────────────────────────────┘

Locked behaviour (BR-094):

  • Once Submitted, an Estimate is read-only — all Item edits, Worksheet changes, commercial rule edits are blocked
  • Cascade from Tender state (Won/Lost/Archived) moves Estimate to Archived (read-only, uneditable)
  • Only Admin can unlock (recovery scenario; rare)

Submit transition mechanics (BR-019c):

  • Submit is user-initiated but conditional: the transition checks that all child Items are submission-ready (Priced, Reviewed, or Locked).
  • Estimators can navigate to Publisher preview and review the output regardless of Item status.
  • The final Submit action itself is gated — if any Item is Unpriced or Plugged, the action fires an anomaly list rather than committing the Submitted state.

5. Real-time Collaboration (BR-095)

Model: Multiple Users with access can open the same Estimate simultaneously. Editing locks apply at Item granularity:

  • When a User begins editing an Item (or any Worksheet children), the Item enters a lock state
  • Other Users see it as “currently edited by [User]” — read-only on that Item
  • Lock releases on:
    • User closes / navigates away from the Item
    • Idle timeout (default 10 minutes — admin-configurable)
    • Admin override

Concurrent editing on different Items is unrestricted.

🟡 Flagged for Oxcon: confirm explicit per-Item locking model vs. Google-Docs-style field-level concurrent editing (more complex but more elegant).


6. Validation / Invariants

  1. One Tender per Estimate. Every Estimate’s tender_id points to exactly one Tender.
  2. Lead Estimator required. Every Estimate has a lead_estimator_id pointing to a User with Lead Estimator role. BR-093.
  3. State enum. Estimate status ∈ {In Progress, Reviewed, Submitted, Archived}.
  4. Archived non-reversible via state machine. Archived Estimates cannot be “un-archived” via state machine (Admin recovery only).
  5. Unique identification. estimate_number is free-text and may collide globally, but within a Tender it should be unique (soft constraint — UI prevents collision).
  6. Submit guard. Cannot transition Estimate to Submitted when any child Item has status ∈ {Unpriced, Plugged}. All Items must be Priced, Reviewed, or Locked. (BR-019c).

7. Worked Examples

For end-to-end Tender + Estimate flows (base/alternative/strategy variants, won/lost cascades), see tender.md §6 Worked Examples. Both example scenarios there illustrate how Estimate states interact with Tender states.