| Pipeline | Cadence | Direction | What it does |
|---|---|---|---|
| Forward sync orchestrator | rate(15 minutes) | Uniphi → HubSpot | Pulls Companies, then Contacts (currently disabled), then Deals. Writes everything one-way into HubSpot. |
| Reverse sync | rate(5 minutes) | HubSpot → Uniphi | Per-deal triggers and bi-directional updates. Three jobs in one Lambda: (1) initial-sync triggered deals, (2) push win % for opted-in deals, (3) push bi-dir field edits for opted-in deals. |
| Flag (HubSpot deal property) | Default | What it controls | FR |
|---|---|---|---|
| uniphi_trigger_sync | false | One-shot: create a NEW Uniphi project (+contract +team) from this HubSpot deal. Used on first sync of a deal. | Original |
| live_sync_enabled | false | Bi-directional editing of dealname and description. While ON, HubSpot edits push to Uniphi every 5 min AND the forward sync stops overwriting those fields so a user edit isn't clobbered. | FR-039 |
| push_probability_to_uniphi | false | Sync the dealstage-derived win % (or override) to the Uniphi project's WinProbability / RevenueProbability fields every 5 min. | FR-042 |
| HubSpot Deal Field | Uniphi Project Field | Behaviour |
|---|---|---|
| dealname | Project.Name | Bi-dir. HubSpot is source of truth while flag is on. |
| description | Project.Description | Bi-dir. HubSpot is source of truth while flag is on. |
| amount | Contract.OriginalContract | Forward only for now (Uniphi → HubSpot). Cross-write needs contract-update path — follow-up. |
| closedate | Contract.PracticalCompletionDate | Forward only for now. Date semantics need confirmation before bi-dir. |
| HubSpot dealstage | Win % | Uniphi fraction |
|---|---|---|
| Lead appointmentscheduled | 10% | 0.10 |
| Opportunity qualifiedtobuy | 20% | 0.20 |
| Proposal decisionmakerboughtin | 30% | 0.30 |
| Submitted 5826719 | 30% | 0.30 |
| Closed Won closedwon | 100% | 1.00 |
| Closed Lost closedlost | 0% | 0.00 |
| Cancelled 7929420 | 0% | 0.00 |
| Order | Rule |
|---|---|
| 1 | Prefer status Active over Pending over Expired over Cancelled |
| 2 | Within the preferred status, pick the contract with the highest OriginalContract + ApprovedVariations |
| Override | Where | What it does |
|---|---|---|
| uniphi_probability_override | HubSpot deal property (0–100) | When set, this win % is pushed to Uniphi instead of the dealstage-derived default. Empty ⇒ use stage map. |
| Consolidation override | DDB pk=CONSOLIDATION, sk=ORG#<id> — edit via /consolidation | Forces a Uniphi org to roll up under a different parent org with a canonical name. Wins over the regex patterns in company-consolidation.ts. |
| EXCLUDED_UNIPHI_ORG_IDS | src/config/constants.ts | Hard-coded skip-list. Org 4 (GJ Pty Ltd internal) is excluded entirely to stop the Ausgrid rename loop. |
| Uniphi Field | HubSpot Property | Notes |
|---|---|---|
| Organisation.ID | uniphi_org_id | Primary key |
| Organisation.Name | name | Canonical name if consolidated |
| Organisation.URL | website | |
| Organisation.Sites[] | uniphi_site_{state} | One per AU state (VIC, NSW, QLD, SA, WA, TAS, NT, ACT) |
| Organisation.Sites[].Address | uniphi_site_{state}_address | Site address per state |
| Priority | Match Field | Method |
|---|---|---|
| 1 | uniphi_org_id | Exact match — previously synced record |
| 2 | Company Group | Regex pattern consolidation (see below) |
| 3 | domain | Website domain match (normalized) |
| 4 | name | 4-tier fuzzy name match (exact, substring, core, word overlap) |
| HubSpot Property | Source | Formula / Notes |
|---|---|---|
| uniphi_revenue_fy2021 … uniphi_revenue_fy2030 | Cashflow (revenue Level-3 codes) | p/c-aware chronological walk per project; sums Committed-classified entries per FY. Past periods = Actuals (always Committed); future periods walk against OriginalContract + ApprovedVariations - Claimed cap (5% tolerance). |
| uniphi_revenue_total | Cashflow (all FYs) | Sum of walked-Committed across all FYs. Displayed as "Lifetime Revenue" on client-detail. |
| uniphi_forecast_next_12m | Cashflow | Rolling 12-month window from today. Committed-only (same walk). Not equal to FY curr Committed — overlaps into FY curr+1. |
| uniphi_order_book | Contract | max(0, (OriginalContract + ApprovedVariations) - Claimed) across active revenue contracts. |
| uniphi_active_invoiced | Contract | Sum of Claimed across active revenue contracts. Shown as "Invoiced to Date". |
| uniphi_ar_balance | Organisation | Sum of Organisation.ARBalance across the consolidated group. Outstanding receivable. |
| uniphi_variation_pipeline | Contract | PendingVariations + SubmittedVariations + PossibleVariations summed. Contract-lifetime; not FY-scoped. |
| uniphi_variation_pending | Contract | Sum of PendingVariations across active revenue contracts. |
| uniphi_variation_submitted | Contract | Sum of SubmittedVariations across active revenue contracts. |
| uniphi_variation_possible | Contract | Sum of PossibleVariations across active revenue contracts. |
| uniphi_active_projects | Project | Count of projects not in Complete / Cancelled / Lost phases. |
| uniphi_upcoming_pc_count | Contract | Count of active contracts with PracticalCompletionDate in the next 12 months. |
| dashboard_url | Constant | Deep-link to /client/<hubspotId> — renders as an "Account Plan" button in HubSpot. |
| Uniphi Field | HubSpot Property | Transform |
|---|---|---|
| Person.ID | uniphi_person_id | Primary key |
| Person.Name | firstname + lastname | Split on first space — "Steve Lee" → first: "Steve", last: "Lee" |
| Person.Email | Available on some persons | |
| Person.Phone | phone | Available on some persons |
| Person.Mobile | mobilephone | Available on some persons |
| Person.Position | jobtitle | |
| Person.IsDisabled | uniphi_is_active | Inverted — IsDisabled=false → "true" |
| Priority | Match Field | Method |
|---|---|---|
| 1 | uniphi_person_id | Exact match — previously synced record |
| 2 | Exact match, case-insensitive | |
| 3 | firstname + lastname | Exact match after normalization |
| Uniphi Field | HubSpot Property | Transform |
|---|---|---|
| Project.ID | uniphi_project_id | Primary key |
| Project.Name | dealname | |
| Project.ProjID | uniphi_project_no | e.g. "P-1234" |
| Project.Description | uniphi_description | HTML stripped to plain text |
| Project.StatusExternal | uniphi_status | RAG status (Amber/Green/Red) |
| Project.CreatedDate | createdate | Unix timestamp (ms) |
| Uniphi Field | HubSpot Property | Transform |
|---|---|---|
| Project.Sector.Description | sector | standard HubSpot field |
| Project.ProjectType.Description | uniphi_project_type | |
| Project.ServiceLine.Description | uniphi_service_line | |
| Project.Region.Description | uniphi_region | |
| Project.Location.Description | uniphi_location | |
| Project.ActualStartDate | uniphi_start_date | Unix timestamp (ms); falls back to Contract.StartDate |
| Uniphi Field | HubSpot Property | Transform |
|---|---|---|
| Contract.OriginalContract + ApprovedVariations | amount | Calculated — sum of original + approved variations |
| Contract.ContractNo | uniphi_contract_no | |
| Contract.IsRevenue | uniphi_contract_type | true → "Revenue", false → "Cost" |
| Contract.Claimed | uniphi_invoiced | Invoiced/claimed amount |
| Contract.PracticalCompletionDate | closedate | Unix timestamp (ms); also stored in uniphi_practical_completion_date as YYYY-MM-DD |
| Uniphi CustomField Name | HubSpot Property | Group |
|---|---|---|
| "Project Street Address" | uniphi_street_address | Address |
| "Project Suburb" | uniphi_suburb | Address |
| "Project State" | uniphi_state | Address |
| "Project Post Code" | uniphi_postcode | Address |
| "Total Project Budget" | uniphi_total_project_budget | Budget |
| "Construction Budget" | uniphi_construction_budget | Budget |
| "Submission Status" | uniphi_submission_status | Bid |
| "Submission Due Date" | uniphi_submission_due_date | Bid |
| "Lead Source" | uniphi_lead_source | Bid |
| "Client Type" | uniphi_client_type | Bid |
| "Award Date" | uniphi_award_date | Bid |
| "Sub-Sectors" | uniphi_sub_sector | Metadata |
| Uniphi Phase | HubSpot Deal Stage | Category |
|---|---|---|
| Lead | Lead (appointmentscheduled) | Pre-award |
| Proposal | Proposal (decisionmakerboughtin) | Pre-award |
| Start up | Closed won | Active |
| Pre Design & DM | Closed won | Active |
| Concept Design | Closed won | Active |
| Schematic Design | Closed won | Active |
| Design Development & VM | Closed won | Active |
| Contractor Tender | Closed won | Active |
| Construction | Closed won | Active |
| Close Out | Closed won | Active |
| Defects Liability | Closed won | Active |
| Complete | Closed won | Complete |
| Lost | Closed lost | Lost |
| Cancelled | Cancelled (7929420) | Cancelled |
| On-Hold | Lead (appointmentscheduled) | Paused |
| Priority | Match Field | Method |
|---|---|---|
| 1 | uniphi_project_id | Exact match — previously synced record |
| 2 | dealname + company | Fuzzy name match AND same associated company |
| Behaviour | Detail |
|---|---|
| HTTP Method | Only PUT supported (PATCH returns 405) |
| Auth | OAuth 2.0 Client Credentials → {baseUrl}/oauth/token |
| Custom Field Name | hubspot_id (same for all entity types) |
| Project PUT | Requires full nested objects (Sector, ProjectType, ServiceLine, Region, Location, CurrentPhase) |
| Finding Client Projects | No direct client ID on Project. Filter Contracts by PrincipalOrganisation.ID |