module Returnly module Builders class ReturnItem attr_accessor :order def initialize(order) @order = order end def build_by_requested_line_items(requested_line_items) is_returned_item = false items = requested_line_items.each_with_object([]) do |request_line_item, return_items| quantity = request_line_item[:units].to_i next return_items unless quantity > 0 inventory_units = inventory_units_by(request_line_item[:order_line_item_id]) if inventory_units.empty? inventory_units = returned_inventory_units_by(request_line_item[:order_line_item_id]) request_line_item[:find_return?] = true is_returned_item = true end inventory_units.take(quantity).each do |inventory_unit| return_items << build_by_inventory_unit(inventory_unit, request_line_item) end return_items end { items: items, is_returned_items: is_returned_item } end def exact_build_by_inventory_unit(inventory_unit, options = {}) Spree::ReturnItem.new( amount: inventory_unit.line_item.price, acceptance_status: 'accepted', inventory_unit_id: inventory_unit.id, reception_status_event: 'receive', resellable: options[:restock] ) end def build_by_inventory_unit(inventory_unit, options = {}) return exact_build_by_inventory_unit(inventory_unit, options) unless options[:find_return?] Spree::ReturnItem.find_by( amount: inventory_unit.line_item.price, inventory_unit_id: inventory_unit.id ) end private def inventory_units_by(line_item_ids) order.inventory_units.includes(:line_item) .where(line_item_id: line_item_ids) .where.not(state: 'returned') end def returned_inventory_units_by(line_item_ids) order.inventory_units.includes(:line_item, :return_items) .where(line_item_id: line_item_ids, state: 'returned') .where(spree_return_items: { reimbursement_id: nil }) end end end end