Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(invoice_custom_sections): add create_invoice_applied_custom_sections service #3008

Open
wants to merge 18 commits into
base: feat-invoice-custom-sections-api-controller
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ def call

if !section_ids.nil? || !section_codes.nil?
customer.skip_invoice_custom_sections = false
return result if customer.applicable_invoice_custom_sections.ids == section_ids ||
customer.applicable_invoice_custom_sections.map(&:code) == section_codes
return result if customer.selected_invoice_custom_sections.ids == section_ids ||
customer.selected_invoice_custom_sections.map(&:code) == section_codes

assign_selected_sections
end
Expand Down
1 change: 1 addition & 0 deletions app/services/invoices/add_on_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def create

create_add_on_fee(invoice)
compute_amounts(invoice)
Invoices::ApplyInvoiceCustomSectionsService.call(invoice:)

invoice.save!

Expand Down
1 change: 1 addition & 0 deletions app/services/invoices/advance_charges_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def create_group_invoice
end

Invoices::ComputeAmountsFromFees.call(invoice:)
Invoices::ApplyInvoiceCustomSectionsService.call(invoice:)

invoice.payment_status = :succeeded
Invoices::TransitionToFinalStatusService.call(invoice:)
Expand Down
34 changes: 34 additions & 0 deletions app/services/invoices/apply_invoice_custom_sections_service.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# frozen_string_literal: true

module Invoices
class ApplyInvoiceCustomSectionsService < BaseService
def initialize(invoice:)
@invoice = invoice
@customer = invoice.customer

super()
end

def call
result.applied_sections = []
return result if customer.skip_invoice_custom_sections

customer.applicable_invoice_custom_sections.each do |custom_section|
invoice.applied_invoice_custom_sections.create!(
code: custom_section.code,
details: custom_section.details,
display_name: custom_section.display_name,
name: custom_section.name
)
end
result.applied_sections = invoice.applied_invoice_custom_sections
result
rescue ActiveRecord::RecordInvalid => e
result.record_validation_failure!(record: e.record)
end

private

attr_reader :invoice, :customer
end
end
1 change: 1 addition & 0 deletions app/services/invoices/create_one_off_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def call
end

Invoices::ComputeAmountsFromFees.call(invoice:, provider_taxes: result.fees_taxes)
Invoices::ApplyInvoiceCustomSectionsService.call(invoice:)
invoice.payment_status = invoice.total_amount_cents.positive? ? :pending : :succeeded
Invoices::TransitionToFinalStatusService.call(invoice:)
invoice.save!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def call
Invoices::ComputeAmountsFromFees.call(invoice:, provider_taxes: result.fees_taxes)
create_credit_note_credit
create_applied_prepaid_credit if should_create_applied_prepaid_credit?
Invoices::ApplyInvoiceCustomSectionsService.call(invoice:)

invoice.payment_status = invoice.total_amount_cents.positive? ? :pending : :succeeded
Invoices::TransitionToFinalStatusService.call(invoice:)
Expand Down
1 change: 1 addition & 0 deletions app/services/invoices/paid_credit_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def call
ActiveRecord::Base.transaction do
create_credit_fee(invoice)
compute_amounts(invoice)
Invoices::ApplyInvoiceCustomSectionsService.call(invoice:)

if License.premium? && wallet_transaction.invoice_requires_successful_payment?
invoice.open!
Expand Down
1 change: 1 addition & 0 deletions app/services/invoices/progressive_billing_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ def call

Credits::ProgressiveBillingService.call(invoice:)
Credits::AppliedCouponsService.call(invoice:)
Invoices::ApplyInvoiceCustomSectionsService.call(invoice:)

totals_result = Invoices::ComputeTaxesAndTotalsService.call(invoice:)
return totals_result if !totals_result.success? && totals_result.error.is_a?(BaseService::UnknownTaxFailure)
Expand Down
3 changes: 3 additions & 0 deletions app/services/invoices/refresh_draft_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ def call
recurring:,
context:
)
Invoices::ApplyInvoiceCustomSectionsService.call(invoice:)

invoice.credit_notes.each do |credit_note|
subscription_id = cn_subscription_ids.find { |h| h[:credit_note_id] == credit_note.id }[:subscription_id]
Expand Down Expand Up @@ -121,6 +122,7 @@ def reset_invoice_values
invoice_subscriptions.destroy_all
invoice.applied_taxes.destroy_all
invoice.error_details.discard_all
invoice.applied_invoice_custom_sections.destroy_all

invoice.taxes_amount_cents = 0
invoice.total_amount_cents = 0
Expand All @@ -129,6 +131,7 @@ def reset_invoice_values
invoice.sub_total_excluding_taxes_amount_cents = 0
invoice.sub_total_including_taxes_amount_cents = 0
invoice.progressive_billing_credit_amount_cents = 0

invoice.save!
end
end
Expand Down
1 change: 1 addition & 0 deletions app/services/invoices/subscription_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def call
recurring:,
context:
)
Invoices::ApplyInvoiceCustomSectionsService.call(invoice:)

set_invoice_generated_status unless invoice.pending?
invoice.save!
Expand Down
4 changes: 4 additions & 0 deletions spec/services/invoices/add_on_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@
let(:service_call) { invoice_service.create }
end

it_behaves_like "applies invoice_custom_sections" do
let(:service_call) { invoice_service.create }
end

context 'with customer timezone' do
before { applied_add_on.customer.update!(timezone: 'America/Los_Angeles') }

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe Invoices::ApplyInvoiceCustomSectionsService, type: :service do
subject(:invoice_service) { described_class.new(invoice:) }

let(:organization) { create(:organization) }
let(:customer) { create(:customer, organization:) }
let(:invoice) { create(:invoice, customer:) }
let(:custom_sections) { create_list(:invoice_custom_section, 3, organization:) }

before do
organization.selected_invoice_custom_sections << custom_sections[1..2]
end

describe '#call' do
context 'when the customer has skip_invoice_custom_sections flag' do
let(:customer) { create(:customer, organization:, skip_invoice_custom_sections: true) }

it 'does not apply any custom sections' do
result = invoice_service.call
expect(result).to be_success
expect(result.applied_sections).to be_empty
expect(invoice.reload.applied_invoice_custom_sections).to be_empty
end
end

context 'when the customer has custom sections' do
before do
customer.selected_invoice_custom_sections << custom_sections[0..1]
end

it 'applies the custom sections to the invoice' do
result = invoice_service.call
expect(result).to be_success
sections = invoice.reload.applied_invoice_custom_sections
expect(sections.map(&:code)).to match_array(custom_sections[0..1].map(&:code))
expect(sections.map(&:details)).to match_array(custom_sections[0..1].map(&:details))
expect(sections.map(&:display_name)).to match_array(custom_sections[0..1].map(&:display_name))
expect(sections.map(&:name)).to match_array(custom_sections[0..1].map(&:name))
end
end

context 'when the customer inherits custom sections from the organization' do
it 'applies the organization\'s sections to the invoice' do
result = invoice_service.call
expect(result).to be_success
sections = invoice.reload.applied_invoice_custom_sections
expect(sections.map(&:code)).to match_array(custom_sections[1..2].map(&:code))
expect(sections.map(&:details)).to match_array(custom_sections[1..2].map(&:details))
expect(sections.map(&:display_name)).to match_array(custom_sections[1..2].map(&:display_name))
expect(sections.map(&:name)).to match_array(custom_sections[1..2].map(&:name))
end
end
end
end
4 changes: 4 additions & 0 deletions spec/services/invoices/create_one_off_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@
let(:service_call) { create_service.call }
end

it_behaves_like "applies invoice_custom_sections" do
let(:service_call) { create_service.call }
end

it 'calls SegmentTrackJob' do
invoice = create_service.call.invoice

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -318,5 +318,9 @@
expect(result.invoice).to be_finalized
end
end

it_behaves_like "applies invoice_custom_sections" do
let(:service_call) { invoice_service.call }
end
end
end
4 changes: 4 additions & 0 deletions spec/services/invoices/paid_credit_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@
let(:service_call) { invoice_service.call }
end

it_behaves_like "applies invoice_custom_sections" do
let(:service_call) { invoice_service.call }
end

it 'does not enqueue an SendEmailJob' do
expect do
invoice_service.call
Expand Down
4 changes: 4 additions & 0 deletions spec/services/invoices/progressive_billing_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,5 +232,9 @@
it_behaves_like 'syncs invoice' do
let(:service_call) { create_service.call }
end

it_behaves_like "applies invoice_custom_sections" do
let(:service_call) { create_service.call }
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@
let(:service_call) { finalize_service.call }
end

it_behaves_like "applies invoice_custom_sections" do
let(:service_call) { finalize_service.call }
end

it 'enqueues a SendWebhookJob' do
expect do
finalize_service.call
Expand Down
19 changes: 19 additions & 0 deletions spec/services/invoices/refresh_draft_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@
.to change { invoice.reload.progressive_billing_credit_amount_cents }.from(1239000).to(0)
end

it_behaves_like "applies invoice_custom_sections" do
let(:service_call) { refresh_service.call }
end

context 'when there is a tax_integration set up' do
let(:integration) { create(:anrok_integration, organization:) }
let(:integration_customer) { create(:anrok_customer, integration:, customer:) }
Expand Down Expand Up @@ -203,6 +207,21 @@
end
end

context 'when invoice has other applied invoice_custom_sections' do
let(:invoice_custom_sections) { create_list(:invoice_custom_section, 4, organization: organization) }
let(:applied_invoice_custom_sections) { create_list(:applied_invoice_custom_section, 2, invoice: invoice) }

before do
applied_invoice_custom_sections
customer.selected_invoice_custom_sections = invoice_custom_sections.take(3)
end

it 'creates new applied_invoice_custom_sections' do
expect { refresh_service.call }.to change { invoice.reload.applied_invoice_custom_sections.count }.from(2).to(3)
expect(invoice.applied_invoice_custom_sections.map(&:code)).to match(customer.selected_invoice_custom_sections.map(&:code))
end
end

it 'flags lifetime usage for refresh' do
create(:usage_threshold, plan: subscription.plan)

Expand Down
4 changes: 4 additions & 0 deletions spec/services/invoices/subscription_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@
let(:service_call) { invoice_service.call }
end

it_behaves_like "applies invoice_custom_sections" do
let(:service_call) { invoice_service.call }
end

it "enqueues a SendWebhookJob" do
expect do
invoice_service.call
Expand Down
25 changes: 25 additions & 0 deletions spec/support/shared_examples/applied_invoice_custom_sections.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# frozen_string_literal: true

RSpec.shared_examples 'applies invoice_custom_sections' do
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

let(:invoice_custom_sections) { create_list(:invoice_custom_section, 4, organization:) }

before do
organization.selected_invoice_custom_sections = invoice_custom_sections[2..3]
end

context 'when the customer has :skip_invoice_custom_sections flag' do
before { customer.update(skip_invoice_custom_sections: true) }

it 'doesn\'t create applied_invoice_custom_section' do
expect { service_call }.not_to change(AppliedInvoiceCustomSection, :count)
end
end

context 'when customer follows organizations invoice_custom_sections' do
it 'creates applied_invoice_custom_sections' do
result = service_call
invoice = result.invoice
expect(invoice.applied_invoice_custom_sections.pluck(:code)).to match_array(organization.selected_invoice_custom_sections.pluck(:code))
end
end
end
Loading