billing: add --dry-run mode and always send manual invoices#3099
Draft
jshearer wants to merge 2 commits into
Draft
billing: add --dry-run mode and always send manual invoices#3099jshearer wants to merge 2 commits into
--dry-run mode and always send manual invoices#3099jshearer wants to merge 2 commits into
Conversation
* Add `--dry-run`: classify every invoice against the livemode Stripe API and report what would happen without creating or modifying anything. The previous testmode trial run misreported manual bills that already had invoices as phantom creates, because the sandbox lacked livemode state. Manual bills already invoiced in an earlier run now report as `AlreadyProcessed` instead of erroring. * Manual invoices are always sent as invoices rather than charged to a stored payment method, even when one is on file. Stored payment methods cover monthly usage overages; manual bills such as contracts and one-off charges should let the customer choose how to pay. Both changes were part of PR #2849, which was closed while the rest of the branch merged via #2883 and #2902, so they never landed. This reapplies them onto current master.
… from --recreate-finalized The classify/execute split returns no Stripe customer for skips resolved in the read-only Phase 1, which silently disabled --clean_up for those tenants. Separately, --recreate-finalized still applied to manual invoices, conflicting with the new `AlreadyProcessed` handling that makes manual reruns idempotent. * --clean_up falls back to a `find_customer` lookup when the `Skip` action carries no customer, so it again removes stale draft invoices for `FreeTier`, `FutureTrialStart`, and `LessThanMinimum` tenants. Phase 1 stays free of Stripe calls, so the lookup only runs under --clean_up. * Manual invoices are excluded from --recreate-finalized so an already-sent open manual invoice is not voided and reissued. An open manual invoice reports `AlreadyProcessed`, and a manual draft is refreshed through the normal Update path.
473d8e8 to
5810d41
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
--dry-runmodeThe invoice generator's trial-run workflow ran against a testmode Stripe account, which lacked livemode invoice state, so manual bills that already had open or paid invoices showed up as phantom creates.
--dry-runruns against the livemode API in read-only mode and reports what each invoice would do without creating or modifying anything in Stripe.To make that safe, the per-invoice work is separated into two phases:
classifyperforms only reads (validation and Stripe lookups) and returns the action that would be taken.executeperforms all writes (customer and invoice creation, line items, amount verification).--dry-runstops afterclassifyand logs the would-be action; a normal run classifies and then executes, so both paths share the same decision logic.A behavior change rides along with this: manual bills that already have an open, paid, void, or uncollectible invoice in Stripe are now classified as
AlreadyProcessedand skipped instead of erroring. This is expected for date-range-overlapping manual bills invoiced in a previous run, and it applies to real runs too, not only dry runs.Always send manual invoices
Stored payment methods cover monthly usage overages. Manual bills such as contracts and one-off charges should be sent as invoices so the customer decides how to pay, rather than being charged automatically. Manual invoices now use
send_invoiceregardless of--charge-type, both at creation and during the send phase, even when a payment method is on file.