module Returnly class RefundCalculator attr_accessor :line_items, :order def self.process(order, line_items) RefundPresenter.present_estimate new(order, line_items) end def initialize(order, line_items) self.line_items = line_items self.order = order end def set_tax(return_item) percent_of_tax = (return_item.amount <= 0) ? 0 : return_item.amount / Spree::ReturnItem.refund_amount_calculator.new.compute(return_item) additional_tax_total = percent_of_tax * return_item.inventory_unit.additional_tax_total included_tax_total = percent_of_tax * return_item.inventory_unit.included_tax_total return_item.additional_tax_total = additional_tax_total return_item.included_tax_total = included_tax_total return_item end def shipping_tax order.all_adjustments.where(source_type: 'Spree::TaxRate', adjustable_type: 'Spree::Shipment').sum(&:amount) end def line_items_return_items found_return_items = {} line_items.each do |line_item| with_available_inventory_units line_item do |inventory_unit, quantity| next unless quantity > 0 found_return_items[line_item[:order_line_item_id]] ||= [] return_item = create_return_item(inventory_unit, restock: line_item[:restock]) found_return_items[line_item[:order_line_item_id]] << set_tax(return_item) end end found_return_items end def line_item_inventory_unit(line_item) returnable_inventory_units.select { |iu| iu.line_item_id == line_item[:order_line_item_id].to_i } end def line_item(id) returnable_line_items.find { |i| i.id == id.to_i } end def returnable_inventory_units @_inventory_units ||= order.inventory_units.includes(:line_item) .where(line_item_id: requested_line_items) .where('state is not "returned"') end def returnable_line_items @_line_items ||= returnable_inventory_units.map(&:line_item) end def requested_line_items line_items.map { |item| item[:order_line_item_id] } end protected def create_return_item(inventory_unit, restock: false) Spree::ReturnItem.new( amount: inventory_unit.line_item.price, acceptance_status: 'accepted', inventory_unit_id: inventory_unit.id, reception_status_event: 'receive', resellable: restock ) end def with_available_inventory_units(line_item) quantity = line_item[:units].to_i available_inventory_units = line_item_inventory_unit(line_item).slice(0, quantity) available_inventory_units.each do |inventory_unit| yield inventory_unit, quantity end end end end