feat: payment links table + outstanding balance emails #524
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
ldraney/basketball-api!524
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/payment-links-outstanding-balance"
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
payment_linkstable (migration 048) for unified per-player Stripe Payment Link trackingPOST /email/outstanding-balanceadmin endpoint andoutstanding_balancesblast queryChanges
alembic/versions/048_add_payment_links_table.py: new migration — createspayment_linkstable, addsoutstanding_balanceto emailtype enumsrc/basketball_api/models.py:PaymentLinkmodel,PaymentLinkStatusenum,outstanding_balanceemail typesrc/basketball_api/routes/admin.py: new outstanding balance endpoint, subscription status filter on first-paymentsrc/basketball_api/routes/checkout.py: remove proration, charge flat monthly_feesrc/basketball_api/services/email.py:send_outstanding_balance_email, clean up first-payment copysrc/basketball_api/services/email_queries.py:query_outstanding_balancesfor blast systemscripts/backfill_payment_links.py: backfill script with dry-run modeTest Plan
/email/outstanding-balanceendpoint withtest_emailparamReview Checklist
Related Notes
project-westside-basketball— parent projectPR #524 Review
Scope: Adds
payment_linkstable (migration 048),PaymentLinkmodel, outstanding-balance email endpoint + blast query, backfill script, and monthly billing cleanup. Already deployed to prod as hotfix; migration applied with 98 rows.DOMAIN REVIEW
Model layer — Clean. Proper FK indexes, unique constraint on
(player_id, product_id, tenant_id). Enum additions consistent with existing patterns.Migration 048 — Correct
create_table, proper FK/indexes.ALTER TYPE emailtype ADD VALUE IF NOT EXISTSis the right Postgres pattern. Downgrade can't remove the enum value (Postgres limitation) — acceptable.Admin route — Auth-gated, groups by parent, error aggregation follows established pattern.
test_emailfilter works correctly.Email service — Properly escapes all user-supplied data. Uses
_brand_wrapperconsistently. Logs toemail_log. Plain-text fallback included.Backfill script — Two-phase (monthly links + pending orders). Dry-run by default — good safety pattern.
Checkout — Removes April-specific proration, charges flat monthly_fee. Aligns with Payment Link strategy.
BLOCKERS
1. No test coverage for new functionality.
New endpoint, email function, query function, backfill script, and model — all untested. Per standard criteria this is a blocker.
Mitigation context: This is deployed to prod as a hotfix with 98 rows of real data. Main is out of sync with prod until this merges.
NITS
backfill_payment_links.py:96—product_type="subscription"should useProductType.subscriptionfor type consistencybackfill_payment_links.py:255—Query.get()deprecated in SQLAlchemy 2.0, usedb.get(Product, order.product_id)email_queries.pyduplicates grouped-by-parent HTML construction fromemail.py— DRY concern for latercheckout.py—_calculate_prorated_centsappears to be dead code after this changeoutstanding_balancefrom emailtype (Postgres limitation) — worth a commentVERDICT: NOT APPROVED
Reason: Zero test coverage on new functionality.
Recommended path: Given this is already deployed and the migration is applied, the pragmatic approach is to merge to unblock main, then immediately open a follow-up issue for test coverage. The code quality itself is solid — this is a process call, not a quality call.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.