fix: prevent past_due status cascading to newly paid subscriptions#782
Open
lutz-grex wants to merge 1 commit intouseautumn:devfrom
Open
fix: prevent past_due status cascading to newly paid subscriptions#782lutz-grex wants to merge 1 commit intouseautumn:devfrom
lutz-grex wants to merge 1 commit intouseautumn:devfrom
Conversation
When a customer has an unpaid invoice, all products on the same Stripe subscription were marked as past_due — including newly purchased products with fully paid invoices. This blocked users from accessing the app even with a valid, paid subscription. Root cause: new products were merged onto unhealthy (past_due) Stripe subscriptions via getTargetSubscriptionCusProduct, then syncCustomerProductStatus applied the subscription-level past_due status to all products uniformly. Fix: - Reject unhealthy subscriptions (past_due, incomplete, unpaid, paused) as merge targets in fetchStripeSubscriptionForBilling, forcing creation of a new Stripe subscription for the new product - Clean up expired product items from the old subscription after transitioning to prevent future charges for the expired product
|
@lutz-grex is attempting to deploy a commit to the Autumn Team on Vercel. A member of the Team first needs to authorize it. |
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.
Summary
When a customer has an unpaid invoice, all products on the same Stripe subscription were marked as past_due — including newly purchased products with fully paid invoices. This blocked users from accessing the app even with a valid, paid subscription.
Root cause: new products were merged onto unhealthy (past_due) Stripe subscriptions via getTargetSubscriptionCusProduct, then syncCustomerProductStatus applied the subscription-level past_due status to all products uniformly.
Fix:
Related Issues
None identified yet — this was reported by a user
Type of Change
Checklist
Screenshots (if applicable)
Additional Context
Changed files
classifyStripeSubscriptionUtils.ts— AddedisStripeSubscriptionUnhealthy()helper that detects payment-problematic statuses (past_due,incomplete,incomplete_expired,unpaid,paused)fetchStripeSubscriptionForBilling.ts— Returnsundefinedwhen the target subscription is unhealthy, forcing the billing system to create a new Stripe subscription instead of merging onto the problematic one. Includes aninfo-level log for production traceability.cleanupOldSubscriptionItems.ts(new) — After transitioning to a new subscription, removes the expired product's items from the old subscription. Cancels the old subscription entirely if no items remain. Usesproration_behavior: "none"to avoid generating credits for already-unpaid items.executeStripeBillingPlan.ts— CallscleanupOldSubscriptionItems()after the subscription action completes.Edge cases handled
if (!newStripeSubscription) returnexit prevents cleanup from running when no new subscription was created.isStripeSubscriptionCanceledguard prevents redundant Stripe API calls.Summary by cubic
Prevented past_due status from cascading to newly paid products by avoiding merges onto unhealthy Stripe subscriptions and cleaning up old subscription items after moving. Users with a new paid product are no longer blocked by an unpaid invoice on another product.
Written for commit ab8d8ae. Summary will update on new commits.
Greptile Summary
Prevents newly purchased products from being blocked when customers have unpaid invoices on existing subscriptions. Previously, new products merged onto unhealthy (
past_due) Stripe subscriptions inherited the payment-problematic status, blocking legitimate access.Key Changes:
Bug fixes
past_due,incomplete,incomplete_expired,unpaid,paused) as merge targets infetchStripeSubscriptionForBilling, forcing creation of new Stripe subscriptions for new productsImprovements
isStripeSubscriptionUnhealthy()utility to centralize detection of payment-problematic subscription statusesConfidence Score: 4/5
cleanupOldSubscriptionItems.ts- ensure the item removal logic handles all edge cases correctly in productionImportant Files Changed
isStripeSubscriptionUnhealthy()helper to detect payment-problematic subscription statusesFlowchart
%%{init: {'theme': 'neutral'}}%% flowchart TD A[Customer purchases new product] --> B{Existing subscription?} B -->|No| C[Create new subscription] B -->|Yes| D{Check subscription health} D -->|Healthy: active/trialing| E[Merge onto existing subscription] D -->|Unhealthy: past_due/incomplete/unpaid/paused| F[Force new subscription creation] F --> G[Execute billing plan on new subscription] G --> H{Old product status?} H -->|Expired| I[cleanupOldSubscriptionItems] H -->|Canceling| J[Skip cleanup - handled at period end] I --> K{Remove items from old subscription} K --> L{Any items remaining?} L -->|No| M[Cancel old subscription entirely] L -->|Yes| N[Remove only expired product items] E --> O[Update existing subscription] C --> P[Product active on new subscription] M --> P N --> P O --> PLast reviewed commit: ab8d8ae
(3/5) Reply to the agent's comments like "Can you suggest a fix for this @greptileai?" or ask follow-up questions!