Review: Migration: add monthly ProductCategory, first_payment EmailType, seed prorated product

review-873-2026-04-06 Doc

review ready

Verdict: READY

Scope is solid. All file targets verified against codebase. Single-repo, single-agent pass. One minor traceability gap (missing arch note) does not block execution.

Template Completeness

  • [x] Type — Feature
  • [x] Lineage — decomposed from #366, Ticket A of 3
  • [x] Repo — forgejo_admin/basketball-api
  • [x] User Story — clear developer-facing story for schema prerequisite
  • [x] Context — explains why enum values and product row are needed before tickets B and C
  • [x] File Targets — 2 files to modify, 1 to create, with line numbers
  • [x] Acceptance Criteria — 5 testable conditions
  • [x] Test Expectations — unit + integration tests, run command provided
  • [x] Constraints — migration ordering, Postgres enum safety, idempotency patterns
  • [x] Checklist — PR, tests, no unrelated changes
  • [x] Related — project, parent issue, spec, plan reference

Traceability

  • [x] story:WS-S7 — "As an admin, I want to send branded email announcements so that parent comms are professional and consistent" (verified in project-westside-basketball user-stories section, Admin list)
  • [x] arch:basketball-api — basketball-api component label present
  • [ ] arch note MISSING — [SCOPE] Create architecture note arch-basketball-api for component basketball-api (platform-wide gap, does not block this ticket)
  • [x] Forgejo issue — forgejo_admin/basketball-api#367, open

File Targets

  • [x] src/basketball_api/models.py:63-70 — verified: EmailType enum at lines 63-70, interest_notification at line 70. Correct insertion point for first_payment.
  • [x] src/basketball_api/models.py:123-128 — verified: ProductCategory enum at lines 123-128, equipment at line 127. Correct insertion point for monthly.
  • [x] alembic/versions/031_add_monthly_category_and_first_payment_email.py — verified: 031 slot is free. Latest migration is 030_add_registration_type_to_registrations.py. No collision.

Repo Placement

OK. Issue filed on basketball-api, all file targets within basketball-api. Single repo, no cross-repo concerns.

Dependencies

  • [x] Parent: forgejo_admin/basketball-api#366 (board #872, backlog) — decomposition parent, not a blocker for this child ticket
  • [x] Downstream: #368 (board #874, Ticket B — checkout endpoint) depends on this migration completing first
  • [x] Downstream: #369 (board #875, Ticket C — email + blast) depends on this migration completing first
  • [x] In-progress: #274 (board #733, fixing 9 jersey/checkout tests) — no conflict with enum/migration work
  • Dependencies are documented in the Lineage section of the issue. No unresolved blockers.

Acceptance Criteria

5 AC, all verifiable programmatically by an agent:
  • Enum membership: ProductCategory.monthly and EmailType.first_payment — testable via Python assert
  • Product row seed: queryable via SQL or ORM after migration
  • Migration apply: alembic upgrade head — concrete command
  • Migration downgrade: product row removal verified, enum values persist (Postgres limitation documented)
No ambiguous criteria. All are specific and testable.

Blast Radius

Low. Adding new enum values is additive-only — no existing code paths break.
  • EmailType consumed by services/email.py and services/jersey_sync.py — neither references the new values, so no breakage
  • ProductCategory consumed by services/jersey_sync.py — same, no breakage from new member
  • Rollback is straightforward: downgrade removes product row; enum values remain but are harmless

Decomposition Assessment

No decomposition needed.
  • 2 files to modify + 1 file to create = 3 file targets in 1 repo — within three-thing limit
  • 5 acceptance criteria — at the limit but each is trivial to verify
  • Estimated agent work: <5 minutes — within five-minute rule
  • No independent subtasks that warrant parallelization

Recommendation

  • [SCOPE] Create architecture note arch-basketball-api for the basketball-api component. This is a platform-wide gap affecting many tickets, not specific to this one. Does not block execution.
No other actions needed. Ticket is ready for agent dispatch.