From 257cd07ee620086c5f94cd960f6f2458256e5b09 Mon Sep 17 00:00:00 2001 From: Pranav Date: Wed, 25 Jun 2025 18:53:36 -0700 Subject: [PATCH] fix: Check if there are any subscriptions before we create a default subscription (#11813) Avoid creating duplicate subscriptions. --- .../billing/create_stripe_customer_service.rb | 16 +++++ .../create_stripe_customer_service_spec.rb | 63 ++++++++++++++++++- 2 files changed, 78 insertions(+), 1 deletion(-) diff --git a/enterprise/app/services/enterprise/billing/create_stripe_customer_service.rb b/enterprise/app/services/enterprise/billing/create_stripe_customer_service.rb index 76c09a27a..e4df1050b 100644 --- a/enterprise/app/services/enterprise/billing/create_stripe_customer_service.rb +++ b/enterprise/app/services/enterprise/billing/create_stripe_customer_service.rb @@ -4,6 +4,8 @@ class Enterprise::Billing::CreateStripeCustomerService DEFAULT_QUANTITY = 2 def perform + return if existing_subscription? + customer_id = prepare_customer_id subscription = Stripe::Subscription.create( { @@ -50,4 +52,18 @@ class Enterprise::Billing::CreateStripeCustomerService price_ids = default_plan['price_ids'] price_ids.first end + + def existing_subscription? + stripe_customer_id = account.custom_attributes['stripe_customer_id'] + return false if stripe_customer_id.blank? + + subscriptions = Stripe::Subscription.list( + { + customer: stripe_customer_id, + status: 'active', + limit: 1 + } + ) + subscriptions.data.present? + end end diff --git a/spec/enterprise/services/enterprise/billing/create_stripe_customer_service_spec.rb b/spec/enterprise/services/enterprise/billing/create_stripe_customer_service_spec.rb index 95edf73a1..f5b0bbe86 100644 --- a/spec/enterprise/services/enterprise/billing/create_stripe_customer_service_spec.rb +++ b/spec/enterprise/services/enterprise/billing/create_stripe_customer_service_spec.rb @@ -6,6 +6,7 @@ describe Enterprise::Billing::CreateStripeCustomerService do let(:account) { create(:account) } let!(:admin1) { create(:user, account: account, role: :administrator) } let(:admin2) { create(:user, account: account, role: :administrator) } + let(:subscriptions_list) { double } describe '#perform' do before do @@ -19,8 +20,9 @@ describe Enterprise::Billing::CreateStripeCustomerService do it 'does not call stripe methods if customer id is present' do account.update!(custom_attributes: { stripe_customer_id: 'cus_random_number' }) - + allow(subscriptions_list).to receive(:data).and_return([]) allow(Stripe::Customer).to receive(:create) + allow(Stripe::Subscription).to receive(:list).and_return(subscriptions_list) allow(Stripe::Subscription).to receive(:create) .and_return( { @@ -78,4 +80,63 @@ describe Enterprise::Billing::CreateStripeCustomerService do ) end end + + describe 'when checking for existing subscriptions' do + before do + create( + :installation_config, + { name: 'CHATWOOT_CLOUD_PLANS', value: [ + { 'name' => 'A Plan Name', 'product_id' => ['prod_hacker_random'], 'price_ids' => ['price_hacker_random'] } + ] } + ) + end + + context 'when account has no stripe_customer_id' do + it 'creates a new subscription' do + customer = double + allow(Stripe::Customer).to receive(:create).and_return(customer) + allow(customer).to receive(:id).and_return('cus_random_number') + allow(Stripe::Subscription).to receive(:create).and_return( + { + plan: { id: 'price_random_number', product: 'prod_random_number' }, + quantity: 2 + }.with_indifferent_access + ) + + create_stripe_customer_service.new(account: account).perform + + expect(Stripe::Customer).to have_received(:create) + expect(Stripe::Subscription).to have_received(:create) + end + end + + context 'when account has stripe_customer_id' do + let(:stripe_customer_id) { 'cus_random_number' } + + before do + account.update!(custom_attributes: { stripe_customer_id: stripe_customer_id }) + end + + context 'when customer has active subscriptions' do + before do + allow(Stripe::Subscription).to receive(:list).and_return(subscriptions_list) + allow(subscriptions_list).to receive(:data).and_return(['subscription']) + allow(Stripe::Subscription).to receive(:create) + end + + it 'does not create a new subscription' do + create_stripe_customer_service.new(account: account).perform + + expect(Stripe::Subscription).not_to have_received(:create) + expect(Stripe::Subscription).to have_received(:list).with( + { + customer: stripe_customer_id, + status: 'active', + limit: 1 + } + ) + end + end + end + end end