Skip to content

Commit e56acb2

Browse files
authored
fix(e-invoices): Handle zero-fee invoices in allowance calculation (#5287)
## Context Invoices with zero-amount fees (e.g. yearly plans with only fixed charges terminated mid-period) cause `Invoices::GenerateDocumentsJob` to fail with `ArgumentError: must be initialized with a finite value` when the billing entity has e-invoicing enabled. Scenario to reproduce: Preconditions: - Organization billing entity with E-Invoicing enabled - Plan with Subscription Fee amount = 0 Steps: 1. Add a subscription with the Plan to a customer 2. Terminate subscription Actual result in Sidekiq: Invoices::GenerateDocumentsJob, ArgumentError: must be initialized with a finite value ## Description Root cause: If all fees are zero, `fdiv(0)` produced `Infinity` which `Money.new` rejects. Fix: Added a guard before the division when fees are zero.
1 parent b747f59 commit e56acb2

3 files changed

Lines changed: 36 additions & 1 deletion

File tree

app/serializers/e_invoices/invoices/common.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ def taxes(&block)
6767
end
6868

6969
def allowances_per_tax_rate
70+
fees_total = invoice.fees.sum(:precise_amount_cents)
71+
7072
invoice.fees.group_by(&:taxes_rate).map do |tax_rate, fees|
7173
total_amount = fees.sum(&:precise_amount_cents)
7274

@@ -76,7 +78,8 @@ def allowances_per_tax_rate
7678

7779
[tax_rate, total_amount - charged_amount]
7880
else
79-
[tax_rate, total_amount.fdiv(invoice.fees.sum(:precise_amount_cents)) * allowances]
81+
proportion = fees_total.zero? ? 0 : total_amount.fdiv(fees_total)
82+
[tax_rate, proportion * allowances]
8083
end
8184
end.to_h
8285
end

spec/serializers/e_invoices/invoices/factur_x/builder_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,22 @@
315315
expect(subject).to contains_xml_node("#{root}[3]/ram:CategoryTradeTax/ram:RateApplicablePercent").with_value("10.00")
316316
end
317317
end
318+
319+
context "when all fees have zero precise_amount_cents" do
320+
let(:invoice) { create(:invoice, coupons_amount_cents: 100, invoice_type:) }
321+
let(:invoice_fee1) { create(:fee, invoice:, taxes_rate: 0.0, precise_amount_cents: 0, taxes_precise_amount_cents: 0) }
322+
let(:invoice_fee2) { nil }
323+
let(:invoice_fee3) { nil }
324+
let(:invoice_fee4) { nil }
325+
326+
it "does not raise an error" do
327+
expect { subject }.not_to raise_error
328+
end
329+
330+
it "does not contain SpecifiedTradeAllowanceCharge tags" do
331+
expect(subject.xpath(root).length).to eq(0)
332+
end
333+
end
318334
end
319335

320336
context "when SpecifiedTradePaymentTerms tag" do

spec/serializers/e_invoices/invoices/ubl/builder_spec.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,22 @@
221221
expect(subject).to contains_xml_node("#{root}[3]/cac:TaxCategory/cac:TaxScheme/cbc:ID").with_value("VAT")
222222
end
223223
end
224+
225+
context "when all fees have zero precise_amount_cents" do
226+
let(:invoice) { create(:invoice, coupons_amount_cents: 100, invoice_type:) }
227+
let(:invoice_fee1) { create(:fee, invoice:, taxes_rate: 0.0, precise_amount_cents: 0, taxes_precise_amount_cents: 0) }
228+
let(:invoice_fee2) { nil }
229+
let(:invoice_fee3) { nil }
230+
let(:invoice_fee4) { nil }
231+
232+
it "does not raise an error" do
233+
expect { subject }.not_to raise_error
234+
end
235+
236+
it "does not contain AllowanceCharge tags" do
237+
expect(subject.xpath(root).length).to eq(0)
238+
end
239+
end
224240
end
225241

226242
context "when TaxTotal tag" do

0 commit comments

Comments
 (0)