mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-26 01:33:22 +00:00
Bring adjuster and prioritizer from spree_core
This commit is contained in:
28
app/models/spree/stock/adjuster.rb
Normal file
28
app/models/spree/stock/adjuster.rb
Normal 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
|
||||
47
app/models/spree/stock/prioritizer.rb
Normal file
47
app/models/spree/stock/prioritizer.rb
Normal 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
|
||||
111
spec/models/spree/stock/prioritizer_spec.rb
Normal file
111
spec/models/spree/stock/prioritizer_spec.rb
Normal 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
|
||||
Reference in New Issue
Block a user