module Solidus module Returnly class Calculator attr_accessor :line_items, :order def self.process(order, line_items) new(order, line_items).calculated_estimate end def initialize(order, line_items) self.line_items = line_items self.order = order end def calculated_estimate total = 0.0 sub_total = 0.0 line_items_return_items.values.flatten.each do |return_item| total += return_item.total sub_total += return_item.pre_tax_amount end { total_amount: total, subtotal_amount: sub_total, tax_amount: total - sub_total, discount_amount: order.promo_total, shipping_amount: order.shipment_total, line_items: present_line_items } end def present_line_items line_items_return_items.values.map do |return_items| line_item = return_items.first.inventory_unit.line_item total_amount = 0.0 sub_total = 0.0 return_items.each do |return_item| total_amount += return_item.total sub_total += return_item.pre_tax_amount end { order_line_item_id: line_item.id, quantity: return_items.size, total_amount: total_amount, tax_amount: total_amount - sub_total } end 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 line_items_return_items found_return_items = {} line_items.each do |line_item| quantity = line_item[:quantity].to_i next unless quantity > 0 available_inventory_units = line_item_inventory_unit(line_item).slice(0, quantity) available_inventory_units.each do |inventory_unit| found_return_items[line_item[:order_line_item_id]] ||= [] return_item = Spree::ReturnItem.new({ amount: inventory_unit.line_item.price, acceptance_status: 'accepted', inventory_unit_id: inventory_unit.id, reception_status_event: 'receive' }) 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 end end end