Skip to main content

Entity Relationship Overview

Conference 1──* University 1──* Athlete 1──* NilDeal *──1 Brand
                    │                │           │
                    │                │           ├──1 Sport
                    │                │           ├──1 Position
                    │                │           └──1 ReportingPeriod
                    │                │
                    │                ├──* AthleteNote
                    │                └─── (activity_log via entity_id)

                    ├──* User
                    ├──* ReportingPeriod
                    ├──* BudgetAllocation
                    └──* PeerGroup

Tables

conferences

The top-level organizational unit. Seeded with 10 real conferences.
ColumnTypeNotes
idUUID (PK)Auto-generated
nameVARCHAR(100)Unique. E.g., “SEC”, “ACC”, “Big Ten”
divisionVARCHAR(20)Default “FBS”

universities

Each institution belongs to one conference.
ColumnTypeNotes
idUUID (PK)
nameVARCHAR(200)Unique. E.g., “Blue Mountain State”
conference_idUUID (FK → conferences)
divisionVARCHAR(20)
stateVARCHAR(2)US state code
enrollmentINTEGER
athletic_budgetNUMERIC(14,2)Annual budget

sports

Global sport definitions shared across all universities.
ColumnTypeNotes
idUUID (PK)
nameVARCHAR(100)Unique. E.g., “Football”, “Basketball (M)”
Seeded: Football, Basketball (M), Basketball (W), Baseball, Track & Field, Soccer (W)

positions

Sport-specific positions.
ColumnTypeNotes
idUUID (PK)
sport_idUUID (FK → sports)
nameVARCHAR(100)E.g., “Quarterback”
abbreviationVARCHAR(10)E.g., “QB”
Seeded: 10 Football positions (QB, WR, RB, TE, OL, DB, LB, DL, K/P, S), 5 Basketball, 8 Baseball, 5 Track, 4 Soccer = ~32 total

athletes

Student-athletes belonging to a university.
ColumnTypeNotes
idUUID (PK)
university_idUUID (FK)Scoping filter for all queries
sport_idUUID (FK)
position_idUUID (FK)
first_nameVARCHAR(100)
last_nameVARCHAR(100)
jersey_numberINTEGERNullable
emailVARCHAR(200)
phoneVARCHAR(20)
class_yearVARCHAR(20)Freshman through Graduate
eligibility_yearINTEGER1-5
eligibility_totalINTEGERDefault 5
redshirt_statusBOOLEAN
transfer_statusVARCHAR(50)
athlete_codeVARCHAR(20)Unique. Format: ATH-00001
is_activeBOOLEANSoft delete flag
created_atTIMESTAMPTZAuto
updated_atTIMESTAMPTZAuto on update

brands

Sponsors and brand partners.
ColumnTypeNotes
idUUID (PK)
nameVARCHAR(200)Unique. E.g., “Nike”, “Gatorade”
industry_categoryVARCHAR(100)E.g., “Apparel”, “Beverage”
Seeded: 20 brands (Nike, Adidas, Under Armour, Gatorade, Red Bull, etc.)

nil_deals

The central table. Every NIL agreement is a row here.
ColumnTypeNotes
idUUID (PK)
deal_codeVARCHAR(30)Unique. Format: NIL-2025-0001
athlete_idUUID (FK)
university_idUUID (FK)Denormalized for query performance
brand_idUUID (FK)
sport_idUUID (FK)
position_idUUID (FK)
reporting_period_idUUID (FK)
deal_typeVARCHAR(30)endorsement, social_media, appearance, licensing, camp_clinic
compensation_typeVARCHAR(30)cash, product, equity, revenue_share, mixed
total_value_usdNUMERIC(12,2)
guaranteed_value_usdNUMERIC(12,2)
performance_incentives_usdNUMERIC(12,2)
deal_start_dateDATE
deal_end_dateDATE
deal_statusVARCHAR(20)active, expired, cancelled, pending
verification_statusVARCHAR(20)verified, pending_review, needs_review
contract_file_keyVARCHAR(500)S3/MinIO object key
ai_extraction_dataJSONBRaw AI extraction output
ai_confidence_scoresJSONBPer-field confidence (0.0-1.0)
submitted_byUUID (FK → users)
submitted_atTIMESTAMPTZ
verified_byUUID (FK → users)
verified_atTIMESTAMPTZ
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

reporting_periods

Academic year periods for deal grouping.
ColumnTypeNotes
idUUID (PK)
university_idUUID (FK)
academic_yearVARCHAR(20)E.g., “2025-26”
start_dateDATE
end_dateDATE
submit_deadlineDATE
statusVARCHAR(20)open or closed

budget_allocations

Per-sport budget caps per reporting period.
ColumnTypeNotes
idUUID (PK)
university_idUUID (FK)
sport_idUUID (FK)
reporting_period_idUUID (FK)
annual_cap_usdNUMERIC(12,2)Editable via Budget page
created_atTIMESTAMPTZ
updated_atTIMESTAMPTZ

users

Platform users scoped to a university.
ColumnTypeNotes
idUUID (PK)
university_idUUID (FK)
first_nameVARCHAR(100)
last_nameVARCHAR(100)
emailVARCHAR(200)Unique globally
password_hashVARCHAR(200)bcrypt
roleVARCHAR(30)admin, agreement_manager, read_only
tierVARCHAR(20)standard, premium
titleVARCHAR(100)
sport_limitationsUUID[]Optional sport-level access restriction
is_activeBOOLEAN
last_active_atTIMESTAMPTZ
reset_tokenVARCHAR(200)For forgot-password flow
reset_token_expiresTIMESTAMPTZ1-hour TTL
created_atTIMESTAMPTZ

peer_groups

Custom benchmark comparison groups.
ColumnTypeNotes
idUUID (PK)
university_idUUID (FK)
nameVARCHAR(100)E.g., “Custom Peer Group”
conference_idsUUID[]Array of conference IDs to compare against

athlete_notes

Internal staff notes on athletes.
ColumnTypeNotes
idUUID (PK)
athlete_idUUID (FK)
user_idUUID (FK)Who wrote it
contentTEXT
created_atTIMESTAMPTZ

activity_log

Audit trail for all mutations.
ColumnTypeNotes
idUUID (PK)
university_idUUID (FK)
entity_typeVARCHAR(50)“deal”, “athlete”, etc.
entity_idUUIDThe affected record
actionVARCHAR(50)created, verified, flagged, etc.
detailsJSONBStructured context (deal_code, description, etc.)
user_idUUID (FK)
created_atTIMESTAMPTZ

Key Indexes

All foreign key columns are indexed by SQLAlchemy. The most performance-critical queries:
  • nil_deals filtered by university_id + deal_status — covers dashboard KPIs, budget, reporting
  • nil_deals filtered by sport_id + position_id — covers benchmarks
  • athletes filtered by university_id + is_active — covers roster list
  • activity_log filtered by entity_type + entity_id — covers athlete detail activity