From f20844c2a0853d2f1368e1b80354e57389e96c01 Mon Sep 17 00:00:00 2001 From: Rob Harrington Date: Sun, 5 Apr 2015 15:25:44 +1000 Subject: [PATCH] Adding editable scope for variants in outgoing exchanges --- lib/open_food_network/permissions.rb | 39 +++++ .../lib/open_food_network/permissions_spec.rb | 164 ++++++++++++++++-- 2 files changed, 187 insertions(+), 16 deletions(-) diff --git a/lib/open_food_network/permissions.rb b/lib/open_food_network/permissions.rb index bc3fb99019..6284099845 100644 --- a/lib/open_food_network/permissions.rb +++ b/lib/open_food_network/permissions.rb @@ -197,6 +197,45 @@ module OpenFoodNetwork end end + # Find the variants that a user is permitted edit within outgoing exchanges + def editable_variants_for_outgoing_exchanges_between(coordinator, hub, options={}) + return Spree::Variant.where("1=0") unless options[:order_cycle] + if managed_enterprises.pluck(:id).include?(hub.id) || managed_enterprises.pluck(:id).include?(coordinator.id) + # Any variants produced by the coordinator, for outgoing exchanges with itself + coordinator_variants = [] + if hub == coordinator + coordinator_variants = Spree::Variant.joins(:product).where('spree_products.supplier_id = (?)', coordinator) + end + + # Any variants of any producers that have granted the hub P-OC + producers = granting(:add_to_order_cycle, to: [hub], scope: Enterprise.is_primary_producer) + permitted_variants = Spree::Variant.joins(:product).where('spree_products.supplier_id IN (?)', producers) + + # PLUS any variants that are already in an outgoing exchange of this hub, so things don't break + # TODO: Remove this when all P-OC are sorted out + active_variants = [] + options[:order_cycle].exchanges.outgoing.where(receiver_id: hub).limit(1).each do |exchange| + active_variants = exchange.variants + end + + Spree::Variant.where(id: coordinator_variants | permitted_variants | active_variants) + else + # Any of my managed producers in this order cycle granted P-OC by the hub + granted_producers = granted(:add_to_order_cycle, by: [hub], scope: managed_producers_in(options[:order_cycle])) + + # Any variants produced by MY PRODUCERS that are in this order cycle, where my producer has granted P-OC to the hub + granting_producers = granting(:add_to_order_cycle, to: [hub], scope: granted_producers) + permitted_variants = Spree::Variant.joins(:product).where('spree_products.supplier_id IN (?)', granting_producers) + + # PLUS any of my incoming producers' variants that are already in an outgoing exchange of this hub, so things don't break + # TODO: Remove this when all P-OC are sorted out + active_variants = Spree::Variant.joins(:exchanges, :product). + where('exchanges.receiver_id = (?) AND spree_products.supplier_id IN (?)', hub, managed_enterprises.is_primary_producer) + + Spree::Variant.where(id: permitted_variants | active_variants) + end + end + def managed_products managed_enterprise_products_ids = managed_enterprise_products.pluck :id permitted_enterprise_products_ids = related_enterprise_products.pluck :id diff --git a/spec/lib/open_food_network/permissions_spec.rb b/spec/lib/open_food_network/permissions_spec.rb index 0a715a720d..bfadbd29b6 100644 --- a/spec/lib/open_food_network/permissions_spec.rb +++ b/spec/lib/open_food_network/permissions_spec.rb @@ -550,25 +550,20 @@ module OpenFoodNetwork it "returns an empty array" do expect(permissions.visible_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc)).to eq [] end - end - # TODO: for backwards compatability, remove later - context "as the manager of a producer which has not granted P-OC to an outgoing hub, but which has variants already in the exchange" do - let!(:ex) { create(:exchange, order_cycle: oc, sender: e1, receiver: e2, incoming: false) } + # TODO: for backwards compatability, remove later + context "but which has variants already in the exchange" do + let!(:ex) { create(:exchange, order_cycle: oc, sender: e1, receiver: e2, incoming: false) } + # This one won't be in the exchange, and so shouldn't be visible + let!(:v3) { create(:variant, product: create(:simple_product, supplier: producer2)) } - # This one won't be in the exchange, and so shouldn't be visible - let!(:v3) { create(:variant, product: create(:simple_product, supplier: producer2)) } + before { ex.variants << v2 } - before do - permissions.stub(:managed_enterprises) { Enterprise.where(id: [producer2]) } - create(:enterprise_relationship, parent: producer1, child: e2, permissions_list: [:add_to_order_cycle]) - ex.variants << v2 - end - - it "returns those variants that are in the exchange" do - visible = permissions.visible_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) - expect(visible).to_not include v1, v3 - expect(visible).to include v2 + it "returns those variants that are in the exchange" do + visible = permissions.visible_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to_not include v1, v3 + expect(visible).to include v2 + end end end end @@ -622,6 +617,143 @@ module OpenFoodNetwork end end end + + describe "outgoing exchanges" do + context "as a manager of the coordinator" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: [e1]) } + create(:enterprise_relationship, parent: producer1, child: e2, permissions_list: [:add_to_order_cycle]) + end + + it "returns all variants of any producer which has granted the outgoing hub P-OC" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to include v1 + expect(visible).to_not include v2 + end + + context "where the coordinator produces products" do + let!(:v3) { create(:variant, product: create(:simple_product, supplier: e1)) } + + it "returns any variants produced by the coordinator itself for exchanges with 'self'" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e1, order_cycle: oc) + expect(visible).to include v3 + expect(visible).to_not include v1, v2 + end + + it "does not return coordinator's variants for exchanges with other hubs, when permission has not been granted" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to include v1 + expect(visible).to_not include v2, v3 + end + end + + # TODO: for backwards compatability, remove later + context "when an exchange exists between the coordinator and the hub within this order cycle" do + let!(:ex) { create(:exchange, order_cycle: oc, sender: e1, receiver: e2, incoming: false) } + + # producer2 produces v2 and has not granted P-OC to e2 (or e1 for that matter) + before { ex.variants << v2 } + + it "returns those variants that are in the exchange" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to include v1, v2 + end + end + end + + context "as manager of an outgoing hub" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: [e2]) } + create(:enterprise_relationship, parent: producer1, child: e2, permissions_list: [:add_to_order_cycle]) + end + + it "returns all variants of any producer which has granted the outgoing hub P-OC" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to include v1 + expect(visible).to_not include v2 + end + + # TODO: for backwards compatability, remove later + context "when an exchange exists between the coordinator and the hub within this order cycle" do + let!(:ex) { create(:exchange, order_cycle: oc, sender: e1, receiver: e2, incoming: false) } + + # producer2 produces v2 and has not granted P-OC to e2 + before { ex.variants << v2 } + + it "returns those variants that are in the exchange" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to include v1, v2 + end + end + end + + context "as the manager of a producer which has granted P-OC to an outgoing hub" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: [producer1]) } + create(:enterprise_relationship, parent: producer1, child: e2, permissions_list: [:add_to_order_cycle]) + end + + context "where my producer is in the order cycle" do + let!(:ex) { create(:exchange, order_cycle: oc, sender: producer1, receiver: e1, incoming: true) } + + context "where the outgoing hub has granted P-OC to my producer" do + before do + create(:enterprise_relationship, parent: e2, child: producer1, permissions_list: [:add_to_order_cycle]) + end + + it "returns all of my produced variants" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to include v1 + expect(visible).to_not include v2 + end + end + + context "where the outgoing hub has not granted P-OC to my producer" do + # No permission granted + + it "does not return my variants" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to_not include v1, v2 + end + end + end + + context "where my producer isn't in the order cycle" do + # No incoming exchange + + it "does not return my variants" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to_not include v1, v2 + end + end + end + + context "as the manager of a producer which has not granted P-OC to an outgoing hub" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: [producer2]) } + create(:enterprise_relationship, parent: producer1, child: e2, permissions_list: [:add_to_order_cycle]) + end + + it "returns an empty array" do + expect(permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc)).to eq [] + end + + # TODO: for backwards compatability, remove later + context "but which has variants already in the exchange" do + let!(:ex) { create(:exchange, order_cycle: oc, sender: e1, receiver: e2, incoming: false) } + # This one won't be in the exchange, and so shouldn't be visible + let!(:v3) { create(:variant, product: create(:simple_product, supplier: producer2)) } + + before { ex.variants << v2 } + + it "returns those variants that are in the exchange" do + visible = permissions.editable_variants_for_outgoing_exchanges_between(e1, e2, order_cycle: oc) + expect(visible).to_not include v1, v3 + expect(visible).to include v2 + end + end + end + end end describe "finding managed products" do