From 68cec744367d9c8582ad55905a0973ee92741f55 Mon Sep 17 00:00:00 2001 From: Jorge Manrubia Date: Wed, 17 Dec 2025 10:51:51 +0100 Subject: [PATCH] Extract parent class, validate plans can be downgraded/upgraded --- .../subscriptions/downgrades_controller.rb | 28 ++++------------ .../subscriptions/update_plan_controller.rb | 32 +++++++++++++++++++ .../subscriptions/upgrades_controller.rb | 28 ++++------------ .../downgrades_controller_test.rb | 9 +++++- .../subscriptions/upgrades_controller_test.rb | 9 +++++- 5 files changed, 60 insertions(+), 46 deletions(-) create mode 100644 saas/app/controllers/account/subscriptions/update_plan_controller.rb diff --git a/saas/app/controllers/account/subscriptions/downgrades_controller.rb b/saas/app/controllers/account/subscriptions/downgrades_controller.rb index 565e0d2ac..d06795841 100644 --- a/saas/app/controllers/account/subscriptions/downgrades_controller.rb +++ b/saas/app/controllers/account/subscriptions/downgrades_controller.rb @@ -1,28 +1,12 @@ -class Account::Subscriptions::DowngradesController < ApplicationController - before_action :ensure_admin - - def create - portal_session = Stripe::BillingPortal::Session.create( - customer: subscription.stripe_customer_id, - return_url: account_settings_url(anchor: "subscription"), - flow_data: { - type: "subscription_update_confirm", - subscription_update_confirm: { - subscription: subscription.stripe_subscription_id, - items: [ { id: stripe_subscription_item_id, price: Plan.paid.stripe_price_id } ] - } - } - ) - - redirect_to portal_session.url, allow_other_host: true - end +class Account::Subscriptions::DowngradesController < Account::Subscriptions::UpdatePlanController + before_action :ensure_downgradeable private - def subscription - @subscription ||= Current.account.subscription + def target_plan + Plan.paid end - def stripe_subscription_item_id - Stripe::Subscription.retrieve(subscription.stripe_subscription_id).items.data.first.id + def ensure_downgradeable + head :bad_request unless subscription.plan == Plan.paid_with_extra_storage end end diff --git a/saas/app/controllers/account/subscriptions/update_plan_controller.rb b/saas/app/controllers/account/subscriptions/update_plan_controller.rb new file mode 100644 index 000000000..c6a665cec --- /dev/null +++ b/saas/app/controllers/account/subscriptions/update_plan_controller.rb @@ -0,0 +1,32 @@ +class Account::Subscriptions::UpdatePlanController < ApplicationController + before_action :ensure_admin + + def create + portal_session = Stripe::BillingPortal::Session.create( + customer: subscription.stripe_customer_id, + return_url: account_settings_url(anchor: "subscription"), + flow_data: { + type: "subscription_update_confirm", + subscription_update_confirm: { + subscription: subscription.stripe_subscription_id, + items: [ { id: stripe_subscription_item_id, price: target_plan.stripe_price_id } ] + } + } + ) + + redirect_to portal_session.url, allow_other_host: true + end + + private + def target_plan + raise NotImplementedError + end + + def subscription + @subscription ||= Current.account.subscription + end + + def stripe_subscription_item_id + Stripe::Subscription.retrieve(subscription.stripe_subscription_id).items.data.first.id + end +end diff --git a/saas/app/controllers/account/subscriptions/upgrades_controller.rb b/saas/app/controllers/account/subscriptions/upgrades_controller.rb index 97a112329..1de6d8c6c 100644 --- a/saas/app/controllers/account/subscriptions/upgrades_controller.rb +++ b/saas/app/controllers/account/subscriptions/upgrades_controller.rb @@ -1,28 +1,12 @@ -class Account::Subscriptions::UpgradesController < ApplicationController - before_action :ensure_admin - - def create - portal_session = Stripe::BillingPortal::Session.create( - customer: subscription.stripe_customer_id, - return_url: account_settings_url(anchor: "subscription"), - flow_data: { - type: "subscription_update_confirm", - subscription_update_confirm: { - subscription: subscription.stripe_subscription_id, - items: [ { id: stripe_subscription_item_id, price: Plan.paid_with_extra_storage.stripe_price_id } ] - } - } - ) - - redirect_to portal_session.url, allow_other_host: true - end +class Account::Subscriptions::UpgradesController < Account::Subscriptions::UpdatePlanController + before_action :ensure_upgradeable private - def subscription - @subscription ||= Current.account.subscription + def target_plan + Plan.paid_with_extra_storage end - def stripe_subscription_item_id - Stripe::Subscription.retrieve(subscription.stripe_subscription_id).items.data.first.id + def ensure_upgradeable + head :bad_request unless subscription.plan == Plan.paid end end diff --git a/saas/test/controllers/accounts/subscriptions/downgrades_controller_test.rb b/saas/test/controllers/accounts/subscriptions/downgrades_controller_test.rb index acfeedad3..e425806c4 100644 --- a/saas/test/controllers/accounts/subscriptions/downgrades_controller_test.rb +++ b/saas/test/controllers/accounts/subscriptions/downgrades_controller_test.rb @@ -6,7 +6,7 @@ class Account::Subscriptions::DowngradesControllerTest < ActionDispatch::Integra sign_in_as :kevin accounts(:"37s").subscription.update!( stripe_subscription_id: "sub_123", - plan_key: Plan.paid_with_extra_storage.key + plan: Plan.paid_with_extra_storage ) end @@ -30,4 +30,11 @@ class Account::Subscriptions::DowngradesControllerTest < ActionDispatch::Integra post account_subscription_downgrade_path assert_response :forbidden end + + test "downgrade requires downgradeable plan" do + accounts(:"37s").subscription.update!(plan: Plan.paid) + + post account_subscription_downgrade_path + assert_response :bad_request + end end diff --git a/saas/test/controllers/accounts/subscriptions/upgrades_controller_test.rb b/saas/test/controllers/accounts/subscriptions/upgrades_controller_test.rb index 049de5efb..87308842c 100644 --- a/saas/test/controllers/accounts/subscriptions/upgrades_controller_test.rb +++ b/saas/test/controllers/accounts/subscriptions/upgrades_controller_test.rb @@ -6,7 +6,7 @@ class Account::Subscriptions::UpgradesControllerTest < ActionDispatch::Integrati sign_in_as :kevin accounts(:"37s").subscription.update!( stripe_subscription_id: "sub_123", - plan_key: Plan.paid.key + plan: Plan.paid ) end @@ -30,4 +30,11 @@ class Account::Subscriptions::UpgradesControllerTest < ActionDispatch::Integrati post account_subscription_upgrade_path assert_response :forbidden end + + test "upgrade requires upgradeable plan" do + accounts(:"37s").subscription.update!(plan: Plan.paid_with_extra_storage) + + post account_subscription_upgrade_path + assert_response :bad_request + end end