Contract reminder email endpoint #270

Closed
opened 2026-03-31 00:45:19 +00:00 by forgejo_admin · 0 comments

Type

Feature

Lineage

Standalone — discovered during contract signing push for April 2 deadline. Sandra Apaisa fee negotiation ($175/mo for 3 girls) already applied to DB.

Repo

forgejo_admin/basketball-api

User Story

As Marcus,
I want to send contract reminder emails to parents who haven't signed,
So that we can finalize rosters by April 2nd.

Context

16 of 52 rostered players have signed contracts (29%). 17U Elite Queens is at 0%. Season starts April 6. Need a reusable endpoint to send reminder emails — this will be used multiple times as the deadline approaches.

The jersey-reminder endpoint (POST /email/jersey-reminder at admin.py:847) is the pattern to follow. Same test_email param, same email_log audit trail, same gmail_sdk send path.

Contract link format: https://westside-contracts.tail5b443a.ts.net/contract/{contract_token}

Template tone: friendly nudge — "we noticed you haven't signed yet, let us know what we can do to help." Include April 2 deadline. Match existing Westside dark branding (dark bg, pink accents, rgb(233,30,140)).

Multi-player parents (e.g. Sandra Apaisa with 3 girls) must receive ONE email listing all unsigned players with individual contract links.

File Targets

Files the agent should modify or create:

  • src/basketball_api/routes/admin.py — add POST /email/contract-reminder endpoint following jersey-reminder pattern
  • src/basketball_api/services/email.py — add send_contract_reminder_email() function, use existing load_email_template() pattern
  • data/email-templates/contract-reminder.html — HTML email template matching Westside dark branding
  • tests/test_contract_reminder.py — endpoint and email function tests

Files the agent should NOT touch:

  • src/basketball_api/routes/jersey.py — unrelated
  • src/basketball_api/routes/checkout.py — unrelated
  • Contract signing flow in westside-contracts repo — out of scope

Acceptance Criteria

  • POST /email/contract-reminder?test_email=draneylucas@gmail.com sends test email to specified address
  • POST /email/contract-reminder (no param) sends to all parents of unsigned rostered players
  • Multi-player parents receive single grouped email with per-player contract links
  • Each player's contract link uses correct contract_token
  • Emails logged to email_log table
  • Template matches Westside dark branding (dark bg, pink accents)
  • Players with no team are excluded
  • Test records excluded from prod blast

Test Expectations

  • Unit test: contract reminder groups players by parent correctly
  • Unit test: template renders with player name, team, contract link, monthly fee
  • Integration test: endpoint returns 200 with test_email param
  • Integration test: email_log entry created after send
  • Run command: pytest tests/test_contract_reminder.py -v

Constraints

  • Follow existing jersey-reminder pattern in admin.py and email.py
  • Use gmail_sdk for sending (same as all other emails)
  • Use load_email_template() pattern for template loading
  • Log to email_log with type contract_reminder

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • westside-basketball — project this affects
### Type Feature ### Lineage Standalone — discovered during contract signing push for April 2 deadline. Sandra Apaisa fee negotiation ($175/mo for 3 girls) already applied to DB. ### Repo `forgejo_admin/basketball-api` ### User Story As Marcus, I want to send contract reminder emails to parents who haven't signed, So that we can finalize rosters by April 2nd. ### Context 16 of 52 rostered players have signed contracts (29%). 17U Elite Queens is at 0%. Season starts April 6. Need a reusable endpoint to send reminder emails — this will be used multiple times as the deadline approaches. The jersey-reminder endpoint (`POST /email/jersey-reminder` at admin.py:847) is the pattern to follow. Same test_email param, same email_log audit trail, same gmail_sdk send path. Contract link format: `https://westside-contracts.tail5b443a.ts.net/contract/{contract_token}` Template tone: friendly nudge — "we noticed you haven't signed yet, let us know what we can do to help." Include April 2 deadline. Match existing Westside dark branding (dark bg, pink accents, rgb(233,30,140)). Multi-player parents (e.g. Sandra Apaisa with 3 girls) must receive ONE email listing all unsigned players with individual contract links. ### File Targets Files the agent should modify or create: - `src/basketball_api/routes/admin.py` — add `POST /email/contract-reminder` endpoint following jersey-reminder pattern - `src/basketball_api/services/email.py` — add `send_contract_reminder_email()` function, use existing `load_email_template()` pattern - `data/email-templates/contract-reminder.html` — HTML email template matching Westside dark branding - `tests/test_contract_reminder.py` — endpoint and email function tests Files the agent should NOT touch: - `src/basketball_api/routes/jersey.py` — unrelated - `src/basketball_api/routes/checkout.py` — unrelated - Contract signing flow in westside-contracts repo — out of scope ### Acceptance Criteria - [ ] `POST /email/contract-reminder?test_email=draneylucas@gmail.com` sends test email to specified address - [ ] `POST /email/contract-reminder` (no param) sends to all parents of unsigned rostered players - [ ] Multi-player parents receive single grouped email with per-player contract links - [ ] Each player's contract link uses correct `contract_token` - [ ] Emails logged to `email_log` table - [ ] Template matches Westside dark branding (dark bg, pink accents) - [ ] Players with no team are excluded - [ ] Test records excluded from prod blast ### Test Expectations - [ ] Unit test: contract reminder groups players by parent correctly - [ ] Unit test: template renders with player name, team, contract link, monthly fee - [ ] Integration test: endpoint returns 200 with test_email param - [ ] Integration test: email_log entry created after send - Run command: `pytest tests/test_contract_reminder.py -v` ### Constraints - Follow existing jersey-reminder pattern in admin.py and email.py - Use `gmail_sdk` for sending (same as all other emails) - Use `load_email_template()` pattern for template loading - Log to `email_log` with type `contract_reminder` ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes ### Related - `westside-basketball` — project this affects
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/basketball-api#270
No description provided.