Review: Baby Betty contradictory jersey state (manual data fix)
Verdict: NEEDS_REFINEMENT
Template Completeness
- [x] Type
- [x] Lineage — standalone, split from #170
- [x] Repo
- [x] What Broke — thorough description with SQL evidence
- [x] Repro Steps — concrete SQL queries
- [x] Expected Behavior
- [x] Environment
- [x] Acceptance Criteria — 3 items, all SQL-verifiable
- [x] Constraints — bonus section, good detail
- [x] Related — links #170 and project
Traceability
- [ ] story:X label — missing. Acceptable: this is an operational data fix, not a user-facing story.
- [x] arch:stripe-webhook — present on board item #393
- [x] Forgejo issue —
forgejo_admin/basketball-api#171, open
File Targets
N/A — ticket explicitly states "this is a manual data fix, not a code change." No file targets to verify. Confirmed the schema claims against the codebase:
- [x]
players.jersey_option— Enum(JerseyOption) at models.py:208, values: reversible, jersey_warmup, opt_out - [x]
players.jersey_order_status— Enum(JerseyOrderStatus) at models.py:209, values: none, pending, paid, shipped - [x]
orders.status— Enum(OrderStatus) at models.py:355, values: pending, paid, refunded, canceled - [x] Legacy opt-out path at jersey.py:264 sets
jersey_option = opt_outfor all parent's players - [x] Legacy checkout at jersey.py:319 sets
jersey_order_status = pendingfor all parent's players
Repo Placement
OK. Issue filed on
forgejo_admin/basketball-api which owns the database. Manual SQL fix targets the same database. No cross-repo concern.Dependencies
- #170 (webhook sync gap) — parent bug, board item #392, status: done. The code fix (
jersey_sync.py) is already merged. No blocker. - #308 (reconciliation script) — in
next_up. Related but independent — that ticket builds a general reconciliation tool. This ticket is a one-off manual fix. No blocker.
Acceptance Criteria
3 criteria, all verifiable via SQL SELECT after the fix:
- [x]
playersrecord for id=161:jersey_option = NULL, jersey_order_status = none— verifiable - [x]
ordersrecord #14:status = canceled— verifiable - [x] Verified via SQL query after fix — verifiable
Criteria are clear and testable. Note: acceptance criterion 1 says
jersey_option = NULL which is valid (nullable column, models.py:208 confirms nullable=True).Blast Radius
ISSUE FOUND: The legacy jersey routes operate on ALL players under a parent (
for p in parent.players at jersey.py:263-265 and jersey.py:318-319). If Baby Betty (id=161) shares a parent with sibling players, those siblings may also have contradictory state from the same legacy checkout flow. The ticket only addresses player id=161 — sibling players are not checked or fixed.The executing agent should run:
If siblings exist with the same contradictory state, the fix SQL must include them.
Decomposition
No decomposition needed. 0 file targets, 3 acceptance criteria, estimated <2 minutes of agent work (SQL transaction).
Recommendation
One refinement needed before READY:
- Add sibling player check to acceptance criteria. The legacy code operates on all players under a parent. Add a criterion: "Verified no sibling players under the same parent have contradictory jersey state. If they do, fix them in the same transaction." This prevents a partial fix that leaves related data inconsistent.
Once the sibling check is added to the Forgejo issue, this ticket is READY.