Schedule API endpoints (practices + events CRUD) #233

Closed
opened 2026-03-28 22:38:09 +00:00 by forgejo_admin · 1 comment

Type

Feature

Lineage

Child of forgejo_admin/basketball-api#230 (decomposed parent). Depends on #232 (data model).

Repo

forgejo_admin/basketball-api

User Story

story:WS-S13 As an admin, I want API endpoints to create, read, update, and delete schedule entries so that the admin frontend can manage practices and events.

Context

This ticket adds the API layer for schedule management. The data model and tables are created in sibling ticket #232 — this ticket depends on that landing first.

Key design decisions (from review of #230):

  • New routes/schedule.py file — admin.py is 1048 lines, and the codebase has precedent for dedicated route files (jersey.py, checkout.py, coaches_api.py).
  • Pydantic schemas defined inline in the route file (no separate schemas.py — matches codebase convention).
  • All endpoints admin-auth + tenant-scoped (matching existing admin route patterns).
  • Division filter uses existing Division(boys/girls) enum.

File Targets

Files to create or modify:

  • src/basketball_api/routes/schedule.py — NEW file. Admin CRUD endpoints with inline Pydantic schemas.
  • src/basketball_api/main.py — register the schedule router
  • tests/test_schedule.py — NEW file. Endpoint tests.

Pattern reference (do NOT modify):

  • src/basketball_api/routes/admin.py — tenant scoping pattern, auth dependency injection
  • src/basketball_api/routes/jersey.py — dedicated route file pattern, inline schemas
  • src/basketball_api/routes/checkout.py — another dedicated route file example

Files NOT to touch:

  • src/basketball_api/models.py — already handled by #232
  • alembic/ — already handled by #232

Acceptance Criteria

  • GET /admin/schedule returns combined { practices: [...], events: [...] }
  • GET /admin/schedule/practices lists practice schedules (filter: division, is_active)
  • POST /admin/schedule/practices creates a practice schedule
  • PUT /admin/schedule/practices/{id} updates a practice schedule
  • DELETE /admin/schedule/practices/{id} deletes a practice schedule
  • GET /admin/schedule/events lists events (filter: division, event_type)
  • POST /admin/schedule/events creates an event
  • PUT /admin/schedule/events/{id} updates an event
  • DELETE /admin/schedule/events/{id} deletes an event
  • All endpoints are tenant-scoped and admin-authenticated

Test Expectations

  • Happy path tests for all 9 endpoints
  • Tenant isolation: can't read/modify other tenant's schedule data
  • Filter tests: division filter, event_type filter, is_active filter on practices
  • 404 on non-existent practice/event ID
  • Validation: required fields enforced by Pydantic schemas
  • Run command: pytest tests/test_schedule.py -v

Constraints

  • Follow routes/jersey.py pattern for file structure (APIRouter, inline Pydantic models, dependency injection)
  • Tenant scoping via same dependency used in routes/admin.py
  • Return proper HTTP status codes: 201 for create, 200 for read/update, 204 for delete
  • Pydantic response schemas should map Division enum values to display labels in a program field (boys→"Kings", girls→"Queens") for frontend convenience

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • Blocked until #232 merges
  • Parent: forgejo_admin/basketball-api#230
  • Sibling: forgejo_admin/basketball-api#232 (data model — BLOCKER)
  • project-westside-basketball
  • Follow-up: Admin schedule view in westside-app
### Type Feature ### Lineage Child of `forgejo_admin/basketball-api#230` (decomposed parent). Depends on #232 (data model). ### Repo `forgejo_admin/basketball-api` ### User Story `story:WS-S13` As an admin, I want API endpoints to create, read, update, and delete schedule entries so that the admin frontend can manage practices and events. ### Context This ticket adds the API layer for schedule management. The data model and tables are created in sibling ticket #232 — this ticket depends on that landing first. **Key design decisions (from review of #230):** - New `routes/schedule.py` file — `admin.py` is 1048 lines, and the codebase has precedent for dedicated route files (jersey.py, checkout.py, coaches_api.py). - Pydantic schemas defined inline in the route file (no separate schemas.py — matches codebase convention). - All endpoints admin-auth + tenant-scoped (matching existing admin route patterns). - Division filter uses existing `Division(boys/girls)` enum. ### File Targets Files to create or modify: - `src/basketball_api/routes/schedule.py` — NEW file. Admin CRUD endpoints with inline Pydantic schemas. - `src/basketball_api/main.py` — register the schedule router - `tests/test_schedule.py` — NEW file. Endpoint tests. Pattern reference (do NOT modify): - `src/basketball_api/routes/admin.py` — tenant scoping pattern, auth dependency injection - `src/basketball_api/routes/jersey.py` — dedicated route file pattern, inline schemas - `src/basketball_api/routes/checkout.py` — another dedicated route file example Files NOT to touch: - `src/basketball_api/models.py` — already handled by #232 - `alembic/` — already handled by #232 ### Acceptance Criteria - [ ] `GET /admin/schedule` returns combined `{ practices: [...], events: [...] }` - [ ] `GET /admin/schedule/practices` lists practice schedules (filter: division, is_active) - [ ] `POST /admin/schedule/practices` creates a practice schedule - [ ] `PUT /admin/schedule/practices/{id}` updates a practice schedule - [ ] `DELETE /admin/schedule/practices/{id}` deletes a practice schedule - [ ] `GET /admin/schedule/events` lists events (filter: division, event_type) - [ ] `POST /admin/schedule/events` creates an event - [ ] `PUT /admin/schedule/events/{id}` updates an event - [ ] `DELETE /admin/schedule/events/{id}` deletes an event - [ ] All endpoints are tenant-scoped and admin-authenticated ### Test Expectations - [ ] Happy path tests for all 9 endpoints - [ ] Tenant isolation: can't read/modify other tenant's schedule data - [ ] Filter tests: division filter, event_type filter, is_active filter on practices - [ ] 404 on non-existent practice/event ID - [ ] Validation: required fields enforced by Pydantic schemas - Run command: `pytest tests/test_schedule.py -v` ### Constraints - Follow `routes/jersey.py` pattern for file structure (APIRouter, inline Pydantic models, dependency injection) - Tenant scoping via same dependency used in `routes/admin.py` - Return proper HTTP status codes: 201 for create, 200 for read/update, 204 for delete - Pydantic response schemas should map Division enum values to display labels in a `program` field (boys→"Kings", girls→"Queens") for frontend convenience ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes - [ ] Blocked until #232 merges ### Related - Parent: `forgejo_admin/basketball-api#230` - Sibling: `forgejo_admin/basketball-api#232` (data model — BLOCKER) - `project-westside-basketball` - Follow-up: Admin schedule view in westside-app
Author
Owner

Scope Review: READY

Review note: review-630-2026-03-28

All template sections present and complete. Traceability triangle verified (story:WS-S13, arch:basketball-api, Forgejo #233). All file targets confirmed against codebase -- pattern references (jersey.py structure, admin.py auth, checkout.py) validated. Blocker #232 documented in labels and body. No blast radius concerns -- clean greenfield, no existing schedule route code. 10 AC is on the upper boundary but mechanical CRUD with strong pattern precedent. No decomposition needed.

## Scope Review: READY Review note: `review-630-2026-03-28` All template sections present and complete. Traceability triangle verified (story:WS-S13, arch:basketball-api, Forgejo #233). All file targets confirmed against codebase -- pattern references (jersey.py structure, admin.py auth, checkout.py) validated. Blocker #232 documented in labels and body. No blast radius concerns -- clean greenfield, no existing schedule route code. 10 AC is on the upper boundary but mechanical CRUD with strong pattern precedent. No decomposition needed.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/basketball-api#233
No description provided.