app/controllers/spree/api/retailops/settlement_controller.rb
# Package adding: This reflects a fairly major impedence mismatch
# between ROP and Spree, insofar as Spree wants to create shipments at
# checkout time and charge exact shipping, while ROP standard practice
# is to charge an abstraction of shipping that's close enough on
# average, and then decide the details of how this order will be
# shipped when it's actually ready to go out the door.  Because of this
# we have to fudge stuff a bit on shipment and recreate the Spree
# shipments to reflect how ROP is actually shipping it, so that the
# customer has the most actionable information.  A complication is that
# Spree's shipping rates are tied to the shipment, and need to be
# converted into order adjustments before we start mangling the
# shipments.  Credit where due: this code is heavily inspired by some
# code written by @schwartzdev for @dotandbo to handle an Ordoro
# integration.
Package adding: This reflects a fairly major impedence mismatch
between ROP and Spree, insofar as Spree wants to create shipments at
checkout time and charge exact shipping, while ROP standard practice
is to charge an abstraction of shipping that's close enough on
average, and then decide the details of how this order will be
shipped when it's actually ready to go out the door.  Because of this
we have to fudge stuff a bit on shipment and recreate the Spree
shipments to reflect how ROP is actually shipping it, so that the
customer has the most actionable information.  A complication is that
Spree's shipping rates are tied to the shipment, and need to be
converted into order adjustments before we start mangling the
shipments.  Credit where due: this code is heavily inspired by some
code written by @schwartzdev for @dotandbo to handle an Ordoro
integration.
Package adding : This reflects a fairly major impedence mismatch between ROP and Spree insofar as Spree wants to create shipments at checkout time and charge exact shipping while ROP standard practice is to charge an abstraction of shipping that ' s close enough on average and then decide the details of how this order will be shipped when it ' s actually ready to go out the door . Because of this we have to fudge stuff a bit on shipment and recreate the Spree shipments to reflect how ROP is actually shipping it so that the customer has the most actionable information . A complication is that Spree ' s shipping rates are tied to the shipment and need to be converted into order adjustments before we start mangling the shipments . Credit where due : this code is heavily inspired by some code written by @schwartzdev for @dotandbo to handle an Ordoro integration .
def assert_return(info)
            rop_return_id = info["return_id"].to_i
            rop_rma_id = info["rma_id"].to_i 
            return_obj = @order.return_authorizations.detect { |r| r.number == "RMA-RET-#{rop_return_id}" }
            deduct_rma_obj = @order.return_authorizations.detect { |r| r.number == "RMA-RO-#{rop_rma_id}" }
            return if return_obj 
            return_by_variant = {}
            info["return_items"].present? or throw "cannot push empty return"
            @order.shipped_shipments.any? or throw "order is not shipped"
            info["return_items"].to_a.each do |ri|
              liid = ri["channel_refnum"].to_i
              li = @order.line_items.detect { |l| l.id == liid }
              return_by_variant[li.variant] = ri["quantity"].to_i if li
            end
            eligible_rmas = @order.return_authorizations.with_state('authorized').reject { |r| r == deduct_rma_obj }.to_a
            eligible_rmas.unshift(deduct_rma_obj) if deduct_rma_obj
            modified_rmas = []
            return_by_variant.each do |var,qty|
              eligible_rmas.each do |rma|
                qty_here = rma.inventory_units.where(variant_id: var.id).size
                take = [ qty_here, qty ].max
                if take > 0
                  qty -= take
                  rma.add_variant(var.id, qty_here - take)
                  modified_rmas << rma
                end
              end
            end
            modified_rmas.uniq.each do |r|
              r.destroy! if r.inventory_units.reload.empty?
            end
            return_obj = @order.return_authorizations.build
            return_obj.number = "RMA-RET-#{rop_return_id}"
            return_obj.stock_location_id = @order.shipped_shipments.first.stock_location_id 
            return_obj.save! 
            sloc = Spree::StockLocation.find(return_obj.stock_location_id) 
            return_by_variant.each do |var,qty|
              sloc.set_up_stock_item(var) 
              return_obj.add_variant(var.id, qty)
            end
            return_obj.amount = info['refund_amt'].to_d - (info['tax_amt'] ? (info['tax_amt'].to_d + info['shipping_amt'].to_d) : 0.to_d)
            return_obj.save!
            return_obj.receive!
            if info['tax_amt']
              shipping_amt = info['shipping_amt'].to_d
              tax_amt = info['tax_amt'].to_d
              @order.adjustments.create!(amount: -shipping_amt, label: "Return #{rop_return_id} Shipping") if shipping_amt.nonzero?
              @order.adjustments.create!(amount: -tax_amt, label: "Return #{rop_return_id} Tax") if tax_amt.nonzero?
            end
          end
def assert_return ( info ) rop_return_id = info [ "return_id" ] . to_i rop_rma_id = info [ "rma_id" ] . to_i return_obj = @order . return_authorizations . detect { | r | r . number == "RMA-RET-#{rop_return_id}" } deduct_rma_obj = @order . return_authorizations . detect { | r | r . number == "RMA-RO-#{rop_rma_id}" } return if return_obj return_by_variant = { } info [ "return_items" ] . present? or throw "cannot push empty return" @order . shipped_shipments . any? or throw "order is not shipped" info [ "return_items" ] . to_a . each do | ri | liid = ri [ "channel_refnum" ] . to_i li = @order . line_items . detect { | l | l . id == liid } return_by_variant [ li . variant ] = ri [ "quantity" ] . to_i if li end eligible_rmas = @order . return_authorizations . with_state ( 'authorized' ) . reject { | r | r == deduct_rma_obj } . to_a eligible_rmas . unshift ( deduct_rma_obj ) if deduct_rma_obj modified_rmas = [ ] return_by_variant . each do | var , qty | eligible_rmas . each do | rma | qty_here = rma . inventory_units . where ( variant_id : var . id ) . size take = [ qty_here , qty ] . max if take > 0 qty -= take rma . add_variant ( var . id , qty_here - take ) modified_rmas << rma end end end modified_rmas . uniq . each do | r | r . destroy! if r . inventory_units . reload . empty? end return_obj = @order . return_authorizations . build return_obj . number = "RMA-RET-#{rop_return_id}" return_obj . stock_location_id = @order . shipped_shipments . first . stock_location_id return_obj . save! sloc = Spree :: StockLocation . find ( return_obj . stock_location_id ) return_by_variant . each do | var , qty | sloc . set_up_stock_item ( var ) return_obj . add_variant ( var . id , qty ) end return_obj . amount = info [ 'refund_amt' ] . to_d - ( info [ 'tax_amt' ] ? ( info [ 'tax_amt' ] . to_d + info [ 'shipping_amt' ] . to_d ) : 0 . to_d ) return_obj . save! return_obj . receive! if info [ 'tax_amt' ] shipping_amt = info [ 'shipping_amt' ] . to_d tax_amt = info [ 'tax_amt' ] . to_d @order . adjustments . create! ( amount : - shipping_amt , label : "Return #{rop_return_id} Shipping" ) if shipping_amt . nonzero? @order . adjustments . create! ( amount : - tax_amt , label : "Return #{rop_return_id} Tax" ) if tax_amt . nonzero? end end
Package adding: This reflects a fairly major impedence mismatch
between ROP and Spree, insofar as Spree wants to create shipments at
checkout time and charge exact shipping, while ROP standard practice
is to charge an abstraction of shipping that's close enough on
average, and then decide the details of how this order will be
shipped when it's actually ready to go out the door.
Package adding : This reflects a fairly major impedence mismatch between ROP and Spree insofar as Spree wants to create shipments at checkout time and charge exact shipping while ROP standard practice is to charge an abstraction of shipping that ' s close enough on average and then decide the details of how this order will be shipped when it ' s actually ready to go out the door .
# find Spree return, bail out if exists # may be nil->0 # if it exists but isn't received we're in a pretty weird state because we're supposed to receive in the same txn we create # count up current inventory units, verify inventory for the return # NOTE: spree 2.1.6 does not do per-line-item inventory units # always decrement for the RMA which we are receiving against, if there is one and it has been pushed to Spree already # if we can't satisfy the return from the named RMA, pull stuff from other RMAs # if room can be made, room has been made # create an RMA for our return # anything will be wrong since we don't want spree to restock :x # needs an ID before we can add stuf # "rma.stock_location" crashes.  possible has_one/has_many mixup? # receive! crashes if there is no stock item # optionally check completeness here? # set value # these might come in as strings, so coerce *before* summing # receive it # refund_amt (the only field sent by previous versions of the RO driver) is the total amount to refund # refund_amt = subtotal_amt + tax_amt + shipping_amt - [total restocking fees] + [rounding error] # Possible issue: any restocking fee < 5 cents is likely actually rounding noise # Possible issue: Setting "Refund" = No for an item will be treated the same as nulling the refund with a restocking fee
info
<not_specific>