Skip to content

Instantly share code, notes, and snippets.

@jetsgit
Created May 16, 2014 17:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jetsgit/9789d6e1905fa27bb43f to your computer and use it in GitHub Desktop.
Save jetsgit/9789d6e1905fa27bb43f to your computer and use it in GitHub Desktop.
git diff 2-1-stable 2-2-stable core/app/models/spree/adjustment.rb
diff --git a/core/app/models/spree/adjustment.rb b/core/app/models/spree/adjustment.rb
index 35f90f9..c4f7be0 100644
--- a/core/app/models/spree/adjustment.rb
+++ b/core/app/models/spree/adjustment.rb
@@ -1,10 +1,8 @@
# Adjustments represent a change to the +item_total+ of an Order. Each adjustment
# has an +amount+ that can be either positive or negative.
#
-# Adjustments can be open/closed/finalized
-#
-# Once an adjustment is finalized, it cannot be changed, but an adjustment can
-# toggle between open/closed as needed
+# Adjustments can be "opened" or "closed".
+# Once an adjustment is closed, it will not be automatically updated.
#
# Boolean attributes:
#
@@ -26,15 +24,11 @@ module Spree
class Adjustment < ActiveRecord::Base
belongs_to :adjustable, polymorphic: true
belongs_to :source, polymorphic: true
- belongs_to :originator, polymorphic: true
- belongs_to :order, :class_name => 'Spree::Order'
+ belongs_to :order, :class_name => "Spree::Order"
validates :label, presence: true
validates :amount, numericality: true
- after_save :update_adjustable
- after_destroy :update_adjustable
-
state_machine :state, initial: :open do
event :close do
transition from: :open, to: :closed
@@ -43,66 +37,55 @@ module Spree
event :open do
transition from: :closed, to: :open
end
-
- event :finalize do
- transition from: [:open, :closed], to: :finalized
- end
end
- scope :tax, -> { where(originator_type: 'Spree::TaxRate') }
+ after_create :update_adjustable_adjustment_total
+
+ scope :open, -> { where(state: 'open') }
+ scope :closed, -> { where(state: 'closed') }
+ scope :tax, -> { where(source_type: 'Spree::TaxRate') }
scope :price, -> { where(adjustable_type: 'Spree::LineItem') }
- scope :shipping, -> { where(originator_type: 'Spree::ShippingMethod') }
+ scope :shipping, -> { where(adjustable_type: 'Spree::Shipment') }
scope :optional, -> { where(mandatory: false) }
scope :eligible, -> { where(eligible: true) }
scope :charge, -> { where("#{quoted_table_name}.amount >= 0") }
scope :credit, -> { where("#{quoted_table_name}.amount < 0") }
- scope :promotion, -> { where(originator_type: 'Spree::PromotionAction') }
- scope :manual, -> { where(originator_type: nil) }
+ scope :promotion, -> { where(source_type: 'Spree::PromotionAction') }
scope :return_authorization, -> { where(source_type: "Spree::ReturnAuthorization") }
scope :included, -> { where(included: true) }
scope :additional, -> { where(included: false) }
- def promotion?
- originator_type == 'Spree::PromotionAction'
- end
-
- # Update the boolean _eligible_ attribute which determines which adjustments
- # count towards the order's adjustment_total.
- def set_eligibility
- result = mandatory || ((amount != 0 || promotion?) && eligible_for_originator?)
- update_column(:eligible, result)
+ def closed?
+ state == "closed"
end
- # Allow originator of the adjustment to perform an additional eligibility of the adjustment
- # Should return _true_ if originator is absent or doesn't implement _eligible?_
- def eligible_for_originator?
- return true if originator.nil?
- !originator.respond_to?(:eligible?) || originator.eligible?(source)
+ def promotion?
+ source.class < Spree::PromotionAction
end
- # Update both the eligibility and amount of the adjustment. Adjustments
- # delegate updating of amount to their Originator when present, but only if
- # +locked+ is false. Adjustments that are +locked+ will never change their amount.
+ # Recalculate amount given a target e.g. Order, Shipment, LineItem
+ #
+ # Passing a target here would always be recommended as it would avoid
+ # hitting the database again and would ensure you're compute values over
+ # the specific object amount passed here.
#
- # Adjustments delegate updating of amount to their Originator when present,
- # but only if when they're in "open" state, closed or finalized adjustments
- # are not recalculated.
+ # Noop if the adjustment is locked.
#
- # It receives +calculable+ as the updated source here so calculations can be
- # performed on the current values of that source. If we used +source+ it
- # could load the old record from db for the association. e.g. when updating
- # more than on line items at once via accepted_nested_attributes the order
- # object on the association would be in a old state and therefore the
- # adjustment calculations would not performed on proper values
- def update!(calculable = nil)
- return if immutable?
- # Fix for #3381
- # If we attempt to call 'source' before the reload, then source is currently
- # the order object. After calling a reload, the source is the Shipment.
- reload
- calculable = source unless calculable == source
- originator.update_adjustment(self, calculable) if originator.present?
- set_eligibility
+ # If the adjustment has no source, do not attempt to re-calculate the amount.
+ # Chances are likely that this was a manually created adjustment in the admin backend.
+ def update!(target = nil)
+ return amount if closed?
+ if source.present?
+ amount = source.compute_amount(target || adjustable)
+ self.update_columns(
+ amount: amount,
+ updated_at: Time.now,
+ )
+ if promotion?
+ self.update_column(:eligible, source.promotion.eligible?(adjustable))
+ end
+ end
+ amount
end
def currency
@@ -113,14 +96,11 @@ module Spree
Spree::Money.new(amount, { currency: currency })
end
- def immutable?
- state != "open"
- end
-
private
- def update_adjustable
- adjustable.update! if adjustable.is_a? Order
- end
+ def update_adjustable_adjustment_total
+ # Cause adjustable's total to be recalculated
+ Spree::ItemAdjustments.new(adjustable).update if adjustable
+ end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment