module Seshbot::Packing
Constants
- VERSION
Public Class Methods
_bundle_items_legacy(recipes, items)
click to toggle source
# File lib/seshbot/packing/package.rb, line 122 def _bundle_items_legacy(recipes, items) # get the cans first, and separate them out cans = _filter_by_sku_fragment_prefix(items, 'C') remaining_cans = [] unless cans.empty? bundle_items_by_type = LineItem.merge_line_items(cans) bundle_items_by_type = unpack(recipes, bundle_items_by_type) new_can_items = pack(recipes, bundle_items_by_type) # separate out all the C324s separated_c324s = _filter_by_sku_fragment_prefix(new_can_items, 'C324') logger.debug "bundling - Cans: #{cans.map(&:to_s)}" logger.debug " - Removed C324s: #{separated_c324s.map(&:to_s)}" remaining_cans = _filter_by_sku_fragment_prefix(new_can_items, 'C324', inverse: true) logger.debug " - Remaining skus: #{remaining_cans.map(&:to_s)}" end # merge the remaining with the original leftover non_cans = _filter_by_sku_fragment_prefix(items, 'C', inverse: true) remaining_items = non_cans + remaining_cans logger.debug "bundling - Substituting:" logger.debug " - remaining items: #{remaining_items.map(&:to_s)}" # substitute C's for B's remaining_items = _substitute_sku(remaining_items, /^C/, 'B') logger.debug " - skus updated to: #{remaining_items.map(&:to_s)}" # get a hash of {pack_6: 5, pack_12: 1} bundle_items_by_type = LineItem.merge_line_items(remaining_items) # dismantle packages into individual units (e.g., {pack_6: 7}) bundle_items_by_type = unpack(recipes, bundle_items_by_type) # repackage into the 'best' packaging we can figure out (e.g., {pack_12: 2}) new_remaining_items = pack(recipes, bundle_items_by_type) separated_c324s ||= [] results = new_remaining_items + separated_c324s results end
_bundle_items_single_phase(recipes, items)
click to toggle source
# File lib/seshbot/packing/package.rb, line 162 def _bundle_items_single_phase(recipes, items) # get a list of items merged together by variant type (e.g., 10xBIGI-C301 + 5xBISS-C301 => 15xBUND-C301)) merged_items = LineItem.merge_line_items(items) # dismantle packages into individual units unpacked_items = unpack(recipes, merged_items) # repackage into the 'best' packaging we can figure out pack(recipes, unpacked_items) end
_filter_by_sku_fragment_prefix(items, sku_fragment, inverse: false)
click to toggle source
# File lib/seshbot/packing/package.rb, line 171 def _filter_by_sku_fragment_prefix(items, sku_fragment, inverse: false) items.select do |i| matches = i.sku_fragment.start_with? sku_fragment inverse ? !matches : matches end end
_is_legacy(fulfilled_at)
click to toggle source
private
# File lib/seshbot/packing/package.rb, line 116 def _is_legacy(fulfilled_at) effective_fulfilled_at = fulfilled_at.nil? ? DateTime.now : fulfilled_at is_legacy = effective_fulfilled_at < DateTime.parse('2021-04-23T08:00:00+09:00') is_legacy end
_pack_single_step(recipes, items, unpacking:)
click to toggle source
# File lib/seshbot/packing/package.rb, line 182 def _pack_single_step(recipes, items, unpacking:) recipe = Recipe::find_best_recipe(recipes, items, unpacking: unpacking) if recipe.nil? # its as packed/unpacked as it can get return items end before = LineItem::summarise(items) items = Recipe::apply_recipe(recipe, items) after = LineItem::summarise(items) logger.debug "bundling - applying recipe (#{unpacking ? 'unpacking' : 'packing'}) #{Recipe::summarise(recipe)}: #{before} -> #{after}" items end
_substitute_sku(items, re, sub)
click to toggle source
# File lib/seshbot/packing/package.rb, line 178 def _substitute_sku(items, re, sub) items.map { |i| LineItem.new(i.sku_fragment.gsub(re, sub), i.quantity) } end
bundle_items(recipes, items, fulfilled_at: nil)
click to toggle source
# File lib/seshbot/packing/package.rb, line 21 def bundle_items(recipes, items, fulfilled_at: nil) if !fulfilled_at.nil? && fulfilled_at < DateTime.parse('2020-01-14T08:00:00+09:00') logger.debug "bundling - Not Bundling (pre-2020 order) ==" return items end is_legacy = _is_legacy(fulfilled_at) is_legacy_str = is_legacy ? " (LEGACY)" : "" logger.debug "bundling - Bundling Items: #{items.map(&:to_s)}. Fulfilled at: #{fulfilled_at || '(no fulfillment date)'}#{is_legacy_str}" results = [] if is_legacy results = _bundle_items_legacy(recipes, items) else phases = recipes.values.map { |r| r['phase'] || 0 }.map(&:to_i).uniq.sort results = items phases.each do |phase| phase_recipes = recipes.select { |name, recipe| (recipe['phase'] || 0) == phase }.to_h logger.debug "bundling - PHASE #{phase}" results = _bundle_items_single_phase(phase_recipes, results) end end logger.debug "bundling - Bundled result:" logger.debug " - IN: #{items.map(&:to_s)}" logger.debug " - OUT: #{results.map(&:to_s)}" results end
logger()
click to toggle source
# File lib/seshbot/packing/package.rb, line 9 def logger if @@logger.nil? if defined?(Rails) @@logger = Rails.logger else @@logger = Logger.new(STDERR) @@logger.level = 1 end end @@logger end
pack(recipes, items)
click to toggle source
# File lib/seshbot/packing/package.rb, line 95 def pack(recipes, items) prev_result = items # keep trying to 'pack' until it stabilises (e.g., 6x6pack => 1x24pack+2x6pack => 1x24pack+1x12pack) (1..1000).each do |i| new_result = _pack_single_step(recipes, prev_result, unpacking: false) # no changes, break out is_unchanged = new_result.map { |li| [li.sku_fragment, li.quantity] }.sort == prev_result.map { |li| [li.sku_fragment, li.quantity] }.sort return new_result if is_unchanged prev_result = new_result end error_message = "bundling - could not pack - infinite loop? (latest: #{prev_result.map(&:to_s)})" logger.error error_message raise error_message end
unbundle_items(recipes, items, fulfilled_at: nil)
click to toggle source
# File lib/seshbot/packing/package.rb, line 55 def unbundle_items(recipes, items, fulfilled_at: nil) logger.debug "bundling - Unbundling Items: #{items.map(&:to_s)}" results = [] phases = recipes.values.map { |r| r['phase'] || 0 }.map(&:to_i).uniq.sort.reverse results = items phases.each do |phase| phase_recipes = recipes.select { |name, recipe| (recipe['phase'] || 0) == phase }.to_h logger.debug "bundling - PHASE #{phase}" # get a list of items merged together by variant type (e.g., 10xBIGI-C301 + 5xBISS-C301 => 15xBUND-C301)) merged_items = LineItem.merge_line_items(results) results = unpack(recipes, merged_items) end logger.debug "bundling - Unbundle result:" logger.debug " - IN: #{items.map(&:to_s)}" logger.debug " - OUT: #{results.map(&:to_s)}" results end
unpack(recipes, items)
click to toggle source
# File lib/seshbot/packing/package.rb, line 80 def unpack(recipes, items) prev_result = items (1..1000).each do |i| new_result = _pack_single_step(recipes, prev_result, unpacking: true) is_unchanged = new_result.map { |li| [li.sku_fragment, li.quantity] }.sort == prev_result.map { |li| [li.sku_fragment, li.quantity] }.sort return new_result if is_unchanged prev_result = new_result end error_message = "bundling - could not unpack - infinite loop? (latest: #{prev_result.map(&:to_s)})" logger.error error_message raise error_message end