From 9dbe270e26e3cee74396985d14da31bd9ad2e8dc Mon Sep 17 00:00:00 2001 From: Noah Silvera Date: Fri, 17 Oct 2025 15:32:32 -0400 Subject: [PATCH] Fix shipment adjustments not persisting on order recalculate A commit was made in #6315 (5979f25c2a324cb87a9783eff4e5d4aaa1d409da) in service of the in memory order updater #5872 that changed the behavior in the OrderTaxation class to set the adjustment value but not persist it. Instead, the persistence happens when the order is saved. If a shipment is changed, and an associated adjustment is changed, the shipment adjustment will be autosaved when the order is. However, if a shipment is *not* changed, but the adjustment is, the adjustment will *not* be autosaved when the order is. In #6315, we ensured that these changed associations cannot get left behind by setting `autosave: true`, which forces the model to check if it has any associations that need saving instead of telling it's relation "nope I haven't changed" We can do the same thing here for the shipment to ensure changing adjustments will make the shipment tell it's order "I have changed", even if none of it's direct properties have changed. You can test this change by removing the `autosave: true` option the adjustments and running 'when the address has changed to a different state' specs. They fail with the error "expected `order.shipments.first.adjustments.first.amount` to have changed from 1 to 2, but did not change", demonstrating a scenario where the shipment adjustment changes do not get persisted. (cherry picked from commit b47e0f0716020c28c97391c6900b9cab21c85638) --- core/app/models/spree/shipment.rb | 2 +- core/spec/models/spree/order_updater_spec.rb | 71 ++++++++++++++++---- 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/core/app/models/spree/shipment.rb b/core/app/models/spree/shipment.rb index 2dbb167138..cb1dd767e3 100644 --- a/core/app/models/spree/shipment.rb +++ b/core/app/models/spree/shipment.rb @@ -9,7 +9,7 @@ class Shipment < Spree::Base belongs_to :order, class_name: 'Spree::Order', touch: true, inverse_of: :shipments, optional: true belongs_to :stock_location, class_name: 'Spree::StockLocation', optional: true - has_many :adjustments, as: :adjustable, inverse_of: :adjustable, dependent: :delete_all + has_many :adjustments, as: :adjustable, inverse_of: :adjustable, dependent: :delete_all, autosave: true has_many :inventory_units, dependent: :destroy, inverse_of: :shipment has_many :shipping_rates, -> { order(:cost) }, dependent: :destroy, inverse_of: :shipment has_many :shipping_methods, through: :shipping_rates diff --git a/core/spec/models/spree/order_updater_spec.rb b/core/spec/models/spree/order_updater_spec.rb index 0b680e117f..7aad5633ee 100644 --- a/core/spec/models/spree/order_updater_spec.rb +++ b/core/spec/models/spree/order_updater_spec.rb @@ -72,14 +72,14 @@ module Spree let(:tax_category) { create(:tax_category) } let(:ship_address) { create(:address, state: new_york) } let(:new_york) { create(:state, state_code: "NY") } - let(:tax_zone) { create(:zone, states: [new_york]) } + let(:new_york_tax_zone) { create(:zone, states: [new_york]) } - let!(:tax_rate) do + let!(:new_york_tax_rate) do create( :tax_rate, name: "New York Sales Tax", tax_categories: [tax_category], - zone: tax_zone, + zone: new_york_tax_zone, included_in_price: false, amount: 0.1 ) @@ -111,21 +111,66 @@ module Spree end context 'when the address has changed to a different state' do - let(:new_shipping_address) { create(:address) } + let(:oregon) { create(:state, state_code: "OR") } + let(:oregon_tax_zone) { create(:zone, states: [oregon]) } + let!(:oregon_tax_rate) do + create( + :tax_rate, + name: "Oregon Sales Tax", + tax_categories: [tax_category], + zone: oregon_tax_zone, + included_in_price: false, + amount: 0.2 + ) + end + let(:new_address) { create(:address, state: oregon) } + let(:shipping_method) { create(:shipping_method, tax_category:, zones: [oregon_tax_zone, new_york_tax_zone], cost: 10) } + let(:shipping_rate) do + create(:shipping_rate, cost: 10, shipping_method: shipping_method) + end + let(:shipment) { order.shipments[0] } + + subject do + order.ship_address = new_address + order.bill_address = new_address + + order.recalculate + end before do - order.ship_address = new_shipping_address + shipment.shipping_rates = [shipping_rate] + shipment.selected_shipping_rate_id = shipping_rate.id + order.recalculate end - it 'removes the old taxes' do + it 'updates the taxes to reflect the new state' do expect { - order.recalculate + subject }.to change { - order.all_adjustments.tax.count - }.from(1).to(0) + order.additional_tax_total + }.from(2).to(4) + end - expect(order.additional_tax_total).to eq 0 - expect(order.adjustment_total).to eq 0 + it 'updates the shipment taxes to reflect the new state' do + expect { + subject + }.to change { + order.shipments.first.additional_tax_total + }.from(1).to(2) + .and change { + order.shipments.first.adjustments.first.amount + }.from(1).to(2) + end + + it 'updates the line item taxes to reflect the new state' do + expect { + subject + }.to change { + order.line_items.first.additional_tax_total + }.from(1).to(2) + .and change { + order.line_items.first.adjustments.first.amount + }.from(1).to(2) end end @@ -179,7 +224,7 @@ module Spree order_taxes: [ Spree::Tax::ItemTax.new( label: "Delivery Fee", - tax_rate:, + tax_rate: new_york_tax_rate, amount: 2.60, included_in_price: false ) @@ -188,7 +233,7 @@ module Spree Spree::Tax::ItemTax.new( item_id: line_item.id, label: "Item Tax", - tax_rate:, + tax_rate: new_york_tax_rate, amount: 1.40, included_in_price: false )