prorate-a-subscription-plan-change
Use when a subscriber upgrades, downgrades or changes billing period mid-cycle. Computes the proration credit and charge in exact minor units and names which of the two common conventions applies.
- License 许可
- MIT
- 最近更新
- 2026-11-11
- Stars
- ★ 80
- Forks
- 17
01 前言 Front Matter
- name
- prorate-a-subscription-plan-change
- description
- Use when a subscriber upgrades, downgrades or changes billing period mid-cycle. Computes the proration credit and charge in exact minor units and names which of the two common conventions applies.
02 资源文件 3
- 许可证LICENSE1.0 KB
- 参考文档SOURCE.md360 B
- 参考文档TRUST.auto.yaml2.2 KB
03 SKILL.md 正文
Prorate a subscription plan change
Proration means charging for the days on the new plan and crediting the unused days on the old one. Do the arithmetic in integer minor units and name the convention, because the two conventions disagree by up to a full period.
Procedure
-
Pick the convention and write it down:
- Unused-time credit (Stripe-style): credit the old plan for days not used, charge the new plan for days remaining.
- Foregone-time (some legacy billers): keep the old period's charge whole and switch at the next renewal. No credit, no charge.
-
Establish the period in whole days:
term_days,used_days,remaining_days = term_days - used_days. -
Prorate with integer division, flooring the credit in the customer's favour:
credit_minor = old_amount_minor * remaining_days // term_days.charge_minor = new_amount_minor * remaining_days // term_days. -
Compute the net due:
net_minor = charge_minor - credit_minor. Positive is an immediate charge; negative is an account credit or a small refund. -
Worked example, monthly term of 30 days, day 10 used (remaining 20):
- old plan USD 29.00 = 2900 minor; credit = 2900*20//30 = 1933.
- new plan USD 99.00 = 9900 minor; charge = 9900*20//30 = 6600.
- net = 6600 - 1933 = 4667 minor = USD 46.67 due now.
-
On a downgrade the net is usually negative; carry it as an account credit rather than cash, unless the account closes.
-
Keep the period anchor fixed on upgrades: the next renewal stays on the original day so the customer does not get a shortened period.
-
Post the credit and the charge as two ledger lines, not one netted line, so revenue recognition can split them.
-
On an annual-to-monthly switch, convert both sides to a daily rate before prorating so term lengths compare correctly.
-
Round consistently — floor the customer's credit and the charge alike — so support cannot cherry-pick the direction.
-
Store the proration as an immutable event carrying term_days and remaining_days, so a dispute is reconstructible.
-
Handle a mid-cycle downgrade-plus-upgrade in one transaction only if the period anchor is unchanged; otherwise post two events.
-
Recompute proration only from stored dates, never from "today", so the amount does not drift daily.
-
Reconcile the sum of proration events for the period to the invoice total; a mismatch is a missed event.
Pitfalls
-
Using a 30-day denominator for a 28/29/31-day month shifts the result; use the actual
term_daysof that period. -
Float division (
2900*20/30 = 1933.333) leaks fractions of a cent; integer//floors exactly. -
A mid-cycle upgrade that also resets the period anchor silently shortens the paid month.
-
Netting credit and charge into one line loses the audit trail and breaks any per-plan revenue report.
-
Applying foregone-time on a downgrade while claiming unused-time on an upgrade is inconsistent and looks like double-billing.
-
Mixing annual and monthly amounts without a common daily rate inflates one leg and misprices the switch.
-
Rounding credit up and charge down in different code paths produces a cent the customer eventually finds.
-
Recomputing the proration on every page load from today's date makes the amount drift daily.
-
A downgrade-plus-upgrade that resets the anchor can silently hand the customer a longer period.
Verification
python3 -c "old=2900;new=9900;term=30;rem=20;print(old*rem//term, new*rem//term, new*rem//term-old*rem//term)"
# 1933 6600 4667 -> credit 19.33, charge 66.00, net 46.67 due
Report: the convention chosen, term_days, and the net due in minor units for one worked change.
04 同仓库更多 Skills
recipe-performance
Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold/warm/background-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout/paint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.
mexc-spot-websocket
MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.
mexc-spot-rest
MEXC Spot REST workflows for public data, signed account requests, orders, wallet/admin actions, and secure signing without exposing API keys.
mexc-futures-websocket
MEXC Futures WebSocket workflows for public streams, private account/order/position streams, ping/pong, subscriptions, and depth maintenance.
0xklen-version-and-refresh-sanctions-lists
暂无简介
verify-tests-cover-changed-lines
Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.