894 lines
36 KiB
Markdown
894 lines
36 KiB
Markdown
# Project Felt — Phase 3 Product Specification
|
|
|
|
## Complete Venue Platform
|
|
|
|
**Version:** 0.1 Draft
|
|
**Date:** 2026-02-28
|
|
**Depends on:** Phase 1 (Tournaments) + Phase 2 (Cash Games)
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
1. [Overview](#1-overview)
|
|
2. [Dealer Management](#2-dealer-management)
|
|
3. [Player Loyalty System](#3-player-loyalty-system)
|
|
4. [Private Venues & Memberships](#4-private-venues--memberships)
|
|
5. [Venue Analytics & Reporting](#5-venue-analytics--reporting)
|
|
6. [Public Venue Presence](#6-public-venue-presence)
|
|
7. [Data Architecture](#7-data-architecture)
|
|
8. [API Design](#8-api-design)
|
|
9. [Roadmap](#9-roadmap)
|
|
|
|
---
|
|
|
|
## 1. Overview
|
|
|
|
### What Phase 3 Adds
|
|
|
|
Phase 1 manages tournaments. Phase 2 manages cash games. Phase 3 manages **everything else** — the people, the relationships, and the business intelligence that turn a poker room into a venue that players return to.
|
|
|
|
Phase 3 has four pillars:
|
|
1. **Dealer Management** — Scheduling, skills, shifts, rotation
|
|
2. **Player Loyalty** — Points, tiers, rewards, promotions
|
|
3. **Private Venues & Memberships** — Access control, member management, invitations
|
|
4. **Analytics & Public Presence** — Business intelligence, venue profiles, event publishing
|
|
|
|
### Design Principles
|
|
|
|
1. **Everything connects.** Dealer scheduling integrates with tournament and cash table assignments. Loyalty points accrue from tournaments AND cash games. Analytics aggregate across all operations.
|
|
2. **Progressive adoption.** Venues can enable Phase 3 features individually. A small bar might only want dealer scheduling. A large room wants everything. No feature forces adoption of another.
|
|
3. **Player-visible value.** Players should see the value of Phase 3 — loyalty rewards, membership benefits, career stats. This drives word-of-mouth to other venues.
|
|
4. **Operator simplicity.** Every Phase 3 feature must be simpler to use than the spreadsheet/whiteboard it replaces. If it's not, we've failed.
|
|
|
|
---
|
|
|
|
## 2. Dealer Management
|
|
|
|
### 2.1 Dealer Profiles
|
|
|
|
Each dealer is a user in the system (they may also be a player — dual roles supported). Their profile contains:
|
|
|
|
**Identity:** Name, contact info, photo, employee ID (venue-assigned)
|
|
|
|
**Skill Tags:**
|
|
|
|
| Category | Tags (examples) |
|
|
|----------|----------------|
|
|
| Game variants | Hold'em, Omaha, PLO Hi-Lo, Stud, Razz, Draw, Short Deck, Mixed |
|
|
| Betting structures | No-Limit, Pot-Limit, Fixed-Limit |
|
|
| Format specialization | Cash games, Tournaments, Both |
|
|
| Experience level | Trainee, Standard, Experienced, Senior |
|
|
| Special skills | High-stakes tables, Final table dealing, Celebrity/VIP events |
|
|
| Languages | Danish, English, German, etc. |
|
|
|
|
Skills are tagged by the venue manager. A dealer can request skill additions (e.g., after training on a new game), subject to manager approval.
|
|
|
|
**Availability Windows:**
|
|
Dealers set weekly recurring availability (e.g., "Available Mon-Fri 4PM-12AM, Sat 12PM-12AM, not available Sunday"). They can override specific dates (e.g., "Unavailable Dec 24-26"). The scheduling system respects these.
|
|
|
|
### 2.2 Schedule Management
|
|
|
|
**Shift Templates:**
|
|
Venues define recurring shift templates:
|
|
|
|
```
|
|
Morning: 10:00 — 18:00
|
|
Afternoon: 14:00 — 22:00
|
|
Evening: 18:00 — 02:00
|
|
Tournament: Based on tournament schedule (variable)
|
|
Split: 10:00 — 14:00, 18:00 — 22:00
|
|
```
|
|
|
|
Templates are building blocks. The actual schedule is assembled from templates assigned to specific dealers on specific dates.
|
|
|
|
**Schedule Builder (Operator UI):**
|
|
|
|
Week view with dealers on the Y-axis and days on the X-axis. Drag-and-drop shift assignment. Color-coded by shift type. Conflict detection (double-booking, availability violations, skill mismatch) shown in real-time.
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────────────┐
|
|
│ DEALER SCHEDULE — Week of Mar 2 │
|
|
│ │
|
|
│ Mon Tue Wed Thu Fri Sat Sun │
|
|
│ Anna K. [Eve] [Eve] [---] [Eve] [Eve] [Aft] [---] │
|
|
│ Mike S. [Mor] [Mor] [Mor] [Mor] [Mor] [---] [---] │
|
|
│ Chris L. [Aft] [---] [Aft] [Aft] [Eve] [Eve] [Aft] │
|
|
│ Sarah D. [---] [Aft] [Eve] [---] [Aft] [Eve] [Eve] │
|
|
│ Tom H. [Mor] [Mor] [Mor] [Mor] [---] [Mor] [---] │
|
|
│ │
|
|
│ ⚠ Warning: Friday Evening needs 3 dealers, only 2 assigned │
|
|
│ ⚠ Warning: Chris L. exceeds 40h this week │
|
|
└──────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Scheduling constraints (auto-enforced):**
|
|
- Maximum hours per week (configurable, default 40)
|
|
- Minimum rest between shifts (configurable, default 10 hours)
|
|
- Availability windows respected
|
|
- Skill requirements per table/game met
|
|
- Minimum staffing levels per shift (configurable)
|
|
|
|
### 2.3 Shift Trading
|
|
|
|
Dealers can trade shifts with each other — the system facilitates this while enforcing skill requirements.
|
|
|
|
**Trading flow:**
|
|
1. Dealer A posts a shift for trade ("Friday Evening available")
|
|
2. System shows the post to all dealers who: (a) are available that day, (b) have the required skills, (c) wouldn't exceed hour limits
|
|
3. Dealer B offers to take it
|
|
4. If manager approval is required (venue-configurable): manager approves/rejects
|
|
5. If no approval required: trade is instant
|
|
6. Both dealers notified. Schedule updated. Audit log recorded.
|
|
|
|
**Drop without trade:** A dealer can drop a shift (with enough notice, venue-configurable). The system posts it as an open shift. If unclaimed by a threshold time, the manager is notified.
|
|
|
|
### 2.4 Dealer Assignment to Tables
|
|
|
|
Phase 3 connects dealer scheduling to Phase 1 (tournaments) and Phase 2 (cash games):
|
|
|
|
**Cash game dealer assignment:**
|
|
- Operator assigns a dealer to a cash table from the on-shift dealer pool
|
|
- System shows only dealers who: (a) are on shift, (b) have the matching game skill
|
|
- Dealer rotation timer (configurable: push every 30/45/60 minutes)
|
|
- When the rotation timer hits, system suggests the next dealer and shows who's available
|
|
|
|
**Tournament dealer assignment:**
|
|
- Tournament tables can have assigned dealers
|
|
- Multi-table tournaments: dealers rotate across tables per the rotation schedule
|
|
- Final table: system can flag dealers with "final table" skill for assignment
|
|
|
|
### 2.5 Dealer Mobile Experience
|
|
|
|
Dealers access their schedule and shift management via the same mobile PWA (role-based views):
|
|
|
|
- **My Schedule:** See upcoming shifts, with venue details and game/table assignments
|
|
- **Trade Board:** See available shifts for trade. Offer to take shifts. Post own shifts.
|
|
- **Clock In/Out:** Tap to start/end shift. Automatic time tracking.
|
|
- **Notifications:** Shift reminders, trade offers, schedule changes, rotation alerts
|
|
- **Hours Summary:** Current week hours, pay period total, overtime status
|
|
|
|
### 2.6 Work Hours & Reporting
|
|
|
|
**Automatic tracking:** Clock-in/clock-out via mobile or Leaf UI. Break tracking (configurable: paid/unpaid breaks, minimum break duration compliance).
|
|
|
|
**Reports (for venue manager):**
|
|
- Hours per dealer per period (week, month, pay period)
|
|
- Overtime alerts
|
|
- No-show / late arrival log
|
|
- Shift trade history
|
|
- Skill utilization (which game skills are most in-demand)
|
|
|
|
**Export:** CSV for payroll integration. Standard format compatible with common payroll systems.
|
|
|
|
---
|
|
|
|
## 3. Player Loyalty System
|
|
|
|
### 3.1 Points Engine
|
|
|
|
Points are the currency of loyalty. Venues configure how players earn them.
|
|
|
|
**Point accrual rules (all configurable):**
|
|
|
|
| Activity | Default Points | Example |
|
|
|----------|---------------|---------|
|
|
| Tournament entry | 1 point per €1 buy-in | €50 tournament = 50 points |
|
|
| Tournament finish (top 10%) | Bonus 50 points | ITM finish = bonus |
|
|
| Cash game play | 1 point per hour | 4-hour session = 4 points |
|
|
| Cash game buy-in | 0.5 points per €1 | €200 buy-in = 100 points |
|
|
| League participation | 10 points per event | Season regular = loyalty bonus |
|
|
| Referral | 25 points per new player | Bring a friend |
|
|
| Special events | Custom | Venue-defined promotions |
|
|
|
|
**Multipliers (stackable):**
|
|
- Time-based: "2x points on Tuesday nights" (drive traffic on slow nights)
|
|
- Game-based: "1.5x points on PLO tables" (incentivize new games)
|
|
- Tier-based: "Gold members earn 1.5x base points"
|
|
- Event-based: "3x points during anniversary week"
|
|
|
|
**Point expiry:** Configurable. Options: never expire, expire after X months of inactivity, expire after calendar year. Venues choose.
|
|
|
|
### 3.2 Tier System
|
|
|
|
Players progress through tiers based on point accumulation:
|
|
|
|
| Tier | Threshold (example) | Benefits (example) |
|
|
|------|--------------------|--------------------|
|
|
| Bronze | 0 points | Base point earning, basic profile |
|
|
| Silver | 500 points/quarter | 1.25x point multiplier, priority waitlist |
|
|
| Gold | 2,000 points/quarter | 1.5x multiplier, free tournament entry/month, comp credits |
|
|
| Platinum | 5,000 points/quarter | 2x multiplier, VIP event access, dedicated floor contact |
|
|
|
|
**Tier configuration:**
|
|
- Tier names, thresholds, and benefits are fully customizable per venue
|
|
- Evaluation period: monthly, quarterly, or annual
|
|
- Tier maintenance: "maintain or drop" vs. "earn once, keep forever" (venue choice)
|
|
- Grace period: configurable period before tier demotion (e.g., 1 month grace after missing threshold)
|
|
|
|
### 3.3 Rewards Catalog
|
|
|
|
Venues define what players can spend points on:
|
|
|
|
| Category | Examples |
|
|
|----------|---------|
|
|
| Tournament entries | Free buy-in to weekly tournament (500 points) |
|
|
| Food & beverage | €10 bar credit (200 points), free coffee (50 points) |
|
|
| Merchandise | Venue t-shirt (1,000 points), branded card protector (300 points) |
|
|
| Seat upgrades | Priority seat selection in next tournament (100 points) |
|
|
| Cash game | Free hour of rake-free play (800 points) |
|
|
| Events | VIP event invitation (2,000 points) |
|
|
| Custom | Whatever the venue wants to offer |
|
|
|
|
**Redemption flow:**
|
|
1. Player views rewards on mobile → selects reward → confirms
|
|
2. System deducts points, generates reward voucher with unique code
|
|
3. Player shows voucher to staff (or staff scans QR code)
|
|
4. Staff marks voucher as redeemed in the system
|
|
5. All tracked for analytics (which rewards are popular, cost per redemption)
|
|
|
|
### 3.4 Automated Promotions
|
|
|
|
Venues can create promotions that trigger automatically:
|
|
|
|
**Promotion types:**
|
|
- **Time-based:** "Double points every Wednesday 2-6PM"
|
|
- **Birthday:** "100 bonus points on your birthday month"
|
|
- **Win-back:** "Been away 30+ days? Come back and earn 3x points this visit"
|
|
- **Achievement:** "Play your 100th tournament? 500 bonus points"
|
|
- **Seasonal:** "Holiday tournament series — 2x points on all December events"
|
|
- **Referral:** "Refer a friend who plays 3 events — both get 200 bonus points"
|
|
|
|
Promotions are created in the operator UI with start/end dates, targeting rules, and automatic application. No manual tracking.
|
|
|
|
### 3.5 Cross-Venue Loyalty (Multi-Venue Operators)
|
|
|
|
For operators running multiple venues:
|
|
- Player loyalty tier is shared across all venues
|
|
- Points earned at any venue count toward tier status
|
|
- Rewards can be redeemed at any venue (or restricted to earning venue — operator choice)
|
|
- Leaderboards can span all venues or be venue-specific
|
|
- Corporate-level promotions push to all venues
|
|
|
|
### 3.6 Display & Mobile Integration
|
|
|
|
**Player mobile view:**
|
|
```
|
|
┌─────────────────────────────┐
|
|
│ MY LOYALTY │
|
|
│ │
|
|
│ ★ GOLD MEMBER │
|
|
│ 2,450 / 5,000 to Platinum │
|
|
│ ████████░░░░ 49% │
|
|
│ │
|
|
│ Available Points: 1,200 │
|
|
│ Lifetime Points: 8,750 │
|
|
│ │
|
|
│ [View Rewards] [History] │
|
|
│ │
|
|
│ Active Promotions: │
|
|
│ 🔥 2x points tonight! │
|
|
│ 🎂 Birthday month bonus │
|
|
└─────────────────────────────┘
|
|
```
|
|
|
|
**Display node views:**
|
|
- Loyalty leaderboard (top earners this month/quarter)
|
|
- Current promotions ("2x Points Tonight!")
|
|
- Tier benefits overview
|
|
- All auto-cycle in signage playlists
|
|
|
|
---
|
|
|
|
## 4. Private Venues & Memberships
|
|
|
|
### 4.1 Venue Privacy Modes
|
|
|
|
| Mode | Visibility | Registration |
|
|
|------|-----------|-------------|
|
|
| Public | Anyone sees schedule, events, games | Open — anyone can join |
|
|
| Semi-Private | Schedule visible, limited detail | Requires application + approval |
|
|
| Private | Invisible to non-members | Invite-only |
|
|
|
|
Privacy mode affects:
|
|
- Public venue page visibility
|
|
- Whether the venue appears in search/discovery
|
|
- Whether events are listed publicly
|
|
- Whether non-members can join waitlists or register for tournaments
|
|
|
|
### 4.2 Membership Management
|
|
|
|
**Membership tiers (venue-defined):**
|
|
|
|
| Tier | Example | Access |
|
|
|------|---------|--------|
|
|
| Standard | €20/month | Tournament access, cash game access |
|
|
| Premium | €50/month | + Priority waitlist, league eligibility |
|
|
| VIP | €100/month | + High-stakes games, private events, guest passes |
|
|
| Founding | By invitation | Full access, lifetime rate, governance input |
|
|
|
|
**Member lifecycle:**
|
|
1. **Application:** Player applies via venue page or invitation link
|
|
2. **Approval:** Venue operator reviews application. Auto-approve rules (e.g., referred by existing member) available.
|
|
3. **Payment:** Monthly/annual fee (tracked in Felt — payment processing via Stripe or venue's own system)
|
|
4. **Active membership:** Access granted per tier
|
|
5. **Renewal:** Auto-reminder before expiry. Grace period configurable.
|
|
6. **Suspension/Cancellation:** Operator can suspend or cancel. Player can self-cancel with configurable notice period.
|
|
|
|
**Invite system:**
|
|
- Members generate invite links (limited per member per month — configurable)
|
|
- Invited players get a pre-approved application
|
|
- Referral credit for the inviting member (loyalty points or other reward)
|
|
- Guest passes: temporary access for specific events (configurable per tier — e.g., VIP members get 2 guest passes per month)
|
|
|
|
### 4.3 Member Communications
|
|
|
|
**In-app messaging:**
|
|
- Venue → all members (announcements)
|
|
- Venue → tier-specific (e.g., VIP event invitations)
|
|
- Venue → individual member (private message)
|
|
- Delivered via mobile PWA notification + optional email/SMS
|
|
|
|
**Automated communications:**
|
|
- Welcome message on membership approval
|
|
- Renewal reminders (7 days, 1 day before expiry)
|
|
- Event announcements (new tournaments, special events)
|
|
- Membership tier changes (upgrade/downgrade notifications)
|
|
- Win-back messages for lapsed members
|
|
|
|
### 4.4 Member Directory (Optional)
|
|
|
|
Venues can enable a member directory (privacy settings per member):
|
|
- Members can see who else is a member (first name + last initial)
|
|
- Opt-in: members choose what to share (photo, game preferences, bio)
|
|
- Useful for building community in private clubs
|
|
- Disabled by default — venue must explicitly enable
|
|
|
|
---
|
|
|
|
## 5. Venue Analytics & Reporting
|
|
|
|
### 5.1 Revenue Dashboard
|
|
|
|
**Real-time revenue tracking:**
|
|
- Tournament revenue: entry fees collected, house take
|
|
- Cash game revenue: rake collected per table, per game type
|
|
- Membership revenue: fees collected
|
|
- Combined: total revenue by day/week/month/year
|
|
|
|
**Visualizations:**
|
|
- Revenue trend line (last 30/90/365 days)
|
|
- Revenue by source (pie: tournaments vs. cash vs. memberships)
|
|
- Revenue by game type (which games make the most money?)
|
|
- Revenue by day of week (which nights are strongest?)
|
|
- Revenue by time of day (when are the peak revenue hours?)
|
|
|
|
### 5.2 Player Analytics
|
|
|
|
**Player engagement metrics:**
|
|
- Active players (played in last 7/30/90 days)
|
|
- New player acquisition rate
|
|
- Player retention rate (% returning within 30 days)
|
|
- Player lifetime value (total revenue attributed per player)
|
|
- Visit frequency distribution
|
|
|
|
**Player segmentation:**
|
|
- By game preference (tournament vs. cash vs. both)
|
|
- By stakes level
|
|
- By loyalty tier
|
|
- By visit frequency (regular, occasional, lapsed)
|
|
- By value (high-value, medium, low)
|
|
|
|
All player analytics are aggregated — individual player data is not exposed to other players.
|
|
|
|
### 5.3 Operational Analytics
|
|
|
|
**Table utilization:**
|
|
- Seats occupied vs. available over time (heatmap by hour of day / day of week)
|
|
- Average table utilization rate
|
|
- Table open/close patterns
|
|
|
|
**Tournament analytics:**
|
|
- Fill rates (registered vs. capacity)
|
|
- Average entries per tournament
|
|
- Most popular tournament formats
|
|
- Late registration patterns
|
|
- Prize pool trends
|
|
|
|
**Waitlist analytics:**
|
|
- Average wait time by game/stakes
|
|
- Waitlist conversion rate (joined → seated)
|
|
- Waitlist abandonment rate
|
|
- Peak demand times
|
|
|
|
**Dealer analytics:**
|
|
- Hours worked per dealer
|
|
- Shift coverage rates
|
|
- Trade frequency
|
|
- Rotation compliance
|
|
|
|
### 5.4 Multi-Venue Benchmarking
|
|
|
|
For operators with multiple venues:
|
|
- Side-by-side venue comparison (revenue, utilization, player engagement)
|
|
- Identify best practices from top-performing venues
|
|
- Flag underperforming venues with specific metrics
|
|
- Cross-venue player flow (which players play at multiple venues?)
|
|
|
|
### 5.5 Export & Integration
|
|
|
|
- **CSV export:** All reports exportable for Excel/accounting
|
|
- **PDF reports:** Formatted reports for stakeholders
|
|
- **API access:** All analytics available via REST API for custom integrations
|
|
- **Scheduled reports:** Auto-generate and email weekly/monthly reports to venue owner
|
|
|
|
---
|
|
|
|
## 6. Public Venue Presence
|
|
|
|
### 6.1 Venue Profile Page
|
|
|
|
Each venue gets a public page at `venue-name.felt.io` (or custom domain):
|
|
|
|
- Venue name, logo, photos, description
|
|
- Location with map
|
|
- Hours of operation
|
|
- Current games running (live, for public venues)
|
|
- Upcoming events and tournaments
|
|
- Game offerings (types and stakes)
|
|
- Contact information
|
|
|
|
SEO-optimized for "poker near [city]" searches.
|
|
|
|
### 6.2 Event Publishing
|
|
|
|
**Automated schedule publishing:**
|
|
- Weekly tournament schedule auto-published to venue page
|
|
- Upcoming special events with registration
|
|
- League schedules and current standings
|
|
|
|
**External publishing (API integrations):**
|
|
- Poker Atlas format export (automatic submission)
|
|
- Hendon Mob format export (tournament results)
|
|
- Social media API integration (auto-post new events to venue's Facebook/Instagram)
|
|
- iCal feed for players to subscribe to venue schedule
|
|
|
|
### 6.3 Online Registration
|
|
|
|
Players can register for upcoming tournaments from the venue page:
|
|
- View tournament details (format, buy-in, blind structure, starting stack)
|
|
- Register (with or without pre-payment — venue configurable)
|
|
- See current registrant count and capacity
|
|
- Cancel registration (within venue's cancellation policy)
|
|
- Automatic reminders before the event
|
|
|
|
---
|
|
|
|
## 7. Data Architecture
|
|
|
|
### New Tables (extends Phase 1 + 2 schema)
|
|
|
|
```sql
|
|
-- =====================
|
|
-- DEALER MANAGEMENT
|
|
-- =====================
|
|
|
|
CREATE TABLE dealers (
|
|
id TEXT PRIMARY KEY,
|
|
player_id TEXT REFERENCES players(id), -- Dealer may also be a player
|
|
name TEXT NOT NULL,
|
|
email TEXT,
|
|
phone TEXT,
|
|
photo_url TEXT,
|
|
employee_id TEXT,
|
|
status TEXT NOT NULL DEFAULT 'active', -- active, inactive, terminated
|
|
hire_date DATE,
|
|
notes TEXT,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE dealer_skills (
|
|
id TEXT PRIMARY KEY,
|
|
dealer_id TEXT NOT NULL REFERENCES dealers(id),
|
|
skill_type TEXT NOT NULL, -- game_variant, betting, format, experience, special, language
|
|
skill_value TEXT NOT NULL, -- "holdem", "no_limit", "tournament", "senior", "high_stakes", "danish"
|
|
verified BOOLEAN NOT NULL DEFAULT false,
|
|
verified_by TEXT,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE shift_templates (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL, -- "Evening"
|
|
start_time TIME NOT NULL, -- "18:00"
|
|
end_time TIME NOT NULL, -- "02:00"
|
|
break_minutes INTEGER DEFAULT 0,
|
|
color TEXT, -- Hex color for schedule UI
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE dealer_schedules (
|
|
id TEXT PRIMARY KEY,
|
|
dealer_id TEXT NOT NULL REFERENCES dealers(id),
|
|
date DATE NOT NULL,
|
|
template_id TEXT REFERENCES shift_templates(id),
|
|
start_time DATETIME NOT NULL,
|
|
end_time DATETIME NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'scheduled', -- scheduled, confirmed, in_progress, completed, no_show, traded
|
|
actual_start DATETIME,
|
|
actual_end DATETIME,
|
|
notes TEXT,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
UNIQUE(dealer_id, date, template_id)
|
|
);
|
|
|
|
CREATE TABLE dealer_availability (
|
|
id TEXT PRIMARY KEY,
|
|
dealer_id TEXT NOT NULL REFERENCES dealers(id),
|
|
day_of_week INTEGER, -- 0=Mon, 6=Sun (NULL for specific date override)
|
|
specific_date DATE, -- For one-off availability changes
|
|
available_from TIME, -- NULL = not available
|
|
available_to TIME,
|
|
is_available BOOLEAN NOT NULL DEFAULT true,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE shift_trades (
|
|
id TEXT PRIMARY KEY,
|
|
schedule_id TEXT NOT NULL REFERENCES dealer_schedules(id),
|
|
offering_dealer TEXT NOT NULL REFERENCES dealers(id),
|
|
taking_dealer TEXT REFERENCES dealers(id), -- NULL = open for offers
|
|
status TEXT NOT NULL DEFAULT 'posted', -- posted, offered, approved, completed, cancelled
|
|
requires_approval BOOLEAN NOT NULL DEFAULT false,
|
|
approved_by TEXT,
|
|
approved_at DATETIME,
|
|
notes TEXT,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE dealer_time_clock (
|
|
id TEXT PRIMARY KEY,
|
|
dealer_id TEXT NOT NULL REFERENCES dealers(id),
|
|
schedule_id TEXT REFERENCES dealer_schedules(id),
|
|
clock_in DATETIME NOT NULL,
|
|
clock_out DATETIME,
|
|
break_start DATETIME,
|
|
break_end DATETIME,
|
|
total_hours REAL, -- Calculated on clock-out
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- =====================
|
|
-- LOYALTY SYSTEM
|
|
-- =====================
|
|
|
|
CREATE TABLE loyalty_config (
|
|
id TEXT PRIMARY KEY,
|
|
venue_id TEXT NOT NULL,
|
|
point_expiry_months INTEGER, -- NULL = never expire
|
|
evaluation_period TEXT DEFAULT 'quarterly', -- monthly, quarterly, annual
|
|
grace_period_days INTEGER DEFAULT 30,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE loyalty_tiers (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL, -- "Gold"
|
|
sort_order INTEGER NOT NULL,
|
|
threshold_points INTEGER NOT NULL, -- Points needed per evaluation period
|
|
point_multiplier REAL NOT NULL DEFAULT 1.0,
|
|
color TEXT, -- Hex color for UI
|
|
icon TEXT, -- Icon identifier
|
|
benefits_json TEXT, -- JSON description of benefits
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE loyalty_accrual_rules (
|
|
id TEXT PRIMARY KEY,
|
|
activity_type TEXT NOT NULL, -- tournament_entry, cash_hour, cash_buyin, league_event, referral, custom
|
|
points_per_unit REAL NOT NULL, -- Points per €1, per hour, per event, etc.
|
|
unit TEXT NOT NULL, -- "currency", "hour", "event", "flat"
|
|
conditions_json TEXT, -- Optional JSON conditions (game type, stakes, time window)
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE loyalty_multipliers (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL, -- "Tuesday Double Points"
|
|
multiplier REAL NOT NULL, -- 2.0 for double
|
|
conditions_json TEXT NOT NULL, -- Time windows, game types, tier requirements
|
|
start_date DATETIME,
|
|
end_date DATETIME,
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE player_loyalty (
|
|
id TEXT PRIMARY KEY,
|
|
player_id TEXT NOT NULL REFERENCES players(id) UNIQUE,
|
|
current_tier_id TEXT REFERENCES loyalty_tiers(id),
|
|
current_points INTEGER NOT NULL DEFAULT 0,
|
|
lifetime_points INTEGER NOT NULL DEFAULT 0,
|
|
period_points INTEGER NOT NULL DEFAULT 0, -- Points in current evaluation period
|
|
tier_locked_until DATETIME, -- Grace period end
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE loyalty_transactions (
|
|
id TEXT PRIMARY KEY,
|
|
player_id TEXT NOT NULL REFERENCES players(id),
|
|
type TEXT NOT NULL, -- earn, redeem, expire, adjust
|
|
points INTEGER NOT NULL, -- Positive for earn, negative for redeem/expire
|
|
source TEXT, -- tournament_id, session_id, promotion_id, reward_id
|
|
description TEXT, -- "Tournament entry: Friday €50 NLH"
|
|
balance_after INTEGER NOT NULL,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE loyalty_rewards (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL, -- "Free Tournament Entry"
|
|
description TEXT,
|
|
category TEXT NOT NULL, -- tournament, food_beverage, merchandise, seat, cash_game, event, custom
|
|
points_cost INTEGER NOT NULL,
|
|
min_tier_id TEXT REFERENCES loyalty_tiers(id), -- Minimum tier to access this reward
|
|
quantity_available INTEGER, -- NULL = unlimited
|
|
quantity_redeemed INTEGER NOT NULL DEFAULT 0,
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE loyalty_redemptions (
|
|
id TEXT PRIMARY KEY,
|
|
player_id TEXT NOT NULL REFERENCES players(id),
|
|
reward_id TEXT NOT NULL REFERENCES loyalty_rewards(id),
|
|
points_spent INTEGER NOT NULL,
|
|
voucher_code TEXT NOT NULL UNIQUE,
|
|
status TEXT NOT NULL DEFAULT 'issued', -- issued, redeemed, expired, cancelled
|
|
redeemed_at DATETIME,
|
|
redeemed_by TEXT, -- Staff member who confirmed redemption
|
|
expires_at DATETIME,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE loyalty_promotions (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL,
|
|
type TEXT NOT NULL, -- time_based, birthday, winback, achievement, seasonal, referral
|
|
config_json TEXT NOT NULL, -- Trigger conditions, point amounts, multipliers
|
|
start_date DATETIME,
|
|
end_date DATETIME,
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
auto_apply BOOLEAN NOT NULL DEFAULT true,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
-- =====================
|
|
-- MEMBERSHIPS
|
|
-- =====================
|
|
|
|
CREATE TABLE membership_tiers (
|
|
id TEXT PRIMARY KEY,
|
|
name TEXT NOT NULL, -- "VIP"
|
|
description TEXT,
|
|
monthly_fee INTEGER, -- Cents (NULL = free tier)
|
|
annual_fee INTEGER, -- Cents (discounted annual option)
|
|
max_members INTEGER, -- NULL = unlimited
|
|
guest_passes_monthly INTEGER DEFAULT 0,
|
|
benefits_json TEXT, -- JSON description of access and benefits
|
|
sort_order INTEGER NOT NULL,
|
|
is_active BOOLEAN NOT NULL DEFAULT true,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE memberships (
|
|
id TEXT PRIMARY KEY,
|
|
player_id TEXT NOT NULL REFERENCES players(id),
|
|
tier_id TEXT NOT NULL REFERENCES membership_tiers(id),
|
|
status TEXT NOT NULL DEFAULT 'pending', -- pending, active, suspended, cancelled, expired
|
|
applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
approved_at DATETIME,
|
|
approved_by TEXT,
|
|
billing_cycle TEXT DEFAULT 'monthly', -- monthly, annual
|
|
current_period_start DATETIME,
|
|
current_period_end DATETIME,
|
|
auto_renew BOOLEAN NOT NULL DEFAULT true,
|
|
cancelled_at DATETIME,
|
|
cancel_reason TEXT,
|
|
invited_by TEXT REFERENCES players(id),
|
|
invite_code TEXT,
|
|
notes TEXT,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE guest_passes (
|
|
id TEXT PRIMARY KEY,
|
|
member_id TEXT NOT NULL REFERENCES memberships(id),
|
|
guest_name TEXT NOT NULL,
|
|
guest_email TEXT,
|
|
event_id TEXT, -- Specific event, or NULL for general access
|
|
valid_date DATE NOT NULL,
|
|
status TEXT NOT NULL DEFAULT 'issued', -- issued, used, expired, cancelled
|
|
used_at DATETIME,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
|
|
CREATE TABLE venue_settings_privacy (
|
|
id TEXT PRIMARY KEY,
|
|
privacy_mode TEXT NOT NULL DEFAULT 'public', -- public, semi_private, private
|
|
show_schedule BOOLEAN NOT NULL DEFAULT true,
|
|
show_games BOOLEAN NOT NULL DEFAULT true,
|
|
show_waitlist BOOLEAN NOT NULL DEFAULT false,
|
|
require_membership BOOLEAN NOT NULL DEFAULT false,
|
|
member_directory_enabled BOOLEAN NOT NULL DEFAULT false,
|
|
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 8. API Design
|
|
|
|
### Dealer Management
|
|
|
|
```
|
|
GET /dealers List dealers
|
|
POST /dealers Create dealer profile
|
|
GET /dealers/:id Get dealer detail
|
|
PUT /dealers/:id Update dealer
|
|
POST /dealers/:id/skills Add skill
|
|
DELETE /dealers/:id/skills/:skillId Remove skill
|
|
|
|
GET /schedule Get schedule (date range, filters)
|
|
POST /schedule Assign shift
|
|
PUT /schedule/:id Update shift
|
|
DELETE /schedule/:id Remove shift
|
|
|
|
GET /shifts/templates List shift templates
|
|
POST /shifts/templates Create template
|
|
|
|
POST /shifts/trades Post shift for trade
|
|
GET /shifts/trades List available trades
|
|
POST /shifts/trades/:id/offer Offer to take shift
|
|
POST /shifts/trades/:id/approve Approve trade (manager)
|
|
|
|
POST /dealers/:id/clock-in Clock in
|
|
POST /dealers/:id/clock-out Clock out
|
|
GET /dealers/:id/hours Hours report (date range)
|
|
```
|
|
|
|
### Loyalty System
|
|
|
|
```
|
|
GET /loyalty/config Get loyalty configuration
|
|
PUT /loyalty/config Update loyalty configuration
|
|
GET /loyalty/tiers List tiers
|
|
POST /loyalty/tiers Create tier
|
|
PUT /loyalty/tiers/:id Update tier
|
|
|
|
GET /loyalty/rules List accrual rules
|
|
POST /loyalty/rules Create rule
|
|
GET /loyalty/multipliers List active multipliers
|
|
POST /loyalty/multipliers Create multiplier
|
|
|
|
GET /loyalty/rewards List available rewards
|
|
POST /loyalty/rewards Create reward
|
|
POST /loyalty/redeem Redeem reward (player)
|
|
POST /loyalty/redemptions/:id/confirm Confirm redemption (staff)
|
|
|
|
GET /loyalty/promotions List promotions
|
|
POST /loyalty/promotions Create promotion
|
|
|
|
GET /loyalty/leaderboard Loyalty leaderboard
|
|
```
|
|
|
|
### Player Loyalty (Mobile)
|
|
|
|
```
|
|
GET /me/loyalty My loyalty status (tier, points, promotions)
|
|
GET /me/loyalty/history My point transaction history
|
|
GET /me/loyalty/rewards Available rewards for my tier
|
|
POST /me/loyalty/redeem Redeem a reward
|
|
GET /me/loyalty/vouchers My active vouchers
|
|
```
|
|
|
|
### Memberships
|
|
|
|
```
|
|
GET /memberships/tiers List membership tiers
|
|
POST /memberships/apply Apply for membership
|
|
GET /memberships List all memberships (operator)
|
|
PUT /memberships/:id Update membership (approve, suspend, etc.)
|
|
POST /memberships/:id/renew Trigger renewal
|
|
|
|
POST /memberships/:id/guest-pass Issue guest pass
|
|
GET /memberships/:id/guest-passes List guest passes
|
|
|
|
GET /me/membership My membership status
|
|
POST /me/membership/cancel Cancel my membership
|
|
POST /me/membership/invite Generate invite link
|
|
```
|
|
|
|
### Analytics
|
|
|
|
```
|
|
GET /analytics/revenue Revenue dashboard (date range, source filters)
|
|
GET /analytics/players Player engagement metrics
|
|
GET /analytics/tables Table utilization metrics
|
|
GET /analytics/tournaments Tournament performance metrics
|
|
GET /analytics/waitlist Waitlist analytics
|
|
GET /analytics/dealers Dealer metrics
|
|
GET /analytics/loyalty Loyalty program metrics
|
|
GET /analytics/export Export report (CSV/PDF)
|
|
```
|
|
|
|
### Public Venue
|
|
|
|
```
|
|
GET /venue/profile Public venue profile
|
|
PUT /venue/profile Update venue profile (operator)
|
|
GET /venue/schedule Public event schedule
|
|
GET /venue/games Current games (public venues)
|
|
POST /venue/events/:id/register Register for event (player)
|
|
GET /venue/events/:id/registrations List registrations (operator)
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Roadmap
|
|
|
|
### v3.0 — Dealer Management
|
|
|
|
- Dealer profiles with skill tags
|
|
- Shift templates and schedule builder
|
|
- Shift trading system
|
|
- Clock-in/clock-out with hours tracking
|
|
- Dealer assignment to cash tables and tournaments
|
|
- Dealer mobile experience (schedule, trade board, clock)
|
|
- Basic reporting (hours, shifts, trades)
|
|
|
|
### v3.1 — Player Loyalty
|
|
|
|
- Points engine with configurable accrual rules
|
|
- Tier system with automated evaluation
|
|
- Rewards catalog and redemption flow
|
|
- Point multipliers (time-based, game-based, tier-based)
|
|
- Loyalty display on mobile and venue screens
|
|
- Basic promotions (birthday, time-based)
|
|
|
|
### v3.2 — Memberships & Privacy
|
|
|
|
- Venue privacy modes (public, semi-private, private)
|
|
- Membership tiers with fee tracking
|
|
- Application and approval workflow
|
|
- Invite system and guest passes
|
|
- Member communications
|
|
- Optional member directory
|
|
|
|
### v3.3 — Analytics & Public Presence
|
|
|
|
- Revenue dashboards
|
|
- Player engagement analytics
|
|
- Operational analytics (tables, waitlists, tournaments)
|
|
- Public venue profile page
|
|
- Event publishing with online registration
|
|
- External publishing (Poker Atlas, Hendon Mob, social)
|
|
- Scheduled reports
|
|
|
|
### v3.4 — Advanced Features
|
|
|
|
- Cross-venue loyalty (multi-venue operators)
|
|
- Multi-venue benchmarking analytics
|
|
- Dealer rotation automation
|
|
- Advanced promotions engine (winback, achievement, referral chains)
|
|
- Custom reporting builder
|
|
- API access for third-party integrations
|
|
- White-label options for enterprise
|
|
|
|
---
|
|
|
|
*Phase 3 turns Felt from a poker management tool into the operating system for the venue. At this point, every tournament, every cash game, every dealer shift, every player visit, every dollar — it all flows through Felt. That's the endgame.*
|