Tournament product creation + per-player Stripe checkout links #457
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#457
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 — discovered during Utah Invitational tournament fee billing (2026-04-12). Related to generic blast system (sibling ticket #456). Product model supports
category='tournament'but no admin endpoints or per-player checkout orchestration exists.Repo
forgejo_admin/basketball-apiUser Story
As an admin
I want to bill players for tournament entry fees at team-specific rates via Stripe
So that event costs are collected before registration deadlines
Context
ProductCategory.tournamentexists (models.py L126) andProductType.one_timeexists (L117-120), but there's no admin endpoint to create tournament products with team-specific pricing. Current checkout flow (routes/checkout.pyL103POST /create-session) is self-service — parent clicks a generic product link. Tournament billing needs admin-driven: create products per team/price tier, generate unique Stripe checkout URLs per player, embed those URLs in blast emails via{{checkout_url}}placeholder. First consumer: Utah Invitational (17U Elite $55, 17U Select $65, 16U Elite $55).File Targets
Files the agent should modify or create:
src/basketball_api/models.py— AddTournamentmodel (id, name, event_date, description, created_at) andTournamentProductjoin table (tournament_id, product_id, team_id).alembic/versions/NNN_add_tournament_tables.py— NEW. Determine the next available migration number from remote main HEAD (do NOT hardcode — checkalembic/versions/for the latest slot).src/basketball_api/routes/admin.py— AddPOST /admin/tournaments(create tournament with team-specific products in one call) andPOST /admin/tournaments/{id}/checkout-links(generate per-player Stripe checkout URLs).src/basketball_api/routes/checkout.py— Addcreate_player_checkout_session(player, product)helper extracted from existing create-session logic.Files the agent should NOT touch:
services/email.py— email blast is separate ticket #456services/email_queries.py— query registry is separate ticket #456POST /create-sessionendpoint — keep self-service flow untouchedAcceptance Criteria
POST /admin/tournamentscreates tournament + N products (one per team/price) in one callPOST /admin/tournaments/{id}/checkout-linksreturns{player_id: checkout_url}mapcategory='tournament',type='one_time'GET /admin/tournaments/{id}with invalid ID returns 404POST /admin/tournaments/{id}/checkout-linksfor player not on any tournament team returns 400 with clear messageTest Expectations
pytest tests/ -k "tournament"Constraints
ProductCategory.tournamentalready exists — no enum migration neededChecklist
Related
project-westside-basketball— parent projectstory:WS-S33— user storytournament_committedquery and{{checkout_url}}placeholdersop-email-send— blast gate for actual sendsScope Review: NEEDS_REFINEMENT
Review note:
review-994-2026-04-12Ticket is well-structured with all template sections present, verified user story (WS-S33), and clear file targets. Three issues need fixing before this moves to next_up:
032is wrong. Local repo has up to 030, but merged PRs reference 040-044 on remote main. Replace with instruction to use next available migration slot from remote main HEAD.arch:emailis a mislabel. This ticket is about Stripe checkout + tournament product models, not email. The email blast is explicitly the sibling ticket (#456). Change toarch:basketball-apiorarch:checkouton board item #994.Scope refinement from review-994-2026-04-12 (NEEDS_REFINEMENT):
Three fixes applied to issue body:
Migration number — Changed from hardcoded
032toNNNwith instruction to determine next available slot from remote main HEAD. Remote main has migrations up to 044; hardcoding would cause collision.Arch label — Changed board item from
arch:emailtoarch:checkout. This ticket creates Tournament models and Stripe checkout orchestration, not email infrastructure (that's #456).Error-path acceptance criteria — Added three edge cases: 404 for invalid tournament ID, 400 for player without matching team product, and idempotent/409 behavior for duplicate checkout-link generation.
Scope Review: NEEDS_REFINEMENT (re-review v2)
Review note:
review-994-2026-04-12-v2Re-review of board item #994. Previous review flagged 3 issues — only 1 was fixed.
Previous Findings Status
032. Remote main has migrations up to 044; next available slot is at least 045. Replace with instruction to use next available slot from remote main HEAD.Additional Finding
arch-checkoutnote exists in pal-e-docs. Create architecture note for the checkout/commerce component (non-blocking).Two
[BODY]fixes remain before this ticket is READY.