feat: tryout day -- roster, check-in, walk-ups #47
No reviewers
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!47
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "46-tryout-day-roster-checkin"
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?
Summary
Implements tryout-day functionality for March 13: mobile coach roster with photo cards, printable roster table, admin check-in dashboard with live status updates, idempotent tryout number assignment, and Stripe payment redirect.
Changes
src/basketball_api/routes/tryouts.py(new): All tryout-day endpoints -- /pay redirect, assign-numbers, coach roster cards, print table, admin dashboard, check-in POSTsrc/basketball_api/main.py: Register tryouts routertests/test_tryouts.py(new): 20 tests covering all endpoints -- redirect, idempotent assignment, auth enforcement, HTML validation, 404 handlingTest Plan
pytest --collect-only tests/test_tryouts.py-- 20 tests collectedruff check src/ tests/-- All checks passed/tryouts/roster/westside-kings-queenson mobile to verify card layout/tryouts/roster/westside-kings-queens/printto verify table formatting/tryouts/admin/westside-kings-queensReview Checklist
Related
plan-2026-03-08-tryout-prepAdd tryout-day endpoints for coach roster (mobile cards with search/filter), print-optimized roster table, admin check-in dashboard with live status, idempotent tryout number assignment, and Stripe payment redirect. Endpoints: - GET /pay -> 302 to Stripe checkout - POST /tryouts/admin/{slug}/assign-numbers (auth, idempotent) - GET /tryouts/roster/{slug} (public, noindex, mobile-first cards) - GET /tryouts/roster/{slug}/print (public, print-optimized table) - GET /tryouts/admin/{slug} (auth, admin check-in dashboard) - POST /tryouts/admin/{slug}/checkin/{id} (auth, mark checked in) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>PR #47 Review
Title: feat: tryout day -- roster, check-in, walk-ups
Branch:
46-tryout-day-roster-checkin->mainScope: 4 files changed, +1077 lines, 0 deletions
BLOCKERS
None.
NITS
Duplicated Stripe payment link default. The PR adds
stripe_tryout_linktoconfig.pywith a default value ofhttps://buy.stripe.com/aFa8wRbky5KwgL0bI60VO01. Meanwhile,src/basketball_api/routes/register.py:41still has the same URL hardcoded asSTRIPE_TRYOUT_LINK. The PR body explicitly states it does not modifyregister.py, and this is not a regression, but the duplication will drift over time. Consider a follow-up to haveregister.pyalso read fromsettings.stripe_tryout_link.Coach roster and print view are public (no auth). The docstring on
tryout_roster()says "Public-but-unlisted: no auth required, noindex meta tag." This is a deliberate design choice and thenoindexmeta tag is present. Just confirming this is intentional -- anyone with the URL can see player names, ages, schools, positions, heights, and photos.No un-check-in endpoint. The
checkin_playerendpoint setschecked_in = Trueand is idempotent, but there is no way to undo a check-in via the API. Not a blocker for tryout day MVP, but worth noting if accidental check-ins happen.Admin dashboard queries all players (no Registration join). Unlike the coach roster and print view which join on Registration, the admin dashboard loads all players for the tenant. This means players without a Registration record appear in the admin view. This appears intentional (to spot walk-ups or data issues), but the behavior difference is worth documenting.
Stripe link is a public payment link, not a secret. The
buy.stripe.comURL is a Stripe Payment Link -- it is designed to be shared publicly and contains no secret material. Storing it inconfig.pyas a default is fine. No credential leak concern here.SOP COMPLIANCE
46-tryout-day-roster-checkinreferences issue #46)plan-2026-03-08-tryout-prepCloses #46tests/test_tryouts.py).envfiles, or credentials committedregister.pyormodels.py(per issue constraint stated in PR body)/tenants/{slug}/roster)CODE QUALITY NOTES
html.escape()on all user-supplied data in templates. No XSS vectors found.basketball_api.brand-- visual consistency maintained.require_role("admin")at module level so tests can override it cleanly. Same pattern asadmin.py._get_tenant_or_404helper avoids code duplication across endpoints._calc_agehelper handlesNoneDOB gracefully.fetch()for check-in with proper error handling (button disable, re-enable on failure, alert on error)._clean_all) and theadmin_client/public_clientseparation correctly validates auth enforcement.VERDICT: APPROVED