diff --git a/app/services/customers/manage_invoice_custom_sections_service.rb b/app/services/customers/manage_invoice_custom_sections_service.rb new file mode 100644 index 00000000000..771549a6e6d --- /dev/null +++ b/app/services/customers/manage_invoice_custom_sections_service.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module Customers + class ManageInvoiceCustomSectionsService < BaseService + def initialize(customer:, skip_invoice_custom_sections:, section_ids:) + @customer = customer + @section_ids = section_ids + @skip_invoice_custom_sections = skip_invoice_custom_sections + + super + end + + def call + return result.not_found_failure!(resource: "customer") unless customer + raise_invalid_params if skip_invoice_custom_sections && section_ids.present? + + ActiveRecord::Base.transaction do + unless skip_invoice_custom_sections.nil? + customer.selected_invoice_custom_sections = [] if !!skip_invoice_custom_sections + customer.skip_invoice_custom_sections = skip_invoice_custom_sections + end + + unless section_ids.nil? + customer.skip_invoice_custom_sections = false + return result if customer.applicable_invoice_custom_sections.ids == section_ids + + assign_selected_sections + end + customer.save! + end + result + rescue ActiveRecord::RecordInvalid => e + result.record_validation_failure!(record: e.record) + end + + private + + attr_reader :customer, :section_ids, :skip_invoice_custom_sections + + def raise_invalid_params + result.validation_failure!(errors: {invoice_custom_sections: ['skip_sections_and_selected_ids_sent_together']}) + end + + def assign_selected_sections + # Note: when assigning organization's sections, an empty array will be sent + customer.selected_invoice_custom_sections = customer.organization.invoice_custom_sections.where(id: section_ids) + end + end +end diff --git a/app/services/customers/update_service.rb b/app/services/customers/update_service.rb index ea3c3e4de1d..066a07d5438 100644 --- a/app/services/customers/update_service.rb +++ b/app/services/customers/update_service.rb @@ -116,6 +116,12 @@ def call customer.reset_dunning_campaign! end + Customers::ManageInvoiceCustomSectionsService.call( + customer:, + skip_invoice_custom_sections: args[:skip_invoice_custom_sections], + section_ids: args[:selected_invoice_custom_section_ids] + ).raise_if_error! + customer.save! customer.reload diff --git a/app/services/invoice_custom_sections/create_service.rb b/app/services/invoice_custom_sections/create_service.rb index 3a6ad26cac3..7deb6b49186 100644 --- a/app/services/invoice_custom_sections/create_service.rb +++ b/app/services/invoice_custom_sections/create_service.rb @@ -11,7 +11,7 @@ def initialize(organization:, create_params:, selected: false) def call invoice_custom_section = organization.invoice_custom_sections.create!(create_params) - SelectService.call(section: invoice_custom_section, organization:) if selected + Organizations::SelectInvoiceCustomSectionService.call(section: invoice_custom_section) if selected result.invoice_custom_section = invoice_custom_section result rescue ActiveRecord::RecordInvalid => e diff --git a/app/services/invoice_custom_sections/deselect/for_all_usages_service.rb b/app/services/invoice_custom_sections/deselect/for_all_usages_service.rb deleted file mode 100644 index 18a94ea3f5e..00000000000 --- a/app/services/invoice_custom_sections/deselect/for_all_usages_service.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: true - -module InvoiceCustomSections - module Deselect - class ForAllUsagesService < BaseService - def initialize(section:) - @section = section - super - end - - def call - deselect_for_all_usages - result - end - - private - - attr_reader :section - - def deselect_for_all_usages - InvoiceCustomSectionSelection.where(invoice_custom_section_id: section.id).destroy_all - result.invoice_custom_section = section - end - end - end -end diff --git a/app/services/invoice_custom_sections/deselect/for_organization_service.rb b/app/services/invoice_custom_sections/deselect/for_organization_service.rb deleted file mode 100644 index 9032ddbf5b4..00000000000 --- a/app/services/invoice_custom_sections/deselect/for_organization_service.rb +++ /dev/null @@ -1,31 +0,0 @@ -# frozen_string_literal: true - -module InvoiceCustomSections - module Deselect - class ForOrganizationService < BaseService - def initialize(section:) - @section = section - @organization = section.organization - super - end - - def call - deselect_for_organization - result - end - - private - - attr_reader :section, :organization - - def deselect_for_organization - return unless organization.selected_invoice_custom_sections.include?(section) - - InvoiceCustomSectionSelection.where( - organization_id: organization.id, invoice_custom_section_id: section.id - ).destroy_all - result.section = section - end - end - end -end diff --git a/app/services/invoice_custom_sections/deselect_all_service.rb b/app/services/invoice_custom_sections/deselect_all_service.rb new file mode 100644 index 00000000000..d4ed862e0b0 --- /dev/null +++ b/app/services/invoice_custom_sections/deselect_all_service.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module InvoiceCustomSections + class DeselectAllService < BaseService + def initialize(section:) + @section = section + super + end + + def call + deselect_for_all + result + end + + private + + attr_reader :section + + def deselect_for_all + InvoiceCustomSectionSelection.where(invoice_custom_section_id: section.id).destroy_all + result.invoice_custom_section = section + end + end +end diff --git a/app/services/invoice_custom_sections/destroy_service.rb b/app/services/invoice_custom_sections/destroy_service.rb index a3c4094aeff..51779e8595c 100644 --- a/app/services/invoice_custom_sections/destroy_service.rb +++ b/app/services/invoice_custom_sections/destroy_service.rb @@ -12,7 +12,7 @@ def call ActiveRecord::Base.transaction do invoice_custom_section.discard - Deselect::ForAllUsagesService.call(section: invoice_custom_section).raise_if_error! + DeselectAllService.call(section: invoice_custom_section).raise_if_error! result.invoice_custom_section = invoice_custom_section result end diff --git a/app/services/invoice_custom_sections/update_service.rb b/app/services/invoice_custom_sections/update_service.rb index 8432b9b72ff..dc07ff9415d 100644 --- a/app/services/invoice_custom_sections/update_service.rb +++ b/app/services/invoice_custom_sections/update_service.rb @@ -12,9 +12,9 @@ def initialize(invoice_custom_section:, update_params:, selected: false) def call invoice_custom_section.update!(update_params) if selected - SelectService.call(section: invoice_custom_section, organization: invoice_custom_section.organization) + Organizations::SelectInvoiceCustomSectionService.call(section: invoice_custom_section) else - Deselect::ForOrganizationService.call(section: invoice_custom_section) + Organizations::DeselectInvoiceCustomSectionService.call(section: invoice_custom_section) end result.invoice_custom_section = invoice_custom_section result diff --git a/app/services/organizations/deselect_invoice_custom_section_service.rb b/app/services/organizations/deselect_invoice_custom_section_service.rb new file mode 100644 index 00000000000..e2ce115f39f --- /dev/null +++ b/app/services/organizations/deselect_invoice_custom_section_service.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +module Organizations + class DeselectInvoiceCustomSectionService < BaseService + def initialize(section:) + @section = section + @organization = section.organization + super + end + + def call + deselect_for_organization + result.section = section + result + end + + private + + attr_reader :section, :organization + + def deselect_for_organization + return unless organization.selected_invoice_custom_sections.include?(section) + + InvoiceCustomSectionSelection.where( + organization_id: organization.id, invoice_custom_section_id: section.id + ).destroy_all + end + end +end diff --git a/app/services/invoice_custom_sections/select_service.rb b/app/services/organizations/select_invoice_custom_section_service.rb similarity index 67% rename from app/services/invoice_custom_sections/select_service.rb rename to app/services/organizations/select_invoice_custom_section_service.rb index 12c4f5f02aa..a72fba2f0d5 100644 --- a/app/services/invoice_custom_sections/select_service.rb +++ b/app/services/organizations/select_invoice_custom_section_service.rb @@ -1,15 +1,15 @@ # frozen_string_literal: true -module InvoiceCustomSections - class SelectService < BaseService - def initialize(section:, organization:) +module Organizations + class SelectInvoiceCustomSectionService < BaseService + def initialize(section:) @section = section - @organization = organization + @organization = section.organization super end def call - select_for_organization if organization + select_for_organization result end diff --git a/spec/services/customers/manage_invoice_custom_sections_service_spec.rb b/spec/services/customers/manage_invoice_custom_sections_service_spec.rb new file mode 100644 index 00000000000..2746124cd34 --- /dev/null +++ b/spec/services/customers/manage_invoice_custom_sections_service_spec.rb @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +require "rails_helper" + +RSpec.describe Customers::ManageInvoiceCustomSectionsService do + let(:customer) { create(:customer) } + let(:invoice_custom_sections) { create_list(:invoice_custom_section, 4, organization: customer.organization) } + let(:skip_invoice_custom_sections) { nil } + let(:service) { described_class.new(customer: customer, section_ids:, skip_invoice_custom_sections:) } + let(:section_ids) { nil } + + before do + customer.selected_invoice_custom_sections << invoice_custom_sections[0] if customer + customer.organization.selected_invoice_custom_sections = invoice_custom_sections[2..3] if customer + end + + describe "#call" do + context "when customer is not found" do + let(:customer) { nil } + + it "returns not found failure" do + result = service.call + expect(result).not_to be_success + expect(result.error).to be_a(BaseService::NotFoundFailure) + expect(result.error.message).to eq("customer_not_found") + end + end + + context "when sending skip_invoice_custom_sections: true AND selected_ids" do + let(:skip_invoice_custom_sections) { true } + let(:section_ids) { [1, 2, 3] } + + it "raises an error" do + result = service.call + expect(result).not_to be_success + expect(result.error).to be_a(BaseService::ValidationFailure) + expect(result.error.message).to include("skip_sections_and_selected_ids_sent_together") + end + end + + context "when updating selected_invoice_custom_sections" do + context "when section_ids match customer's applicable sections" do + let(:section_ids) { [invoice_custom_sections.first.id] } + + it "returns the result without changes" do + result = service.call + expect(result).to be_success + expect(customer.applicable_invoice_custom_sections.ids).to match_array(section_ids) + end + end + + context "when section_ids match organization's selected sections" do + let(:section_ids) { invoice_custom_sections[2..3].map(&:id) } + + it "still sets selected invoice_custom_sections as custom" do + service.call + expect(customer.reload.selected_invoice_custom_sections.ids).to match_array(invoice_custom_sections[2..3].map(&:id)) + expect(customer.applicable_invoice_custom_sections.ids).to match_array(section_ids) + end + end + + context "when section_ids are totally custom" do + let(:section_ids) { invoice_custom_sections[1..2].map(&:id) } + + it "assigns customer sections" do + service.call + expect(customer.reload.selected_invoice_custom_sections.ids).to match_array(section_ids) + expect(customer.applicable_invoice_custom_sections.ids).to match_array(section_ids) + end + end + + context "when selected_ids are an empty array" do + let(:section_ids) { [] } + + it "assigns organization sections" do + service.call + expect(customer.reload.selected_invoice_custom_sections.ids).to match_array([]) + expect(customer.applicable_invoice_custom_sections.ids).to match_array(customer.organization.selected_invoice_custom_sections.ids) + end + end + + context "when setting invoice_custom_sections_ids when previously customer had skip_invoice_custom_sections" do + let(:section_ids) { [] } + + before { customer.update(skip_invoice_custom_sections: true) } + + it "sets skip_invoice_custom_sections to false" do + service.call + expect(customer.reload.skip_invoice_custom_sections).to be false + expect(customer.selected_invoice_custom_sections.ids).to match_array([]) + expect(customer.applicable_invoice_custom_sections.ids).to match_array(customer.organization.selected_invoice_custom_sections.ids) + end + end + end + + context "when updating customer to skip_invoice_custom_sections" do + let(:skip_invoice_custom_sections) { true } + + before { customer.selected_invoice_custom_sections << invoice_custom_sections[1] } + + it "sets skip_invoice_custom_sections to true" do + service.call + expect(customer.reload.skip_invoice_custom_sections).to be true + expect(customer.selected_invoice_custom_sections).to be_empty + expect(customer.applicable_invoice_custom_sections).to be_empty + end + end + + context "when an ActiveRecord::RecordInvalid error is raised" do + let(:section_ids) { invoice_custom_sections[1..2].map(&:id) } + + before do + allow(customer).to receive(:selected_invoice_custom_sections=).and_raise(ActiveRecord::RecordInvalid.new(customer)) + end + + it "returns record validation failure" do + result = service.call + expect(result).not_to be_success + expect(result.error).to be_a(BaseService::ValidationFailure) + end + end + end +end diff --git a/spec/services/customers/update_service_spec.rb b/spec/services/customers/update_service_spec.rb index ebc7f0f196c..dccc73f6c1e 100644 --- a/spec/services/customers/update_service_spec.rb +++ b/spec/services/customers/update_service_spec.rb @@ -309,6 +309,97 @@ end end + context 'when updating invoice_custom_sections' do + let(:invoice_custom_sections) { create_list(:invoice_custom_section, 4, organization:) } + + before do + customer.selected_invoice_custom_sections << invoice_custom_sections[0] + organization.selected_invoice_custom_sections = invoice_custom_sections[2..3] + end + + context 'when customer is set to skip_invoice_custom_sections: true' do + let(:update_args) do + { + id: customer.id, + skip_invoice_custom_sections: true + } + end + + it 'clears customer selected invoice custom sections' do + result = customers_service.call + expect(result).to be_success + expect(customer.reload.selected_invoice_custom_sections).to be_empty + expect(customer.applicable_invoice_custom_sections).to be_empty + end + end + + context 'when setting to invoice custom sections that match with organization selected invoice custom sections' do + let(:update_args) do + { + id: customer.id, + selected_invoice_custom_section_ids: [] + } + end + + it 'assigns organization sections to customer' do + result = customers_service.call + expect(result).to be_success + expect(customer.reload.selected_invoice_custom_sections).to be_empty + expect(customer.applicable_invoice_custom_sections.ids).to match_array(invoice_custom_sections[2..3].map(&:id)) + end + end + + context 'when setting custom invoice_custom_sections for the customer' do + let(:update_args) do + { + id: customer.id, + selected_invoice_custom_section_ids: invoice_custom_sections[1..2].map(&:id) + } + end + + it 'assigns customer sections' do + result = customers_service.call + expect(result).to be_success + expect(customer.reload.selected_invoice_custom_sections.ids).to match_array(invoice_custom_sections[1..2].map(&:id)) + end + end + + context 'when setting custom invoice_custom_sections for the customer with skipped invoice_custom_sections' do + let(:update_args) do + { + id: customer.id, + selected_invoice_custom_section_ids: invoice_custom_sections[1..2].map(&:id) + } + end + + before { customer.update!(skip_invoice_custom_sections: true) } + + it 'updates skip_invoice_custom_sections to false' do + result = customers_service.call + expect(result).to be_success + expect(customer.reload.skip_invoice_custom_sections).to be false + expect(customer.selected_invoice_custom_sections.ids).to match_array(invoice_custom_sections[1..2].map(&:id)) + end + end + + context 'when sending both: skip_invoice_custom_sections and selected_invoice_custom_section_ids' do + let(:update_args) do + { + id: customer.id, + skip_invoice_custom_sections: true, + selected_invoice_custom_section_ids: invoice_custom_sections[1..2].map(&:id) + } + end + + it 'returns an error' do + result = customers_service.call + expect(result).not_to be_success + expect(result.error).to be_a(BaseService::ValidationFailure) + expect(result.error.messages[:invoice_custom_sections]).to include('skip_sections_and_selected_ids_sent_together') + end + end + end + context 'when organization has eu tax management' do let(:eu_auto_tax_service) { instance_double(Customers::EuAutoTaxesService) } diff --git a/spec/services/invoice_custom_sections/create_service_spec.rb b/spec/services/invoice_custom_sections/create_service_spec.rb index f503b361b09..eb3106437e3 100644 --- a/spec/services/invoice_custom_sections/create_service_spec.rb +++ b/spec/services/invoice_custom_sections/create_service_spec.rb @@ -21,7 +21,7 @@ end before do - allow(InvoiceCustomSections::SelectService).to receive(:call).and_call_original + allow(Organizations::SelectInvoiceCustomSectionService).to receive(:call).and_call_original end context 'when selected is true' do @@ -31,8 +31,8 @@ expect { service_result }.to change(organization.invoice_custom_sections, :count).by(1) .and change(organization.reload.selected_invoice_custom_sections, :count).by(1) expect(service_result.invoice_custom_section).to be_persisted.and have_attributes(create_params) - expect(InvoiceCustomSections::SelectService).to have_received(:call) - .with(section: service_result.invoice_custom_section, organization: organization) + expect(Organizations::SelectInvoiceCustomSectionService).to have_received(:call) + .with(section: service_result.invoice_custom_section) end end @@ -42,8 +42,8 @@ it 'creates an invoice_custom_section that belongs to the organization' do expect { service_result }.to change(organization.invoice_custom_sections, :count).by(1) expect(service_result.invoice_custom_section).to be_persisted.and have_attributes(create_params) - expect(InvoiceCustomSections::SelectService).not_to have_received(:call) - .with(section: service_result.invoice_custom_section, organization: organization) + expect(Organizations::SelectInvoiceCustomSectionService).not_to have_received(:call) + .with(section: service_result.invoice_custom_section) end end end diff --git a/spec/services/invoice_custom_sections/deselect/for_organization_service_spec.rb b/spec/services/invoice_custom_sections/deselect/for_organization_service_spec.rb deleted file mode 100644 index 043ec4b6496..00000000000 --- a/spec/services/invoice_custom_sections/deselect/for_organization_service_spec.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true - -require 'rails_helper' - -RSpec.describe InvoiceCustomSections::Deselect::ForOrganizationService, type: :service do - describe '#call' do - subject(:service_result) { described_class.call(section:) } - - let(:organization) { create(:organization) } - let(:section) { create(:invoice_custom_section, organization:) } - - context 'when the section is selected' do - before { organization.selected_invoice_custom_sections << section } - - it 'selects the section for the organization' do - expect { service_result }.to change(organization.reload.selected_invoice_custom_sections, :count).from(1).to(0) - expect(service_result).to be_success - expect(organization.selected_invoice_custom_sections).to eq([]) - end - end - - context 'when the section is not selected' do - it 'does not fail' do - service_result - expect(organization.selected_invoice_custom_sections).to eq([]) - end - end - end -end diff --git a/spec/services/invoice_custom_sections/deselect/for_all_usages_service_spec.rb b/spec/services/invoice_custom_sections/deselect_all_service_spec.rb similarity index 82% rename from spec/services/invoice_custom_sections/deselect/for_all_usages_service_spec.rb rename to spec/services/invoice_custom_sections/deselect_all_service_spec.rb index 3cd356daf2c..3c360fdc086 100644 --- a/spec/services/invoice_custom_sections/deselect/for_all_usages_service_spec.rb +++ b/spec/services/invoice_custom_sections/deselect_all_service_spec.rb @@ -2,7 +2,7 @@ require 'rails_helper' -RSpec.describe InvoiceCustomSections::Deselect::ForAllUsagesService, type: :service do +RSpec.describe InvoiceCustomSections::DeselectAllService, type: :service do describe '#call' do subject(:service_result) { described_class.call(section:) } @@ -16,7 +16,7 @@ customer.selected_invoice_custom_sections << section end - it 'selects the section for the organization' do + it 'deselects the section for the organization and customer' do expect { service_result }.to change(organization.selected_invoice_custom_sections, :count).from(1).to(0) .and change(customer.selected_invoice_custom_sections, :count).from(1).to(0) expect(InvoiceCustomSectionSelection.count).to eq(0) @@ -24,7 +24,7 @@ end context 'when the section is not selected' do - it 'selects the section for the organization' do + it 'does not update anything' do service_result expect(InvoiceCustomSectionSelection.count).to eq(0) end diff --git a/spec/services/invoice_custom_sections/destroy_service_spec.rb b/spec/services/invoice_custom_sections/destroy_service_spec.rb index 363beb06a67..4428f4f5910 100644 --- a/spec/services/invoice_custom_sections/destroy_service_spec.rb +++ b/spec/services/invoice_custom_sections/destroy_service_spec.rb @@ -10,7 +10,7 @@ let(:invoice_custom_section) { create(:invoice_custom_section, organization:) } before do - allow(InvoiceCustomSections::Deselect::ForAllUsagesService).to receive(:call).and_call_original + allow(InvoiceCustomSections::DeselectAllService).to receive(:call).and_call_original organization.selected_invoice_custom_sections << invoice_custom_section customer.selected_invoice_custom_sections << invoice_custom_section end @@ -21,10 +21,11 @@ result = service_result expect(result.invoice_custom_section.discarded?).to be(true) - expect(InvoiceCustomSections::Deselect::ForAllUsagesService).to have_received(:call) + expect(InvoiceCustomSections::DeselectAllService).to have_received(:call) .with(section: invoice_custom_section) expect(organization.selected_invoice_custom_sections).to eq([]) expect(customer.selected_invoice_custom_sections).to eq([]) + expect(customer.applicable_invoice_custom_sections).to eq([]) end end end diff --git a/spec/services/invoice_custom_sections/update_service_spec.rb b/spec/services/invoice_custom_sections/update_service_spec.rb index 5991d5af9fa..98392ba6025 100644 --- a/spec/services/invoice_custom_sections/update_service_spec.rb +++ b/spec/services/invoice_custom_sections/update_service_spec.rb @@ -11,8 +11,8 @@ let(:selected) { true } before do - allow(InvoiceCustomSections::SelectService).to receive(:call).and_call_original - allow(InvoiceCustomSections::Deselect::ForOrganizationService).to receive(:call).and_call_original + allow(Organizations::SelectInvoiceCustomSectionService).to receive(:call).and_call_original + allow(Organizations::DeselectInvoiceCustomSectionService).to receive(:call).and_call_original end describe '#call' do @@ -22,8 +22,8 @@ expect(result).to be_success expect(result.invoice_custom_section.name).to eq('Updated Name') - expect(InvoiceCustomSections::SelectService).to have_received(:call) - .with(section: invoice_custom_section, organization: organization) + expect(Organizations::SelectInvoiceCustomSectionService).to have_received(:call) + .with(section: invoice_custom_section) end context 'when pass selected as false' do @@ -31,7 +31,7 @@ it 'calls Deselect::ForOrganizationService when selected is false' do service_result - expect(InvoiceCustomSections::Deselect::ForOrganizationService).to have_received(:call) + expect(Organizations::DeselectInvoiceCustomSectionService).to have_received(:call) .with(section: invoice_custom_section) end end diff --git a/spec/services/organizations/deselect_invoice_custom_section_service_spec.rb b/spec/services/organizations/deselect_invoice_custom_section_service_spec.rb new file mode 100644 index 00000000000..e249fc24be0 --- /dev/null +++ b/spec/services/organizations/deselect_invoice_custom_section_service_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe Organizations::DeselectInvoiceCustomSectionService, type: :service do + describe '#call' do + subject(:service_call) { described_class.call(section:) } + + let(:organization) { create(:organization) } + let(:section) { create(:invoice_custom_section, organization:) } + + context 'when section is not selected for the organization' do + it 'deselects the section for the organization' do + result = service_call + expect(result).to be_success + expect(result.section.selected_for_organization?).to be false + end + end + + context 'when section is selected for the organization' do + before do + organization.selected_invoice_custom_sections << section + end + + it 'deselects the section for the organization' do + expect { service_call }.to change(organization.selected_invoice_custom_sections, :count).by(-1) + expect(organization.invoice_custom_sections).to include(section) + expect(section.selected_for_organization?).to be false + end + end + end +end diff --git a/spec/services/invoice_custom_sections/select_service_spec.rb b/spec/services/organizations/select_invoice_custom_section_service_spec.rb similarity index 63% rename from spec/services/invoice_custom_sections/select_service_spec.rb rename to spec/services/organizations/select_invoice_custom_section_service_spec.rb index 3fea0e7c404..6b61d8341ce 100644 --- a/spec/services/invoice_custom_sections/select_service_spec.rb +++ b/spec/services/organizations/select_invoice_custom_section_service_spec.rb @@ -2,12 +2,12 @@ require 'rails_helper' -RSpec.describe InvoiceCustomSections::SelectService, type: :service do +RSpec.describe Organizations::SelectInvoiceCustomSectionService, type: :service do describe '#call' do - subject(:service_result) { described_class.call(organization:, section:) } + subject(:service_result) { described_class.call(section:) } let(:organization) { create(:organization) } - let(:section) { create(:invoice_custom_section) } + let(:section) { create(:invoice_custom_section, organization:) } it 'selects the section for the organization' do expect { service_result }.to change(organization.selected_invoice_custom_sections, :count).by(1)