-
Notifications
You must be signed in to change notification settings - Fork 103
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat (invoice_custom_sections): customer update service (#2960)
## Description Added service to manage invoice_custom_sections on customer level
- Loading branch information
1 parent
58466c8
commit 5437092
Showing
19 changed files
with
382 additions
and
113 deletions.
There are no files selected for viewing
49 changes: 49 additions & 0 deletions
49
app/services/customers/manage_invoice_custom_sections_service.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 0 additions & 26 deletions
26
app/services/invoice_custom_sections/deselect/for_all_usages_service.rb
This file was deleted.
Oops, something went wrong.
31 changes: 0 additions & 31 deletions
31
app/services/invoice_custom_sections/deselect/for_organization_service.rb
This file was deleted.
Oops, something went wrong.
24 changes: 24 additions & 0 deletions
24
app/services/invoice_custom_sections/deselect_all_service.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
app/services/organizations/deselect_invoice_custom_section_service.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
10 changes: 5 additions & 5 deletions
10
...invoice_custom_sections/select_service.rb → .../select_invoice_custom_section_service.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
123 changes: 123 additions & 0 deletions
123
spec/services/customers/manage_invoice_custom_sections_service_spec.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Oops, something went wrong.