From 6f29a8b64239de51e2930a09cebc11f8186cd4ca Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 9 Mar 2016 13:29:33 +1100 Subject: [PATCH] Refresh cache when inventory setting product_selection_from_inventory_only is changed --- app/models/spree/preference_decorator.rb | 31 +++++++++++++++++++ lib/open_food_network/products_cache.rb | 7 +++++ spec/features/admin/enterprises_spec.rb | 26 ++++++++++++++++ .../open_food_network/products_cache_spec.rb | 10 ++++++ spec/models/spree/preference_spec.rb | 23 ++++++++++++++ 5 files changed, 97 insertions(+) create mode 100644 app/models/spree/preference_decorator.rb create mode 100644 spec/models/spree/preference_spec.rb diff --git a/app/models/spree/preference_decorator.rb b/app/models/spree/preference_decorator.rb new file mode 100644 index 0000000000..c3ab3f9a94 --- /dev/null +++ b/app/models/spree/preference_decorator.rb @@ -0,0 +1,31 @@ +require 'open_food_network/products_cache' + +module Spree + Preference.class_eval do + after_save :refresh_products_cache + + # When the setting preferred_product_selection_from_inventory_only has changed, we want to + # refresh all active exchanges for this enterprise. + def refresh_products_cache + if product_selection_from_inventory_only_changed? + OpenFoodNetwork::ProductsCache.distributor_changed(enterprise) + end + end + + + private + + def product_selection_from_inventory_only_changed? + key =~ product_selection_from_inventory_only_regex + end + + def enterprise + enterprise_id = key.match(product_selection_from_inventory_only_regex)[1] + enterprise = Enterprise.find enterprise_id + end + + def product_selection_from_inventory_only_regex + /^enterprise\/product_selection_from_inventory_only\/(\d+)$/ + end + end +end diff --git a/lib/open_food_network/products_cache.rb b/lib/open_food_network/products_cache.rb index bdf9ee79b1..d5b39609d9 100644 --- a/lib/open_food_network/products_cache.rb +++ b/lib/open_food_network/products_cache.rb @@ -88,6 +88,13 @@ module OpenFoodNetwork end + def self.distributor_changed(enterprise) + Exchange.cachable.where(receiver_id: enterprise).each do |exchange| + refresh_cache exchange.receiver, exchange.order_cycle + end + end + + private def self.exchanges_featuring_variants(variants, distributor: nil) diff --git a/spec/features/admin/enterprises_spec.rb b/spec/features/admin/enterprises_spec.rb index aed96b5a91..4bd58715eb 100644 --- a/spec/features/admin/enterprises_spec.rb +++ b/spec/features/admin/enterprises_spec.rb @@ -251,6 +251,32 @@ feature %q{ end + describe "inventory settings", js: true do + let!(:enterprise) { create(:distributor_enterprise) } + let!(:product) { create(:simple_product) } + let!(:order_cycle) { create(:simple_order_cycle, distributors: [enterprise], variants: [product.variants.first]) } + + before do + Delayed::Job.destroy_all + quick_login_as_admin + end + + it "refreshes the cache when I change what products appear on my shopfront" do + # Given a product that's not in my inventory, but is in an active order cycle + + # When I change which products appear on the shopfront + visit edit_admin_enterprise_path(enterprise) + within(".side_menu") { click_link 'Inventory Settings' } + choose 'enterprise_preferred_product_selection_from_inventory_only_1' + + # Then a job should have been enqueued to refresh the cache + expect do + click_button 'Update' + end.to enqueue_job RefreshProductsCacheJob, distributor_id: enterprise.id, order_cycle_id: order_cycle.id + end + end + + context "as an Enterprise user", js: true do let(:supplier1) { create(:supplier_enterprise, name: 'First Supplier') } let(:supplier2) { create(:supplier_enterprise, name: 'Another Supplier') } diff --git a/spec/lib/open_food_network/products_cache_spec.rb b/spec/lib/open_food_network/products_cache_spec.rb index 7db47543ad..6b0bc61eb2 100644 --- a/spec/lib/open_food_network/products_cache_spec.rb +++ b/spec/lib/open_food_network/products_cache_spec.rb @@ -376,6 +376,16 @@ module OpenFoodNetwork end end + describe "when a distributor enterprise is changed" do + let(:d) { create(:distributor_enterprise) } + let(:oc) { create(:open_order_cycle, distributors: [d]) } + + it "updates each distribution the enterprise is active in" do + expect(ProductsCache).to receive(:refresh_cache).with(d, oc) + ProductsCache.distributor_changed d + end + end + describe "refreshing the cache" do let(:distributor) { double(:distributor) } let(:order_cycle) { double(:order_cycle) } diff --git a/spec/models/spree/preference_spec.rb b/spec/models/spree/preference_spec.rb new file mode 100644 index 0000000000..ff71c9c9c6 --- /dev/null +++ b/spec/models/spree/preference_spec.rb @@ -0,0 +1,23 @@ +require 'spec_helper' + +module Spree + describe Preference do + describe "refreshing the products cache" do + it "reports when product_selection_from_inventory_only has changed" do + p = Preference.new(key: 'enterprise/product_selection_from_inventory_only/123') + expect(p.send(:product_selection_from_inventory_only_changed?)).to be_true + end + + it "reports when product_selection_from_inventory_only has not changed" do + p = Preference.new(key: 'enterprise/shopfront_message/123') + expect(p.send(:product_selection_from_inventory_only_changed?)).to be_false + end + + it "looks up the referenced enterprise" do + e = create(:distributor_enterprise) + p = Preference.new(key: "enterprise/product_selection_from_inventory_only/#{e.id}") + expect(p.send(:enterprise)).to eql e + end + end + end +end