1. Purpose
A Code is an admin-defined, required classifier on an entity — distinct from optional Categorization. Codes drive integration with downstream systems (Workbench) and enforce tiered validation at export time. Unlike Categorizations (reporting-only, never affect behaviour), Codes are integration-linked and their enforcement hardens as the Estimate moves toward Cost Management export.
Two Codes are seeded and locked (via Workbench integration):
- Workcentre — applied to Items, migrated from Benchmark’s
activity(113 options) - Activity Code — applied to Resources, migrated from Benchmark’s
cost_code(33 options)
Key difference from Categorization: Codes are required (soft in Estimate, hard at export); Categorizations are optional and never affect system behaviour.
2. Attributes
Code
| Attribute | Type | Required | Default | Notes |
|---|---|---|---|---|
id | UUID | ✅ | generated | System-managed |
name | string | ✅ | — | Human-readable name (e.g., “Workcentre”, “Activity Code”) |
scope | enum (multi-select) | ✅ | — | Entity types this Code applies to: Items or Resources. v1 locked scope—no Tenders or Estimates. Codes are line-level classifiers only; Categorization handles broader entities. |
sync_source | string (nullable) | ❌ | null | External system identifier if synced (e.g., “workbench”, “xero”). Null = admin-defined. BR-128: Codes can be sourced from external systems |
description | long text | ❌ | null | Explainer for admins; e.g., “Aligns with Workbench workcentre dimension for integration” |
locked | boolean | ❌ | false | Two Codes locked by Oxcon via Workbench: Workcentre and Activity Code. Protects integration integrity; admins cannot edit these definitions, only sync updates. Custom Codes can be created (locked = false) |
created_at / updated_at | timestamp | ✅ | system | Audit |
created_by / updated_by | User ref | ✅ | system | Audit |
Code Option
| Attribute | Type | Required | Default | Notes |
|---|---|---|---|---|
id | UUID | ✅ | generated | System-managed |
value | string | ✅ | — | The code itself; e.g., “A-PG00”, “PL-EXCAVTE” |
display_label | string | ❌ | null | Human-friendly label; e.g., “Management Staff” for value “A-PG00”. Falls back to value if null |
code_id | Code ref | ✅ | — | Parent Code (foreign key) |
parent_option_id | Code Option ref (nullable) | ❌ | null | For hierarchical Codes (e.g., parent category → child subcategory). Initial Codes are flat; reserved for future hierarchies |
external_id | string (nullable) | ❌ | null | If synced from external system (BR-128), maps back to the external ID. E.g., Workbench workcentre ID |
created_at / updated_at | timestamp | ✅ | system | Audit |
created_by / updated_by | User ref | ✅ | system | Audit |
3. Relationships
Inbound (things referring to Code)
| From | Cardinality | Notes |
|---|---|---|
| Code Option | CodeOption M:1 Code | Every Code Option belongs to exactly one Code |
Outbound (things Code references)
| To | Cardinality | Required | Notes |
|---|---|---|---|
| Code Option | Code 1:M CodeOption | ✅ | A Code defines its allowed options (1 to many) |
Code Option usage (applied to entities)
| To | Cardinality | Required | Notes |
|---|---|---|---|
| Item | Item M:0..1 CodeOption (Workcentre) | tiered (BR-127) | Soft at Estimate (nullable); hard at Cost Mgmt export |
| Resource | Resource M:0..1 CodeOption (Activity Code) | tiered (BR-127) | Soft at Estimate (nullable); hard at Cost Mgmt export |
| (future) | Tender / Estimate | M:0..1 | Extensible for additional Code scopes |
4. Validation / Invariants
Rules that must hold at all times:
- Exactly one Code per scope. Within a given entity type (Items, Resources), at most one Code per entity. E.g., an Item has one Workcentre Code Option, not multiple.
- Code Option cardinality. A Code Option belongs to exactly one Code; no orphaned options.
- Scope validity.
scopemust be one of: Items or Resources. (v1 enforcement; no Tenders or Estimates). - Locked Code edit protection. Codes with
locked = truecannot have their definition or options edited by users (UI enforces). Only sync updates from external source allowed. - Hierarchical consistency. If a Code Option has a
parent_option_id, the parent must belong to the same Code. - Required Code enforcement (BR-127).
- Items with Workcentre scope:
workcentre_option_idis soft-required in working Estimate; hard-required at Cost Mgmt export - Resources with Activity Code scope:
activity_code_option_idis soft-required in working Estimate; hard-required at Cost Mgmt export
- Items with Workcentre scope:
- External ID uniqueness. If
external_idis populated (synced Codes), it should be unique within the Code’s sync source.
5. Derived / Computed Attributes
| Attribute | Derivation | Notes |
|---|---|---|
has_missing_assignments | Count entities in scope with null Code Option refs | Used by Anomaly Review to flag incomplete Codes |
is_externally_synced | sync_source is not null | Read-only UI state; affects editability |
6. Worked Examples
Example 1 — Workcentre Code (Items), migrated from Benchmark
Context: Benchmark’s activity table (113 rows) migrates to oxFlow as the Workcentre Code, applied to Items. Shows how Items get tagged, and what happens when some Items are untagged.
Code:
id: <UUID-workcentre>
name: "Workcentre"
scope: [Items]
sync_source: "workbench"
description: "Aligns with Workbench workcentre dimension for project cost tracking"
locked: true
created_by: <system>
Code Options (sample of 113):
1. value: "A-PG00", display_label: "Management Staff", external_id: "wc_001"
2. value: "A-PG01", display_label: "Site Supervision", external_id: "wc_002"
3. value: "E-EX01", display_label: "Excavation & Earthworks", external_id: "wc_003"
...
113. value: "Z-RISK", display_label: "Risk & Contingency", external_id: "wc_113"
Items applied (sample):
Item A: "Concrete formwork"
workcentre_option_id: <Option E-EX01 "Excavation & Earthworks">
Item B: "Timber framing"
workcentre_option_id: <Option A-PG00 "Management Staff">
Item C: "Risk allowance"
workcentre_option_id: null // NOT YET ASSIGNED
Anomaly Review flags:
⚠️ Item C missing Workcentre Code — soft warning in Estimate view
🔴 Cost Mgmt export BLOCKED until Item C assigned a Workcentre
Estimator action:
1. In Anomaly Review, clicks Item C
2. Selects "Z-RISK" (Risk & Contingency) from Workcentre dropdown
3. Export now succeeds; Workbench receives all Items with assigned Workcentres
Example 2 — Activity Code (Resources), migrated from Benchmark; defaults post-migration
Context: Benchmark’s cost_code table (33 rows) migrates to oxFlow as the Activity Code Code, applied to Resources. Shows admin’s capability to assign defaults and edit options.
Code:
id: <UUID-activitycode>
name: "Activity Code"
scope: [Resources]
sync_source: "workbench"
description: "Classifies resources by cost category for Workbench reporting"
locked: true
created_by: <system>
Code Options (sample of 33):
1. value: "M-REININ", display_label: "Reinforcement (In)", external_id: "ac_001"
2. value: "M-FORM", display_label: "Formwork Materials", external_id: "ac_002"
3. value: "P-CRAN35", display_label: "Crane 35T (Plant)", external_id: "ac_003"
4. value: "C-CARPENTRY", display_label: "Carpentry Labour", external_id: "ac_004"
...
33. value: "S-FORM", display_label: "Formwork (Subcontract)", external_id: "ac_033"
Resources assigned (sample):
Resource: "Carpenter — general (Auckland, incl. tools)"
activity_code_option_id: <Option C-CARPENTRY "Carpentry Labour">
[Post-migration default: admin mapped Benchmark cost_code PL-CARPEN → C-CARPENTRY]
Resource: "Reinforcement steel — 500MPa coil"
activity_code_option_id: <Option M-REININ "Reinforcement (In)">
Resource: "Mobile crane 35T (dry hire)"
activity_code_option_id: <Option P-CRAN35 "Crane 35T (Plant)">
Resource: "Subcontracted formwork package"
activity_code_option_id: <Option S-FORM "Formwork (Subcontract)">
Post-migration admin tasks:
- Verify all Resources have Activity Code assigned
- Edit `display_label` for clarity if Benchmark cost_code values were cryptic
- Flag any Resources with null activity_code_option_id for estimator review (Anomaly Review lists them)
- Set up Workbench sync to pull new Activity Code options if external system changes
7. Admin management
Who can edit Codes and options: Admins only (BR-085, roles-permissions.md).
Scenarios:
-
Creating a custom Code (not Workbench-synced):
- Admins only — Lead Estimators cannot create custom Codes
- Admin defines name, scope (Items or Resources), description
- Adds Code Options manually
locked = false(editable in future)- No
sync_source
-
Updating a locked Workbench-synced Code:
- Per BR-128, sync is pull-only — Admin manually triggers a refresh in the UI to pull the latest Code Options from Workbench. There is no push from Workbench and no scheduled/automatic sync in v1.
- On refresh, oxFlow pulls the current option list and reconciles: new options added, existing options kept, obsolete options archived.
- Admins cannot manually edit the definition between refreshes; read-only in UI
sync_source = "workbench",locked = true
-
Viewing missing Code assignments:
- Anomaly Review reports which Items/Resources lack a required Code Option
- Admin can bulk-assign defaults or export for estimator review
-
Bulk Code assignment (UI pattern, v1):
- Users with permission can select multiple Items (or Resources) and assign the same Code Option in one action
- Improves UX for large-scale assignment workflows (e.g., post-migration cleanup)
8. Migration highlights
From Benchmark
-
Benchmark
activitytable (113 rows) → oxFlow Workcentre Code + 113 Code Options (applied to Items)activity_id→code_option.external_idactivity_desc→code_option.value(code) +code_option.display_label(if distinct)- Naming: “Workcentre” chosen to align with Workbench (Benchmark called it “Activity”)
-
Benchmark
cost_codetable (33 rows) → oxFlow Activity Code Code + 33 Code Options (applied to Resources)cost_code_id→code_option.external_idcost_code_desc→code_option.value(code) + optionalcode_option.display_label- Naming: “Activity Code” chosen to align with Workbench (Benchmark naming reversed to clarify scope)
-
Post-migration tasks:
- Map Benchmark’s item.activity_id → Item.workcentre_option_id
- Map Benchmark’s resource.cost_code_id → Resource.activity_code_option_id
- Any unmapped Items/Resources flagged as requiring Code assignment (Anomaly Review)
- Estimate submissions/exports blocked until all Codes resolved