feat: Queens pink palette for girls first-payment emails #415
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!415
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "413-queens-pink-email"
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
Girls division players now receive first-payment emails with the Queens pink accent (
#e91e8c) instead of Kings red (#d42026). Boys division and all other email types remain unchanged.Changes
src/basketball_api/brand.py— addedCOLOR_QUEENS_PINKandCOLOR_QUEENS_PINK_HOVERconstants after the existing Kings reds.src/basketball_api/services/email.py:_BRAND_QUEENS_PINK = "#e91e8c"next to_BRAND_RED._brand_wrapper()now takes an optionalaccent_colorkwarg (defaults to_BRAND_RED); the 3px header bottom border uses it. All 10 existing callers are unaffected thanks to the default value.send_first_payment_email()selects accent based onplayer.division: Queens pink forDivision.girls, brand red otherwise. The accent is threaded through the h3 color, CTA button background, player-name<strong>highlight, and the_brand_wrappercall.Divisionto the existingbasketball_api.modelsimport block.tests/test_first_payment_email.py— two new tests asserting the correct hex color appears (and the other does not) for girls and boys division players.Backward Compatibility
The 10 other
_brand_wrapper()callers (jersey-reminder, profile-reminder, roster-export, tryout-announcement, contract-signed, etc.) are unchanged — they continue to use_BRAND_REDvia the default parameter.Review Checklist
ruff formatcleanruff checkclean_brand_wrapper(accent_color=...)send_first_payment_emailmodified; no other email builders touchedmainTest Plan
ruff formatandruff checkon all modified files — cleanpytest tests/test_first_payment_email.py -v— 7/7 passed (including both new tests)mainbefore this branch's changes)Related Notes
src/basketball_api/brand.pysrc/basketball_api/services/email.pysrc/basketball_api/models.py(Division.boys,Division.girls)Related
PR #415 Review
DOMAIN REVIEW
Stack: Python / SQLAlchemy / email rendering (basketball-api). Applied Python/PEP + OWASP + SQLAlchemy lens.
Diff surface: 3 files, +62/-6. Changes are tightly scoped:
brand.py: two new color token constants added after existing Kings reds. Matches acceptance criteria exactly (#e91e8c/#f23d9e).services/email.py:_BRAND_QUEENS_PINKconstant,_brand_wrapper()grows optionalaccent_color: str = _BRAND_REDkwarg (backward compatible default), header border now usesaccent_color, andsend_first_payment_email()threads the accent through h3, CTA button, player-name<strong>, and the wrapper call.Divisionadded to the existingbasketball_api.modelsimport block.tests/test_first_payment_email.py: two new tests — girls asserts#e91e8cpresent and#d42026absent; boys asserts the inverse.Caller safety (critical check): Verified against local
main. The seven other_brand_wrapper(...)call sites (lines 508, 635, 830, 1071, 1294, 1398, plus the def) are NOT modified by the diff — only line 963 (first_payment) gains theaccent_color=accentkwarg. The new parameter defaults to_BRAND_RED, so every untouched caller renders identically. No unintended visual regressions for jersey-reminder, profile-reminder, roster-export, tryout-announcement, contract-signed, etc. (Note: PR body says "10 other callers" but the actual count in source is 7. Cosmetic PR-body inaccuracy, not a code issue.)None-division safety:
Player.divisionisMapped[Division | None](nullable). The expressionplayer.division == Division.girlsevaluates toFalsewhendivision is None, cleanly falling through to_BRAND_RED. No crash, no implicit coercion. Kings players (boys or null) correctly get red/black.Circular import:
Divisionis added to the already-existingfrom basketball_api.models import (...)block. Sincemodelsis already imported byservices/email.py, there is zero new import surface — no circular risk.Color propagation audit in
send_first_payment_email: accent flows to (1) h3 color, (2) CTA background, (3)<strong>player-name highlight, (4) wrapper header border. I checked the rest of the function for stray_BRAND_REDreferences in the first-payment builder — none remain inside this function's body. No other email builder function was touched by the diff.PEP / Ruff: Signature change is formatted across lines cleanly, type hint on the new kwarg is correct (
str), default is a module-level constant (not a mutable default). PR body confirmsruff formatandruff checkclean.Test quality: Both new tests use the existing
parent_and_playerfixture, mockget_gmail_client, mutateplayer.division, and do positive+negative hex assertions. Hex-in-HTML assertion is reasonable since the colors appear inline via f-strings. Covers both branches of the new conditional. Good coverage for a visual branding change.BLOCKERS
None.
NITS
_accent_for_division(division) -> strif Queens pink expands to other email types later — not needed for this PR since only one caller branches on division today. YAGNI holds.assert "#d42026" not in htmlin the girls test is strict and correct given the current template, but will become fragile if anyone ever hardcodes another red somewhere in the wrapper footer. Acceptable for now; the strictness is actually a feature that will catch regressions.SOP COMPLIANCE
413-queens-pink-email)ruff format/ruff checkclean per PR bodyPROCESS OBSERVATIONS
Textbook small, reviewable change. High DF impact (fast to land), near-zero CFR risk (default-parameter refactor, single caller changed, two-branch test coverage). Documentation-ready: the constants live in
brand.pywhere the convention says brand tokens live, so future Queens surfaces (web, contracts, jerseys) can importCOLOR_QUEENS_PINKdirectly. Good foundation if girls-division branding expands beyond first-payment emails.VERDICT: APPROVED