Warm up welcome email copy + fix null team edge case #404

Open
opened 2026-04-08 22:20:03 +00:00 by forgejo_admin · 0 comments
Contributor

Type

Feature

Lineage

Standalone — discovered during post-signing user flow investigation (2026-04-08).

Repo

forgejo_admin/basketball-api

User Story

As a parent who just signed their kid's contract
I want a warm, personal welcome email that tells me exactly what to do next
So that I feel connected to the team and know to join GroupMe immediately

Context

Current email copy is functional but generic:

"Congratulations! {player_name} is officially part of {team_name}. The contract has been signed and we're excited to have you on board!"

Desired tone (per Lucas):

"Hey, great to have you officially signed on... please join your team's GroupMe so you can stay up to date on everything!"

The GroupMe CTA should be more urgent/clear — it's the primary communication channel for game updates, practice changes, and tournament logistics. Parents who don't join miss critical info.

Also: Outbox event #13 (Creed Draney Jr) has team_id=11 which doesn't exist (teams are 1–7). The processor falls back to "Westside Kings & Queens" with no GroupMe link. The email template should handle missing teams more explicitly, and the contract signing flow should validate team_id before writing to outbox.

File Targets

Files the agent should modify:

  • src/basketball_api/services/email.py — update send_contract_signed_email() HTML template (~lines 932-961) and plain text fallback (~lines 966-973)
  • src/basketball_api/services/outbox.py — add validation: warn if team_id in payload doesn't resolve to a real team

Files the agent should NOT touch:

  • k8s/ — infrastructure changes are in the outbox bug ticket
  • src/basketball_api/models.py — schema changes are in the GroupMe tracking ticket

Acceptance Criteria

  • Email subject and body use warmer, more personal tone
  • GroupMe CTA is prominent and explains WHY to join ("stay up to date on games, practices, and tournaments")
  • Plain text fallback matches HTML tone
  • Lucas approves final template on phone (draneylucas@gmail.com test send)
  • Outbox processor logs a clear warning when team_id doesn't resolve (not silent fallback)

Test Expectations

  • Unit test: email renders with valid team + GroupMe URL
  • Unit test: email renders gracefully with missing team (fallback org name, no GroupMe button)
  • Test send to draneylucas@gmail.com for visual approval
  • Run command: pytest tests/ -k contract_signed_email

Constraints

  • Email is MJML-based HTML — maintain existing responsive design patterns
  • Must pass Gmail rendering (no broken layouts on mobile Gmail app)
  • No changes to email sending infrastructure — copy/template only
  • Lucas must approve before any real sends (per email blast gate)

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • westside-basketball — project this affects
  • src/basketball_api/services/email.py:888-1010 — current template
  • src/basketball_api/services/outbox.py:62-110 — team resolution logic
### Type Feature ### Lineage Standalone — discovered during post-signing user flow investigation (2026-04-08). ### Repo `forgejo_admin/basketball-api` ### User Story As a parent who just signed their kid's contract I want a warm, personal welcome email that tells me exactly what to do next So that I feel connected to the team and know to join GroupMe immediately ### Context Current email copy is functional but generic: > "Congratulations! {player_name} is officially part of {team_name}. The contract has been signed and we're excited to have you on board!" Desired tone (per Lucas): > "Hey, great to have you officially signed on... please join your team's GroupMe so you can stay up to date on everything!" The GroupMe CTA should be more urgent/clear — it's the primary communication channel for game updates, practice changes, and tournament logistics. Parents who don't join miss critical info. **Also:** Outbox event #13 (Creed Draney Jr) has `team_id=11` which doesn't exist (teams are 1–7). The processor falls back to "Westside Kings & Queens" with no GroupMe link. The email template should handle missing teams more explicitly, and the contract signing flow should validate team_id before writing to outbox. ### File Targets Files the agent should modify: - `src/basketball_api/services/email.py` — update `send_contract_signed_email()` HTML template (~lines 932-961) and plain text fallback (~lines 966-973) - `src/basketball_api/services/outbox.py` — add validation: warn if team_id in payload doesn't resolve to a real team Files the agent should NOT touch: - `k8s/` — infrastructure changes are in the outbox bug ticket - `src/basketball_api/models.py` — schema changes are in the GroupMe tracking ticket ### Acceptance Criteria - [ ] Email subject and body use warmer, more personal tone - [ ] GroupMe CTA is prominent and explains WHY to join ("stay up to date on games, practices, and tournaments") - [ ] Plain text fallback matches HTML tone - [ ] Lucas approves final template on phone (draneylucas@gmail.com test send) - [ ] Outbox processor logs a clear warning when team_id doesn't resolve (not silent fallback) ### Test Expectations - [ ] Unit test: email renders with valid team + GroupMe URL - [ ] Unit test: email renders gracefully with missing team (fallback org name, no GroupMe button) - [ ] Test send to draneylucas@gmail.com for visual approval - Run command: `pytest tests/ -k contract_signed_email` ### Constraints - Email is MJML-based HTML — maintain existing responsive design patterns - Must pass Gmail rendering (no broken layouts on mobile Gmail app) - No changes to email sending infrastructure — copy/template only - Lucas must approve before any real sends (per email blast gate) ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes ### Related - `westside-basketball` — project this affects - `src/basketball_api/services/email.py:888-1010` — current template - `src/basketball_api/services/outbox.py:62-110` — team resolution logic
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
ldraney/basketball-api#404
No description provided.