Add skip_proration flag to first-payment endpoint and checkout route #458

Closed
opened 2026-04-12 19:36:19 +00:00 by forgejo_admin · 0 comments

Type

Feature

Lineage

Standalone — discovered during Marcus's 2026-04-12 custom contract batch (Jaxon Gerber $50/mo flat rate). Related to forgejo_admin/basketball-api #424 (prior batch).

Repo

forgejo_admin/basketball-api

User Story

As an admin,
I want to send a first-payment email with a flat fee (no proration)
So that players with custom deals get charged the exact amount agreed upon.

Context

send_first_payment_email() and GET /checkout/first-payment both auto-prorate via _calculate_prorated_fee() (formula: round(fee * 25/30 / 5) * 5). Marcus requested Jaxon Gerber (id=106) at $50/mo flat — no proration. Current code would show $40 in the email and charge $40 at Stripe checkout. No override exists.

Both the endpoint and checkout live on branch 369-first-payment-email-blast (not yet merged to main). The branch is deployed to the running pod.

File Targets

Files the agent should modify:

  • src/basketball_api/services/email.pysend_first_payment_email() accepts skip_proration bool, skips _calculate_prorated_fee() when true, adjusts email text to say "April fee" instead of "Prorated April fee"
  • src/basketball_api/routes/admin.pyPOST /admin/email/first-payment accepts skip_proration query param, passes through to send function
  • src/basketball_api/routes/checkout.pyGET /checkout/first-payment accepts prorate query param (default true), charges monthly_fee * 100 cents directly when false

Files the agent should NOT touch:

  • src/basketball_api/services/email_queries.py — not related
  • src/basketball_api/services/outbox.py — not related

Acceptance Criteria

  • When skip_proration=true on the blast endpoint, email shows flat fee (e.g. "$50") not prorated fee ("$40")
  • When skip_proration=true, checkout URL includes &prorate=false query param
  • When prorate=false on checkout route, Stripe session uses monthly_fee * 100 cents directly
  • When flag is not set, existing proration behavior is unchanged
  • EmailLog entry is created for both prorated and non-prorated sends

Test Expectations

  • Unit test: send_first_payment_email with skip_proration=True uses monthly_fee directly
  • Unit test: send_first_payment_email with skip_proration=False (default) prorates as before
  • Unit test: checkout route with prorate=false charges exact monthly_fee * 100
  • Run command: pytest tests/test_first_payment_email.py tests/test_first_payment_blast.py -v

Constraints

  • Branch from 369-first-payment-email-blast, not main (that's where the endpoint lives)
  • Match existing route style in routes/admin.py
  • Do not change the proration formula itself — only add the skip flag

Checklist

  • PR opened
  • Tests pass
  • No unrelated changes
  • project-westside-basketball — parent project
  • sop-contract-offer — contract offer operational SOP
  • story:WS-S23 — custom contract terms per player
### Type Feature ### Lineage Standalone — discovered during Marcus's 2026-04-12 custom contract batch (Jaxon Gerber $50/mo flat rate). Related to `forgejo_admin/basketball-api #424` (prior batch). ### Repo `forgejo_admin/basketball-api` ### User Story As an admin, I want to send a first-payment email with a flat fee (no proration) So that players with custom deals get charged the exact amount agreed upon. ### Context `send_first_payment_email()` and `GET /checkout/first-payment` both auto-prorate via `_calculate_prorated_fee()` (formula: `round(fee * 25/30 / 5) * 5`). Marcus requested Jaxon Gerber (id=106) at $50/mo flat — no proration. Current code would show $40 in the email and charge $40 at Stripe checkout. No override exists. Both the endpoint and checkout live on branch `369-first-payment-email-blast` (not yet merged to main). The branch is deployed to the running pod. ### File Targets Files the agent should modify: - `src/basketball_api/services/email.py` — `send_first_payment_email()` accepts `skip_proration` bool, skips `_calculate_prorated_fee()` when true, adjusts email text to say "April fee" instead of "Prorated April fee" - `src/basketball_api/routes/admin.py` — `POST /admin/email/first-payment` accepts `skip_proration` query param, passes through to send function - `src/basketball_api/routes/checkout.py` — `GET /checkout/first-payment` accepts `prorate` query param (default true), charges `monthly_fee * 100` cents directly when false Files the agent should NOT touch: - `src/basketball_api/services/email_queries.py` — not related - `src/basketball_api/services/outbox.py` — not related ### Acceptance Criteria - [ ] When `skip_proration=true` on the blast endpoint, email shows flat fee (e.g. "$50") not prorated fee ("$40") - [ ] When `skip_proration=true`, checkout URL includes `&prorate=false` query param - [ ] When `prorate=false` on checkout route, Stripe session uses `monthly_fee * 100` cents directly - [ ] When flag is not set, existing proration behavior is unchanged - [ ] EmailLog entry is created for both prorated and non-prorated sends ### Test Expectations - [ ] Unit test: `send_first_payment_email` with `skip_proration=True` uses monthly_fee directly - [ ] Unit test: `send_first_payment_email` with `skip_proration=False` (default) prorates as before - [ ] Unit test: checkout route with `prorate=false` charges exact monthly_fee * 100 - Run command: `pytest tests/test_first_payment_email.py tests/test_first_payment_blast.py -v` ### Constraints - Branch from `369-first-payment-email-blast`, not main (that's where the endpoint lives) - Match existing route style in `routes/admin.py` - Do not change the proration formula itself — only add the skip flag ### Checklist - [ ] PR opened - [ ] Tests pass - [ ] No unrelated changes ### Related - `project-westside-basketball` — parent project - `sop-contract-offer` — contract offer operational SOP - `story:WS-S23` — custom contract terms per player
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#458
No description provided.