Email function + blast endpoint: send_first_payment_email + POST /admin/email/first-payment #369
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#369
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
Decomposed from
forgejo_admin/basketball-api#366. Ticket C of 3 — depends on A (migration, merged as PR #370). Independent of B (checkout endpoint).Repo
forgejo_admin/basketball-apiUser Story
As an admin (Marcus)
I want to blast a branded payment email to all parents who signed contracts
So that they receive a personalized Stripe payment link for their prorated first monthly fee
Context
Send date: Wednesday April 8, 8:00 AM — after the first practice (Tuesday April 7). Email framing is post-practice: "Great first practice! Here's how billing works."
Two components: (1)
send_first_payment_email()inservices/email.pybuilds a branded HTML email using_brand_wrapper()with per-player CTA linking to the checkout endpoint. (2)POST /admin/email/first-paymentinroutes/admin.pyqueries allcontract_status=signedplayers and sends the email to each, with atest_emailsafety param.Email tone: Friendly-firm, Marcus voice. Post-practice energy. Clearly explain:
Email framing (post-practice, not pre-practice):
CTA links to
{base_url}/checkout/first-payment?token={contract_token}— this is basketball-api's base_url, NOT frontend_url, because it's a redirect endpoint.File Targets
Files to modify:
src/basketball_api/services/email.py— add_calculate_prorated_fee()helper andsend_first_payment_email()function (before the MJML template loader section ~line 1102)src/basketball_api/routes/admin.py— addFirstPaymentBlastResponseschema andPOST /admin/email/first-paymentendpoint (after jersey-reminder ~line 895), addsend_first_payment_emailto imports, addContractStatusto model importsFiles to create:
tests/test_first_payment_email.py— email function teststests/test_first_payment_blast.py— blast endpoint tests (needs localadmin_clientfixture with auth override, same pattern astests/test_players.py:84)Files NOT to touch:
src/basketball_api/routes/checkout.py— that's ticket Bsrc/basketball_api/routes/webhooks.py— no changes neededAcceptance Criteria
send_first_payment_email()sends branded HTML email with player name, prorated amount, and checkout CTA{base_url}/checkout/first-payment?token={contract_token}email_type=EmailType.first_paymentPOST /admin/email/first-paymentsends to allcontract_status=signedplayerstest_emailparam restricts blast to one parent's players{ sent_count, errors }Test Expectations
first_paymenttypepytest tests/test_first_payment_email.py tests/test_first_payment_blast.py -vConstraints
_brand_wrapper()pattern (Westside red/black palette)admin.py:847-895admin_clientfixture must be defined in test file (not in conftest) — same pattern astest_players.py:84get_gmail_clientin email tests (@patch("basketball_api.services.email.get_gmail_client"))send_first_payment_emailin blast tests (@patch("basketball_api.routes.admin.send_first_payment_email"))Checklist
Related
westside-basketball— projectforgejo_admin/basketball-api#366~/pal-e-platform/docs/superpowers/plans/2026-04-06-first-payment-email.md(Tasks 3 + 4)Scope Review: READY
Review note:
review-875-2026-04-06Scope is solid — all template sections present, file targets verified against codebase, traceability triangle complete (story:WS-S7 confirmed on project page). Hard dependency on #367 (migration) correctly documented. 9 AC are concrete and machine-verifiable. Single-repo, follows established blast pattern. No decomposition needed.
[SCOPE] arch-basketball-api and arch-email notes do not exist in pal-e-docs (pre-existing platform gap, not a blocker).
Scope update (2026-04-06): Email timing changed from pre-practice (April 7) to post-practice (Wednesday April 8, 8:00 AM). Framing flipped to "Great first practice!" tone. Added requirements to explain proration in plain language and inform parents that their card will be saved for automatic monthly billing on the 1st. Subject line updated accordingly.