From c70993ce755d1d36e182cc1ef6cf8e1c8f895ea0 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Fri, 19 Aug 2016 10:17:41 +1000 Subject: [PATCH] Find producer properties of items sold by a shop --- app/models/producer_property.rb | 9 ++++ app/models/spree/property_decorator.rb | 3 ++ spec/models/producer_property_spec.rb | 64 ++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/app/models/producer_property.rb b/app/models/producer_property.rb index 5b9fdd6d1c..bf1f083936 100644 --- a/app/models/producer_property.rb +++ b/app/models/producer_property.rb @@ -8,6 +8,15 @@ class ProducerProperty < ActiveRecord::Base after_destroy :refresh_products_cache_from_destroy + scope :sold_by, ->(shop) { + joins(producer: {supplied_products: {variants: {exchanges: :order_cycle}}}). + merge(Exchange.outgoing). + merge(Exchange.to_enterprise(shop)). + merge(OrderCycle.active). + select('DISTINCT producer_properties.*') + } + + def property_name property.name if property end diff --git a/app/models/spree/property_decorator.rb b/app/models/spree/property_decorator.rb index 58657ad3b1..50e450a03b 100644 --- a/app/models/spree/property_decorator.rb +++ b/app/models/spree/property_decorator.rb @@ -1,5 +1,7 @@ module Spree Property.class_eval do + has_many :producer_properties + scope :applied_by, ->(enterprise) { select('DISTINCT spree_properties.*'). joins(:product_properties). @@ -14,6 +16,7 @@ module Spree select('DISTINCT spree_properties.*') } + after_save :refresh_products_cache # When a Property is destroyed, dependent-destroy will destroy all ProductProperties, diff --git a/spec/models/producer_property_spec.rb b/spec/models/producer_property_spec.rb index eaa7f0de0c..2d0009ce12 100644 --- a/spec/models/producer_property_spec.rb +++ b/spec/models/producer_property_spec.rb @@ -1,14 +1,70 @@ require 'spec_helper' describe ProducerProperty do - describe "products caching" do - let(:producer) { create(:supplier_enterprise) } - let(:pp) { producer.producer_properties.first } + let(:producer) { create(:supplier_enterprise) } + let(:pp) { producer.producer_properties.first } + + before do + producer.set_producer_property 'Organic Certified', 'NASAA 54321' + end + + describe ".sold_by" do + let!(:shop) { create(:distributor_enterprise) } + let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } + let(:product) { create(:simple_product, supplier: producer) } + let(:producer_other) { create(:supplier_enterprise) } + let(:product_other) { create(:simple_product, supplier: producer_other) } + let(:pp_other) { producer_other.producer_properties.first } before do - producer.set_producer_property 'Organic Certified', 'NASAA 54321' + producer_other.set_producer_property 'Spiffy', 'Ya' end + describe "with an associated producer property" do + it "returns the producer property" do + expect(ProducerProperty.sold_by(shop)).to eq [pp] + end + end + + describe "with a producer property for a producer not carried by that shop" do + let!(:exchange) { create(:exchange, order_cycle: oc, incoming: true, sender: producer_other, receiver: oc.coordinator) } + + it "doesn't return the producer property" do + expect(ProducerProperty.sold_by(shop)).not_to include pp_other + end + end + + describe "with a producer property for a product in a different shop" do + let(:shop_other) { create(:distributor_enterprise) } + let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } + let!(:exchange) { create(:exchange, order_cycle: oc, incoming: false, sender: oc.coordinator, receiver: shop_other, variants: [product_other.variants.first]) } + + it "doesn't return the producer property" do + expect(ProducerProperty.sold_by(shop)).not_to include pp_other + end + end + + describe "with a producer property for a product in a closed order cycle" do + before do + oc.update_attributes! orders_close_at: 1.week.ago + end + + it "doesn't return the producer property" do + expect(ProducerProperty.sold_by(shop)).not_to include pp + end + end + + describe "with a duplicate producer property" do + let(:product2) { create(:simple_product, supplier: producer) } + let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first, product2.variants.first]) } + + it "doesn't return duplicates" do + expect(ProducerProperty.sold_by(shop).to_a.count).to eq 1 + end + end + end + + describe "products caching" do it "refreshes the products cache on change" do expect(OpenFoodNetwork::ProductsCache).to receive(:producer_property_changed).with(pp) pp.value = 123