Bring Package from spree_core

This commit is contained in:
Luis Ramos
2020-07-01 17:18:07 +01:00
parent 0ca8b6aab6
commit b7255130b6
2 changed files with 226 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
module Spree
module Stock
class Package
ContentItem = Struct.new(:variant, :quantity, :state)
attr_reader :stock_location, :order, :contents
attr_accessor :shipping_rates
def initialize(stock_location, order, contents=[])
@stock_location = stock_location
@order = order
@contents = contents
@shipping_rates = Array.new
end
def add(variant, quantity, state=:on_hand)
contents << ContentItem.new(variant, quantity, state)
end
def weight
contents.sum { |item| item.variant.weight * item.quantity }
end
def on_hand
contents.select { |item| item.state == :on_hand }
end
def backordered
contents.select { |item| item.state == :backordered }
end
def find_item(variant, state=:on_hand)
contents.select do |item|
item.variant == variant &&
item.state == state
end.first
end
def quantity(state=nil)
case state
when :on_hand
on_hand.sum { |item| item.quantity }
when :backordered
backordered.sum { |item| item.quantity }
else
contents.sum { |item| item.quantity }
end
end
def empty?
quantity == 0
end
def flattened
flat = []
contents.each do |item|
item.quantity.times do
flat << ContentItem.new(item.variant, 1, item.state)
end
end
flat
end
def flattened=(flattened)
contents.clear
flattened.each do |item|
current_item = find_item(item.variant, item.state)
if current_item
current_item.quantity += 1
else
add(item.variant, item.quantity, item.state)
end
end
end
def currency
#TODO calculate from first variant?
end
def shipping_categories
contents.map { |item| item.variant.shipping_category }.compact.uniq
end
def shipping_methods
shipping_categories.map { |sc| sc.shipping_methods }.flatten.uniq
end
def inspect
out = "#{order} - "
out << contents.map do |content_item|
"#{content_item.variant.name} #{content_item.quantity} #{content_item.state}"
end.join('/')
out
end
def to_shipment
shipment = Spree::Shipment.new
shipment.order = order
shipment.stock_location = stock_location
shipment.shipping_rates = shipping_rates
contents.each do |item|
item.quantity.times do |n|
unit = shipment.inventory_units.build
unit.pending = true
unit.order = order
unit.variant = item.variant
unit.state = item.state.to_s
end
end
shipment
end
end
end
end

View File

@@ -0,0 +1,110 @@
require 'spec_helper'
module Spree
module Stock
describe Package do
let(:variant) { build(:variant, weight: 25.0) }
let(:stock_location) { build(:stock_location) }
let(:order) { build(:order) }
subject { Package.new(stock_location, order) }
it 'calculates the weight of all the contents' do
subject.add variant, 4
subject.weight.should == 100.0
end
it 'filters by on_hand and backordered' do
subject.add variant, 4, :on_hand
subject.add variant, 3, :backordered
subject.on_hand.count.should eq 1
subject.backordered.count.should eq 1
end
it 'calculates the quantity by state' do
subject.add variant, 4, :on_hand
subject.add variant, 3, :backordered
subject.quantity.should eq 7
subject.quantity(:on_hand).should eq 4
subject.quantity(:backordered).should eq 3
end
it 'returns nil for content item not found' do
item = subject.find_item(variant, :on_hand)
item.should be_nil
end
it 'finds content item for a variant' do
subject.add variant, 4, :on_hand
item = subject.find_item(variant, :on_hand)
item.quantity.should eq 4
end
it 'get flattened contents' do
subject.add variant, 4, :on_hand
subject.add variant, 2, :backordered
flattened = subject.flattened
flattened.select { |i| i.state == :on_hand }.size.should eq 4
flattened.select { |i| i.state == :backordered }.size.should eq 2
end
it 'set contents from flattened' do
flattened = [Package::ContentItem.new(variant, 1, :on_hand),
Package::ContentItem.new(variant, 1, :on_hand),
Package::ContentItem.new(variant, 1, :backordered),
Package::ContentItem.new(variant, 1, :backordered)]
subject.flattened = flattened
subject.on_hand.size.should eq 1
subject.on_hand.first.quantity.should eq 2
subject.backordered.size.should eq 1
end
# Contains regression test for #2804
it 'builds a list of shipping methods from all categories' do
shipping_method1 = create(:shipping_method)
shipping_method2 = create(:shipping_method)
variant1 = mock_model(Variant, shipping_category: shipping_method1.shipping_categories.first)
variant2 = mock_model(Variant, shipping_category: shipping_method2.shipping_categories.first)
variant3 = mock_model(Variant, shipping_category: nil)
contents = [Package::ContentItem.new(variant1, 1),
Package::ContentItem.new(variant1, 1),
Package::ContentItem.new(variant2, 1),
Package::ContentItem.new(variant3, 1)]
package = Package.new(stock_location, order, contents)
package.shipping_methods.size.should eq 2
end
it "can convert to a shipment" do
flattened = [Package::ContentItem.new(variant, 2, :on_hand),
Package::ContentItem.new(variant, 1, :backordered)]
subject.flattened = flattened
shipping_method = build(:shipping_method)
subject.shipping_rates = [ Spree::ShippingRate.new(shipping_method: shipping_method, cost: 10.00, selected: true) ]
shipment = subject.to_shipment
shipment.order.should == subject.order
shipment.stock_location.should == subject.stock_location
shipment.inventory_units.size.should == 3
first_unit = shipment.inventory_units.first
first_unit.variant.should == variant
first_unit.state.should == 'on_hand'
first_unit.order.should == subject.order
first_unit.should be_pending
last_unit = shipment.inventory_units.last
last_unit.variant.should == variant
last_unit.state.should == 'backordered'
last_unit.order.should == subject.order
shipment.shipping_method.should eq shipping_method
end
end
end
end