feat: reconcile api_and_webhooks entitlement from billing plan

This commit is contained in:
Shivam Mishra
2026-07-09 17:51:32 +05:30
parent d3b294fe9c
commit d50bccf4e5
3 changed files with 61 additions and 1 deletions
@@ -37,8 +37,10 @@ class Enterprise::Billing::ReconcilePlanFeaturesService
def perform
account.disable_features(*PREMIUM_PLAN_FEATURES)
account.disable_features('captain_integration_v2') if default_plan?
account.disable_features('api_and_webhooks')
account.enable_features(*current_plan_features)
account.enable_features('captain_integration_v2') if captain_v2_default_eligible?
account.enable_features('api_and_webhooks') if api_and_webhooks_eligible?
account.enable_features(*manually_managed_features)
account.save!
end
@@ -56,6 +58,10 @@ class Enterprise::Billing::ReconcilePlanFeaturesService
end
end
def api_and_webhooks_eligible?
!default_plan? && account.custom_attributes['subscription_status'] == 'active'
end
def default_plan?
default_plan_name = cloud_plans.first&.dig('name')
return false if default_plan_name.blank?
@@ -54,7 +54,7 @@ class Internal::Accounts::InternalAttributesService
def valid_feature_list
Enterprise::Billing::ReconcilePlanFeaturesService::BUSINESS_PLAN_FEATURES +
Enterprise::Billing::ReconcilePlanFeaturesService::ENTERPRISE_PLAN_FEATURES +
%w[inbound_emails]
%w[inbound_emails api_and_webhooks]
end
# Account notes functionality removed for now
@@ -0,0 +1,54 @@
require 'rails_helper'
describe Enterprise::Billing::ReconcilePlanFeaturesService do
let(:account) { create(:account) }
before do
create(:installation_config, {
name: 'CHATWOOT_CLOUD_PLANS',
value: [
{ 'name' => 'Hacker', 'product_id' => ['plan_id_hacker'], 'price_ids' => ['price_hacker'] },
{ 'name' => 'Startups', 'product_id' => ['plan_id_startups'], 'price_ids' => ['price_startups'] }
]
})
end
describe '#perform' do
context 'with api_and_webhooks feature' do
it 'enables the feature for a paid plan with an active subscription' do
account.update!(custom_attributes: { 'plan_name' => 'Startups', 'subscription_status' => 'active' })
described_class.new(account: account).perform
expect(account.reload).to be_feature_enabled('api_and_webhooks')
end
it 'disables the feature for a paid plan on trial' do
account.enable_features!('api_and_webhooks')
account.update!(custom_attributes: { 'plan_name' => 'Startups', 'subscription_status' => 'trialing' })
described_class.new(account: account).perform
expect(account.reload).not_to be_feature_enabled('api_and_webhooks')
end
it 'disables the feature on the default plan' do
account.enable_features!('api_and_webhooks')
account.update!(custom_attributes: { 'plan_name' => 'Hacker', 'subscription_status' => 'active' })
described_class.new(account: account).perform
expect(account.reload).not_to be_feature_enabled('api_and_webhooks')
end
it 'keeps the feature enabled when manually managed' do
account.update!(custom_attributes: { 'plan_name' => 'Hacker', 'subscription_status' => 'trialing' })
Internal::Accounts::InternalAttributesService.new(account).manually_managed_features = ['api_and_webhooks']
described_class.new(account: account).perform
expect(account.reload).to be_feature_enabled('api_and_webhooks')
end
end
end
end