Files
openfoodnetwork/app/services/order_adjustments_fetcher.rb
Matt-Yorkley 98fdbb8621 Update deprecated #scoped calls
Model#scoped is now deprecated. Model#where(nil) in Rails 4 returns the same result as Model#scoped in Rails 3
2020-02-22 11:06:51 +00:00

85 lines
2.3 KiB
Ruby

# This class allows orders with eager-loaded adjustment objects to calculate various adjustment
# types without triggering additional queries.
#
# For example; `order.adjustments.shipping.sum(&:amount)` would normally trigger a new query
# regardless of whether or not adjustments have been preloaded, as `#shipping` is an adjustment
# scope, eg; `scope :shipping, where(originator_type: 'Spree::ShippingMethod')`.
#
# Here the adjustment scopes are moved to a shared module, and `adjustments.loaded?` is used to
# check if the objects have already been fetched and initialized. If they have, `order.adjustments`
# will be an Array, and we can select the required objects without hitting the database. If not, it
# will fetch the adjustments via their scopes as normal.
class OrderAdjustmentsFetcher
include AdjustmentScopes
def initialize(order)
@order = order
end
def admin_and_handling_total
admin_and_handling_fees.map(&:amount).sum
end
def payment_fee
sum_adjustments "payment_fee"
end
def ship_total
sum_adjustments "shipping"
end
def line_item_adjustments(line_item)
if adjustments_eager_loaded?
adjustments.select{ |adjustment| adjustment.source_id == line_item.id }
else
adjustments.where(source_id: line_item.id)
end
end
private
attr_reader :order
def adjustments
order.adjustments
end
def adjustments_eager_loaded?
adjustments.loaded?
end
def sum_adjustments(scope)
collect_adjustments(scope).map(&:amount).sum
end
def collect_adjustments(scope)
if adjustments_eager_loaded?
adjustment_scope = public_send("#{scope}_scope")
adjustments.select do |adjustment|
match_by_scope(adjustment, adjustment_scope)
end
else
adjustments.where(nil).public_send scope
end
end
def admin_and_handling_fees
if adjustments_eager_loaded?
adjustments.select do |adjustment|
match_by_scope(adjustment, eligible_scope) &&
adjustment.originator_type == 'EnterpriseFee' &&
adjustment.source_type != 'Spree::LineItem'
end
else
adjustments.eligible.
where("originator_type = ? AND source_type != ?", 'EnterpriseFee', 'Spree::LineItem')
end
end
def match_by_scope(adjustment, scope)
adjustment.public_send(scope.keys.first) == scope.values.first
end
end