Skip to content
Closed
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
72 changes: 72 additions & 0 deletions core/app/models/spree/adjustable_updater.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
module Spree
class AdjustableUpdater
attr_reader :adjustable

def self.update(adjustable)
return adjustable unless adjustable.persisted?

adjustableUpdater = Spree::AdjustableUpdater.new(adjustable)

# Promotion adjustments must be applied first, then tax adjustments.
# This fits the criteria for VAT tax as outlined here:
# http://www.hmrc.gov.uk/vat/managing/charging/discounts-etc.htm#1
#
# It also fits the criteria for sales tax as outlined here:
# http://www.boe.ca.gov/formspubs/pub113/

# Rails.application.config.spree.adjustments_updater.pre_tax_updaters.each { |adjusterKlass| adjusterKlass.new(adjustableUpdate).update }
Spree::AdjustmentsUpdater::Promotion.new(adjustableUpdater).update

# We want to select the best promotion for the order, but the remainder
# of the calculations here are done in the OrderUpdater instead.
return if Spree::Order === adjustable

# Rails.application.config.spree.adjustments_updater.tax_updater.new(adjustableUpdater).update
# Rails.application.config.spree.adjustments_updater.post_tax_updaters.each { |adjusterKlass| adjusterKlass.new(adjustableUpdate).update }
Spree::AdjustmentsUpdater::Tax.new(adjustableUpdater).update
Spree::AdjustmentsUpdater::Cancellation.new(adjustableUpdater).update

adjustableUpdater.persist if adjustable.changed?

adjustableUpdater.adjustable
end

# @param adjustable [Order, LineItem, Shipment] the item whose adjustments should be updated
def initialize(adjustable)
@adjustable = adjustable
@attributes_to_persist = {adjustment_total: 0}
end

def set_attribute(attribute, value, include_in_adjustment_total = true)
# Setting totals for the order here would be incorrect. Order's
# totals are the sum of the adjustments on all child models, as well as
# its own.
return if Spree::Order === adjustable

adjustable.send("#{attribute}=", value)
@attributes_to_persist[attribute] = value

add_to_adjustment_total(value) if include_in_adjustment_total
end

def add_to_adjustment_total(value)
adjustable.adjustment_total += value
@attributes_to_persist[:adjustment_total] += value
end

def adjustments
# This is done intentionally to avoid loading the association. If the
# association is loaded, the records may become stale due to code
# elsewhere in Spree. When that is remedied, this should be changed to
# just item.adjustments
@adjustments ||= adjustable.adjustments.all.to_a
end

def persist
attributes = @attributes_to_persist
attributes[:updated_at] = Time.current

adjustable.update_columns(attributes)
end
end
end
2 changes: 1 addition & 1 deletion core/app/models/spree/adjustment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ def currency

def update_adjustable_adjustment_total
# Cause adjustable's total to be recalculated
ItemAdjustments.new(adjustable).update
AdjustableUpdater.update(adjustable)
end

def require_promotion_code?
Expand Down
22 changes: 22 additions & 0 deletions core/app/models/spree/adjustments_updater/cancellation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module Spree
module AdjustmentsUpdater
class Cancellation

def initialize(adjustableUpdater)
@adjustableUpdater = adjustableUpdater
end

def update
item_cancellation_total = adjustments.select(&:cancellation?).map(&:update!).compact.sum

@adjustableUpdater.add_to_adjustment_total(item_cancellation_total)
end

private

def adjustments
@adjustableUpdater.adjustments
end
end
end
end
25 changes: 25 additions & 0 deletions core/app/models/spree/adjustments_updater/promotion.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module Spree
module AdjustmentsUpdater
class Promotion

def initialize(adjustableUpdater)
@adjustableUpdater = adjustableUpdater
end

def update
promotion_adjustments = adjustments.select(&:promotion?)
promotion_adjustments.each(&:update!)

promo_total = Spree::Config.promotion_chooser_class.new(promotion_adjustments).update

@adjustableUpdater.set_attribute(:promo_total, promo_total)
end

private

def adjustments
@adjustments ||= @adjustableUpdater.adjustments
end
end
end
end
33 changes: 33 additions & 0 deletions core/app/models/spree/adjustments_updater/tax.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Tax adjustments come in not one but *two* exciting flavours:
# Included & additional

# Included tax adjustments are those which are included in the price.
# These ones should not affect the eventual total price.
#
# Additional tax adjustments are the opposite, affecting the final total.
module Spree
module AdjustmentsUpdater
class Tax

def initialize(adjustableUpdater)
@adjustableUpdater = adjustableUpdater
end

def update
tax = adjustments.select(&:tax?)

included_tax_total = tax.select(&:included?).map(&:update!).compact.sum
additional_tax_total = tax.reject(&:included?).map(&:update!).compact.sum

@adjustableUpdater.set_attribute(:included_tax_total, included_tax_total, false)
@adjustableUpdater.set_attribute(:additional_tax_total, additional_tax_total)
end

private

def adjustments
@adjustments ||= @adjustableUpdater.adjustments
end
end
end
end
2 changes: 1 addition & 1 deletion core/app/models/spree/line_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ def update_adjustments
end

def recalculate_adjustments
Spree::ItemAdjustments.new(self).update
Spree::AdjustableUpdater.update(self)
end

def update_tax_charge
Expand Down
2 changes: 1 addition & 1 deletion core/app/models/spree/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -504,7 +504,7 @@ def create_proposed_shipments

def apply_free_shipping_promotions
Spree::PromotionHandler::FreeShipping.new(self).activate
shipments.each { |shipment| ItemAdjustments.new(shipment).update }
shipments.each { |shipment| AdjustableUpdater.update(shipment) }
updater.update_shipment_total
persist_totals
end
Expand Down
2 changes: 1 addition & 1 deletion core/app/models/spree/order_contents.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def after_add_or_remove(line_item, options = {})
shipment = options[:shipment]
shipment.present? ? shipment.update_amounts : order.ensure_updated_shipments
PromotionHandler::Cart.new(order, line_item).activate
ItemAdjustments.new(line_item).update
AdjustableUpdater.update(line_item)
reload_totals
line_item
end
Expand Down
2 changes: 1 addition & 1 deletion core/app/models/spree/order_updater.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def run_hooks
end

def recalculate_adjustments
all_adjustments.includes(:adjustable).map(&:adjustable).uniq.each { |adjustable| Spree::ItemAdjustments.new(adjustable).update }
all_adjustments.includes(:adjustable).map(&:adjustable).uniq.each { |adjustable| Spree::AdjustableUpdater.update(adjustable) }
end

# Updates the following Order total values:
Expand Down
2 changes: 1 addition & 1 deletion core/app/models/spree/shipment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ def manifest_unstock(item)
end

def recalculate_adjustments
Spree::ItemAdjustments.new(self).update
Spree::AdjustableUpdater.update(self)
end

def set_cost_zero_when_nil
Expand Down
Loading