Extract #load_products logic into a new service

This commit is contained in:
Matt-Yorkley
2019-09-27 16:35:40 +01:00
parent 535e389fb4
commit d5e90c3c6c
3 changed files with 139 additions and 54 deletions

View File

@@ -0,0 +1,70 @@
# Returns a (paginatable) AR object for the products in stock for a given distributor and OC.
# The stock-checking includes on_demand and stock level overrides from variant_overrides.
class ShopProductsService
def initialize(distributor, order_cycle)
@distributor = distributor
@order_cycle = order_cycle
end
def relation
Spree::Product.where(id: distributed_products)
end
private
def distributed_products
@order_cycle.
variants_distributed_by(@distributor).
merge(stocked_variants_and_overrides).
select("DISTINCT spree_variants.product_id")
end
def stocked_variants_and_overrides
Spree::Variant.
joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.variant_id = spree_variants.id
AND variant_overrides.hub_id = #{@distributor.id}").
joins(:stock_items).
where(query_stock_with_overrides)
end
def query_stock_with_overrides
"( #{variant_not_overriden} AND ( #{variant_on_demand} OR #{variant_in_stock} ) )
OR ( #{variant_overriden} AND ( #{override_on_demand} OR #{override_in_stock} ) )
OR ( #{variant_overriden} AND ( #{override_on_demand_null} AND #{variant_on_demand} ) )
OR ( #{variant_overriden} AND ( #{override_on_demand_null}
AND #{variant_not_on_demand} AND #{variant_in_stock} ) )"
end
def variant_not_overriden
"variant_overrides.id IS NULL"
end
def variant_overriden
"variant_overrides.id IS NOT NULL"
end
def variant_in_stock
"spree_stock_items.count_on_hand > 0"
end
def variant_on_demand
"spree_stock_items.backorderable IS TRUE"
end
def variant_not_on_demand
"spree_stock_items.backorderable IS FALSE"
end
def override_on_demand
"variant_overrides.on_demand IS TRUE"
end
def override_in_stock
"variant_overrides.count_on_hand > 0"
end
def override_on_demand_null
"variant_overrides.on_demand IS NULL"
end
end

View File

@@ -32,64 +32,11 @@ module OpenFoodNetwork
def load_products
return unless @order_cycle
Spree::Product.where(id: distributed_products).
ShopProductsService.new(@distributor, @order_cycle).relation.
order(taxon_order).
each { |product| scoper.scope(product) }
end
def distributed_products
@order_cycle.
variants_distributed_by(@distributor).
merge(stocked_variants_with_overrides).
select("DISTINCT spree_variants.product_id")
end
def stocked_variants_with_overrides
Spree::Variant.
joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.variant_id = spree_variants.id AND variant_overrides.hub_id = #{@distributor.id}").
joins(:stock_items).
where(query_stock_with_overrides)
end
def query_stock_with_overrides
"( #{variant_not_overriden} AND ( #{variant_in_stock} OR #{variant_on_demand} ) )
OR ( #{variant_overriden} AND ( #{override_on_demand} OR #{override_in_stock} ) )
OR ( #{variant_overriden} AND ( #{override_on_demand_null} AND #{variant_on_demand} ) )
OR ( #{variant_overriden} AND ( #{override_on_demand_null} AND #{variant_not_on_demand} AND #{variant_in_stock} ) )"
end
def variant_not_overriden
"variant_overrides.id IS NULL"
end
def variant_overriden
"variant_overrides.id IS NOT NULL"
end
def variant_in_stock
"spree_stock_items.count_on_hand > 0"
end
def variant_on_demand
"spree_stock_items.backorderable IS TRUE"
end
def variant_not_on_demand
"spree_stock_items.backorderable IS FALSE"
end
def override_on_demand
"variant_overrides.on_demand IS TRUE"
end
def override_in_stock
"variant_overrides.count_on_hand > 0"
end
def override_on_demand_null
"variant_overrides.on_demand IS NULL"
end
def scoper
ScopeProductToHub.new(@distributor)
end

View File

@@ -0,0 +1,68 @@
require 'spec_helper'
describe ShopProductsService do
let(:distributor) { create(:distributor_enterprise) }
let(:product) { create(:product) }
let(:variant) { product.variants.first }
let(:order_cycle) do
create(:simple_order_cycle, distributors: [distributor], variants: [variant])
end
describe "product distributed by distributor in the OC" do
it "returns products" do
expect(described_class.new(distributor, order_cycle).relation).to eq([product])
end
end
describe "product distributed by distributor in another OC" do
let(:reference_variant) { create(:product).variants.first }
let(:order_cycle) do
create(:simple_order_cycle, distributors: [distributor], variants: [reference_variant])
end
let(:another_order_cycle) do
create(:simple_order_cycle, distributors: [distributor], variants: [variant])
end
it "does not return product" do
expect(described_class.new(distributor, order_cycle).relation).to_not include product
end
end
describe "product distributed by another distributor in the OC" do
let(:another_distributor) { create(:distributor_enterprise) }
let(:order_cycle) do
create(:simple_order_cycle, distributors: [another_distributor], variants: [variant])
end
it "does not return product" do
expect(described_class.new(distributor, order_cycle).relation).to_not include product
end
end
describe "filtering products that are out of stock" do
context "with regular variants" do
it "returns product when variant is in stock" do
expect(described_class.new(distributor, order_cycle).relation).to include product
end
it "does not return product when variant is out of stock" do
variant.update_attribute(:on_hand, 0)
expect(described_class.new(distributor, order_cycle).relation).to_not include product
end
end
context "with variant overrides" do
let!(:override) { create(:variant_override, hub: distributor, variant: variant, count_on_hand: 0) }
it "does not return product when an override is out of stock" do
expect(described_class.new(distributor, order_cycle).relation).to_not include product
end
it "returns product when an override is in stock" do
variant.update_attribute(:on_hand, 0)
override.update_attribute(:count_on_hand, 10)
expect(described_class.new(distributor, order_cycle).relation).to include product
end
end
end
end