From bd0c73e8f566a2eda91e144a3c186ea498d50f49 Mon Sep 17 00:00:00 2001 From: Vincent Pochet Date: Tue, 3 Dec 2024 11:32:17 +0100 Subject: [PATCH] fix(customer): Catch ActiveRecord::RecordNotUnique when creating with API --- app/services/customers/create_service.rb | 22 +++++++------- .../integrations/salesforce/create_spec.rb | 29 +++++++++---------- .../integrations/salesforce/update_spec.rb | 29 +++++++++---------- 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/app/services/customers/create_service.rb b/app/services/customers/create_service.rb index 4211dfebb15..3bfe6266a77 100644 --- a/app/services/customers/create_service.rb +++ b/app/services/customers/create_service.rb @@ -12,21 +12,21 @@ def create_from_api(organization:, params:) unless valid_metadata_count?(metadata: params[:metadata]) return result.single_validation_failure!( field: :metadata, - error_code: 'invalid_count' + error_code: "invalid_count" ) end unless valid_finalize_zero_amount_invoice?(params[:finalize_zero_amount_invoice]) return result.single_validation_failure!( field: :finalize_zero_amount_invoice, - error_code: 'invalid_value' + error_code: "invalid_value" ) end unless valid_integration_customers_count?(integration_customers: params[:integration_customers]) return result.single_validation_failure!( field: :integration_customers, - error_code: 'invalid_count_per_integration_type' + error_code: "invalid_count_per_integration_type" ) end @@ -52,7 +52,7 @@ def create_from_api(organization:, params:) customer.legal_number = params[:legal_number] if params.key?(:legal_number) customer.net_payment_term = params[:net_payment_term] if params.key?(:net_payment_term) customer.external_salesforce_id = params[:external_salesforce_id] if params.key?(:external_salesforce_id) - customer.finalize_zero_amount_invoice = params[:finalize_zero_amount_invoice] || 'inherit' if params.key?(:finalize_zero_amount_invoice) + customer.finalize_zero_amount_invoice = params[:finalize_zero_amount_invoice] || "inherit" if params.key?(:finalize_zero_amount_invoice) customer.firstname = params[:firstname] if params.key?(:firstname) customer.lastname = params[:lastname] if params.key?(:lastname) customer.customer_type = params[:customer_type] if params.key?(:customer_type) @@ -108,6 +108,8 @@ def create_from_api(organization:, params:) result.record_validation_failure!(record: e.record) rescue BaseService::FailedResult => e result.fail_with_error!(e) + rescue ActiveRecord::RecordNotUnique + result.single_validation_failure!(field: :external_id, error_code: "value_already_exist") end def create(**args) @@ -117,7 +119,7 @@ def create(**args) unless valid_metadata_count?(metadata: args[:metadata]) return result.single_validation_failure!( field: :metadata, - error_code: 'invalid_count' + error_code: "invalid_count" ) end @@ -304,11 +306,11 @@ def handle_api_billing_configuration(customer, params, new_customer) def create_or_update_provider_customer(customer, billing_configuration = {}) provider_class = case billing_configuration[:payment_provider] || customer.payment_provider - when 'stripe' + when "stripe" PaymentProviderCustomers::StripeCustomer - when 'gocardless' + when "gocardless" PaymentProviderCustomers::GocardlessCustomer - when 'adyen' + when "adyen" PaymentProviderCustomers::AdyenCustomer end @@ -325,7 +327,7 @@ def create_or_update_provider_customer(customer, billing_configuration = {}) def track_customer_created(customer) SegmentTrackJob.perform_later( membership_id: CurrentContext.membership, - event: 'customer_created', + event: "customer_created", properties: { customer_id: customer.id, created_at: customer.created_at, @@ -333,7 +335,7 @@ def track_customer_created(customer) organization_id: customer.organization_id } ) - SendWebhookJob.perform_later('customer.created', customer) + SendWebhookJob.perform_later("customer.created", customer) end def should_create_billing_configuration?(billing, customer) diff --git a/spec/graphql/mutations/integrations/salesforce/create_spec.rb b/spec/graphql/mutations/integrations/salesforce/create_spec.rb index 004cd465280..c71fb035ae6 100644 --- a/spec/graphql/mutations/integrations/salesforce/create_spec.rb +++ b/spec/graphql/mutations/integrations/salesforce/create_spec.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -require 'rails_helper' +require "rails_helper" RSpec.describe Mutations::Integrations::Salesforce::Create, type: :graphql do - let(:required_permission) { 'organization:integrations:create' } + let(:required_permission) { "organization:integrations:create" } let(:membership) { create(:membership) } - let(:name) { 'Salesforce 1' } - let(:code) { 'salesforce_test' } + let(:name) { "Salesforce 1" } + let(:code) { "salesforce_test" } let(:script_endpoint_url) { Faker::Internet.url } let(:mutation) do @@ -24,13 +24,13 @@ around { |test| lago_premium!(&test) } - before { membership.organization.update!(premium_integrations: ['salesforce']) } + before { membership.organization.update!(premium_integrations: ["salesforce"]) } - it_behaves_like 'requires current user' - it_behaves_like 'requires current organization' - it_behaves_like 'requires permission', 'organization:integrations:create' + it_behaves_like "requires current user" + it_behaves_like "requires current organization" + it_behaves_like "requires permission", "organization:integrations:create" - it 'creates a salesforce integration' do + it "creates a salesforce integration" do result = execute_graphql( current_user: membership.user, current_organization: membership.organization, @@ -40,18 +40,17 @@ input: { name:, code:, - instanceId: 'this-is-random-uuid' + instanceId: "this-is-random-uuid" } } ) - pp result - result_data = result['data']['createSalesforceIntegration'] + result_data = result["data"]["createSalesforceIntegration"] aggregate_failures do - expect(result_data['id']).to be_present - expect(result_data['code']).to eq(code) - expect(result_data['name']).to eq(name) + expect(result_data["id"]).to be_present + expect(result_data["code"]).to eq(code) + expect(result_data["name"]).to eq(name) end end end diff --git a/spec/graphql/mutations/integrations/salesforce/update_spec.rb b/spec/graphql/mutations/integrations/salesforce/update_spec.rb index 3ce1fe5a23b..417fcf08ed4 100644 --- a/spec/graphql/mutations/integrations/salesforce/update_spec.rb +++ b/spec/graphql/mutations/integrations/salesforce/update_spec.rb @@ -1,15 +1,15 @@ # frozen_string_literal: true -require 'rails_helper' +require "rails_helper" RSpec.describe Mutations::Integrations::Salesforce::Update, type: :graphql do - let(:required_permission) { 'organization:integrations:update' } + let(:required_permission) { "organization:integrations:update" } let(:integration) { create(:salesforce_integration, organization:) } let(:organization) { membership.organization } let(:membership) { create(:membership) } - let(:name) { 'Salesforce 1' } - let(:code) { 'salesforce_work' } - let(:instance_id) { 'salesforce_link' } + let(:name) { "Salesforce 1" } + let(:code) { "salesforce_work" } + let(:instance_id) { "salesforce_link" } let(:mutation) do <<-GQL @@ -28,14 +28,14 @@ before do integration - membership.organization.update!(premium_integrations: ['salesforce']) + membership.organization.update!(premium_integrations: ["salesforce"]) end - it_behaves_like 'requires current user' - it_behaves_like 'requires current organization' - it_behaves_like 'requires permission', 'organization:integrations:update' + it_behaves_like "requires current user" + it_behaves_like "requires current organization" + it_behaves_like "requires permission", "organization:integrations:update" - it 'updates a salesforce integration' do + it "updates a salesforce integration" do result = execute_graphql( current_user: membership.user, current_organization: membership.organization, @@ -51,13 +51,12 @@ } ) - pp result - result_data = result['data']['updateSalesforceIntegration'] + result_data = result["data"]["updateSalesforceIntegration"] aggregate_failures do - expect(result_data['name']).to eq(name) - expect(result_data['code']).to eq(code) - expect(result_data['instanceId']).to eq(instance_id) + expect(result_data["name"]).to eq(name) + expect(result_data["code"]).to eq(code) + expect(result_data["instanceId"]).to eq(instance_id) end end end