diff --git a/app/serializers/api/product_serializer.rb b/app/serializers/api/product_serializer.rb index 816d18c3ce..9ca174d863 100644 --- a/app/serializers/api/product_serializer.rb +++ b/app/serializers/api/product_serializer.rb @@ -1,4 +1,4 @@ -require 'open_food_network/variant_proxy' +require 'open_food_network/scope_variant_to_hub' class Api::ProductSerializer < ActiveModel::Serializer # TODO @@ -43,9 +43,13 @@ class Api::CachedProductSerializer < ActiveModel::Serializer has_one :master, serializer: Api::VariantSerializer def variants + # We use the in_stock? method here instead of the in_stock scope because we need to + # look up the stock as overridden by VariantOverrides, and the scope method is not affected + # by them. + object.variants. for_distribution(options[:current_order_cycle], options[:current_distributor]). - in_stock. - map { |v| OpenFoodNetwork::VariantProxy.new(v, options[:current_distributor]) } + each { |v| v.scope_to_hub options[:current_distributor] }. + select(&:in_stock?) end end diff --git a/lib/open_food_network/product_proxy.rb b/lib/open_food_network/product_proxy.rb deleted file mode 100644 index 2d1cca0b72..0000000000 --- a/lib/open_food_network/product_proxy.rb +++ /dev/null @@ -1,23 +0,0 @@ -require 'open_food_network/variant_proxy' - -module OpenFoodNetwork - # Variants can have several fields overridden on a per-enterprise basis by the - # VariantOverride model. These overrides can be applied to variants by wrapping their - # products in this proxy, which wraps the product's variants in VariantProxy. - class ProductProxy - instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ } - - def initialize(product, hub) - @product = product - @hub = hub - end - - def variants - @product.variants.map { |v| VariantProxy.new(v, @hub) } - end - - def method_missing(name, *args, &block) - @product.send(name, *args, &block) - end - end -end diff --git a/lib/open_food_network/scope_variant_to_hub.rb b/lib/open_food_network/scope_variant_to_hub.rb new file mode 100644 index 0000000000..89a527ea19 --- /dev/null +++ b/lib/open_food_network/scope_variant_to_hub.rb @@ -0,0 +1,18 @@ +module OpenFoodNetwork + module ScopeVariantToHub + def price + VariantOverride.price_for(@hub, self) || super + end + + def count_on_hand + VariantOverride.count_on_hand_for(@hub, self) || super + end + end +end + +Spree::Variant.class_eval do + def scope_to_hub(hub) + extend OpenFoodNetwork::ScopeVariantToHub + @hub = hub + end +end diff --git a/lib/open_food_network/variant_proxy.rb b/lib/open_food_network/variant_proxy.rb deleted file mode 100644 index 7a16bb4114..0000000000 --- a/lib/open_food_network/variant_proxy.rb +++ /dev/null @@ -1,27 +0,0 @@ -module OpenFoodNetwork - # Variants can have several fields overridden on a per-enterprise basis by the - # VariantOverride model. These overrides can be applied to variants by wrapping in an - # instance of the VariantProxy class. This class proxies most methods back to the wrapped - # variant, but checks for overrides when fetching some properties. - class VariantProxy - instance_methods.each { |m| undef_method m unless m =~ /(^__|^send$|^object_id$)/ } - - def initialize(variant, hub) - @variant = variant - @hub = hub - end - - def price - VariantOverride.price_for(@hub, @variant) || @variant.price - end - - def price_with_fees(distributor, order_cycle) - price + @variant.fees_for(distributor, order_cycle) - end - - - def method_missing(name, *args, &block) - @variant.send(name, *args, &block) - end - end -end diff --git a/spec/lib/open_food_network/product_proxy_spec.rb b/spec/lib/open_food_network/product_proxy_spec.rb deleted file mode 100644 index e8a8565949..0000000000 --- a/spec/lib/open_food_network/product_proxy_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'open_food_network/product_proxy' -require 'open_food_network/variant_proxy' - -module OpenFoodNetwork - describe ProductProxy do - let(:hub) { double(:hub) } - let(:p) { double(:product, name: 'name') } - let(:pp) { ProductProxy.new(p, hub) } - - describe "delegating calls to proxied product" do - it "delegates name" do - pp.name.should == 'name' - end - end - - describe "fetching the variants" do - let(:v1) { double(:variant) } - let(:v2) { double(:variant) } - let(:p) { double(:product, variants: [v1, v2]) } - - it "returns variants wrapped in VariantProxy" do - # #class is proxied too, so we test that it worked by #object_id - pp.variants.map(&:object_id).sort.should_not == [v1.object_id, v2.object_id].sort - end - end - end -end diff --git a/spec/lib/open_food_network/scope_variant_to_hub_spec.rb b/spec/lib/open_food_network/scope_variant_to_hub_spec.rb new file mode 100644 index 0000000000..b657afeb9b --- /dev/null +++ b/spec/lib/open_food_network/scope_variant_to_hub_spec.rb @@ -0,0 +1,35 @@ +require 'open_food_network/scope_variant_to_hub' + +module OpenFoodNetwork + describe ScopeVariantToHub do + let(:hub) { create(:distributor_enterprise) } + let(:v) { create(:variant, price: 11.11, count_on_hand: 1) } + let(:vo) { create(:variant_override, hub: hub, variant: v, price: 22.22, count_on_hand: 2) } + + describe "overriding price" do + it "returns the overridden price when one is present" do + vo + v.scope_to_hub hub + v.price.should == 22.22 + end + + it "returns the variant's price otherwise" do + v.scope_to_hub hub + v.price.should == 11.11 + end + end + + describe "overriding stock levels" do + it "returns the overridden stock level when one is present" do + vo + v.scope_to_hub hub + v.count_on_hand.should == 2 + end + + it "returns the variant's stock level otherwise" do + v.scope_to_hub hub + v.count_on_hand.should == 1 + end + end + end +end diff --git a/spec/lib/open_food_network/variant_proxy_spec.rb b/spec/lib/open_food_network/variant_proxy_spec.rb deleted file mode 100644 index 6439c502a5..0000000000 --- a/spec/lib/open_food_network/variant_proxy_spec.rb +++ /dev/null @@ -1,27 +0,0 @@ -require 'open_food_network/variant_proxy' - -module OpenFoodNetwork - describe VariantProxy do - let(:hub) { double(:hub) } - let(:v) { double(:variant, sku: 'sku123', price: 'global price') } - let(:vp) { VariantProxy.new(v, hub) } - - describe "delegating calls to proxied variant" do - it "delegates sku" do - vp.sku.should == 'sku123' - end - end - - describe "looking up the price" do - it "returns the override price when there is one" do - VariantOverride.stub(:price_for) { 'override price' } - vp.price.should == 'override price' - end - - it "returns the global price otherwise" do - VariantOverride.stub(:price_for) { nil } - vp.price.should == 'global price' - end - end - end -end