Bring adjuster and prioritizer from spree_core

This commit is contained in:
Luis Ramos
2020-07-01 16:03:46 +01:00
parent d18fec7125
commit 3ae2877d4e
3 changed files with 186 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
# Used by Prioritizer to adjust item quantities
# see prioritizer_spec for use cases
module Spree
module Stock
class Adjuster
attr_accessor :variant, :need, :status
def initialize(variant, quantity, status)
@variant = variant
@need = quantity
@status = status
end
def adjust(item)
if item.quantity >= need
item.quantity = need
@need = 0
elsif item.quantity < need
@need -= item.quantity
end
end
def fulfilled?
@need == 0
end
end
end
end

View File

@@ -0,0 +1,47 @@
module Spree
module Stock
class Prioritizer
attr_reader :packages, :order
def initialize(order, packages, adjuster_class=Adjuster)
@order = order
@packages = packages
@adjuster_class = adjuster_class
end
def prioritized_packages
sort_packages
adjust_packages
prune_packages
packages
end
private
def adjust_packages
order.line_items.each do |line_item|
adjuster = @adjuster_class.new(line_item.variant, line_item.quantity, :on_hand)
visit_packages(adjuster)
adjuster.status = :backordered
visit_packages(adjuster)
end
end
def visit_packages(adjuster)
packages.each do |package|
item = package.find_item adjuster.variant, adjuster.status
adjuster.adjust(item) if item
end
end
def sort_packages
# order packages by preferred stock_locations
end
def prune_packages
packages.reject! { |pkg| pkg.empty? }
end
end
end
end

View File

@@ -0,0 +1,111 @@
require 'spec_helper'
module Spree
module Stock
describe Prioritizer do
let(:order) { create(:order_with_line_items, line_items_count: 2) }
let(:stock_location) { build(:stock_location) }
let(:variant1) { order.line_items[0].variant }
let(:variant2) { order.line_items[1].variant }
def pack
package = Package.new(order, stock_location)
yield(package) if block_given?
package
end
it 'keeps a single package' do
package1 = pack do |package|
package.add variant1, 1, :on_hand
package.add variant2, 1, :on_hand
end
packages = [package1]
prioritizer = Prioritizer.new(order, packages)
packages = prioritizer.prioritized_packages
packages.size.should eq 1
end
it 'removes duplicate packages' do
package1 = pack do |package|
package.add variant1, 1, :on_hand
package.add variant2, 1, :on_hand
end
package2 = pack do |package|
package.add variant1, 1, :on_hand
package.add variant2, 1, :on_hand
end
packages = [package1, package2]
prioritizer = Prioritizer.new(order, packages)
packages = prioritizer.prioritized_packages
packages.size.should eq 1
end
it 'split over 2 packages' do
package1 = pack do |package|
package.add variant1, 1, :on_hand
end
package2 = pack do |package|
package.add variant2, 1, :on_hand
end
packages = [package1, package2]
prioritizer = Prioritizer.new(order, packages)
packages = prioritizer.prioritized_packages
packages.size.should eq 2
end
it '1st has some, 2nd has remaining' do
order.line_items[0].stub(:quantity => 5)
package1 = pack do |package|
package.add variant1, 2, :on_hand
end
package2 = pack do |package|
package.add variant1, 5, :on_hand
end
packages = [package1, package2]
prioritizer = Prioritizer.new(order, packages)
packages = prioritizer.prioritized_packages
packages.count.should eq 2
packages[0].quantity.should eq 2
packages[1].quantity.should eq 3
end
it '1st has backorder, 2nd has some' do
order.line_items[0].stub(:quantity => 5)
package1 = pack do |package|
package.add variant1, 5, :backordered
end
package2 = pack do |package|
package.add variant1, 2, :on_hand
end
packages = [package1, package2]
prioritizer = Prioritizer.new(order, packages)
packages = prioritizer.prioritized_packages
packages[0].quantity(:backordered).should eq 3
packages[1].quantity(:on_hand).should eq 2
end
it '1st has backorder, 2nd has all' do
order.line_items[0].stub(:quantity => 5)
package1 = pack do |package|
package.add variant1, 3, :backordered
package.add variant2, 1, :on_hand
end
package2 = pack do |package|
package.add variant1, 5, :on_hand
end
packages = [package1, package2]
prioritizer = Prioritizer.new(order, packages)
packages = prioritizer.prioritized_packages
packages[0].quantity(:backordered).should eq 0
packages[1].quantity(:on_hand).should eq 5
end
end
end
end