Skip to content
Merged
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
12 changes: 6 additions & 6 deletions lib/secretariat/invoice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,17 @@ def tax_reason_text
tax_reason || TAX_EXEMPTION_REASONS[tax_category]
end

def tax_category_code(version: 2)
def tax_category_code(tax, version: 2)
if version == 1
return TAX_CATEGORY_CODES_1[tax_category] || 'S'
return TAX_CATEGORY_CODES_1[tax.tax_category || tax_category] || 'S'
end
TAX_CATEGORY_CODES[tax_category] || 'S'
TAX_CATEGORY_CODES[tax.tax_category || tax_category] || 'S'
end

def taxes
taxes = {}
line_items.each do |line_item|
taxes[line_item.tax_percent] = Tax.new(tax_percent: BigDecimal(line_item.tax_percent)) if taxes[line_item.tax_percent].nil?
taxes[line_item.tax_percent] = Tax.new(tax_percent: BigDecimal(line_item.tax_percent), tax_category: line_item.tax_category) if taxes[line_item.tax_percent].nil?
taxes[line_item.tax_percent].tax_amount += BigDecimal(line_item.tax_amount)
taxes[line_item.tax_percent].base_amount += BigDecimal(line_item.net_amount) * line_item.quantity
end
Expand All @@ -91,7 +91,7 @@ def valid?
end
taxes.each do |tax|
calc_tax = tax.base_amount * BigDecimal(tax.tax_percent) / BigDecimal(100)
calc_tax = calc_tax.round(2, :down)
calc_tax = calc_tax.round(2)
if tax.tax_amount != calc_tax
@errors << "Tax amount and calculated tax amount deviate for rate #{tax.tax_percent}: #{tax.tax_amount} / #{calc_tax}"
return false
Expand Down Expand Up @@ -230,7 +230,7 @@ def to_xml(version: 1, validate: true)
xml['ram'].ExemptionReason tax_reason_text
end
Helpers.currency_element(xml, 'ram', 'BasisAmount', tax.base_amount, currency_code, add_currency: version == 1)
xml['ram'].CategoryCode tax_category_code(version: version)
xml['ram'].CategoryCode tax_category_code(tax, version: version)

percent = by_version(version, 'ApplicablePercent', 'RateApplicablePercent')
xml['ram'].send(percent, Helpers.format(tax.tax_percent))
Expand Down
1 change: 1 addition & 0 deletions lib/secretariat/line_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def valid?
end

calculated_tax = charge_price * BigDecimal(tax_percent) / BigDecimal(100)
calculated_tax = calculated_tax.round(2)
if calculated_tax != tax
@errors << "Tax and calculated tax deviate: #{tax} / #{calculated_tax}"
return false
Expand Down
1 change: 1 addition & 0 deletions lib/secretariat/tax.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ module Secretariat
Tax = Struct.new('Tax',
:tax_percent,
:tax_amount,
:tax_category,
:base_amount,
keyword_init: true
) do
Expand Down
53 changes: 39 additions & 14 deletions test/invoice_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -130,27 +130,40 @@ def make_de_invoice_with_multiple_tax_rates
)
line_item = LineItem.new(
name: 'Depfu Starter Plan',
quantity: 1,
quantity: 2,
Copy link
Contributor Author

@SubandiK SubandiK Dec 18, 2024

Choose a reason for hiding this comment

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

I changed the quantity here, because I wanted a quantity of 1 for the 7% item, to show the rounding problem, but still keep a test with a quantity of > 1 around.

unit: :PIECE,
gross_amount: '23.80',
net_amount: '20',
charge_amount: '20',
charge_amount: '40',
tax_category: :STANDARDRATE,
tax_percent: '19',
tax_amount: "3.80",
tax_amount: "7.60",
origin_country_code: 'DE',
currency_code: 'EUR'
)
line_item2 = LineItem.new(
name: 'Cup of Coffee',
quantity: 2,
quantity: 1,
unit: :PIECE,
gross_amount: '2.14',
net_amount: '2',
charge_amount: '4',
gross_amount: '2.68',
net_amount: '2.50',
charge_amount: '2.50',
tax_category: :STANDARDRATE,
tax_percent: '7',
tax_amount: "0.28",
tax_amount: "0.18",
origin_country_code: 'DE',
currency_code: 'EUR'
)
line_item3 = LineItem.new(
name: 'Returnable Deposit',
quantity: 1,
unit: :PIECE,
gross_amount: '5',
net_amount: '5',
charge_amount: '5',
tax_category: :ZEROTAXPRODUCTS,
tax_percent: '0',
tax_amount: "0",
origin_country_code: 'DE',
currency_code: 'EUR'
)
Expand All @@ -162,18 +175,18 @@ def make_de_invoice_with_multiple_tax_rates
seller: seller,
buyer: buyer,
buyer_reference: "112233",
line_items: [line_item, line_item2],
line_items: [line_item, line_item2, line_item3],
currency_code: 'USD',
payment_type: :CREDITCARD,
payment_text: 'Kreditkarte',
payment_iban: 'DE02120300000000202051',
payment_terms_text: "Zahlbar innerhalb von 14 Tagen ohne Abzug",
tax_category: :STANDARDRATE,
tax_amount: '4.08',
basis_amount: '24',
grand_total_amount: '28.08',
tax_amount: '7.78',
basis_amount: '47.50',
grand_total_amount: '55.28',
due_amount: 0,
paid_amount: '28.08',
paid_amount: '55.28',
payment_due_date: Date.today + 14
)
end
Expand Down Expand Up @@ -296,7 +309,7 @@ def test_de_multiple_taxes_invoice_v2
assert_equal [], errors
end

def test_de_multiple_taxes_invoice_against_schematron
def test_de_multiple_taxes_invoice_against_schematron_1
xml = make_de_invoice_with_multiple_tax_rates.to_xml(version: 1)
v = Validator.new(xml, version: 1)
errors = v.validate_against_schematron
Expand All @@ -308,5 +321,17 @@ def test_de_multiple_taxes_invoice_against_schematron
end
assert_equal [], errors
end
def test_de_multiple_taxes_invoice_against_schematron_2
xml = make_de_invoice_with_multiple_tax_rates.to_xml(version: 2)
v = Validator.new(xml, version: 2)
errors = v.validate_against_schematron
if !errors.empty?
puts xml
errors.each do |error|
puts "#{error[:line]}: #{error[:message]}"
end
end
assert_equal [], errors
end
end
end