Class: Spree::Stock::Coordinator

Inherits:
Object
  • Object
show all
Defined in:
app/models/spree/stock/coordinator.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(order, inventory_units = nil) ⇒ Coordinator

Returns a new instance of Coordinator.



6
7
8
9
10
# File 'app/models/spree/stock/coordinator.rb', line 6

def initialize(order, inventory_units = nil)
  @order = order
  @inventory_units = inventory_units || InventoryUnitBuilder.new(order).units
  @preallocated_inventory_units = []
end

Instance Attribute Details

#inventory_unitsObject (readonly)

Returns the value of attribute inventory_units.



4
5
6
# File 'app/models/spree/stock/coordinator.rb', line 4

def inventory_units
  @inventory_units
end

#orderObject (readonly)

Returns the value of attribute order.



4
5
6
# File 'app/models/spree/stock/coordinator.rb', line 4

def order
  @order
end

Instance Method Details

#build_location_configured_packages(packages = Array.new) ⇒ Object

Build packages for the inventory units that have preferred stock locations first

Certain variants have been selected to be fulfilled from a particular stock location during the process of the order being created. The rest of the service objects the coordinator uses do a lot of automated logic to determine which stock location is best for the inventory unit to be fulfilled from, but for these special snowflakes we KNOW which stock location they should be fulfilled from. So rather than sending these units through the rest of the packing / prioritization, lets just put them in packages we know they should be in and deal with other automatically- handled inventory units otherwise.



36
37
38
39
40
41
42
43
44
45
46
# File 'app/models/spree/stock/coordinator.rb', line 36

def build_location_configured_packages(packages = Array.new)
  order.order_stock_locations.where(shipment_fulfilled: false).group_by(&:stock_location).each do |stock_location, stock_location_configurations|
    units = stock_location_configurations.flat_map do |stock_location_configuration|
      unallocated_inventory_units.select { |iu| iu.variant == stock_location_configuration.variant }.take(stock_location_configuration.quantity)
    end
    packer = build_packer(stock_location, units)
    packages += packer.packages
    @preallocated_inventory_units += units
  end
  packages
end

#build_packages(packages = Array.new) ⇒ Object

Build packages as per stock location

It needs to check whether each stock location holds at least one stock item for the order. In case none is found it wouldn’t make any sense to build a package because it would be empty. Plus we avoid errors down the stack because it would assume the stock location has stock items for the given order

Returns an array of Package instances



57
58
59
60
61
62
63
64
65
# File 'app/models/spree/stock/coordinator.rb', line 57

def build_packages(packages = Array.new)
  StockLocation.active.each do |stock_location|
    units_for_location = unallocated_inventory_units.select { |unit| stock_location.stock_item(unit.variant) }
    next unless units_for_location.any?
    packer = build_packer(stock_location, units_for_location)
    packages += packer.packages
  end
  packages
end

#packagesObject



18
19
20
21
22
23
# File 'app/models/spree/stock/coordinator.rb', line 18

def packages
  packages = build_location_configured_packages
  packages = build_packages(packages)
  packages = prioritize_packages(packages)
  packages = estimate_packages(packages)
end

#shipmentsObject



12
13
14
15
16
# File 'app/models/spree/stock/coordinator.rb', line 12

def shipments
  packages.map do |package|
    package.to_shipment.tap { |s| s.address = order.ship_address }
  end
end