[DONE] Add payment_links table and outstanding balance email #518

Closed
opened 2026-05-08 05:28:36 +00:00 by forgejo_admin · 0 comments
Contributor

Type

Feature

User Story

As a coach, when a parent asks "how do I pay?", I need to look up their player and resend a persistent payment link. As an admin, I need to blast all parents an email showing everything they owe with a Pay Now link per item.

Lineage

Standalone — enables payment link persistence and outstanding balance emails.

Repo

basketball-api

Context

Stripe Payment Links don't expire (unlike Checkout Sessions). We mint one per product per player, store it in a dedicated payment_links table, and use it for outstanding balance emails and on-demand resend.

Acceptance Criteria

  • New payment_links table with schema: player_id, parent_id, product_id, description, amount_cents, stripe_payment_link_id, stripe_payment_link_url, status, order_id, paid_at
  • Unique constraint on (player_id, product_id, tenant_id)
  • outstanding_balance EmailType enum value added
  • Backfill script that mints Stripe Payment Links for signed players, creates missing price tiers, copies existing pending Orders
  • query_outstanding_balances in QUERY_REGISTRY
  • send_outstanding_balance_email branded email function
  • POST /admin/email/outstanding-balance?test_email= endpoint

File Targets

  • src/basketball_api/models.py — PaymentLinkStatus enum, PaymentLink model, outstanding_balance EmailType
  • alembic/versions/048_add_payment_links_table.py — migration
  • scripts/backfill_payment_links.py — backfill script
  • src/basketball_api/services/email_queries.py — query_outstanding_balances
  • src/basketball_api/services/email.py — send_outstanding_balance_email
  • src/basketball_api/routes/admin.py — POST /admin/email/outstanding-balance

Test Expectations

  • Backfill dry-run lists players without errors
  • Backfill --commit creates payment_links rows and mints Stripe links
  • Test email sends to draneylucas@gmail.com with correct items

Constraints

  • Must use _brand_wrapper (System 1) for email styling
  • Backfill must be idempotent (unique constraint prevents duplicates)
  • Dry-run by default, --commit to execute

Checklist

  • Migration runs clean
  • Backfill script tested dry-run
  • Test email sent and reviewed
  • Endpoint accessible via admin auth
  • westside-billing-status-2026-05 (billing status note)
  • PR #498 (Payment Link migration from Checkout Sessions)
### Type Feature ### User Story As a coach, when a parent asks "how do I pay?", I need to look up their player and resend a persistent payment link. As an admin, I need to blast all parents an email showing everything they owe with a Pay Now link per item. ### Lineage Standalone — enables payment link persistence and outstanding balance emails. ### Repo basketball-api ### Context Stripe Payment Links don't expire (unlike Checkout Sessions). We mint one per product per player, store it in a dedicated `payment_links` table, and use it for outstanding balance emails and on-demand resend. ### Acceptance Criteria - [ ] New `payment_links` table with schema: player_id, parent_id, product_id, description, amount_cents, stripe_payment_link_id, stripe_payment_link_url, status, order_id, paid_at - [ ] Unique constraint on (player_id, product_id, tenant_id) - [ ] `outstanding_balance` EmailType enum value added - [ ] Backfill script that mints Stripe Payment Links for signed players, creates missing price tiers, copies existing pending Orders - [ ] `query_outstanding_balances` in QUERY_REGISTRY - [ ] `send_outstanding_balance_email` branded email function - [ ] `POST /admin/email/outstanding-balance?test_email=` endpoint ### File Targets - `src/basketball_api/models.py` — PaymentLinkStatus enum, PaymentLink model, outstanding_balance EmailType - `alembic/versions/048_add_payment_links_table.py` — migration - `scripts/backfill_payment_links.py` — backfill script - `src/basketball_api/services/email_queries.py` — query_outstanding_balances - `src/basketball_api/services/email.py` — send_outstanding_balance_email - `src/basketball_api/routes/admin.py` — POST /admin/email/outstanding-balance ### Test Expectations - Backfill dry-run lists players without errors - Backfill --commit creates payment_links rows and mints Stripe links - Test email sends to draneylucas@gmail.com with correct items ### Constraints - Must use `_brand_wrapper` (System 1) for email styling - Backfill must be idempotent (unique constraint prevents duplicates) - Dry-run by default, --commit to execute ### Checklist - [ ] Migration runs clean - [ ] Backfill script tested dry-run - [ ] Test email sent and reviewed - [ ] Endpoint accessible via admin auth ### Related - westside-billing-status-2026-05 (billing status note) - PR #498 (Payment Link migration from Checkout Sessions)
forgejo_admin 2026-05-08 05:32:19 +00:00
forgejo_admin changed title from Add payment_links table and outstanding balance email to [DONE] Add payment_links table and outstanding balance email 2026-05-08 05:41:20 +00:00
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#518
No description provided.