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 ac1f74860..79e5ee258 100644 --- a/enterprise/app/services/enterprise/billing/create_stripe_customer_service.rb +++ b/enterprise/app/services/enterprise/billing/create_stripe_customer_service.rb @@ -4,15 +4,17 @@ class Enterprise::Billing::CreateStripeCustomerService DEFAULT_QUANTITY = 2 def perform - return if existing_subscription? + active_sub = active_subscription + return false if active_sub && !default_plan_subscription?(active_sub) customer_id = prepare_customer_id - subscription = Stripe::Subscription.create(customer: customer_id, items: [{ price: price_id, quantity: default_quantity }]) + subscription = active_sub || Stripe::Subscription.create(customer: customer_id, items: [{ price: price_id, quantity: default_quantity }]) custom_attributes = build_custom_attributes(customer_id, subscription) custom_attributes.except!('is_creating_customer') account.update!(custom_attributes: custom_attributes) Enterprise::Billing::ReconcilePlanFeaturesService.new(account: account).perform + true end private @@ -44,18 +46,21 @@ class Enterprise::Billing::CreateStripeCustomerService price_ids.first end - def existing_subscription? + def active_subscription stripe_customer_id = account.custom_attributes['stripe_customer_id'] - return false if stripe_customer_id.blank? + return nil if stripe_customer_id.blank? - subscriptions = Stripe::Subscription.list( + Stripe::Subscription.list( { customer: stripe_customer_id, status: 'active', limit: 1 } - ) - subscriptions.data.present? + ).data.first + end + + def default_plan_subscription?(subscription) + default_plan['price_ids'].include?(subscription['plan']['id']) end def build_custom_attributes(customer_id, subscription) diff --git a/enterprise/app/services/enterprise/billing/handle_stripe_event_service.rb b/enterprise/app/services/enterprise/billing/handle_stripe_event_service.rb index f69edeb45..9760caacf 100644 --- a/enterprise/app/services/enterprise/billing/handle_stripe_event_service.rb +++ b/enterprise/app/services/enterprise/billing/handle_stripe_event_service.rb @@ -47,9 +47,8 @@ class Enterprise::Billing::HandleStripeEventService def current_plan_credits plan_name = account.custom_attributes['plan_name'] - return { responses: 0, documents: 0 } if plan_name.blank? - - get_plan_credits(plan_name) + plan_credits = get_plan_credits(plan_name) if plan_name.present? + plan_credits || { responses: 0, documents: 0 } end def update_account_attributes(subscription, plan) @@ -71,19 +70,28 @@ class Enterprise::Billing::HandleStripeEventService # skipping self hosted plan events return if account.blank? - Enterprise::Billing::CreateStripeCustomerService.new(account: account).perform + previous_monthly_credits = current_plan_credits[:responses] + return unless Enterprise::Billing::CreateStripeCustomerService.new(account: account).perform + + account.with_lock do + previous_usage = { responses: account.custom_attributes['captain_responses_usage'].to_i, monthly: previous_monthly_credits } + adjust_captain_credits(previous_usage, new_plan_credits: 0) + account.reset_response_usage + end end def handle_subscription_credits(plan, previous_usage) - current_limits = account.limits || {} + adjust_captain_credits(previous_usage, new_plan_credits: get_plan_credits(plan['name'])[:responses]) + end + def adjust_captain_credits(previous_usage, new_plan_credits:) + current_limits = account.limits || {} current_credits = current_limits['captain_responses'].to_i - new_plan_credits = get_plan_credits(plan['name'])[:responses] consumed_topup_credits = [previous_usage[:responses] - previous_usage[:monthly], 0].max - updated_credits = current_credits - consumed_topup_credits - previous_usage[:monthly] + new_plan_credits + updated_credits = [current_credits - consumed_topup_credits - previous_usage[:monthly] + new_plan_credits, 0].max - Rails.logger.info("Updating subscription credits for account #{account.id}: #{current_credits} -> #{updated_credits}") + Rails.logger.info("Updating captain credits for account #{account.id}: #{current_credits} -> #{updated_credits}") account.update!(limits: current_limits.merge('captain_responses' => updated_credits)) 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 0dd8189c4..d2dbf646a 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 @@ -145,10 +145,10 @@ describe Enterprise::Billing::CreateStripeCustomerService do account.update!(custom_attributes: { stripe_customer_id: stripe_customer_id }) end - context 'when customer has active subscriptions' do + context 'when customer has an active non-default subscription' do before do allow(Stripe::Subscription).to receive(:list).and_return(subscriptions_list) - allow(subscriptions_list).to receive(:data).and_return(['subscription']) + allow(subscriptions_list).to receive(:data).and_return([{ 'plan' => { 'id' => 'price_paid_plan' } }]) allow(Stripe::Subscription).to receive(:create) end