Preskoči na sadržaj

E2: Match & Stadium Management - Tasks

Epic: E2: Match & Stadium Management

Task Legend

Symbol Status
⬜ Not started
🟡 In progress
✅ Complete
❌ Blocked

E2-F1: Match CRUD API

Feature: E2-F1: Match CRUD API

Status Task Verification
⬜ Create Match database migration (id, home_team, away_team, competition, kick_off_time, venue_id, status, created_at, updated_at) Run migrations
⬜ Implement POST /admin/matches endpoint with required fields Returns 201 with match_id
⬜ Implement GET /admin/matches endpoint with pagination Returns list of matches
⬜ Implement GET /admin/matches/{id} endpoint Returns match details
⬜ Implement PUT /admin/matches/{id} endpoint Updates match details
⬜ Implement DELETE /admin/matches/{id} endpoint (soft delete) Match status becomes "deleted"
⬜ Add status validation (draft, published, cancelled, closed) Invalid status transition returns 400
⬜ Add RBAC check for Match Manager role Non-admin returns 403

E2-F2: Sales Phase Configuration

Feature: E2-F2: Sales Phase Configuration

Status Task Verification
⬜ Create SalesPhase database migration (id, match_id, phase_type, start_at, end_at, eligibility_rules_json, ticket_limit) Run migrations
⬜ Implement POST /admin/matches/{id}/sales-phases endpoint Creates phase
⬜ Implement GET /admin/matches/{id}/sales-phases endpoint Returns phases for match
⬜ Implement PUT /admin/matches/{id}/sales-phases/{phase_id} endpoint Updates phase
⬜ Add overlap validation (phases cannot have overlapping dates) Overlapping dates return 400
⬜ Add eligibility_rules_json schema validation Invalid JSON structure returns 400

E2-F3: Stadium Template Management

Feature: E2-F3: Stadium Template Management

Status Task Verification
⬜ Create Stadium database migration (id, name, city, country, type, total_capacity, is_template) Run migrations
⬜ Create Sector database migration (id, stadium_id, name, row_count, seats_per_row, technical_seats) Run migrations
⬜ Seed database with Croatian stadium templates (Maksimir, Poljud, Opus Arena, Rujevica, Varazdin) with pre-configured seat maps Query returns 5 templates with complete seat data
⬜ Implement GET /admin/stadiums/templates endpoint Returns list of templates
⬜ Implement GET /admin/stadiums/{id}/sectors endpoint Returns sectors for stadium
⬜ Implement POST /admin/stadiums/{stadiumId}/sectors endpoint Creates sector in template
⬜ Implement PUT /admin/stadiums/{stadiumId}/sectors/{sectorId} endpoint Updates sector
⬜ Implement DELETE /admin/stadiums/{stadiumId}/sectors/{sectorId} endpoint Deletes sector (if no seat map)

E2-F4: Match Stadium Configuration

Feature: E2-F4: Match Stadium Configuration

Status Task Verification
⬜ Create MatchStadiumConfig database migration (id, match_id, stadium_id, config_version) Run migrations
⬜ Create MatchSector database migration (match_id, sector_id, status, price_category_id) Run migrations
⬜ Implement POST /admin/matches/{id}/stadium-config endpoint to copy template Creates match-specific config
⬜ Implement PUT /admin/matches/{id}/sectors/{sector_id} endpoint to set status (active/closed) Sector status updated
⬜ Implement price category assignment to sectors All seats in sector inherit price
⬜ Lock configuration after save (increment config_version) Version incremented

E2-F5: Away Match Stadium Creation

Feature: E2-F5: Away Match Stadium Creation

Status Task Verification
⬜ Implement POST /admin/stadiums endpoint for creating away stadium Creates stadium with type=AWAY
⬜ Add fields for name, city, country, address All fields saved
⬜ Add non_numbered_seats flag for away stadiums Flag persists
⬜ Implement sector creation for away stadium Sectors created with capacity

E2-F6: Match Update Notifications

Feature: E2-F6: Match Update Notifications

Status Task Verification
⬜ Add notification_preference param to PUT /admin/matches/{id} (notify/silent) Param accepted
⬜ If notify: trigger email to all ticket holders Emails queued
⬜ If notify: trigger push notification to all ticket holders Pushes queued
⬜ Log all changes to audit trail regardless of notification preference Audit record created

E2-F7: Match Cancellation Workflow

Feature: E2-F7: Match Cancellation Workflow

Status Task Verification
⬜ Implement POST /admin/matches/{id}/cancel endpoint Requires approval for published matches
⬜ Add Super Admin approval check for published match cancellation Non-super-admin returns 403
⬜ Trigger batch refund job for all paid tickets Refund records created
⬜ Send cancellation notification to all ticket holders Emails/push sent
⬜ Invalidate all QR codes (set ticket status to CANCELLED) Tickets marked cancelled
⬜ Generate cancellation report (tickets, refunds, notifications) Report accessible

E2-F8: Access Control Data Export

Feature: E2-F8: Access Control Data Export

Status Task Verification
⬜ Implement GET /admin/matches/{id}/access-control-export endpoint Returns Excel file
⬜ Export only barcode column (no PII) Excel has barcode only
⬜ Include extra ~1000 codes for unsold seats and late changes Export count > sold tickets
⬜ File naming: MatchID_TicketExport_YYYYMMDD_HHMM.xlsx Filename matches pattern

E2-F9: Match Closure with Attendance

Feature: E2-F9: Match Closure & Attendance

Status Task Verification
⬜ Implement POST /admin/matches/{id}/close endpoint Changes match status to CLOSED
⬜ Accept attendance file upload (Excel with barcodes) File parsed correctly
⬜ Match barcodes to tickets and update status to ATTENDED Matched tickets have ATTENDED status
⬜ Make match closure and attendance update atomic (transaction) Partial failure rolls back both
⬜ If no attendance data: require reason, mark all tickets ATTENDED All tickets updated
⬜ Trigger loyalty points calculation after closure Job triggered

E2-F10: Sector Seat Map Configuration

Feature: E2-F10: Sector Seat Map Configuration

Database Migrations

Status Task Verification
⬜ Create sector_seat_maps table (id, sector_id, seat_map_json JSONB, total_seats, configuration_status, created_at, updated_at) Run migrations
⬜ Create seat_type enum (STANDARD, TECHNICAL, ACCESSIBILITY, COMPANION) Enum created
⬜ Create seats table (id, sector_id, row_identifier, seat_number, seat_type, created_at) Run migrations
⬜ Add UNIQUE constraint on (sector_id, row_identifier, seat_number) Constraint validated
⬜ Create traversal_dir enum (TOP_TO_BOTTOM, BOTTOM_TO_TOP) Enum created
⬜ Create row_strategy enum (CENTER_OUTWARD, LEFT_TO_RIGHT, RIGHT_TO_LEFT) Enum created
⬜ Create sector_snake_configs table (id, sector_id, best_row_index, traversal_direction, within_row_strategy, subsector_grouping_json, created_at) Run migrations

API Endpoints

Status Task Verification
⬜ Implement GET /admin/sectors/{sectorId}/seat-map endpoint Returns seat map JSON for canvas
⬜ Implement POST /admin/sectors/{sectorId}/seat-map endpoint Creates seat map from canvas JSON
⬜ Implement PUT /admin/sectors/{sectorId}/seat-map endpoint Updates existing seat map
⬜ Implement DELETE /admin/sectors/{sectorId}/seat-map endpoint Deletes seat map (if no tickets sold)
⬜ Implement POST /admin/sectors/{sectorId}/seats/generate endpoint Generates Seat records from JSON
⬜ Implement seat generation logic with preview option Preview returns seat list without saving
⬜ Support LTR numbering direction Seats numbered 1, 2, 3...
⬜ Support RTL numbering direction Seats numbered ...3, 2, 1
⬜ Implement POST /admin/sectors/{sectorId}/seats/classify endpoint Bulk classifies seats
⬜ Implement PUT /admin/seats/{seatId}/type endpoint Updates single seat type
⬜ Implement GET /admin/sectors/{sectorId}/snake-config endpoint Returns snake configuration
⬜ Implement PUT /admin/sectors/{sectorId}/snake-config endpoint Updates snake configuration
⬜ Implement GET /admin/matches/{matchId}/sectors/status-summary endpoint Returns sector status aggregates

Business Logic

Status Task Verification
⬜ Validate seat_map_json schema on save Invalid JSON returns 400
⬜ Calculate total_seats from seat_map_json Count matches JSON entries
⬜ Prevent seat map update if seats already generated with tickets sold Returns 409 if locked
⬜ Auto-number seats based on row_labels and numbering_direction Numbers calculated correctly
⬜ Skip gap positions (missing entries) during seat generation Gaps create number jumps

Last Updated: February 2026