feat(payment-gated-subs): Apply activation rules on upgrade of a subscription#5533
Conversation
ancorcruz
left a comment
There was a problem hiding this comment.
I'm worried about the gated + upgrade flow actually gets the previous subscription terminated... We should include in this PR a E2E scenario test to ensure the flow is ok. My concern is ActivateService#activate_from_incomplete only activates the subscription but not consider the upgrade branch as #activate_from_pending does... Is this left on purpose fo a next PR perhaps?
scenario test should live in spec/scenarios/subscriptions/payment_gated_activation_spec.rb and has something like...
describe "plan upgrade with payment successful" do
# 1) Create active subscription on a cheaper plan (no gating).
# 2) Call create_subscription on a pricier plan with activation_rules.
# Assert: previous still active, new sub incomplete, invoice open,
# activation_rules.sole pending.
# 3) simulate_stripe_webhook(status: "succeeded")
# Assert: previous terminated, new sub active, BillSubscriptionJob
# ran with :upgrading for [previous, new] (or [previous] for
# pay-in-arrears new plan), invoice finalized.
end
describe "plan upgrade with payment failure" do
# Same setup; webhook returns "payment_failed".
# Assert: new sub canceled, previous remains active and untouched.
end
describe "plan upgrade with timeout (rules unresolved)" do
# Optional but valuable — covers what happens when nothing resolves
# within timeout_hours and the gated upgrade ages out.
end
@ancorcruz yes, this is going to be handled in a separate PR so it's not too much work on just one PR. It's a separate bullet point on the dive-in |
…ncomplete subscription
…d centralize notifications on notify_started
…ge apply_activation_rules to accept an argument
Context
Part of the payment-gated subscriptions effort. Activation rules were already supported on subscription creation; this extends them to plan upgrades, so an upgrade can be gated until its rules (e.g. payment) resolve before the new plan takes effect.
Description
Subscriptions::ActivateServicebecomes the single entry point for all activations. It auto-detects an upgrade viasubscription.previous_subscription(different plan,yearly_amount_cents≥ the previous) and branches into a newactivate_for_upgradepath that terminates the previous, marks the new active, emits fixed-charge events, firessubscription.started, and bills both with:upgrading.Subscriptions::PlanUpgradeService#callcollapses topending!→ optionalActivationRules::ApplyService→ActivateService.call!. Gated upgrades now follow the same gating path used at subscription creation.Subscriptions::TerminateService#cancel_next_subscriptionearly-returns whenupgrade: true, so the upgrade target we just persisted isn't canceled mid-flow.