diff --git a/app/models/invoice.rb b/app/models/invoice.rb index bacbc7b397f..78193c24791 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -414,7 +414,7 @@ def generate_organization_sequential_id ) do # If previous invoice had different numbering, base sequential id is the total number of invoices organization_sequential_id = if switched_from_customer_numbering? - organization.invoices.with_generated_number.count + organization.invoices.non_self_billed.with_generated_number.count else organization .invoices diff --git a/app/services/customers/create_service.rb b/app/services/customers/create_service.rb index 7def39797d8..e20c16472f2 100644 --- a/app/services/customers/create_service.rb +++ b/app/services/customers/create_service.rb @@ -57,7 +57,7 @@ def create_from_api(organization:, params:) customer.lastname = params[:lastname] if params.key?(:lastname) customer.customer_type = params[:customer_type] if params.key?(:customer_type) - if customer.organization.revenue_share_enabled? + if customer.organization.revenue_share_enabled? && customer.editable? customer.account_type = params[:account_type] if params.key?(:account_type) customer.exclude_from_dunning_campaign = customer.partner_account? end diff --git a/spec/scenarios/invoices/invoice_numbering_spec.rb b/spec/scenarios/invoices/invoice_numbering_spec.rb index 18254f60cad..754adc2a902 100644 --- a/spec/scenarios/invoices/invoice_numbering_spec.rb +++ b/spec/scenarios/invoices/invoice_numbering_spec.rb @@ -746,4 +746,135 @@ end end end + + context 'with partner customer' do + let(:customer_third) { create(:customer, organization:, account_type: 'partner') } + + around { |test| lago_premium!(&test) } + + before { organization.update!(premium_integrations: ['revenue_share']) } + + it 'creates invoice numbers correctly' do + # NOTE: Jul 19th: create the subscription + travel_to(subscription_at) do + create_subscription( + { + external_customer_id: customer_first.external_id, + external_id: customer_first.external_id, + plan_code: monthly_plan.code, + billing_time: 'anniversary', + subscription_at: subscription_at.iso8601 + } + ) + create_subscription( + { + external_customer_id: customer_second.external_id, + external_id: customer_second.external_id, + plan_code: monthly_plan.code, + billing_time: 'anniversary', + subscription_at: subscription_at.iso8601 + } + ) + create_subscription( + { + external_customer_id: customer_third.external_id, + external_id: customer_third.external_id, + plan_code: monthly_plan.code, + billing_time: 'anniversary', + subscription_at: subscription_at.iso8601 + } + ) + + invoices = organization.invoices.order(created_at: :desc).limit(3) + sequential_ids = invoices.pluck(:sequential_id) + organization_sequential_ids = invoices.pluck(:organization_sequential_id) + numbers = invoices.pluck(:number) + + expect(sequential_ids).to match_array([1, 1, 1]) + expect(organization_sequential_ids).to match_array([0, 0, 0]) + expect(numbers).to match_array(%w[ORG-1-001-001 ORG-1-002-001 ORG-1-003-001]) + end + + # NOTE: August 19th: Bill subscription + travel_to(DateTime.new(2023, 8, 19, 12, 12)) do + Subscriptions::BillingService.call + perform_all_enqueued_jobs + + invoices = organization.invoices.order(created_at: :desc).limit(3) + sequential_ids = invoices.pluck(:sequential_id) + organization_sequential_ids = invoices.pluck(:organization_sequential_id) + numbers = invoices.pluck(:number) + + expect(sequential_ids).to match_array([2, 2, 2]) + expect(organization_sequential_ids).to match_array([0, 0, 0]) + expect(numbers).to match_array(%w[ORG-1-001-002 ORG-1-002-002 ORG-1-003-002]) + end + + # NOTE: September 19th: Bill subscription + travel_to(DateTime.new(2023, 9, 19, 12, 12)) do + Subscriptions::BillingService.call + perform_all_enqueued_jobs + + invoices = organization.invoices.order(created_at: :desc).limit(3) + sequential_ids = invoices.pluck(:sequential_id) + organization_sequential_ids = invoices.pluck(:organization_sequential_id) + numbers = invoices.pluck(:number) + + expect(sequential_ids).to match_array([3, 3, 3]) + expect(organization_sequential_ids).to match_array([0, 0, 0]) + expect(numbers).to match_array(%w[ORG-1-001-003 ORG-1-002-003 ORG-1-003-003]) + end + + # NOTE: October 19th: Switching to per_organization numbering and Bill subscription + travel_to(DateTime.new(2023, 10, 19, 12, 12)) do + organization.update!(document_numbering: 'per_organization', document_number_prefix: 'ORG-11') + + Subscriptions::BillingService.call + perform_all_enqueued_jobs + + invoices = organization.invoices.order(created_at: :desc).limit(3) + sequential_ids = invoices.pluck(:sequential_id) + organization_sequential_ids = invoices.pluck(:organization_sequential_id) + numbers = invoices.pluck(:number) + + expect(sequential_ids).to match_array([4, 4, 4]) + expect(organization_sequential_ids).to match_array([7, 8, 0]) + expect(numbers).to match_array(%w[ORG-11-202310-007 ORG-11-202310-008 ORG-11-003-004]) + end + + # NOTE: November 19th: Switching to per_customer numbering and Bill subscription + travel_to(DateTime.new(2023, 11, 19, 12, 12)) do + organization.update!(document_numbering: 'per_customer') + + Subscriptions::BillingService.call + perform_all_enqueued_jobs + + invoices = organization.invoices.order(created_at: :desc).limit(3) + sequential_ids = invoices.pluck(:sequential_id) + organization_sequential_ids = invoices.pluck(:organization_sequential_id) + numbers = invoices.pluck(:number) + + expect(sequential_ids).to match_array([5, 5, 5]) + expect(organization_sequential_ids).to match_array([0, 0, 0]) + expect(numbers).to match_array(%w[ORG-11-001-005 ORG-11-002-005 ORG-11-003-005]) + end + + # NOTE: December 19th: Switching to per_organization numbering and Bill subscription + travel_to(DateTime.new(2023, 12, 19, 12, 12)) do + organization.update!(document_numbering: 'per_organization') + + Subscriptions::BillingService.call + perform_all_enqueued_jobs + + invoices = organization.invoices.order(created_at: :desc).limit(3) + sequential_ids = invoices.pluck(:sequential_id) + organization_sequential_ids = invoices.pluck(:organization_sequential_id) + numbers = invoices.pluck(:number) + + expect(sequential_ids).to match_array([6, 6, 6]) + expect(organization_sequential_ids).to match_array([11, 12, 0]) + expect(numbers).to match_array(%w[ORG-11-202312-011 ORG-11-202312-012 ORG-11-003-006]) + end + end + end end diff --git a/spec/services/customers/create_service_spec.rb b/spec/services/customers/create_service_spec.rb index bd04cb3929d..c2d94d4ced7 100644 --- a/spec/services/customers/create_service_spec.rb +++ b/spec/services/customers/create_service_spec.rb @@ -350,6 +350,25 @@ expect(customer).to be_partner_account expect(customer).to be_exclude_from_dunning_campaign end + + context "when updating a customer that already have an invoice" do + let(:customer) { create(:customer, organization:, account_type: "customer") } + let(:invoice) { create(:invoice, customer: customer) } + + before { invoice } + + it "doesn't update customer to partner" do + result = customers_service.create_from_api( + organization:, + params: create_args.merge(external_id: customer.external_id) + ) + + expect(result).to be_success + + customer = result.customer + expect(customer).to be_customer_account + end + end end end