Mapping of Benchmark Estimating entities, fields, and libraries to their oxFlow equivalents. Feeds:

  • Alpha rate-library migration (proposal A3.8 MUST) — one-time import of the resource library
  • Release full cutover (proposal C5.5 / C5.6 MUST) — migration of all active estimates, libraries, and historical data; Benchmark decommissioned

Status: 🟢 POPULATED — schema review complete against Benchmark_Editable.db (240 MB, 150 tables, 288 projects, 52K+ items, 8K+ resources).

Related docs: glossary.md · concept-map.md · workplan.md (Batch G)

Database details: SQLite 3.x, 150 tables, row counts: project (288), project_item (52,277), project_section (3,250), resource_library (8,135), resource_rate (40,670 with history), item_library (153 subitems), subcontractor_quote_item (83,528).


1. Benchmark schema overview

Benchmark’s schema is a mature, relational estimating database with ~150 tables. Below are the key entities relevant to oxFlow migration, organized by domain:

Project & Estimate containers

Benchmark TableRowsPrimary KeyPurpose
project288project_idTender/Estimate container; 206 columns including cost, margin, spread, commercials, risk tracking
estimates9idEditable estimate snapshots (newer schema); links to project via source_project_id
project_section3,250project_section_idWBS/Heading structure; nests under project; tracks cost, duration, completion %
estimate_sections267idHeading/section grouping in editable estimates (newer schema)

Line items & structure

Benchmark TableRowsPrimary KeyPurpose
project_item52,277project_item_idLine items; nests under project_section or parent project_item (self-referential); tracks qty, rate, cost, prod rate, is_overhead, is_subitem, provisional sum, rate-only flags
estimate_items728idLine items in editable estimates (newer schema); flatter structure than project_item
item_variable62,822Variables within an Item’s Worksheet; manual definitions or calculations
project_variable607Project-level variables; mostly used for production rates and formulas

Resource library

Benchmark TableRowsPrimary KeyPurpose
resource_library8,135resource_library_idResource master; labour, material, plant, subcontract; includes code, description, rate, unit, flagfall, cartage, plugged (placeholder) flag, carbon EPD, currency
resource_rate40,670resource_rate_idRate history table; tracks changes over time with region, effective date ranges, expiry dates (resource_rate_todate); all 8,134 unique resources have multiple historical rates
resource_type2resource_type_idResource classification: PLUG (placeholder), FIXED; NOTE: orthogonal to resource_category below
resource_category5resource_category_idResource domain: LABOUR, MATERIALS, PLANT, SUBCONTRACT, SUBITEM

Item library (Subitems / Recipes)

Benchmark TableRowsPrimary KeyPurpose
item_library153item_library_idSubitem/Recipe definitions; marked as subitem (Y/N); includes cost, rate, production rate, quantity, calculation, cost/rate ranges; 1 has prod_rate set
item_library_resource1,002itemlib_resource_idSubitem composition; many-to-many join between subitem and resource; includes quantity, calculation, crew size, cost/qty ranges
item_library_structure0Unused in this DB — would support hierarchical subitems

Classifiers & codes

Benchmark TableRowsPrimary KeyPurpose
activity113activity_idActivity code (WBS classifier); e.g., “A-PG00 Management Staff”, “E-MS05 Risk”
cost_code33cost_code_idCost code classifier; e.g., “PL-EXCAVTE”, “PL-COMPACT”
resource_groupGrouping table for resources
item_groupGrouping table for items
unit67unit_idUnit definitions; e.g., DAY, EACH, HOUR, m², m³, LS

Subcontracting

Benchmark TableRowsPrimary KeyPurpose
subcontractor185subcontractor_idSubcontractor company master; address, contact, phone, email, type, region, inactive flag
subcontractor_quote542subcontractor_quote_idQuote/adjudication records; links project + subcontractor
subcontractor_quote_item83,528subconquote_item_idQuote line items; rate per item, accepted/selected flags

Commercials & calculations

Benchmark TableRowsPrimary KeyPurpose
project_resourceJoin table linking resources into project items for estimate build-up
project_resource_prodrateProduction rate tracking per project resource

Audit & configuration

Benchmark TableRowsPrimary KeyPurpose
resource_changes3,048Change log for resource updates
activity113activity_idAlso serves as audit log of activities performed
audit_dataGeneral audit trail
configuration_ tables* (boolean, string, float, integer, text)System configuration

Supporting reference data

Benchmark TableRowsPrimary KeyPurpose
organisation0organisation_idCompany master (unused in this DB)
clientclient_idClient/company data (may be separate from organisation)
region, state, depotGeographic & operational scope
currency0currency_idCurrency definitions (unused)
variable_library561Reusable variable definitions
risk_library, risk_register0Risk management (unused)

2. Entity mapping table

High-level Benchmark → oxFlow mapping

Benchmark EntityoxFlow EntityCardinalityNotes
projectTender1:1Benchmark “project” = oxFlow “Tender” (outermost container); 288 projects map to 288 Tenders
projectEstimate1:MOne Benchmark project can have multiple estimate variants (via estimate_sections, separate estimate_items logic)
project_sectionHeading1:1Heading structure; nests up to 5 levels as oxFlow allows
project_itemItem1:1Line items; self-nesting supported in both
item_variableVariable1:1Worksheet variables (calculations, manual entries)
item_libraryRecipe1:1Subitem ≈ Recipe; has internal Worksheet (composition of resources)
item_library_resourceWorksheet Resource1:1Resource line within a Worksheet
resource_libraryResource1:1Atom; lives in a Price Book post-migration
resource_ratePrice Book (archived)1:MEach historical rate window becomes a Price Book with a date-range scope; superseded ones archived. See §4.2.
activityCode “Workcentre” (on Items)1:1Applied to Items. Matches Workbench’s Workcentre dimension.
cost_codeCode “Activity Code” (on Resources)1:1Applied to Resources. Matches Workbench’s Activity Code dimension.
subcontractorCompany (Supplier/Subcontractor role)1:1External organisation; already sync’d from Xero in oxFlow
subcontractor_quoteSubcontract Package Adjudication1:1Adjudication round; outputs system-generated Price Book
subcontractor_quote_itemAdjudication resultBecomes Resources of type Subcontract in Price Book post-award

Known concept mappings

Benchmark conceptoxFlow mappingMigration handling
Section > Item > Resource hierarchyHeading > Item > Worksheet Resource (via Resource in Price Book)Direct tree mapping; drop depth constraint if needed
Subitem (crew/composition)Recipe with Input Parameters + Output UnitItem library ≈ Recipe. Output Unit sourced directly from Benchmark’s item unit field (typically defined in Benchmark).
Resource rate + historyCurrent rate on Resource + archived Price Books for historyEach Benchmark rate window becomes a Price Book with a date-range scope (see §4.2). Archived Price Books retain full history and remain queryable by the Estimate Review Assistant (C4.4).
Project cost calculationItem cost roll-up + Commercials RulesDirect; calculations in Worksheet Variables
Spread/margin mechanicsRule (Percentage / Lump Sum)Benchmark’s spread system → oxFlow Rules
Provisional sum flagItem Type (Provisional Item) or flagSet item type or Provisional flag during migration
Rate-only itemItem Type (Rate-Only Item)Preserve via Item Type
Plugged (placeholder) ratePlug Rate flag on ResourceMark in Resource metadata; flagged by Anomaly Review
Production rateVariable (within Worksheet)Migrate to Worksheet Variable with origin = manual
Overhead/Indirect costItem Flag (Indirect Cost) OR Item TypeCapture is_overhead from project_item; map structurally if not marked
Cost code + Activity code (Benchmark naming)Two separate Codes in oxFlow: Activity Code (Resources) ← Benchmark cost_code; Workcentre (Items) ← Benchmark activity.Naming intentionally re-aligned with Workbench conventions.

3. Field-level mapping per entity

3.1 PROJECT → TENDER / ESTIMATE

Benchmark: project (288 rows)

Benchmark fieldoxFlow fieldTransformationNotes
project_idtender.id / estimate.idUse as external reference; generate new oxFlow IDBenchmark ID stored in audit
project_quote_notender.numberDirect mapE.g., “22-077 R0”
project_desctender.nameTrim if >255 charsDescription of opportunity
principal_client_idtender.client (Company)Join to client; resolve Xero syncClient role on Company
project_locationtender.locationDirect mapSite location
project_date_tenderclosetender.tender_due_dateDirect mapTender deadline
project_start_datetender.contract_start_dateDirect mapWhen work begins
project_costestimate.total_costComputed from items; snapshot for validation
project_profit, project_margin_percent, project_profit_overheadrule.valueCreate commercials Rules for margin/overheadSequence matters; add in order
project_indirectcost_markuprule.value (Indirect Cost Rule)Create as Rule type PercentageMarkup % on indirect costs
project_qty, project_unit_idtender.quantity / tender.unitDirect map if presentMay be empty for many-item tenders
project_comments, project_notestender.notesDirect mapFree text
project_status, project_bid_statustender.statusMap: bid_status (1=Active, 2=Submitted, 3=Won, 4=Lost) → tender.statusProvisional mapping
project_approved_by, project_approval_dateNot mappedDropped; not in oxFlowAdmin notes log instead
project_is_templateNot migratedTemplate projects excluded from migrationFlag for manual review post-cutover
project_winner_id, project_winner_priceNot mappedInformational; archive if neededHistorical data, no active use

Benchmark: estimates (9 rows — newer schema)

Benchmark fieldoxFlow fieldTransformationNotes
idestimate.idUse as external reference; generate new oxFlow ID
nameestimate.nameDirect mapVariant name, e.g., “Base”, “Alt A”
clienttender.client (from parent project)Resolve via source_project_id
referenceestimate.number (or notes)Store as estimate.notes if no dedicated fieldVariant code
statusestimate.statusMap: “draft” → “In Progress”, “reviewed” → “Reviewed”

3.2 PROJECT_SECTION → HEADING

Benchmark: project_section (3,250 rows)

Benchmark fieldoxFlow fieldTransformationNotes
project_section_idheading.idGenerate new ID; store Benchmark ID in audit
project_idheading → estimate (via parent project)Join to parent project → estimate
project_section_numberheading.titleDirect; e.g., “01”, “02.1”WBS number becomes title or separate code field
project_section_descheading.title (append to number if both needed)Combine number + desc if display order important
project_section_overheadNot directly mappedMay flag as Indirect Cost at item level insteadOverhead is a property of contained Items
project_section_cost, project_section_durationDerivedComputed from contained itemsNo storage needed
project_section_actualcost, project_section_costtodateArchivedHistorical; not migrated to active oxFlowPreserve in audit log
sort_orderheading.display_orderPreserve item order

Benchmark: estimate_sections (267 rows)

Benchmark fieldoxFlow fieldTransformationNotes
idheading.idGenerate new; store Benchmark ID
estimate_idheading → estimate.idDirect join
numberheading.title (or schedule_code equivalent)Direct; e.g., “1”, “2”
descriptionheading.titleDirect
levelDepth calculatedInfer from parent chain; constrain to 5

3.3 PROJECT_ITEM → ITEM / WORKSHEET

Benchmark: project_item (52,277 rows)

Benchmark fieldoxFlow fieldTransformationNotes
project_item_iditem.idGenerate new; store Benchmark ID
project_item_textitem.descriptionDirect; trim to 4000 chars if needed
project_item_qtyitem.quantityDirect; REAL → numeric
unit_iditem.unit (via unit table)Map Benchmark unit_id → oxFlow UnitAll 67 Benchmark units must map to oxFlow Unit library
project_item_costDerivedSum of Worksheet Resources × quantity
is_subitemitem.item_typeMap: ‘Y’ → sub-Item, ‘N’ → Itemself-nesting in Item
project_item_parent_iditem.parent (Item)Self-reference to parent Item
project_item_isoverheaditem.item_flag (Indirect Cost)‘Y’ → Indirect Cost flag = trueOR use Item Type (Indirect Item) if introducing
activity_iditem.code_option (Workcentre)Applied to Items — maps to oxFlow’s “Workcentre” CodeBenchmark “Activity” → oxFlow “Workcentre” by design (Workbench alignment)
cost_code_idNot applied to ItemsBenchmark “Cost Code” is applied to Resources in oxFlow (Activity Code), not Items
project_item_prodrate, project_item_produnitidvariable.value / variable.unitCreate Variable(name=“prod_rate”, value=…, unit=…)Variables live in Worksheet
project_item_isprovsumitem.item_type’Y’ → Provisional Item typeFlag for review in Anomaly Dashboard
project_item_rateonlyitem.item_type’Y’ → Rate-Only Item typeSupply-only, no committed quantity
project_item_actualcost, project_item_costtodateArchivedNot migrated; historical dataKeep in audit log
project_item_marginrule.value (Item-specific Rule)If set, create Rule scoped to this ItemMargin as Rule
project_item_noncalculationFlagMark Item to not recalculate costTreated as fixed cost in oxFlow
project_item_calculationworksheet.calculation_blockIf present, migrate to Calculation Block inside Worksheet
project_item_spreadtype, project_item_isspread, project_item_donotspreadrule.scopeSpread type → Rule targetingClassic Benchmark mechanics → oxFlow Rules
project_item_submitamount, project_item_submitratesubmission_value.valueSubmission override if setClient-facing amount post-Commercials
project_item_rateonly, project_item_rateonlyamountitem.plug_rateIf rateonly=‘Y’ and rateonlyamount is set, map to plug_rate (nullable number); otherwise nullRate-plugged Item (direct entry, no Worksheet build-up)
project_item_inactiveitem.item_flag (Inactive)‘Y’ → Inactive flagSoft-disable for history

Benchmark: estimate_items (728 rows)

Benchmark fieldoxFlow fieldTransformationNotes
iditem.idGenerate new; store Benchmark ID
section_iditem.heading (parent Heading)Join to estimate_sections → heading
descriptionitem.descriptionDirect
quantityitem.quantityDirect
unititem.unit (string directly)Map to oxFlow Unit library
is_client_itemitem.item_type’Y’ → Schedule Item, ‘N’ → Normal ItemClient-facing vs internal
is_priceditem.status’Y’ → Priced, ‘N’ → unpriced (flag for review)

3.4 ITEM_LIBRARY → RECIPE

Benchmark: item_library (153 rows)

Benchmark fieldoxFlow fieldTransformationNotes
item_library_idrecipe.idGenerate new; store Benchmark ID
item_library_issubitemN/AAll rows are subitems (Y) or templates; treated as Recipes
unit_idrecipe.output_unit (via unit table)Map Benchmark unit → oxFlow UnitDeclares what unit the Recipe outputs in
item_library_rateDerivedRecipe’s Worksheet evaluates to a rate
item_library_prodrate, item_library_prodrate_unitidvariable (inside Recipe’s Worksheet)Migrate as Variable1 row has prod_rate set; most are 0
item_library_calculationworksheet.calculation_blockMigrate as Calculation Block
item_library_qty, item_library_crewsizeinput_parameterIf meaningful, create Input Parameter(name, unit, default_value)
cost_code_id, activity_idresource.code (on child resources)Propagate to Resource codes via item_library_resource join
item_library_code2, item_library_code3, item_library_code4Extra codesIf multiple code dimensions, store allBenchmark supports up to 4 codes

3.5 ITEM_LIBRARY_RESOURCE → WORKSHEET RESOURCE (inside Recipe)

Benchmark: item_library_resource (1,002 rows)

Benchmark fieldoxFlow fieldTransformationNotes
itemlib_resource_idworksheet_resource.idGenerate new
resource_idworksheet_resource.resource (join to resource_library)Direct; resolve to oxFlow Resource
itemlib_resource_qtyworksheet_resource.quantityDirect; REAL → numeric or expression
itemlib_resource_calculationworksheet_resource.quantity (if expression)Store as expression if calculation present
itemlib_resource_crewsizevariable (Crew Size variable inside Recipe Worksheet)Create as Variable if meaningful
itemlib_resource_prodrateidvariable (Production Rate variable)Join to itemlib_resource_prodrate table
itemlib_resource_textworksheet_resource.notesDirect
range_id, distribution_type, cost/qty min/maxDiscardedMonte Carlo / uncertainty ranges not in scope for oxFlow v1Not carried forward

3.6 RESOURCE_LIBRARY → RESOURCE (in Price Book)

Benchmark: resource_library (8,135 rows)

Benchmark fieldoxFlow fieldTransformationNotes
resource_library_idresource.idGenerate new; store Benchmark ID for audit
resource_library_coderesource.description (prefix) or code attributeBenchmark code becomes Resource identifierE.g., “Ti20H5”
resource_library_descresource.descriptionFull description; e.g., “Timber 200x50 H5”
resource_library_rateresource.rateUse current rate from resource_library; see resource_rate for historySnapshot at migration
unit_idresource.unit (via unit table)Map Benchmark unit → oxFlow UnitAll resources must have Unit
resource_library_typeidNot directly usedBenchmark types (PLUG, FIXED) are orthogonal; ignoreUse category instead
resource_categoryresource.resource_typeMap: LABOUR → Labour, MATERIALS → Material, PLANT → Plant, SUBCONTRACT → Subcontract, SUBITEM → RecipeSUBITEM goes to Recipes, not Resources
activity_idNot applied to ResourcesBenchmark “Activity” is applied to Items in oxFlow (as “Workcentre”), not Resources
cost_code_idcode_option (Activity Code) on ResourceApplied to Resources — maps to oxFlow’s “Activity Code” CodeBenchmark “Cost Code” → oxFlow “Activity Code” by design (Workbench alignment)
FLAGS → Flag Catalog
resource_library_ispluggedFlag: “Plug Rate“‘Y’ → apply Plug Rate flag via Flag Catalog entry; flagged by Anomaly ReviewPlaceholder rates need review
resource_library_iscartageFlag: “Cartage“‘Y’ → apply Cartage flagIf cartage included in rate, document in Cartage Modifier instead
resource_library_isgstFlag: “GST Applicable“‘Y’ → apply flag; ‘N’ → not appliedTax treatment flag
resource_library_iscurrencyFlag: “Multi-Currency“‘Y’ → flag set; assumes AUD primaryCurrency handling in v1
resource_library_isexchlockedFlag: “Exchange Rate Locked“‘Y’ → flag setFor locked FX rates
resource_library_donotinflateFlag: “Do Not Inflate“‘Y’ → flag setExclude from inflation adjustments
MODIFIERS → Modifier Catalog
resource_library_factorModifier: “Factor” (math: multiply)Numeric multiplier; unit-agnosticScaling factor; default 1.0
resource_library_wastageModifier: “Wastage” (math: percentage add)Percentage wastage/loss; e.g., 5%Added to base cost as % increase
resource_library_flagfallModifier: “Flagfall” (math: add)Fixed charge added to rateE.g., callout fee, minimum charge
resource_library_mindistanceModifier: “Minimum Distance” (math: add)Distance-based minimum; unit: kmCartage minimum threshold
resource_library_crewsizeModifier: “Crew Size” (math: multiply)Crew multiplier; e.g., 1.5 crew → 150% rateResource efficiency / crew scaling
DIRECT FIELDS
resource_library_notesresource.notesDirect
resource_library_code2, resource_library_code3, resource_library_code4Extra codesIf multiple code dimensions, store in notes or create Code tags
currency_idCurrency handlingIf multi-currency, store currency code on Resource; assume AUD default
subcontator_idNot applicableSubcontractor resources come from subcontractor_quote_item resultsDon’t pre-link resources to subs
carbon EPD columnsresource.notes or separate flagIf carbon tracking needed, document in notes; can be added post-migration15 carbon columns present
region_id, resource_library_regionscoperesource.categorization (optional)If regionally scoped, tag with Region Categorization OptionOptional in v1

3.7 RESOURCE_RATE → Archived Price Books (historical rates via Price Book date scope)

Benchmark: resource_rate (40,670 rows)

Historical rates are migrated into oxFlow by grouping rates by their validity window and creating a Price Book per window with a date-range scope. Superseded Price Books are flagged as archived but remain queryable (useful for the Estimate Review Assistant, C4.4, and Historical Rate comparisons).

Benchmark fieldoxFlow mappingTransformationNotes
resource_rate_idresource.id (inside an archived Price Book)Each rate window → a Resource entry in the corresponding archived Price Book
resource_library_idresource.source_library_idPointer back to the canonical Resource ID so rate history can be walked per-resource
resource_rateresource.rateDirect
resource_rate_updatedprice_book.scope_startEarliest rate update in the window → start of Price Book scope
resource_rate_todateprice_book.scope_endExpiry date → end of Price Book scopeWhen superseded, Price Book is flagged archived
region_idprice_book.scope_region (or Categorization on Resources within)If regional scoping matters, applied at Price Book scope level

Archived Price Book semantics: read-only, not surfaced in the default Price Book list, queryable by Anomaly Review’s historical comparison layer (Release milestone) and by AI review assistant.


3.8 ACTIVITY → oxFlow Code “Workcentre” (on Items)

Benchmark: activity (113 rows)

Benchmark’s “Activity” table maps to oxFlow’s Workcentre Code, applied to Items. Naming deliberately aligned with Workbench conventions.

Benchmark fieldoxFlow fieldTransformationNotes
activity_idcode_option.idGenerate new; store Benchmark ID
activity_desccode_option.valueE.g., “A-PG00 Management Staff”113 codes
code.name”Workcentre”Single Code named “Workcentre” with 113 options; scope: applied to Items

3.9 COST_CODE → oxFlow Code “Activity Code” (on Resources)

Benchmark: cost_code (33 rows)

Benchmark’s “Cost Code” table maps to oxFlow’s Activity Code Code, applied to Resources. Naming deliberately aligned with Workbench conventions.

Benchmark fieldoxFlow fieldTransformationNotes
cost_code_idcode_option.idGenerate new; store Benchmark ID
cost_code_desccode_option.valueE.g., “PL-EXCAVTE”33 codes
code.name”Activity Code”Single Code named “Activity Code” with 33 options; scope: applied to Resources

3.10 UNIT → UNIT

Benchmark: unit (67 rows)

Benchmark fieldoxFlow fieldTransformationNotes
unit_idunit.idReuse Benchmark ID if no conflicts
unit_descunit.symbol or unit.display_nameMap: e.g., “DAY” → “day”, “EACH” → “ea”, “HOUR” → “hr”, “LS” → “LS”oxFlow has built-in Units; may need to add custom ones

3.11 SUBCONTRACTOR → COMPANY

Benchmark: subcontractor (185 rows)

Benchmark fieldoxFlow fieldTransformationNotes
subcontractor_idcompany.id (already synced from Xero)Match by name or create new; sync from Xero during cutover
subcontractor_companycompany.nameDirect match with Xero sync
subcontractor_address, subcontractor_town, state_id, subcontractor_postcodecompany.addressMap to Xero address fields
subcontractor_contact, subcontractor_phone, subcontractor_emailcompany contact infoMigrate if not in Xero; else Xero is source of truth
subcontractor_type_idcompany.company_role (Subcontractor)Ensure role is set to Subcontractor

3.12 SUBCONTRACTOR_QUOTE → SUBCONTRACT PACKAGE ADJUDICATION

Benchmark: subcontractor_quote (542 rows)

Benchmark fieldoxFlow fieldTransformationNotes
subcontractor_quote_idsubcontract_package_adjudication.idGenerate new; store Benchmark ID
project_idsubcontract_package_adjudication.subcontract_package.estimate.idJoin to parent project → estimate
subcontractor_idsubcontract_package_adjudication.companyLink to Company with Subcontractor role
subcontractor_quote_timestampsubcontract_package_adjudication.created_dateDirect
subcontract_package_adjudication.round_numberExtract from Benchmark; default to 1 if absentRound of adjudication

3.13 SUBCONTRACTOR_QUOTE_ITEM → SUBCONTRACT PACKAGE ADJUDICATION RESULTS

Benchmark: subcontractor_quote_item (83,528 rows)

Benchmark fieldoxFlow fieldTransformationNotes
subcontractor_quote_item_idAdjudication working dataTransient; used to populate system-generated Price Book on award
project_item_idsubcontract_package_adjudication.item (within package scope)Link back to Item being priced
subconquote_item_ratePrice Book Resource rateOn award, create Resource (Type=Subcontract) with this rate in system-generated Price Book
subconquote_item_acceptedAward indicatorIf true, this subcontractor’s quote was accepted for this item
subconquote_item_selectedSelection flagMarks selected quotes during adjudication

4. Lost concepts

Benchmark features with no oxFlow equivalent or intentionally dropped:

Benchmark conceptWhy droppedMigration handlingFallback for users
Resource types (PLUG, FIXED)Orthogonal to oxFlow’s Resource Type taxonomy; not neededDrop; use resource_category insteadResources migrate via category (Labour, Material, etc.); plug rates flagged separately
Spread types & spread mechanicsReplaced by oxFlow’s Rule system (more flexible)Convert each spread to a Rule with appropriate scope (direct-only, percentage, etc.)Rules provide more granular control; training needed on new mechanics
Uncertainty ranges (min/max/distribution)Monte Carlo ranges not in oxFlow scopeDiscarded — not carried forwardFeature consciously dropped; not on roadmap
Regional resource variantsoxFlow scopes via Categorization, not separate Resource copiesMerge regional variants into single Resource; use Categorization tagsLess granular than Benchmark; clarify acceptable precision loss with users
Resource rates with multiple currenciesoxFlow v1 assumes single currency per Price BookMigrate to AUD; flag if currency conversions neededMulti-currency Price Books deferred to post-launch; convert at migration time
Rate history (full audit trail)Not lostHistorical rates migrated into archived Price Books (date-range scoped). Remain queryable — feeds Anomaly Review historical comparison and AI review assistant.See §3.7
Cartage flagfall, mindistance, factor, wastage, crewsizeNot lost — mapped to Modifier CatalogMigrated as Modifier Catalog entries with math operations (flagfall=add, mindistance=add, factor=multiply, wastage=percentage, crewsize=multiply). See §3.6 & §5.Modifier Catalog provides explicit, auditable application.
Overhead/Indirect cost inheritanceoxFlow derives indirect cost structurally; Benchmark flag allowed overrideCapture is_overhead in Item flag; recommend structural reviewMay need post-migration review of edge cases
Provisional sum amount overrideoxFlow Item Types capture intent; amount is computedMigrate provisional flag; preserve amount in notes for validationUsers can re-enter amounts if needed
Claim / contract cost trackingNot in v1 scopeArchive claim_* tables; not migratedPost-launch feature; can import later
Risk register & risk libraryUnused in this Benchmark DB (0 rows)Skip migrationRisk management in oxFlow deferred
TemplatesBenchmark has template projects (is_template = Y); oxFlow v1 has no template mechanismFlag for manual recreation; exclude from active migrationAdmins can clone completed estimates as templates post-launch
Multi-estimate variants per projectBenchmark mixes project + estimates schemas; oxFlow unifies under EstimateFlatten: migrate all estimate_items + estimate_sections per variant as separate Estimates under same TenderOne Tender → many Estimates (base, alt a, alt b, etc.)
Custom fields (custom_ tables)*Benchmark has 10 custom field tables; oxFlow has no custom field framework in v1Audit custom fields; migrate non-empty ones to notes/categorization; flag for admin reviewv2 may add custom field support; data not lost
Variable library561 pre-defined Variables; oxFlow Variables are per-WorksheetMigrate commonly-used ones as Variable patterns in Recipes; rest as templates in notesUsers recreate custom Variables per Worksheet as needed
Project composition / BOMproject_composition table links projects (hierarchies)Flatten to individual projects; preserve parent_proj_id in auditNo parent-child Tender concept in oxFlow v1

5. New concepts

oxFlow features with no Benchmark source; require defaults or admin setup:

oxFlow conceptBenchmark equivalentMigration defaultPost-migration admin setup
Recipe Output Unit (BR-030)Benchmark item_library typically has a unit field (confirm during migration — likely unit_id or similar on the item_library table)Direct map from Benchmark’s item unit field to oxFlow’s Output UnitIf the field is missing for a given Recipe, flag for admin review
Flag CatalogBenchmark boolean/enum Resource fields (isplugged, iscartage, isgst, iscurrency, isexchlocked, donotinflate)Locked: Benchmark Resource-level boolean/enum fields map to Flag Catalog entries. Admin creates catalog entries at migration using field names as seeds (e.g., “Plug Rate”, “Cartage”, “GST Applicable”). Flag values applied to Resources via catalog. Lead Estimator can curate flags post-migration.See §3.6 Flag → Catalog mapping. All 6 boolean fields seeded as flags.
Modifier CatalogBenchmark numeric Resource fields (factor, wastage, flagfall, mindistance, crewsize)Locked: Benchmark numeric/additive fields map to Modifier Catalog entries with math operations (multiply, add, percentage add). Admin creates catalog at migration with field names and default operations (e.g., Factor=multiply, Flagfall=add, Wastage=percentage). Modifier values applied to Resources via catalog with math operation. Lead Estimator can curate modifiers post-migration.See §3.6 Modifier → Catalog mapping. All 5 numeric fields seeded with math operation.
Codes (BR-125–128) — Workcentre + Activity Codeactivity (113) + cost_code (33) tables exist in BenchmarkLocked: Benchmark activity → oxFlow Workcentre Code (applied to Items). Benchmark cost_code → oxFlow Activity Code Code (applied to Resources). Naming aligned with Workbench.Two separate Code dimensions; see §3.8 / §3.9
Reference Rates (BR-144)No Benchmark equivalentNone; admin creates post-migrationRequired for Anomaly Review Layer 2; admin defines expected unit rates per category
Real-time collaborationNo explicit support in BenchmarkNot applicable; Benchmark is single-sessionUsers learn oxFlow’s explicit per-Item locking model
Anomaly Review layers 2 & 3Benchmark has no anomaly dashboardLayer 1 rules (deterministic) can be sourced from data (e.g., Plug Rate flags); Layers 2 & 3 are AI-drivenAdmin populates Reference Rates for Layer 2 (rules-first); Layer 3 (AI) enabled in Release
Price Book AdjudicationNot a standalone concept in Benchmark (subadjudication only)None; requires project dataEstimators learn to create adjudications for resource pricing rounds
Submission Value overridesBenchmark project_item_submitamount field existsMigrate if set; else compute from CommercialsEstimators can override final Submission Values per schedule item
Item Types (Schedule, Normal, Provisional, Rate-Only)Implicit in item flags (is_client_item, is_priced, is_rateonly, is_provsum)Map Benchmark flags → oxFlow Item TypesAdmin & user training on when to use each type
Categorization (optional tagging)Benchmark has resource_category, item_categoryOptionally migrate as Categorization Options; flag for admin reviewAdmin defines Categorization taxonomies post-migration (e.g., trade, location, discipline)

6. Data cleaning & transformation rules

Unit mapping

Benchmark’s 67 units must map to oxFlow’s Unit library. Priority mapping:

Benchmark unitoxFlow mappingNotes
DAYdayBuilt-in
HOURhrBuilt-in
EACH, NOeaBuilt-in
m, m², m³m, m², m³Built-in
LSLSBuilt-in
KG, Tkg, tBuilt-in
WK, MONTHwk, mthCustom add if missing
CARTAGE - KMkm (or cartage-specific)Custom; map logic needed
othersAudit case-by-case~67 total; bulk map to built-in where possible; document custom ones

Action: Audit Benchmark unit table; generate mapping script; test on sample data.

Resource duplicates & merging

Check for duplicate resources (same description, different rates):

SELECT resource_library_desc, COUNT(*) as cnt, COUNT(DISTINCT resource_library_rate) as rate_variants
FROM resource_library
GROUP BY resource_library_desc
HAVING cnt > 1

Action: For duplicates, pick the most recent rate (resource_library_dateupdate max); retire others. Document in audit log.

Stale / expired rates

All 40,670 resource_rate records have expiry dates (resource_rate_todate). Filter:

  • Rates with resource_rate_todate < today: ARCHIVE — do not migrate to active Price Book
  • Rates with resource_rate_todate >= today: MIGRATE

Threshold: Rates expiring within 30 days post-cutover should be reviewed and refreshed.

Plugged (placeholder) rates

1,307 resources marked with resource_library_isplugged = ‘Y’.

Action: Flag all Plug Rate Resources in Anomaly Review; require estimator confirmation before estimate submit.

Orphaned records

  • Orphaned resources: resource_library rows not used in any project_item (via project_resource join)
    • Action: Migrate all; they’re part of the library. Track unused for potential clean-up.
  • Orphaned subitems: item_library rows not used in any project_item
    • Action: Migrate; may be deprecated library items.

Inconsistent units

Detect Items where unit_id differs from contained Resource unit_id:

SELECT pi.project_item_id, pi.unit_id, pr.unit_id as res_unit_id
FROM project_item pi
JOIN project_resource pr ON pi.project_item_id = pr.project_item_id
WHERE pi.unit_id != pr.unit_id

Action: Flag for manual review; estimator must confirm conversion logic in Worksheet Variable.

Activity & Cost Code assignments

Resources not assigned activity_id or cost_code_id:

SELECT COUNT(*) FROM resource_library WHERE activity_id IS NULL
SELECT COUNT(*) FROM resource_library WHERE cost_code_id IS NULL

Action: Set sensible defaults or flag for admin assignment post-migration. Required by Workbench integration (BR-127).

Calculation expressions

10,072 project_items and 9 item_library rows have calculation expressions.

Action: Migrate to Worksheet Calculation Blocks; parse & validate syntax; flag non-standard formulas for review.

Variables

62,822 item_variables; 607 project_variables — mostly calculations and production rates.

Action: Migrate to Worksheet Variables with origin = manual (not sourced from Input Parameters or Program Tasks).

Provisional sums & rate-only items

1,272 items marked is_provsum = ‘Y’; 237 marked is_rateonly = ‘Y’.

Action: Map to Item Types; flag in Anomaly Review for pre-submission verification.

Subcontractor quote integration

83,528 quote items across 542 quotes; clarify which quotes are “active” (accepted/selected):

SELECT COUNT(*) FROM subcontractor_quote_item WHERE subconquote_item_accepted = 'Y'
SELECT COUNT(*) FROM subcontractor_quote_item WHERE subconquote_item_selected = 'Y'

Action: Only accept selected/accepted quotes during migration; others archived.

Margin & spread verification

39,369 items have spread set (is_spread = ‘Y’). Verify spread amounts match cost + margin:

SELECT project_item_id, project_item_cost, project_item_margin, 
       project_item_spreadamount
FROM project_item
WHERE ABS(project_item_spreadamount - (project_item_cost + project_item_margin)) > 0.01

Action: Reconcile; flag discrepancies for estimator review.


7. Cutover plan

7.1 Alpha rate-library migration

Scope: Benchmark Resource Library only → oxFlow Price Book (Internal type).

Steps:

  1. Extract Benchmark resource library:

    • Tables: resource_library (8,135 rows) + resource_type (2 rows) + resource_category (5 rows) + activity (113) + cost_code (33) + unit (67)
    • Filter: Exclude inactive resources (resource_library_isActive != ‘N’ if present; else include all)
    • Apply unit mapping rules (§6)
  2. Transform to oxFlow structure:

    • For each resource_library row, create oxFlow Resource:
      • description ← resource_library_code + ” ” + resource_library_desc (composite)
      • rate ← resource_library_rate
      • unit ← mapped unit (via unit_id)
      • resource_type ← resource_category (Labour / Material / Plant / Subcontract; SUBITEM → handled in recipes phase)
      • code_option (Activity Code) ← Benchmark cost_code (link via cost_code_id; required on Resources)
      • code_option (Workcentre) ← N/A on Resources (Workcentre is applied to Items, not Resources)
      • flags ← set Plug Rate if resource_library_isplugged = ‘Y’
      • notes ← resource_library_notes (preserve)
      • categorization ← resource_category_id (optional; for grouping)
  3. Create oxFlow Price Book (Internal type):

    • Name: “Benchmark Migration - [date]”
    • Type: Internal (no supplier required)
    • Source type: System-generated (lineage to migration)
    • Add all transformed Resources
  4. Validate:

    • Row count: 8,135 Resources in Price Book
    • Unit coverage: All 67 Benchmark units mapped; spot-check 10 Resources
    • Code coverage: All non-null activity_ids assigned (required); cost_codes assigned where appropriate
    • Plug Rate flags: 1,307 flagged; visible in admin UI
    • Rate ranges: Min, max rates sanity-checked (e.g., labour > 0, plant > 0)
  5. Admin review:

    • Confirm Code assignments (Activity Code on Resources, Workcentre on Items)
    • Flag ambiguous conversions (e.g., multi-activity resources → which code?)
    • Review Output Units on migrated Recipes for correctness
  6. Acceptance:

    • Estimators in Alpha can drag Resources from Migrated Benchmark library into Worksheets
    • Library behaves identically to a hand-curated Price Book
    • Rate anomalies flagged by Anomaly Review

7.2 Release full migration

Scope: All remaining entities — active estimates, historical estimates, subitems/recipes, subcontract packages, variable definitions, commercials rules.

Steps:

  1. Communicate freeze date to Oxcon:

    • No new Benchmark entries after [freeze date]
    • All active estimates locked for editing
  2. Final extract from Benchmark (production snapshot):

    • Tables: project, estimates, estimate_items, estimate_sections, project_section, project_item, item_library, item_library_resource, subcontractor, subcontractor_quote*, all supporting tables
    • Full audit: row counts, data quality, orphaned records
  3. Transform entities per mapping (§3):

    • Tenders: project (288) → Tender
    • Estimates: project_item + project_section variants → Estimate + Heading + Item structure
    • Recipes: item_library (153) + item_library_resource (1,002) → Recipe + Worksheet Resource
    • Codes: activity + cost_code → Code options
    • Subcontract packages: Infer from subcontractor_quote groups; create Subcontract Package + Adjudication
    • Rules: project margin, overhead, spread rules → Commercials Rules
    • Variables: item_variable + project_variable → Worksheet Variables
  4. Data cleaning:

    • Apply rules from §6
    • Unit mapping (with fallback review)
    • Code assignment verification (Activity Code on Resources, Workcentre on Items)
    • Duplicate resource merging
    • Archive old rate windows as historical Price Books
  5. Load to oxFlow (staged):

    • Alpha environment (shadow cutover): load all data; run validation suite
    • Shadow test: estimators verify estimate structure, calculations
    • Identify edge cases; fix; reload
  6. Validation suite:

    • Row count sanity (Tenders, Estimates, Items, Resources ±5%)
    • Cost roll-up verification (sample 10 Estimates; total cost matches)
    • Code coverage (all Resources have Activity Code; all Items have Workcentre)
    • Anomaly Review Layer 1 passes (no unresolved critical flags)
    • Unit mapping 100% coverage
    • No orphaned Items, Resources, or invalid references
  7. User acceptance testing (per estimator):

    • Each Oxcon estimator reviews 1–2 active estimates they own
    • Verify structure, calculations, submission amounts correct
    • Sign off or flag for fix
  8. Go-Live window:

    • Shutdown Benchmark (read-only mode)
    • Switch Oxcon team to oxFlow full-time
    • Benchmark remains available for audit/reference for [rollback window]
  9. Benchmark decommissioning:

    • Archive Benchmark_Editable.db (backup + cold storage)
    • Terminate Benchmark licenses (per proposal C5.6)
    • Keep backup for 12 months post-cutover

Timeline: ~4 weeks (extract, transform, load, shadow test, UAT, cutover).


7.3 Rollback plan

Scope & duration: 7 days post-Go-Live (can extend if needed).

Procedure:

  1. Point-in-time restore of oxFlow database to pre-migration state
  2. Benchmark remains read-only, available for comparison
  3. Notify Oxcon if rollback initiated; plan re-cutover
  4. RTO: 4 hours (restore from backup + validation)
  5. RPO: 0 (no data loss; all pre-cutover changes preserved in oxFlow)

Triggers for rollback:

  • Critical data loss or corruption detected (>5% of records affected)
  • Fundamental calculation error affecting all estimates
  • Unrecoverable Anomaly Review failures (Layer 1 validation blocks all submissions)
  • User access issues (authentication, permissions broken across team)

Post-rollback:

  • Root-cause analysis
  • Remediation (typically data quality, code fixes)
  • Re-cutover scheduled after 2-week stabilization