fix: add renewal identification for credit flow (#12999)
This commit is contained in:
committed by
GitHub
parent
399c91adaa
commit
3051da1e44
@@ -50,15 +50,19 @@ class Enterprise::Billing::HandleStripeEventService
|
||||
previous_usage = capture_previous_usage
|
||||
update_account_attributes(subscription, plan)
|
||||
update_plan_features
|
||||
handle_subscription_credits(plan, previous_usage)
|
||||
account.reset_response_usage
|
||||
|
||||
if billing_period_renewed?
|
||||
ActiveRecord::Base.transaction do
|
||||
handle_subscription_credits(plan, previous_usage)
|
||||
account.reset_response_usage
|
||||
end
|
||||
elsif plan_changed?
|
||||
handle_plan_change_credits(plan, previous_usage)
|
||||
end
|
||||
end
|
||||
|
||||
def capture_previous_usage
|
||||
{
|
||||
responses: account.custom_attributes['captain_responses_usage'].to_i,
|
||||
monthly: current_plan_credits[:responses]
|
||||
}
|
||||
{ responses: account.custom_attributes['captain_responses_usage'].to_i, monthly: current_plan_credits[:responses] }
|
||||
end
|
||||
|
||||
def current_plan_credits
|
||||
@@ -71,15 +75,15 @@ class Enterprise::Billing::HandleStripeEventService
|
||||
def update_account_attributes(subscription, plan)
|
||||
# https://stripe.com/docs/api/subscriptions/object
|
||||
account.update(
|
||||
custom_attributes: {
|
||||
stripe_customer_id: subscription.customer,
|
||||
stripe_price_id: subscription['plan']['id'],
|
||||
stripe_product_id: subscription['plan']['product'],
|
||||
plan_name: plan['name'],
|
||||
subscribed_quantity: subscription['quantity'],
|
||||
subscription_status: subscription['status'],
|
||||
subscription_ends_on: Time.zone.at(subscription['current_period_end'])
|
||||
}
|
||||
custom_attributes: account.custom_attributes.merge(
|
||||
'stripe_customer_id' => subscription.customer,
|
||||
'stripe_price_id' => subscription['plan']['id'],
|
||||
'stripe_product_id' => subscription['plan']['product'],
|
||||
'plan_name' => plan['name'],
|
||||
'subscribed_quantity' => subscription['quantity'],
|
||||
'subscription_status' => subscription['status'],
|
||||
'subscription_ends_on' => Time.zone.at(subscription['current_period_end'])
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
@@ -131,6 +135,18 @@ class Enterprise::Billing::HandleStripeEventService
|
||||
account.update!(limits: current_limits.merge('captain_responses' => updated_credits))
|
||||
end
|
||||
|
||||
def handle_plan_change_credits(new_plan, previous_usage)
|
||||
current_limits = account.limits || {}
|
||||
current_credits = current_limits['captain_responses'].to_i
|
||||
|
||||
previous_plan_credits = previous_usage[:monthly]
|
||||
new_plan_credits = get_plan_credits(new_plan['name'])[:responses]
|
||||
|
||||
updated_credits = current_credits - previous_plan_credits + new_plan_credits
|
||||
|
||||
account.update!(limits: current_limits.merge('captain_responses' => updated_credits))
|
||||
end
|
||||
|
||||
def get_plan_credits(plan_name)
|
||||
config = InstallationConfig.find_by(name: CAPTAIN_CLOUD_PLAN_LIMITS).value
|
||||
config = JSON.parse(config) if config.is_a?(String)
|
||||
@@ -141,20 +157,12 @@ class Enterprise::Billing::HandleStripeEventService
|
||||
plan_name = account.custom_attributes['plan_name']
|
||||
return if plan_name.blank?
|
||||
|
||||
# Enable features based on plan hierarchy
|
||||
case plan_name
|
||||
when 'Startups'
|
||||
# Startups plan gets the basic features
|
||||
account.enable_features(*STARTUP_PLAN_FEATURES)
|
||||
when 'Startups' then account.enable_features(*STARTUP_PLAN_FEATURES)
|
||||
when 'Business'
|
||||
# Business plan gets Startups features + Business features
|
||||
account.enable_features(*STARTUP_PLAN_FEATURES)
|
||||
account.enable_features(*BUSINESS_PLAN_FEATURES)
|
||||
account.enable_features(*STARTUP_PLAN_FEATURES, *BUSINESS_PLAN_FEATURES)
|
||||
when 'Enterprise'
|
||||
# Enterprise plan gets all features
|
||||
account.enable_features(*STARTUP_PLAN_FEATURES)
|
||||
account.enable_features(*BUSINESS_PLAN_FEATURES)
|
||||
account.enable_features(*ENTERPRISE_PLAN_FEATURES)
|
||||
account.enable_features(*STARTUP_PLAN_FEATURES, *BUSINESS_PLAN_FEATURES, *ENTERPRISE_PLAN_FEATURES)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -162,6 +170,25 @@ class Enterprise::Billing::HandleStripeEventService
|
||||
@subscription ||= @event.data.object
|
||||
end
|
||||
|
||||
def previous_attributes
|
||||
@previous_attributes ||= JSON.parse((@event.data.previous_attributes || {}).to_json)
|
||||
end
|
||||
|
||||
def plan_changed?
|
||||
return false if previous_attributes['plan'].blank?
|
||||
|
||||
previous_plan_id = previous_attributes.dig('plan', 'id')
|
||||
current_plan_id = subscription['plan']['id']
|
||||
|
||||
previous_plan_id != current_plan_id
|
||||
end
|
||||
|
||||
def billing_period_renewed?
|
||||
return false if previous_attributes['current_period_start'].blank?
|
||||
|
||||
previous_attributes['current_period_start'] != subscription['current_period_start']
|
||||
end
|
||||
|
||||
def account
|
||||
@account ||= Account.where("custom_attributes->>'stripe_customer_id' = ?", subscription.customer).first
|
||||
end
|
||||
|
||||
@@ -32,6 +32,7 @@ describe Enterprise::Billing::HandleStripeEventService do
|
||||
# Setup common subscription mocks
|
||||
allow(event).to receive(:data).and_return(data)
|
||||
allow(data).to receive(:object).and_return(subscription)
|
||||
allow(data).to receive(:previous_attributes).and_return({})
|
||||
allow(subscription).to receive(:[]).with('quantity').and_return('10')
|
||||
allow(subscription).to receive(:[]).with('status').and_return('active')
|
||||
allow(subscription).to receive(:[]).with('current_period_end').and_return(1_686_567_520)
|
||||
@@ -62,7 +63,7 @@ describe Enterprise::Billing::HandleStripeEventService do
|
||||
expect(account).not_to be_feature_enabled('audit_logs')
|
||||
end
|
||||
|
||||
it 'resets captain usage on subscription update' do
|
||||
it 'resets captain usage on billing period renewal' do
|
||||
# Prime the account with some usage
|
||||
5.times { account.increment_response_usage }
|
||||
expect(account.custom_attributes['captain_responses_usage']).to eq(5)
|
||||
@@ -70,6 +71,10 @@ describe Enterprise::Billing::HandleStripeEventService do
|
||||
# Setup for any plan
|
||||
allow(subscription).to receive(:[]).with('plan')
|
||||
.and_return({ 'id' => 'test', 'product' => 'plan_id_startups', 'name' => 'Startups' })
|
||||
allow(subscription).to receive(:[]).with('current_period_start').and_return(1_686_567_520)
|
||||
|
||||
# Simulate billing period renewal with previous_attributes showing old period
|
||||
allow(data).to receive(:previous_attributes).and_return({ 'current_period_start' => 1_683_975_520 })
|
||||
|
||||
stripe_event_service.new.perform(event: event)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user