# Ballbox Target Domain Model ## Intent - Define the final Ballbox ownership model across `network`, `payments`, `tvs`, `sports`, and `players`. - Keep shared physical/operational entities out of product-specific modules. - End state does not require backward compatibility with current naming or legacy intermediate fields. - This target model now matches the shipped Prisma schema and current API/runtime naming. ## Shared Core: `network` - `Club` - top-level organizational entity - `Venue` - belongs to `Club` - required: `clubId` - `VendingMachine` - belongs to `Venue` - required: `venueId` - Ballbox-owned internal identifier - `Screen` - belongs to `Venue` - required: `venueId` - optional link to `VendingMachine` - optional: `vendingMachineId` - `TvDevice` - belongs to `Screen` - required: `screenId` - one device per screen ## Payments - `Product` - global catalog - `PaymentSession` - belongs to `VendingMachine` - belongs to `Product` - required: `vendingMachineId` - required: `productId` - provider/status/audit fields live here unless a separate approvals table becomes necessary later - `PaymentApproval` - optional future extraction if approvals/webhooks need their own lifecycle - `Slot` - not part of current schema - explicitly deferred until machine-maintenance or machine-analytics use cases justify it ## TVs - `Advertiser` - `Campaign` - `Creative` - `Assignment` - joins `Campaign` to `Screen` - required: `campaignId` - required: `screenId` - `Manifest` - runtime projection - not a canonical persisted entity ## Sports - `Coach` - optional link to `Club` - optional: `clubId` - `OpenMatch` - belongs to `Venue` - required: `venueId` - `Class` - belongs to `Venue` - required: `venueId` ## Players - `Player` - `Membership` - belongs to `Player` - belongs to `Club` - required: `playerId` - required: `clubId` - cross-club memberships allowed through multiple rows ## Excluded For Now - `Slot` - `Court` - `Benefit` ## Required/Optional Relationships - `Club 1 -> N Venue` - `Venue 1 -> N VendingMachine` - `Venue 1 -> N Screen` - `VendingMachine 0..1 -> 0..1 Screen` - `Screen 1 -> 0..1 TvDevice` - `VendingMachine 1 -> N PaymentSession` - `Product 1 -> N PaymentSession` - `Screen 1 -> N Assignment` - `Campaign 1 -> N Assignment` - `Club 1 -> N Membership` - `Player 1 -> N Membership` - `Club 0..1 -> N Coach` - `Venue 1 -> N OpenMatch` - `Venue 1 -> N Class` ## Naming Direction - rename current `clubs` shared physical/operational area to `network` - rename current `Device` to `TvDevice` - rename current `Machine` references to `VendingMachine` - rename current `ScreenCampaignAssignment` to `Assignment` - `PaymentSessionRef` migration is already complete; canonical persisted name is `PaymentSession` ## Status - Shared `network` naming is live in Prisma, seed data, `/admin/network`, and `/api/network*`. - `PaymentSession`, `Assignment`, `VendingMachine`, and `TvDevice` are the canonical persisted names. - TVs admin/runtime surfaces now use `tv device` naming and `/api/admin/tvs/tv-devices*`. ## Migration Direction 1. Add final entities and relations in Prisma. 2. Backfill data into final foreign keys. 3. Move app code to final names and final ownership model. 4. Drop legacy compatibility fields and names. 5. End state keeps no retro-compatibility shims.