diff --git a/app/models/invoice/data_presenter.rb b/app/models/invoice/data_presenter.rb index 8c5c4dbbab..f45e35612b 100644 --- a/app/models/invoice/data_presenter.rb +++ b/app/models/invoice/data_presenter.rb @@ -91,6 +91,14 @@ class Invoice Spree::Money.new(shipment.amount + shipment.additional_tax_total, currency:) end + def display_line_item_tax_rate(item) + all_tax_adjustments.select { |a| + a.adjustable.type == 'Spree::LineItem' && a.adjustable.id == item.id + }.map(&:originator).map { |tr| + number_to_percentage(tr.amount * 100, precision: 1) + }.join(", ") + end + def display_shipment_tax_rates all_eligible_adjustments.select { |a| a.originator.type == 'Spree::TaxRate' && a.adjustable_type == 'Spree::Shipment' diff --git a/app/models/invoice/data_presenter/line_item.rb b/app/models/invoice/data_presenter/line_item.rb index 2b43a1a4d8..2b55cca925 100644 --- a/app/models/invoice/data_presenter/line_item.rb +++ b/app/models/invoice/data_presenter/line_item.rb @@ -3,11 +3,10 @@ class Invoice class DataPresenter class LineItem < Invoice::DataPresenter::Base - attributes :added_tax, :currency, :included_tax, :price_with_adjustments, :quantity, + attributes :id, :added_tax, :currency, :included_tax, :price_with_adjustments, :quantity, :variant_id, :unit_price_price_and_unit, :unit_presentation, :enterprise_fee_additional_tax, :enterprise_fee_included_tax attributes_with_presenter :variant - array_attribute :tax_rates, class_name: 'TaxRate' invoice_generation_attributes :added_tax, :included_tax, :price_with_adjustments, :quantity, :variant_id @@ -35,10 +34,6 @@ class Invoice fee_tax = enterprise_fee_included_tax || 0.0 Spree::Money.new(price_with_adjustments - ((included_tax + fee_tax) / quantity), currency:) end - - def display_line_item_tax_rates - tax_rates.map { |tr| number_to_percentage(tr.amount * 100, precision: 1) }.join(", ") - end end end end diff --git a/app/models/spree/line_item.rb b/app/models/spree/line_item.rb index c2810cbcb8..571a9adfd4 100644 --- a/app/models/spree/line_item.rb +++ b/app/models/spree/line_item.rb @@ -193,6 +193,7 @@ module Spree adjustments.tax.additional.sum(:amount) end + # Some of the tax rates may not be applicable depending to the order's tax zone def tax_rates variant&.tax_category&.tax_rates || [] end diff --git a/app/serializers/invoice/line_item_serializer.rb b/app/serializers/invoice/line_item_serializer.rb index 4031327f1f..50e566850d 100644 --- a/app/serializers/invoice/line_item_serializer.rb +++ b/app/serializers/invoice/line_item_serializer.rb @@ -6,7 +6,6 @@ class Invoice :variant_id, :unit_price_price_and_unit, :unit_presentation, :enterprise_fee_additional_tax, :enterprise_fee_included_tax has_one :variant, serializer: Invoice::VariantSerializer - has_many :tax_rates, serializer: Invoice::TaxRateSerializer def enterprise_fee_additional_tax EnterpriseFeeAdjustments.new(object.enterprise_fee_adjustments).total_additional_tax diff --git a/app/views/spree/admin/orders/_invoice_table4.html.haml b/app/views/spree/admin/orders/_invoice_table4.html.haml index a19f7aa20c..5382d3d8ce 100644 --- a/app/views/spree/admin/orders/_invoice_table4.html.haml +++ b/app/views/spree/admin/orders/_invoice_table4.html.haml @@ -32,7 +32,7 @@ %td{:align => "right"} = item.display_amount_with_adjustments_without_taxes %td{:align => "right"} - = item.display_line_item_tax_rates + = @order.display_line_item_tax_rate(item) %td{:align => "right"} = item.display_amount_with_adjustments_and_with_taxes %tr diff --git a/spec/models/invoice/data_presenter_spec.rb b/spec/models/invoice/data_presenter_spec.rb index 864044d502..0a0cc24676 100644 --- a/spec/models/invoice/data_presenter_spec.rb +++ b/spec/models/invoice/data_presenter_spec.rb @@ -11,4 +11,68 @@ describe Invoice::DataPresenter do expect(presenter.display_date).to eq "August 01, 2023" end end + + context "#display_line_item_tax_rate" do + let!(:order){ + create(:order_with_taxes, + product_price: 100, + tax_rate_name: "VAT", + tax_rate_amount: 0.15) + } + let(:non_taxable_line_item) { order.line_items.first } + let(:taxable_line_item) { order.line_items.last } # only the last item one has tax rate + let(:invoice){ order.invoices.latest } + let(:presenter){ Invoice::DataPresenter.new(invoice) } + before do + order.create_tax_charge! + OrderInvoiceGenerator.new(order).generate_or_update_latest_invoice + end + + it "displays nothing when the line item refer to a non taxable product" do + expect(presenter.display_line_item_tax_rate(non_taxable_line_item)).to eq "" + end + + it "displays the tax rate when the line item refer to a taxable product" do + expect(presenter.display_line_item_tax_rate(taxable_line_item)).to eq "15.0%" + end + + context "if multiple tax rates belong to the tax category" do + let(:taxable_line_item_tax_rate){ + order.line_items.last.tax_category.tax_rates.first + } + let(:tax_rate_calculator){ + taxable_line_item_tax_rate.calculator + } + before do + tax_rate_clone = taxable_line_item_tax_rate.dup.tap do |dup| + dup.amount = 0.20 + dup.calculator = tax_rate_calculator.dup.tap do |calc| + calc.calculable = dup + end + end + tax_rate_clone.save! + tax_rate_clone.calculator.save! + order.create_tax_charge! + OrderInvoiceGenerator.new(order).generate_or_update_latest_invoice + end + + it "displays the tax rate when the line item refer to a taxable product" do + expect(order.invoices.count).to eq 2 + expect(presenter.display_line_item_tax_rate(taxable_line_item)).to eq "15.0%, 20.0%" + end + + context "one of the tax rate is appliable to a different tax zone" do + before do + order.line_items.last.tax_category.tax_rates.last.update!(zone: create(:zone)) + order.create_tax_charge! + OrderInvoiceGenerator.new(order).generate_or_update_latest_invoice + end + + it "displays only the tax rates that were applied to the line items" do + expect(order.invoices.count).to eq 3 + expect(presenter.display_line_item_tax_rate(taxable_line_item)).to eq "15.0%" + end + end + end + end end diff --git a/spec/system/admin/invoice_print_spec.rb b/spec/system/admin/invoice_print_spec.rb index f4f922df03..111b1c074b 100644 --- a/spec/system/admin/invoice_print_spec.rb +++ b/spec/system/admin/invoice_print_spec.rb @@ -542,7 +542,7 @@ describe ' # first line item, no tax expect(page).to have_content Spree::Product.first.name.to_s expect(page).to have_content "($12,540.00 / kg)" # unit price - expect(page).to have_content "1 1g $12.54 $12.54 0.0% $12.54" + expect(page).to have_content "1 1g $12.54 $12.54 $12.54" # # second line item, included tax expect(page).to have_content Spree::Product.second.name.to_s expect(page).to have_content "($500,150.00 / kg)" # unit price @@ -645,7 +645,7 @@ describe ' # first line item, no tax expect(page).to have_content Spree::Product.first.name.to_s expect(page).to have_content "($12,540.00 / kg)" # unit price - expect(page).to have_content "1 1g $12.54 $12.54 0.0% $12.54" + expect(page).to have_content "1 1g $12.54 $12.54 $12.54" # second line item, included tax expect(page).to have_content Spree::Product.second.name.to_s expect(page).to have_content "($500,150.00 / kg)" # unit price