module Returnly module Refund class AmountCalculator attr_accessor :refund def initialize(refund) self.refund = refund end def return_item_refund_amount(return_item) (item_price(return_item) * item_price_percentage / 100).round(2, :down) end protected def total_single_items_price refund.line_items.inject(0.0.to_d) do |amount, line_item_hash| line_item = Spree::LineItem.find(line_item_hash['order_line_item_id']) amount += (line_item_price(line_item) * line_item_hash['units'].to_d).round(2, :down) amount end.round(2, :down) end def line_item_price(line_item) (line_item.price + line_item_tax_price(line_item) + line_item_discount_price(line_item)).round(2, :down) end def item_price_percentage [(available_amount * 100 / total_single_items_price).round(2, :down), 100.0.to_d].min end def item_price(return_item) line_item_price(return_item.inventory_unit.line_item) end def line_item_tax_price(line_item) (line_item.adjustments.tax.sum(&:amount).to_d.round(2, :down) / line_item.quantity).round(2, :down) end def line_item_discount_price(line_item) discounter_calculator.calculate( [ { order_line_item_id: line_item.id, units: 1 } ] ) end def line_items_price refund.order.line_items.sum(&:price).round(2, :down) end def available_amount refund.product_available_amount.round(2, :down) end def discounter_calculator @discounter_calculator ||= Returnly::DiscountCalculator.new(refund.order) end end end end