Domain Model: Sponsorship System

arch-domain-sponsorship Architecture

architecture active

Domain Model: Sponsorship System

Diagram

Components

Component Purpose Notes
Sponsor Single model serving both CRM pipeline and presentation layer SQLAlchemy model in basketball-api. Current schema has CRM fields; presentation fields (tier, logo, display_on_site) pending extension.
SponsorStatus Pipeline stages: prospect → contacted → responded → negotiating → committed → declined Postgres enum. Drives outreach workflow and blast targeting.
SponsorCategory Business type classification for targeted pitches 9 values: food, financial, retail, automotive, construction, fitness, dental, grocery, other
SponsorTier Commitment level defining deliverables and pricing Pending enum: title ($5K+), elite ($2.5K), team ($1K), social ($500), player_sponsor ($300-1.2K), community_partner (in-kind)
EmailLog Audit trail for all sponsor outreach sends Existing model, extended with EmailType.sponsor_outreach
MJML Template Branded outreach email with category-targeted pitch sponsor-outreach.html on hostPath. Placeholders: business_name, pitch, sender_name, sender_phone, sponsorship_tiers
Sponsors Page Public landing page displaying committed sponsors Currently hardcoded Svelte. Future: renders from GET /sponsors?display_on_site=true

Key Decisions

  • Single model, dual purpose. One Sponsor row serves both outreach CRM (status pipeline, blast targeting) and presentation (tier, logo, website for landing page). Avoids a second table and a sync problem. Status=committed + display_on_site=true is the boundary between CRM and display.
  • Tier deliverables are documented, not modeled. Each tier's obligations (jersey logo, IG posts, event banners) live in the westside-sponsors pal-e-docs note, not in a database table. At current scale (3 sponsors), Marcus reads the tier checklist. Deliverable tracking model deferred until 10+ committed sponsors.
  • Category pitches are code, not data. CATEGORY_PITCHES dict in sponsor_service.py is developer-managed. Marcus can override per-sponsor via custom_pitch field. Keeps pitch text versionable and reviewable in PRs.
  • Rate limiting is synchronous. time.sleep(3) between sends. Acceptable for current volume (~50 sponsors). Async blast is a future optimization if volume exceeds Gmail daily limits.
  • Tier enum includes community_partner. In-kind sponsors (product exchange, no cash) are first-class in the model. amount_committed is nullable to support this.
  • westside-sponsors — canonical sponsor reference (tiers, active sponsors, lifecycle)
  • arch-domain-westside-basketball — parent domain model (Tenant, Player, Parent entities)
  • arch-email — email system architecture
  • project-westside-agency — sponsor-agent is pathway #8
  • board-westside-sponsors — kanban board for sponsor work