ANC
Data Model

Data Model Overview

Objects, relations, and how they connect in the ANC CRM.

Data Model Overview

Every row in the CRM is a record; every record has an object type; objects relate to each other through typed relations.

Core objects

Company ──┬── Opportunity ──┬── OpportunityRevenueSplit
          │                 ├── OpportunityTeamAllocation
          │                 ├── Estimate
          │                 ├── RfpAnalysis
          │                 ├── DesignRequest
          │                 └── ServiceTicket (WON opps only)
          ├── Person
          ├── Venue ─────────── ServiceTicket / Event
          └── (reverse relations of all above)

Object IDs (for API use)

ObjectID
Companyccd95b3f-4a9a-443c-b8f2-01bff6c479ab
Opportunityc779922d-cf25-4a5e-9382-23eb1c02199e
OpportunityTeamAllocation7416ebb0-94d9-4551-bc2e-1991690849c2

For all others, query metadata:

query { objects { id nameSingular } }

Relations cheat sheet

FromFieldToType
OpportunitycompanyCompanyMANY_TO_ONE
OpportunityrevenueSplitsOpportunityRevenueSplitONE_TO_MANY (reverse)
OpportunityteamAllocationsOpportunityTeamAllocationONE_TO_MANY (reverse)
OpportunityserviceTicketsServiceTicketONE_TO_MANY (reverse)
OpportunityestimatesEstimateONE_TO_MANY (reverse)
CompanyopportunitiesOpportunityONE_TO_MANY
CompanyserviceTicketsServiceTicketONE_TO_MANY
CompanyteamAllocationsOpportunityTeamAllocationONE_TO_MANY
VenuecompanyCompanyMANY_TO_ONE
ServiceTicketvenueVenueMANY_TO_ONE
ServiceTicketopportunityOpportunityMANY_TO_ONE (new 2026-04)
ServiceTicketcompanyCompanyMANY_TO_ONE (via legacy companyIdId)

Enum values

Opportunity.businessUnit

TECHNOLOGY, VENUE_SERVICES, MEDIA_SPONSORSHIP

Opportunity.bidStatus

RFP_RECEIVED, SCOPING, BID_SUBMITTED, SHORTLISTED, WON, LOST, NO_BID

Opportunity.stage

NEW, SCREENING, MEETING, PROPOSAL, CUSTOMER

Opportunity.proposalStage

RFP, SALES_LEAD, BAFO, LOI, EXISTING_CLIENT_BUDGET

Opportunity.priority

PRIORITY_1_RFP, BEST_AND_FINAL, PRICING_COMPLETE

Opportunity.rfpSource

BUILDING_CONNECTED, DIRECT, REFERRAL, COLD_OUTREACH

Company.revenueType

TECHNOLOGY, VENUE_SERVICES, MEDIA_SPONSORSHIP, MULTIPLE_VERTICALS

Company.league

20 values: NFL, NBA, MLB, NHL, NCAA, MLS, WNBA, NWSL, NASCAR, GOLF_PGA, GOLF_LPGA, GOLF_ALL, NON_SPORTS, OTHER, and 6 more for international and minor leagues.

opportunityRevenueSplit.splitType

INSTALL, SERVICE, LICENSING, OTHER

Denormalizations (on purpose)

We flattened some relations for dashboard performance:

  • Per-year revenue + margin on Opportunity: revenue2026, margin2026, revenue2027, margin2027 — denormalized from opportunityRevenueSplit so dashboard widgets don't have to group.
  • League on Opportunity — mirrors Company.league, backfilled from the company. Simpler filtering on opp-level views.
  • Account Executive as TEXT, not RELATION — workspace seats aren't issued for every legacy seller. A TEXT field lets bar charts group by name without creating workspace members.

When to use child records vs. flat fields

Use child recordsUse flat fields
You need per-split detail (INSTALL vs SERVICE)You need a single yearly total
Accounting consumes itDashboard widgets consume it
Split crosses fiscal-year boundariesSingle-year deal

For Team Allocations (Hankook pattern), always use child records — each team is a real allocation, not a split.

On this page