1. Purpose

A Company is an external organisation — client, supplier, subcontractor, or any combination thereof. Companies are synced from Xero (the financial source of truth) in a one-way, read-only pattern; they cannot be created directly in oxFlow. Xero is and will remain the source of truth; oxFlow mirrors Company data from Xero only. Each Company carries one or more Company Roles that determine where and how it can be assigned in the workflow.

Analogy (glossary cooking model): the Company is the vendor or customer — an external entity that participates in the estimate and cost lifecycle.


2. Attributes

AttributeTypeRequiredDefaultNotes
idUUIDgeneratedSystem-managed
namestring (text)Legal name of the organisation; e.g., “Fletcher Construction Ltd”
xero_idstring (unique)Xero’s unique identifier for this organisation. Immutable; prevents duplicate syncs
addresslong textnullPhysical address (street, suburb, postcode). Synced from Xero
contact_infolong textnullPhone, email, or other contact details. Free-form; synced from Xero
noteslong textnulloxFlow-only free-text notes; e.g., “added Subcontractor role 15 Apr after verbal agreement”
company_rolesmulti-select[Supplier]One or more of: Client · Supplier · Subcontractor (BR-082). Initialised from Xero metadata on sync; editable in oxFlow post-sync (BR-083)
created_at / updated_attimestampsystemAudit
created_by / updated_byUser refsystemAudit. created_by is always system (Xero sync); updated_by tracks oxFlow edits

3. Company Roles

Company Role is a multi-select attribute — a single Company can carry any combination of the three roles. Each role governs assignment scope in oxFlow.

RolePurposeAssignment scopeNotes
ClientPurchaser of the work; issues the TenderTender (as client_id)A Tender must have exactly one Client Company (BR-090)
SupplierProvides resources or services via Price BookExternal Price Book (as supplier_id)Set at Price Book creation. Can compete in Price Book Adjudication
SubcontractorBids for Subcontract PackagesSubcontract Package (via Adjudication)Can compete in Subcontract Package Adjudication

Defaulting behaviour (BR-083):

  • Xero customer → Client role (on sync)
  • Xero supplier → Supplier role (on sync)
  • Ambiguous or no metadata → Supplier role (safe default)
  • Admin can assign any role combination post-sync; roles are editable without re-syncing

4. Lifecycle States & Sync

Companies have no lifecycle state machine. Once synced from Xero, a Company persists in oxFlow with:

  • name, xero_id, address, contact_info — read-only from Xero
  • company_roles, notes — editable in oxFlow (not synced back to Xero)

Sync mechanics:

  • One-way (locked): Xero → oxFlow. Triggered periodically or on-demand. Updates to Company attributes in Xero are reflected in oxFlow on the next sync. Duplicate detection via xero_id. No bi-directional sync is planned.

Archival:

  • When a Company is archived in Xero, it is automatically archived in oxFlow on the next sync. Archived Companies remain visible in oxFlow in read-only mode (e.g., for historical reporting) but cannot be selected for new Tenders, Price Books, or Adjudications (BR-080a).

5. Relationships

Inbound (things referring to Company)

FromCardinalityRole contextNotes
TenderTender M:1 CompanyClientBR-090: every Tender must have a Client Company; enforced at Tender creation
Price BookPriceBook M:0..1 CompanySupplierExternal Price Books only; required if source_type = External
Price Book AdjudicationPBA M:M CompanySuppliersMultiple Companies compete with pricing proposals
Subcontract Package AdjudicationSPA M:M CompanySubcontractorsMultiple Companies bid for subcontracted scope

Outbound (things Company references)

ToCardinalityRequiredNotes
Company RoleCompany M:M CompanyRoleMulti-select; minimum one role required (BR-082)

6. Validation / Invariants

Rules that must hold at all times:

  1. Xero ID unique. No two Companies may share the same xero_id. Enforced at sync time.
  2. Name required. name cannot be null.
  3. At least one role. company_roles must contain at least one of: Client, Supplier, Subcontractor. Never empty (BR-082).
  4. Role enum. company_roles values must be one of the three defined Roles. No other values accepted.
  5. No circular references. (N/A for Company; no self-references in relationships.)
  6. Immutable Xero ID. Once synced, xero_id cannot be changed or transferred to another Company (orphaning prevents this).

7. Derived / Computed Attributes

AttributeDerivationNotes
is_clientcompany_roles.contains("Client")Boolean flag for UI filtering
is_suppliercompany_roles.contains("Supplier")Boolean flag for UI filtering
is_subcontractorcompany_roles.contains("Subcontractor")Boolean flag for UI filtering
tender_countCount of Tenders where client_id = this CompanyFor informational dashboards
price_book_countCount of External Price Books where supplier_id = this CompanyUsage tracking

8. Worked Examples

Example A — Fletcher Construction Ltd (Client only)

A Xero customer synced as a Client. Used on five Tenders as the purchaser:

Company:
  name: "Fletcher Construction Ltd"
  xero_id: "XERO-F1428-C" (unique Xero reference)
  address: "Level 5, 150 Queen Street, Auckland, NZ 1010"
  contact_info: "Tel: 09-888-5555 | Contacts: James Riley (james.r@fletcher.co.nz)"
  company_roles: ["Client"] (synced from Xero customer; not Supplier)
  notes: null
  created_at: 2026-03-01T09:30:00Z (sync timestamp)
  created_by: system (Xero sync)

Relationships:
  Tender 1: "Auckland Waterfront Carpark" (Fletcher client)
  Tender 2: "Industrial Estate Extension" (Fletcher client)
  Tender 3: "Retail Complex Fit-out" (Fletcher client)
  Tender 4: "Commercial Tower Lobbies" (Fletcher client)
  Tender 5: "Basement Level Works" (Fletcher client)

Derived:
  is_client = true
  is_supplier = false
  is_subcontractor = false
  tender_count = 5

Example B — Pacific Steel (Supplier → Supplier + Subcontractor)

A Xero supplier initially synced as Supplier. Admin later adds Subcontractor role when invited to bid on subs:

Company:
  name: "Pacific Steel Ltd"
  xero_id: "XERO-PS-2847"
  address: "1 Tauranga Road, Port of Tauranga, NZ 3112"
  contact_info: "Tel: 07-571-9500 | procurement@pacificsteel.co.nz"
  company_roles: ["Supplier", "Subcontractor"] (Supplier synced; Subcontractor added 17 Apr by Admin)
  notes: "Added Subcontractor role when invited to bid on GF slab formwork package. Preferred supplier for structural steel; good capacity for subcontract work."
  created_at: 2026-02-15T14:22:00Z (Xero sync)
  updated_at: 2026-04-17T10:18:00Z (role added in oxFlow)
  created_by: system
  updated_by: admin@oxflow.local

Relationships:
  Price Book: "External — Pacific Steel Q2 2026" (as Supplier)
  Subcontract Package Adjudication #42: "Ground floor slab formwork" (as bidding Subcontractor)
    → winning bid awarded 23 Apr; $45.75/m² for 36m²

Derived:
  is_client = false
  is_supplier = true
  is_subcontractor = true
  price_book_count = 1
  (tender_count = 0, not a client)