From c2ec34ab9f063f41cf46f4c07120646159771958 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Wed, 1 Jul 2020 16:14:02 +0100 Subject: [PATCH] Bring coordinator from spree_core --- app/models/spree/stock/coordinator.rb | 59 +++++++++++++++++++++ spec/models/spree/stock/coordinator_spec.rb | 34 ++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 app/models/spree/stock/coordinator.rb create mode 100644 spec/models/spree/stock/coordinator_spec.rb diff --git a/app/models/spree/stock/coordinator.rb b/app/models/spree/stock/coordinator.rb new file mode 100644 index 0000000000..605b9dc343 --- /dev/null +++ b/app/models/spree/stock/coordinator.rb @@ -0,0 +1,59 @@ +module Spree + module Stock + class Coordinator + attr_reader :order + + def initialize(order) + @order = order + end + + def packages + packages = build_packages + packages = prioritize_packages(packages) + packages = estimate_packages(packages) + end + + # 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 + def build_packages(packages = Array.new) + StockLocation.active.each do |stock_location| + next unless stock_location.stock_items.where(:variant_id => order.line_items.pluck(:variant_id)).exists? + + packer = build_packer(stock_location, order) + packages += packer.packages + end + packages + end + + private + def prioritize_packages(packages) + prioritizer = Prioritizer.new(order, packages) + prioritizer.prioritized_packages + end + + def estimate_packages(packages) + estimator = Estimator.new(order) + packages.each do |package| + package.shipping_rates = estimator.shipping_rates(package) + end + packages + end + + def build_packer(stock_location, order) + Packer.new(stock_location, order, splitters(stock_location)) + end + + def splitters(stock_location) + # extension point to return custom splitters for a location + Rails.application.config.spree.stock_splitters + end + end + end +end diff --git a/spec/models/spree/stock/coordinator_spec.rb b/spec/models/spree/stock/coordinator_spec.rb new file mode 100644 index 0000000000..006fd27b8b --- /dev/null +++ b/spec/models/spree/stock/coordinator_spec.rb @@ -0,0 +1,34 @@ +require 'spec_helper' + +module Spree + module Stock + describe Coordinator do + let!(:order) { create(:order_with_line_items) } + + subject { Coordinator.new(order) } + + context "packages" do + it "builds, prioritizes and estimates" do + subject.should_receive(:build_packages).ordered + subject.should_receive(:prioritize_packages).ordered + subject.should_receive(:estimate_packages).ordered + subject.packages + end + end + + context "build packages" do + it "builds a package for every stock location" do + subject.packages.count == StockLocation.count + end + + context "missing stock items in stock location" do + let!(:another_location) { create(:stock_location, propagate_all_variants: false) } + + it "builds packages only for valid stock locations" do + subject.build_packages.count.should == (StockLocation.count - 1) + end + end + end + end + end +end