From 3adc5a8107f95e2131b830c7da2fa73463ed7948 Mon Sep 17 00:00:00 2001 From: Ikraam Ghoor Date: Fri, 26 Jun 2026 05:11:39 +0200 Subject: [PATCH] Fixed N+1 loading tax categories during tax calculation Calculating order taxes read each line item's tax category through its variant and, when the variant had none, through its product. With the associations unloaded that meant two queries per line item, every time taxes were recalculated. Preloading the variant and product for all line items keeps that load constant regardless of how many items the order has. --- core/app/models/spree/tax_calculator/default.rb | 2 ++ .../models/spree/tax_calculator/default_spec.rb | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/core/app/models/spree/tax_calculator/default.rb b/core/app/models/spree/tax_calculator/default.rb index c6b5423a19e..4f62f251d81 100644 --- a/core/app/models/spree/tax_calculator/default.rb +++ b/core/app/models/spree/tax_calculator/default.rb @@ -23,6 +23,8 @@ def initialize(order) # # @return [Spree::Tax::OrderTax] the calculated taxes for the order def calculate + ActiveRecord::Associations::Preloader.new(records: order.line_items, associations: {variant: :product}).call + Spree::Tax::OrderTax.new( order_id: order.id, order_taxes: order_rates, diff --git a/core/spec/models/spree/tax_calculator/default_spec.rb b/core/spec/models/spree/tax_calculator/default_spec.rb index dca87f50eae..31e84224153 100644 --- a/core/spec/models/spree/tax_calculator/default_spec.rb +++ b/core/spec/models/spree/tax_calculator/default_spec.rb @@ -76,5 +76,18 @@ expect(order_tax.label).to eq "Flat Book Fee" end end + + context "with multiple line items" do + before do + 2.times do + order.contents.add(FactoryBot.create(:product, tax_category: books_category).master) + end + order.reload + end + + it "loads line item variants in a single query" do + expect { calculator.calculate }.to make_database_queries(matching: /from .spree_variants..*\bid. IN \(/im, count: 1) + end + end end end