[DECOMPOSED] Admin schedule: data model + API for practices and events #230
Labels
No labels
domain:backend
domain:devops
domain:frontend
status:approved
status:in-progress
status:needs-fix
status:qa
type:bug
type:devops
type:feature
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
forgejo_admin/basketball-api#230
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Type
Feature
Lineage
Standalone — scoped during admin interface review. No existing schedule entities in the domain model. Current schedule is hardcoded HTML in westside-app.
Repo
forgejo_admin/basketball-apiUser Story
story:WS-S13As an admin, I want to view and manage the program schedule (practices, tournaments, games) so that I have a single source of truth for all planned activities instead of relying on hardcoded HTML or memory.Context
The public schedule page (
westside-app/src/routes/(public)/schedule/+page.svelte) has all schedule data hardcoded: 3 Kings tournaments, 5 Queens tournaments, 8 practice slots across travel and local teams. Marcus has no admin visibility — adding or changing anything requires a code deploy.This ticket adds the backend data model and API endpoints to
basketball-api. The admin frontend view (westside-app/admin/schedule) and the public page refactor are separate follow-up tickets.Architecture decision: two tables, not one.
Practices are recurring weekly (defined by day-of-week + time), while events are date-specific (tournaments, games). These are fundamentally different data shapes. Two tables with clean non-nullable columns beats one table with a maze of nullable fields.
Data Model:
Enum:
EventType—tournament,game,camp,tryout,otherTable:
practice_schedulesTable:
eventsAPI Endpoints (all admin-auth, tenant-scoped):
GET /admin/schedule— combined{ practices: [...], events: [...] }GET /admin/schedule/practices— list (filter: division, is_active)POST /admin/schedule/practices— createPUT /admin/schedule/practices/{id}— updateDELETE /admin/schedule/practices/{id}— deleteGET /admin/schedule/events— list (filter: division, event_type, upcoming)POST /admin/schedule/events— createPUT /admin/schedule/events/{id}— updateDELETE /admin/schedule/events/{id}— deleteSeed data from current hardcoded schedule:
File Targets
Files to create or modify:
src/basketball_api/models.py— addEventTypeenum,PracticeSchedulemodel,Eventmodelsrc/basketball_api/routes/admin.py— add schedule CRUD endpointssrc/basketball_api/schemas.py— add Pydantic request/response schemas for practices and eventsalembic/versions/xxx_add_schedule_tables.py— migration for both tablesscripts/seed_schedule.pyor data migration — populate current schedule dataFiles NOT to touch:
src/basketball_api/routes/public.py— public API is a separate concernAcceptance Criteria
practice_schedulesandeventstablesGET /admin/schedulereturns combined practices + eventsTest Expectations
pytest tests/ -vConstraints
models.py(Mapped types, enum classes, relationship style)routes/admin.py(dependency injection, tenant scoping)String(10)for time fields ("14:00" format) — avoids SQLAlchemy Time serialization complexityparent_event_id) for tournament→game nestingChecklist
Related
project-westside-basketball— parent projectarch-domain-westside-basketball— domain model needs updating after merge (follow-up)westside-app(/admin/schedule)Scope Review: NEEDS_REFINEMENT
Review note:
review-627-2026-03-28Ticket is well-structured with complete template and traceability, but has a critical data model ambiguity and exceeds decomposition limits.
Issues found:
divisionuses "kings/queens" values, butDivisionenum inmodels.pyisboys/girls. TheInterestLeadmodel uses a separate freetextString(20)"program" field for kings/queens. This is a design decision the agent cannot make.src/basketball_api/schemas.pydoes not exist. Codebase defines all Pydantic schemas inline in route files.admin.pyis already 1048 lines. Codebase has precedent for separate route files (jersey.py, checkout.py, coaches_api.py). Considerroutes/schedule.py.Scope Review: NEEDS_REFINEMENT → DECOMPOSED
Review note:
review-627-2026-03-28Findings & Decisions
Division enum mismatch (CRITICAL): Ticket said "kings/queens" but
Divisionenum isboys/girls. Decision: Reuse existingDivision(boys/girls). Kings=boys, Queens=girls — the mapping is stable and matches howTeam.divisionalready works. UI displays program names ("Kings"/"Queens"), DB stores division.Invalid file target:
schemas.pydoesn't exist. Codebase defines Pydantic schemas inline in route files. Decision: Define schemas inline inroutes/schedule.py.Route file placement:
admin.pyis 1048 lines. Decision: Newroutes/schedule.pywith its own router, following precedent ofjersey.py,checkout.py,coaches_api.py.Scope exceeds limits: 5 discrete changes, 9 endpoints, estimated 10-15 min. Decision: Decompose into 2 sub-tickets:
This issue is now the parent. Marking as DECOMPOSED.
Admin schedule view: data model + API endpoints for practices and eventsto [DECOMPOSED] Admin schedule: data model + API for practices and eventsCorrection: Sub-tickets are #232 (data model) and #233 (API endpoints), not #231/#232 as stated above.