diff --git a/app/assets/javascripts/admin/bulk_order_management.js.coffee b/app/assets/javascripts/admin/bulk_order_management.js.coffee index 4c1a319c1a..20ddc177ba 100644 --- a/app/assets/javascripts/admin/bulk_order_management.js.coffee +++ b/app/assets/javascripts/admin/bulk_order_management.js.coffee @@ -1,6 +1,6 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [ - "$scope", "$http", "dataFetcher", "blankOption", "pendingChanges", "VariantUnitManager", "OptionValueNamer", "SpreeApiKey" - ($scope, $http, dataFetcher, blankOption, pendingChanges, VariantUnitManager, OptionValueNamer, SpreeApiKey) -> + "$scope", "$http", "$filter", "dataFetcher", "blankOption", "pendingChanges", "VariantUnitManager", "OptionValueNamer", "SpreeApiKey" + ($scope, $http, $filter, dataFetcher, blankOption, pendingChanges, VariantUnitManager, OptionValueNamer, SpreeApiKey) -> $scope.loading = true $scope.initialiseVariables = -> @@ -42,13 +42,15 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [ if $scope.spree_api_key_ok $http.defaults.headers.common["X-Spree-Token"] = SpreeApiKey dataFetcher("/api/enterprises/accessible?template=bulk_index&q[is_primary_producer_eq]=true").then (data) -> - $scope.suppliers = data + $scope.suppliers = $filter('orderBy')(data, 'name') $scope.suppliers.unshift blankOption() - dataFetcher("/api/enterprises/accessible?template=bulk_index&q[is_distributor_eq]=true").then (data) -> - $scope.distributors = data + dataFetcher("/api/enterprises/accessible?template=bulk_index&q[sells_in][]=own&q[sells_in][]=any").then (data) -> + $scope.distributors = $filter('orderBy')(data, 'name') $scope.distributors.unshift blankOption() - ocFetcher = dataFetcher("/api/order_cycles/accessible").then (data) -> + ocFetcher = dataFetcher("/api/order_cycles/accessible?as=distributor&q[orders_close_at_gt]=#{formatDate(daysFromToday(-90))}").then (data) -> $scope.orderCycles = data + $scope.orderCyclesByID = [] + $scope.orderCyclesByID[oc.id] = oc for oc in $scope.orderCycles $scope.orderCycles.unshift blankOption() $scope.fetchOrders() ocFetcher.then -> @@ -60,7 +62,7 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [ $scope.fetchOrders = -> $scope.loading = true - dataFetcher("/api/orders/managed?template=bulk_index;page=1;per_page=500;q[completed_at_not_null]=true;q[completed_at_gt]=#{$scope.startDate};q[completed_at_lt]=#{$scope.endDate}").then (data) -> + dataFetcher("/api/orders/managed?template=bulk_index;page=1;per_page=500;q[state_not_eq]=canceled;q[completed_at_not_null]=true;q[completed_at_gt]=#{$scope.startDate};q[completed_at_lt]=#{$scope.endDate}").then (data) -> $scope.resetOrders data $scope.loading = false @@ -162,6 +164,11 @@ angular.module("ofn.admin").controller "AdminOrderMgmtCtrl", [ $scope.supplierFilter = $scope.suppliers[0].id $scope.orderCycleFilter = $scope.orderCycles[0].id $scope.quickSearch = "" + + $scope.$watch "orderCycleFilter", (newVal, oldVal) -> + unless $scope.orderCycleFilter == "0" || angular.equals(newVal, oldVal) + $scope.startDate = $scope.orderCyclesByID[$scope.orderCycleFilter].first_order + $scope.endDate = $scope.orderCyclesByID[$scope.orderCycleFilter].last_order ] daysFromToday = (days) -> diff --git a/app/controllers/api/enterprises_controller.rb b/app/controllers/api/enterprises_controller.rb index 468f3a22ad..41b24f30a1 100644 --- a/app/controllers/api/enterprises_controller.rb +++ b/app/controllers/api/enterprises_controller.rb @@ -13,7 +13,8 @@ module Api end def accessible - @enterprises = Enterprise.ransack(params[:q]).result.accessible_by(current_api_user) + permitted = OpenFoodNetwork::Permissions.new(current_api_user).order_cycle_enterprises + @enterprises = permitted.ransack(params[:q]).result render params[:template] || :bulk_index end diff --git a/app/controllers/api/order_cycles_controller.rb b/app/controllers/api/order_cycles_controller.rb index b4b3486778..23b333625e 100644 --- a/app/controllers/api/order_cycles_controller.rb +++ b/app/controllers/api/order_cycles_controller.rb @@ -9,7 +9,16 @@ module Api end def accessible - @order_cycles = OrderCycle.ransack(params[:q]).result.accessible_by(current_api_user) + @order_cycles = if params[:as] == "distributor" + OrderCycle.ransack(params[:q]).result. + involving_managed_distributors_of(current_api_user).order('updated_at DESC') + elsif params[:as] == "producer" + OrderCycle.ransack(params[:q]).result. + involving_managed_producers_of(current_api_user).order('updated_at DESC') + else + OrderCycle.ransack(params[:q]).result.accessible_by(current_api_user) + end + render params[:template] || :bulk_index end end diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 92653a5aa9..3aa4f560a1 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -406,27 +406,34 @@ Spree::Admin::ReportsController.class_eval do end params[:q][:meta_sort] ||= "completed_at.desc" - # -- Search - @search = Spree::Order.complete.not_state(:canceled).managed_by(spree_current_user).search(params[:q]) - orders = @search.result - @line_items = orders.map do |o| - lis = o.line_items.managed_by(spree_current_user) - lis = lis.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present? - lis - end.flatten - #payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments + permissions = OpenFoodNetwork::Permissions.new(spree_current_user) - # -- Prepare form options - my_distributors = Enterprise.is_distributor.managed_by(spree_current_user) - my_suppliers = Enterprise.is_primary_producer.managed_by(spree_current_user) + # -- Search + + @search = Spree::Order.complete.not_state(:canceled).search(params[:q]) + orders = permissions.visible_orders.merge(@search.result) + + @line_items = permissions.visible_line_items.merge(Spree::LineItem.where(order_id: orders)) + @line_items = @line_items.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present? + + line_items_with_hidden_details = @line_items.where("id NOT IN (?)", permissions.editable_line_items) + @line_items.select{ |li| line_items_with_hidden_details.include? li }.each do |line_item| + # TODO We should really be hiding customer code here too, but until we + # have an actual association between order and customer, it's a bit tricky + line_item.order.bill_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil) + line_item.order.ship_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil) + line_item.order.assign_attributes(email: "HIDDEN") + end # My distributors and any distributors distributing products I supply - @distributors = my_distributors | Enterprise.with_distributed_products_outer.merge(Spree::Product.in_any_supplier(my_suppliers)) + @distributors = permissions.visible_enterprises_for_order_reports.is_distributor # My suppliers and any suppliers supplying products I distribute - @suppliers = my_suppliers | my_distributors.map { |d| Spree::Product.in_distributor(d) }.flatten.map(&:supplier).uniq + @suppliers = permissions.visible_enterprises_for_order_reports.is_primary_producer + + @order_cycles = OrderCycle.active_or_complete. + involving_managed_distributors_of(spree_current_user).order('orders_close_at DESC') - @order_cycles = OrderCycle.active_or_complete.accessible_by(spree_current_user).order('orders_close_at DESC') @report_types = REPORT_TYPES[:orders_and_fulfillment] @report_type = params[:report_type] diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 1aa76b88a8..e921167cf0 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -162,17 +162,6 @@ class Enterprise < ActiveRecord::Base end } - # Return enterprises that participate in order cycles that user coordinates, sends to or receives from - scope :accessible_by, lambda { |user| - if user.has_spree_role?('admin') - scoped - else - with_order_cycles_outer. - where('order_cycles.id IN (?)', OrderCycle.accessible_by(user)). - select('DISTINCT enterprises.*') - end - } - def self.find_near(suburb) enterprises = [] diff --git a/app/models/order_cycle.rb b/app/models/order_cycle.rb index adcd596a8c..d16f1d7b8b 100644 --- a/app/models/order_cycle.rb +++ b/app/models/order_cycle.rb @@ -26,7 +26,7 @@ class OrderCycle < ActiveRecord::Base closed. where("order_cycles.orders_close_at >= ?", 31.days.ago). order("order_cycles.orders_close_at DESC") } - + scope :soonest_opening, lambda { upcoming.order('order_cycles.orders_open_at ASC') } scope :distributing_product, lambda { |product| @@ -64,6 +64,23 @@ class OrderCycle < ActiveRecord::Base joins('LEFT OUTER JOIN enterprises ON (enterprises.id = exchanges.sender_id OR enterprises.id = exchanges.receiver_id)') } + scope :involving_managed_distributors_of, lambda { |user| + enterprises = Enterprise.managed_by(user) + + # Order cycles where I managed an enterprise at either end of an outgoing exchange + # ie. coordinator or distibutor + joins(:exchanges).merge(Exchange.outgoing). + where('exchanges.receiver_id IN (?) OR exchanges.sender_id IN (?)', enterprises, enterprises) + } + + scope :involving_managed_producers_of, lambda { |user| + enterprises = Enterprise.managed_by(user) + + # Order cycles where I managed an enterprise at either end of an incoming exchange + # ie. coordinator or producer + joins(:exchanges).merge(Exchange.incoming). + where('exchanges.receiver_id IN (?) OR exchanges.sender_id IN (?)', enterprises, enterprises) + } def self.first_opening_for(distributor) with_distributor(distributor).soonest_opening.first diff --git a/app/views/api/order_cycles/bulk_show.v1.rabl b/app/views/api/order_cycles/bulk_show.v1.rabl index a0a5b16927..b012b879e2 100644 --- a/app/views/api/order_cycles/bulk_show.v1.rabl +++ b/app/views/api/order_cycles/bulk_show.v1.rabl @@ -1,9 +1,11 @@ object @order_cycle attributes :id, :name +node( :first_order ) { |order| order.orders_open_at.strftime("%F") } +node( :last_order ) { |order| (order.orders_close_at + 1.day).strftime("%F") } node( :suppliers ) do |oc| partial 'api/enterprises/bulk_index', :object => oc.suppliers end node( :distributors ) do |oc| partial 'api/enterprises/bulk_index', :object => oc.distributors -end \ No newline at end of file +end diff --git a/lib/open_food_network/order_cycle_permissions.rb b/lib/open_food_network/order_cycle_permissions.rb index 2af60c5696..08fe7b2ee4 100644 --- a/lib/open_food_network/order_cycle_permissions.rb +++ b/lib/open_food_network/order_cycle_permissions.rb @@ -19,7 +19,7 @@ module OpenFoodNetwork if @coordinator.sells == "any" # If the coordinator sells any, relationships come into play - granting(:add_to_order_cycle, to: [@coordinator]).pluck(:id).each do |enterprise_id| + related_enterprises_granting(:add_to_order_cycle, to: [@coordinator]).pluck(:id).each do |enterprise_id| coordinator_permitted << enterprise_id end @@ -30,19 +30,19 @@ module OpenFoodNetwork Enterprise.where(id: coordinator_permitted | all_active) else # Any enterprises that I manage directly, which have granted P-OC to the coordinator - managed_permitted = granting(:add_to_order_cycle, to: [@coordinator], scope: managed_participating_enterprises ).pluck(:id) + managed_permitted = related_enterprises_granting(:add_to_order_cycle, to: [@coordinator], scope: managed_participating_enterprises ).pluck(:id) # Any hubs in this OC that have been granted P-OC by producers I manage in this OC - hubs_permitted = granted(:add_to_order_cycle, by: managed_participating_producers, scope: @order_cycle.distributors).pluck(:id) + hubs_permitted = related_enterprises_granted(:add_to_order_cycle, by: managed_participating_producers, scope: @order_cycle.distributors).pluck(:id) # Any hubs in this OC that have granted P-OC to producers I manage in this OC - hubs_permitting = granting(:add_to_order_cycle, to: managed_participating_producers, scope: @order_cycle.distributors).pluck(:id) + hubs_permitting = related_enterprises_granting(:add_to_order_cycle, to: managed_participating_producers, scope: @order_cycle.distributors).pluck(:id) # Any producers in this OC that have been granted P-OC by hubs I manage in this OC - producers_permitted = granted(:add_to_order_cycle, by: managed_participating_hubs, scope: @order_cycle.suppliers).pluck(:id) + producers_permitted = related_enterprises_granted(:add_to_order_cycle, by: managed_participating_hubs, scope: @order_cycle.suppliers).pluck(:id) # Any producers in this OC that have granted P-OC to hubs I manage in this OC - producers_permitting = granting(:add_to_order_cycle, to: managed_participating_hubs, scope: @order_cycle.suppliers).pluck(:id) + producers_permitting = related_enterprises_granting(:add_to_order_cycle, to: managed_participating_hubs, scope: @order_cycle.suppliers).pluck(:id) managed_active = [] hubs_active = [] @@ -125,7 +125,7 @@ module OpenFoodNetwork 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) + producers = related_enterprises_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 @@ -138,7 +138,7 @@ module OpenFoodNetwork Spree::Variant.where(id: coordinator_variants | permitted_variants | active_variants) else # Any variants produced by MY PRODUCERS that are in this order cycle, where my producer has granted P-OC to the hub - producers = granting(:add_to_order_cycle, to: [hub], scope: managed_participating_producers) + producers = related_enterprises_granting(:add_to_order_cycle, to: [hub], scope: managed_participating_producers) permitted_variants = Spree::Variant.joins(:product).where('spree_products.supplier_id IN (?)', producers) # PLUS any of my incoming producers' variants that are already in an outgoing exchange of this hub, so things don't break @@ -162,7 +162,7 @@ module OpenFoodNetwork 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) + producers = related_enterprises_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 @@ -175,10 +175,10 @@ module OpenFoodNetwork 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_participating_producers) + granted_producers = related_enterprises_granted(:add_to_order_cycle, by: [hub], scope: managed_participating_producers) # 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) + granting_producers = related_enterprises_granting(:add_to_order_cycle, to: [hub], scope: granted_producers) permitted_variants = Spree::Variant.joins(:product).where('spree_products.supplier_id IN (?)', granting_producers) Spree::Variant.where(id: permitted_variants) @@ -216,7 +216,7 @@ module OpenFoodNetwork # Find my managed hubs in this order cycle hubs = managed_participating_hubs # Any incoming exchange where the producer has granted P-OC to one or more of those hubs - producers = granting(:add_to_order_cycle, to: hubs, scope: Enterprise.is_primary_producer).pluck :id + producers = related_enterprises_granting(:add_to_order_cycle, to: hubs, scope: Enterprise.is_primary_producer).pluck :id permitted_exchanges = @order_cycle.exchanges.incoming.where(sender_id: producers).pluck :id # TODO: remove active_exchanges when we think it is safe to do so @@ -235,7 +235,7 @@ module OpenFoodNetwork # Find my producers in this order cycle producers = managed_participating_producers.pluck :id # Any outgoing exchange where the distributor has been granted P-OC by one or more of those producers - hubs = granted(:add_to_order_cycle, by: producers, scope: Enterprise.is_hub) + hubs = related_enterprises_granted(:add_to_order_cycle, by: producers, scope: Enterprise.is_hub) permitted_exchanges = @order_cycle.exchanges.outgoing.where(receiver_id: hubs).pluck :id # TODO: remove active_exchanges when we think it is safe to do so diff --git a/lib/open_food_network/permissions.rb b/lib/open_food_network/permissions.rb index 4edb3d5f39..4da645582d 100644 --- a/lib/open_food_network/permissions.rb +++ b/lib/open_food_network/permissions.rb @@ -5,23 +5,28 @@ module OpenFoodNetwork end def can_manage_complex_order_cycles? - managed_and_related_enterprises_with(:add_to_order_cycle).any? do |e| + managed_and_related_enterprises_granting(:add_to_order_cycle).any? do |e| e.sells == 'any' end end # Find enterprises that an admin is allowed to add to an order cycle - def order_cycle_enterprises + def visible_enterprises_for_order_reports managed_and_related_enterprises_with :add_to_order_cycle end + def order_cycle_enterprises + # Return enterprises that the user manages and those that have granted P-OC to managed enterprises + managed_and_related_enterprises_granting :add_to_order_cycle + end + # Find enterprises for which an admin is allowed to edit their profile def editable_enterprises - managed_and_related_enterprises_with :edit_profile + managed_and_related_enterprises_granting :edit_profile end def variant_override_hubs - managed_and_related_enterprises_with(:add_to_order_cycle).is_hub + managed_and_related_enterprises_granting(:add_to_order_cycle).is_hub end def variant_override_producers @@ -33,7 +38,7 @@ module OpenFoodNetwork # override variants # {hub1_id => [producer1_id, producer2_id, ...], ...} def variant_override_enterprises_per_hub - hubs = managed_and_related_enterprises_with(:add_to_order_cycle).is_distributor + hubs = managed_and_related_enterprises_granting(:add_to_order_cycle).is_distributor # Permissions granted by create_variant_overrides relationship from producer to hub permissions = Hash[ @@ -56,6 +61,51 @@ module OpenFoodNetwork permissions end + # Find enterprises that an admin is allowed to add to an order cycle + def visible_orders + # Any orders that I can edit + editable = editable_orders.pluck(:id) + + # Any orders placed through hubs that my producers have granted P-OC, and which contain my their products + # This is pretty complicated but it's looking for order where at least one of my producers has granted + # P-OC to the distributor AND the order contains products of at least one of THE SAME producers + granted_distributors = related_enterprises_granted(:add_to_order_cycle, by: managed_enterprises.is_primary_producer) + produced = Spree::Order.with_line_items_variants_and_products_outer. + where( + "spree_orders.distributor_id IN (?) AND spree_products.supplier_id IN (?)", + granted_distributors, + related_enterprises_granting(:add_to_order_cycle, to: granted_distributors).merge(managed_enterprises.is_primary_producer) + ).pluck(:id) + + Spree::Order.where(id: editable | produced) + end + + # Find enterprises that an admin is allowed to add to an order cycle + def editable_orders + # Any orders placed through any hub that I manage + managed = Spree::Order.where(distributor_id: managed_enterprises.pluck(:id)).pluck(:id) + + # Any order that is placed through an order cycle one of my managed enterprises coordinates + coordinated = Spree::Order.where(order_cycle_id: coordinated_order_cycles.pluck(:id)).pluck(:id) + + Spree::Order.where(id: managed | coordinated ) + end + + def visible_line_items + # Any line items that I can edit + editable = editable_line_items.pluck(:id) + + # Any from visible orders, where the product is produced by one of my managed producers + produced = Spree::LineItem.where(order_id: visible_orders.pluck(:id)).joins(:product). + where('spree_products.supplier_id IN (?)', managed_enterprises.is_primary_producer.pluck(:id)) + + Spree::LineItem.where(id: editable | produced) + end + + def editable_line_items + Spree::LineItem.where(order_id: editable_orders) + end + def managed_products managed_enterprise_products_ids = managed_enterprise_products.pluck :id permitted_enterprise_products_ids = related_enterprise_products.pluck :id @@ -63,7 +113,7 @@ module OpenFoodNetwork end def managed_product_enterprises - managed_and_related_enterprises_with :manage_products + managed_and_related_enterprises_granting :manage_products end def manages_one_enterprise? @@ -73,11 +123,30 @@ module OpenFoodNetwork private - def managed_and_related_enterprises_with(permission) - managed_enterprise_ids = managed_enterprises.pluck :id - permitting_enterprise_ids = related_enterprises_with(permission).pluck :id + def admin? + @user.admin? + end - Enterprise.where('id IN (?)', managed_enterprise_ids + permitting_enterprise_ids) + def managed_and_related_enterprises_granting(permission) + if admin? + Enterprise.scoped + else + managed_enterprise_ids = managed_enterprises.pluck :id + permitting_enterprise_ids = related_enterprises_granting(permission).pluck :id + + Enterprise.where('id IN (?)', managed_enterprise_ids + permitting_enterprise_ids) + end + end + + def managed_and_related_enterprises_with(permission) + if admin? + Enterprise.scoped + else + managed = managed_enterprises.pluck(:id) + granting = related_enterprises_granting(permission).pluck(:id) + granted = related_enterprises_granted(permission).pluck(:id) + Enterprise.where(id: managed | granting | granted) + end end def managed_enterprises @@ -85,16 +154,12 @@ module OpenFoodNetwork @managed_enterprises = Enterprise.managed_by(@user) end - def related_enterprises_with(permission) - parent_ids = EnterpriseRelationship. - permitting(managed_enterprises). - with_permission(permission). - pluck(:parent_id) - - Enterprise.where('id IN (?)', parent_ids) + def coordinated_order_cycles + return @coordinated_order_cycles unless @coordinated_order_cycles.nil? + @coordinated_order_cycles = OrderCycle.managed_by(@user) end - def granting(permission, options={}) + def related_enterprises_granting(permission, options={}) parent_ids = EnterpriseRelationship. permitting(options[:to] || managed_enterprises). with_permission(permission). @@ -103,7 +168,7 @@ module OpenFoodNetwork (options[:scope] || Enterprise).where('enterprises.id IN (?)', parent_ids) end - def granted(permission, options={}) + def related_enterprises_granted(permission, options={}) child_ids = EnterpriseRelationship. permitted_by(options[:by] || managed_enterprises). with_permission(permission). @@ -117,7 +182,7 @@ module OpenFoodNetwork end def related_enterprise_products - Spree::Product.where('supplier_id IN (?)', related_enterprises_with(:manage_products)) + Spree::Product.where('supplier_id IN (?)', related_enterprises_granting(:manage_products)) end end end diff --git a/spec/controllers/api/order_cycles_controller_spec.rb b/spec/controllers/api/order_cycles_controller_spec.rb index a9cceac796..3bb9a76602 100644 --- a/spec/controllers/api/order_cycles_controller_spec.rb +++ b/spec/controllers/api/order_cycles_controller_spec.rb @@ -4,109 +4,210 @@ require 'spree/api/testing_support/helpers' module Api describe OrderCyclesController do include Spree::Api::TestingSupport::Helpers + include AuthenticationWorkflow render_views - let!(:oc1) { FactoryGirl.create(:simple_order_cycle) } - let!(:oc2) { FactoryGirl.create(:simple_order_cycle) } - let(:coordinator) { oc1.coordinator } - let(:attributes) { [:id, :name, :suppliers, :distributors] } + describe "managed" do + let!(:oc1) { FactoryGirl.create(:simple_order_cycle) } + let!(:oc2) { FactoryGirl.create(:simple_order_cycle) } + let(:coordinator) { oc1.coordinator } + let(:attributes) { [:id, :name, :suppliers, :distributors] } - before do - stub_authentication! - Spree.user_class.stub :find_by_spree_api_key => current_api_user - end + before do + stub_authentication! + Spree.user_class.stub :find_by_spree_api_key => current_api_user + end - context "as a normal user" do - sign_in_as_user! + context "as a normal user" do + sign_in_as_user! - it "should deny me access to managed order cycles" do - spree_get :managed, { :format => :json } - assert_unauthorized! + it "should deny me access to managed order cycles" do + spree_get :managed, { :format => :json } + assert_unauthorized! + end + end + + context "as an enterprise user" do + sign_in_as_enterprise_user! [:coordinator] + + it "retrieves a list of variants with appropriate attributes" do + get :managed, { :format => :json } + keys = json_response.first.keys.map{ |key| key.to_sym } + attributes.all?{ |attr| keys.include? attr }.should == true + end + end + + context "as an administrator" do + sign_in_as_admin! + + it "retrieves a list of variants with appropriate attributes" do + get :managed, { :format => :json } + keys = json_response.first.keys.map{ |key| key.to_sym } + attributes.all?{ |attr| keys.include? attr }.should == true + end end end - context "as an enterprise user" do - sign_in_as_enterprise_user! [:coordinator] + describe "accessible" do + context "without :as parameter" do + let(:oc_supplier) { create(:supplier_enterprise) } + let(:oc_distributor) { create(:distributor_enterprise) } + let(:other_supplier) { create(:supplier_enterprise) } + let(:oc_supplier_user) do + user = create(:user) + user.spree_roles = [] + user.enterprise_roles.create(enterprise: oc_supplier) + user.save! + user + end + let(:oc_distributor_user) do + user = create(:user) + user.spree_roles = [] + user.enterprise_roles.create(enterprise: oc_distributor) + user.save! + user + end + let(:other_supplier_user) do + user = create(:user) + user.spree_roles = [] + user.enterprise_roles.create(enterprise: other_supplier) + user.save! + user + end + let!(:order_cycle) { create(:simple_order_cycle, suppliers: [oc_supplier], distributors: [oc_distributor]) } - it "retrieves a list of variants with appropriate attributes" do - get :managed, { :format => :json } - keys = json_response.first.keys.map{ |key| key.to_sym } - attributes.all?{ |attr| keys.include? attr }.should == true - end - end + context "as the user of a supplier to an order cycle" do + before :each do + stub_authentication! + Spree.user_class.stub :find_by_spree_api_key => oc_supplier_user + spree_get :accessible, { :template => 'bulk_index', :format => :json } + end - context "as an administrator" do - sign_in_as_admin! + it "gives me access" do + json_response.length.should == 1 + json_response[0]['id'].should == order_cycle.id + end + end - it "retrieves a list of variants with appropriate attributes" do - get :managed, { :format => :json } - keys = json_response.first.keys.map{ |key| key.to_sym } - attributes.all?{ |attr| keys.include? attr }.should == true - end - end + context "as the user of some other supplier" do + before :each do + stub_authentication! + Spree.user_class.stub :find_by_spree_api_key => other_supplier_user + spree_get :accessible, { :template => 'bulk_index', :format => :json } + end - context "using the accessible action to list order cycles" do - let(:oc_supplier) { create(:supplier_enterprise) } - let(:oc_distributor) { create(:distributor_enterprise) } - let(:other_supplier) { create(:supplier_enterprise) } - let(:oc_supplier_user) do - user = create(:user) - user.spree_roles = [] - user.enterprise_roles.create(enterprise: oc_supplier) - user.save! - user - end - let(:oc_distributor_user) do - user = create(:user) - user.spree_roles = [] - user.enterprise_roles.create(enterprise: oc_distributor) - user.save! - user - end - let(:other_supplier_user) do - user = create(:user) - user.spree_roles = [] - user.enterprise_roles.create(enterprise: other_supplier) - user.save! - user - end - let!(:order_cycle) { create(:simple_order_cycle, suppliers: [oc_supplier], distributors: [oc_distributor]) } + it "does not give me access" do + json_response.length.should == 0 + end + end - context "as the user of a supplier to an order cycle" do - before :each do + context "as the user of a hub for the order cycle" do + before :each do + stub_authentication! + Spree.user_class.stub :find_by_spree_api_key => oc_distributor_user + spree_get :accessible, { :template => 'bulk_index', :format => :json } + end + + it "gives me access" do + json_response.length.should == 1 + json_response[0]['id'].should == order_cycle.id + end + end + end + + context "when the :as parameter is set to 'distributor'" do + let(:user) { create_enterprise_user } + let(:distributor) { create(:distributor_enterprise) } + let(:producer) { create(:supplier_enterprise) } + let(:coordinator) { create(:distributor_enterprise) } + let!(:oc) { create(:simple_order_cycle, coordinator: coordinator, distributors: [distributor], suppliers: [producer]) } + + let(:params) { { format: :json, as: 'distributor' } } + + before do stub_authentication! - Spree.user_class.stub :find_by_spree_api_key => oc_supplier_user - spree_get :accessible, { :template => 'bulk_index', :format => :json } + Spree.user_class.stub :find_by_spree_api_key => user end - it "gives me access" do - json_response.length.should == 1 - json_response[0]['id'].should == order_cycle.id + context "as the manager of a supplier in an order cycle" do + before do + user.enterprise_roles.create(enterprise: producer) + spree_get :accessible, params + end + + it "does not return the order cycle" do + expect(assigns(:order_cycles)).to_not include oc + end + end + + context "as the manager of a distributor in an order cycle" do + before do + user.enterprise_roles.create(enterprise: distributor) + spree_get :accessible, params + end + + it "returns the order cycle" do + expect(assigns(:order_cycles)).to include oc + end + end + + context "as the manager of the coordinator of an order cycle" do + before do + user.enterprise_roles.create(enterprise: coordinator) + spree_get :accessible, params + end + + it "returns the order cycle" do + expect(assigns(:order_cycles)).to include oc + end end end - context "as the user of some other supplier" do - before :each do + context "when the :as parameter is set to 'producer'" do + let(:user) { create_enterprise_user } + let(:distributor) { create(:distributor_enterprise) } + let(:producer) { create(:supplier_enterprise) } + let(:coordinator) { create(:distributor_enterprise) } + let!(:oc) { create(:simple_order_cycle, coordinator: coordinator, distributors: [distributor], suppliers: [producer]) } + + let(:params) { { format: :json, as: 'producer' } } + + before do stub_authentication! - Spree.user_class.stub :find_by_spree_api_key => other_supplier_user - spree_get :accessible, { :template => 'bulk_index', :format => :json } + Spree.user_class.stub :find_by_spree_api_key => user end - it "does not give me access" do - json_response.length.should == 0 - end - end + context "as the manager of a producer in an order cycle" do + before do + user.enterprise_roles.create(enterprise: producer) + spree_get :accessible, params + end - context "as the user of a hub for the order cycle" do - before :each do - stub_authentication! - Spree.user_class.stub :find_by_spree_api_key => oc_distributor_user - spree_get :accessible, { :template => 'bulk_index', :format => :json } + it "returns the order cycle" do + expect(assigns(:order_cycles)).to include oc + end end - it "gives me access" do - json_response.length.should == 1 - json_response[0]['id'].should == order_cycle.id + context "as the manager of a distributor in an order cycle" do + before do + user.enterprise_roles.create(enterprise: distributor) + spree_get :accessible, params + end + + it "does not return the order cycle" do + expect(assigns(:order_cycles)).to_not include oc + end + end + + context "as the manager of the coordinator of an order cycle" do + before do + user.enterprise_roles.create(enterprise: coordinator) + spree_get :accessible, params + end + + it "returns the order cycle" do + expect(assigns(:order_cycles)).to include oc + end end end end diff --git a/spec/controllers/spree/admin/reports_controller_spec.rb b/spec/controllers/spree/admin/reports_controller_spec.rb index 432bc4e67f..58d406519b 100644 --- a/spec/controllers/spree/admin/reports_controller_spec.rb +++ b/spec/controllers/spree/admin/reports_controller_spec.rb @@ -1,23 +1,25 @@ require 'spec_helper' describe Spree::Admin::ReportsController do - + # Given two distributors and two suppliers let(:ba) { create(:address) } let(:si) { "pick up on thursday please" } - let(:s1) { create(:supplier_enterprise, address: create(:address)) } - let(:s2) { create(:supplier_enterprise, address: create(:address)) } - let(:s3) { create(:supplier_enterprise, address: create(:address)) } - let(:d1) { create(:distributor_enterprise, address: create(:address)) } - let(:d2) { create(:distributor_enterprise, address: create(:address)) } - let(:d3) { create(:distributor_enterprise, address: create(:address)) } + let(:c1) { create(:distributor_enterprise) } + let(:c2) { create(:distributor_enterprise) } + let(:s1) { create(:supplier_enterprise) } + let(:s2) { create(:supplier_enterprise) } + let(:s3) { create(:supplier_enterprise) } + let(:d1) { create(:distributor_enterprise) } + let(:d2) { create(:distributor_enterprise) } + let(:d3) { create(:distributor_enterprise) } let(:p1) { create(:product, price: 12.34, distributors: [d1], supplier: s1) } let(:p2) { create(:product, price: 23.45, distributors: [d2], supplier: s2) } let(:p3) { create(:product, price: 34.56, distributors: [d3], supplier: s3) } # Given two order cycles with both distributors - let(:ocA) { create(:simple_order_cycle, distributors: [d1, d2], suppliers: [s1, s2, s3], variants: [p1.master, p3.master]) } - let(:ocB) { create(:simple_order_cycle, distributors: [d1, d2], suppliers: [s1, s2, s3], variants: [p2.master]) } + let(:ocA) { create(:simple_order_cycle, coordinator: c1, distributors: [d1, d2], suppliers: [s1, s2, s3], variants: [p1.master, p3.master]) } + let(:ocB) { create(:simple_order_cycle, coordinator: c2, distributors: [d1, d2], suppliers: [s1, s2, s3], variants: [p2.master]) } # orderA1 can only be accessed by s1, s3 and d1 let!(:orderA1) do @@ -53,15 +55,29 @@ describe Spree::Admin::ReportsController do order.save order end - - # As a Distributor Enterprise user for d1 + + # As manager of a coordinator (c1) + context "Coordinator Enterprise User" do + before { login_as_enterprise_user [c1] } + + describe 'Orders & Fulfillment' do + it "shows all orders in order cycles I coordinate" do + spree_get :orders_and_fulfillment + + assigns(:line_items).map(&:order).should include orderA1, orderA2 + assigns(:line_items).map(&:order).should_not include orderB1, orderB2 + end + end + end + + # As a Distributor Enterprise user for d1 context "Distributor Enterprise User" do before { login_as_enterprise_user [d1] } describe 'Orders and Distributors' do it "only shows orders that I have access to" do spree_get :orders_and_distributors - + assigns(:search).result.should include(orderA1, orderB1) assigns(:search).result.should_not include(orderA2) assigns(:search).result.should_not include(orderB2) @@ -71,7 +87,7 @@ describe Spree::Admin::ReportsController do describe 'Bulk Coop' do it "only shows orders that I have access to" do spree_get :bulk_coop - + assigns(:search).result.should include(orderA1, orderB1) assigns(:search).result.should_not include(orderA2) assigns(:search).result.should_not include(orderB2) @@ -81,7 +97,7 @@ describe Spree::Admin::ReportsController do describe 'Payments' do it "only shows orders that I have access to" do spree_get :payments - + assigns(:search).result.should include(orderA1, orderB1) assigns(:search).result.should_not include(orderA2) assigns(:search).result.should_not include(orderB2) @@ -89,12 +105,11 @@ describe Spree::Admin::ReportsController do end describe 'Orders & Fulfillment' do - it "only shows orders that I have access to" do + it "only shows orders that I distribute" do spree_get :orders_and_fulfillment - assigns(:search).result.should include(orderA1, orderB1) - assigns(:search).result.should_not include(orderA2) - assigns(:search).result.should_not include(orderB2) + assigns(:line_items).map(&:order).should include orderA1, orderB1 + assigns(:line_items).map(&:order).should_not include orderA2, orderB2 end it "only shows the selected order cycle" do @@ -114,19 +129,31 @@ describe Spree::Admin::ReportsController do it "only shows product line items that I am supplying" do spree_get :bulk_coop - assigns(:line_items).map(&:product).should include(p1) - assigns(:line_items).map(&:product).should_not include(p2) - assigns(:line_items).map(&:product).should_not include(p3) + assigns(:line_items).map(&:product).should include p1 + assigns(:line_items).map(&:product).should_not include p2, p3 end end describe 'Orders & Fulfillment' do - it "only shows product line items that I am supplying" do - spree_get :orders_and_fulfillment + context "where I have granted P-OC to the distributor" do + before do + create(:enterprise_relationship, parent: s1, child: d1, permissions_list: [:add_to_order_cycle]) + end - assigns(:line_items).map(&:product).should include(p1) - assigns(:line_items).map(&:product).should_not include(p2) - assigns(:line_items).map(&:product).should_not include(p3) + it "only shows product line items that I am supplying" do + spree_get :orders_and_fulfillment + + assigns(:line_items).map(&:product).should include p1 + assigns(:line_items).map(&:product).should_not include p2, p3 + end + end + + context "where I have not granted P-OC to the distributor" do + it "does not show me line_items I supply" do + spree_get :orders_and_fulfillment + + assigns(:line_items).map(&:product).should_not include p1, p2, p3 + end end it "only shows the selected order cycle" do @@ -143,7 +170,7 @@ describe Spree::Admin::ReportsController do it "should build distributors for the current user" do spree_get :products_and_inventory - assigns(:distributors).sort.should == [d1, d2, d3].sort + assigns(:distributors).sort.should == [c1, c2, d1, d2, d3].sort end it "builds suppliers for the current user" do @@ -184,7 +211,7 @@ describe Spree::Admin::ReportsController do it "should build distributors for the current user" do spree_get :customers - assigns(:distributors).sort.should == [d1, d2, d3].sort + assigns(:distributors).sort.should == [c1, c2, d1, d2, d3].sort end it "builds suppliers for the current user" do diff --git a/spec/features/admin/bulk_order_management_spec.rb b/spec/features/admin/bulk_order_management_spec.rb index c8ad230a00..1058bebfc0 100644 --- a/spec/features/admin/bulk_order_management_spec.rb +++ b/spec/features/admin/bulk_order_management_spec.rb @@ -238,8 +238,9 @@ feature %q{ end context "order_cycle filter" do - let!(:oc1) { FactoryGirl.create(:simple_order_cycle ) } - let!(:oc2) { FactoryGirl.create(:simple_order_cycle ) } + let!(:distributor) { create(:distributor_enterprise) } + let!(:oc1) { FactoryGirl.create(:simple_order_cycle, distributors: [distributor]) } + let!(:oc2) { FactoryGirl.create(:simple_order_cycle, distributors: [distributor]) } let!(:o1) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, order_cycle: oc1 ) } let!(:o2) { FactoryGirl.create(:order, state: 'complete', completed_at: Time.now, order_cycle: oc2 ) } let!(:li1) { FactoryGirl.create(:line_item, order: o1 ) } @@ -255,20 +256,22 @@ feature %q{ find("div.select2-container#s2id_order_cycle_filter").click order_cycle_names.each { |ocn| page.should have_selector "div.select2-drop-active ul.select2-results li", text: ocn } find("div.select2-container#s2id_order_cycle_filter").click - page.should have_selector "tr#li_#{li1.id}", visible: true - page.should have_selector "tr#li_#{li2.id}", visible: true + page.should have_selector "tr#li_#{li1.id}" + page.should have_selector "tr#li_#{li2.id}" select2_select oc1.name, from: "order_cycle_filter" - page.should have_selector "tr#li_#{li1.id}", visible: true - page.should_not have_selector "tr#li_#{li2.id}", visible: true + page.should have_selector "#loading img.spinner" + page.should_not have_selector "#loading img.spinner" + page.should have_selector "tr#li_#{li1.id}" + page.should_not have_selector "tr#li_#{li2.id}" end it "displays all line items when 'All' is selected from order_cycle filter" do select2_select oc1.name, from: "order_cycle_filter" - page.should have_selector "tr#li_#{li1.id}", visible: true - page.should_not have_selector "tr#li_#{li2.id}", visible: true + page.should have_selector "tr#li_#{li1.id}" + page.should_not have_selector "tr#li_#{li2.id}" select2_select "All", from: "order_cycle_filter" - page.should have_selector "tr#li_#{li1.id}", visible: true - page.should have_selector "tr#li_#{li2.id}", visible: true + page.should have_selector "tr#li_#{li1.id}" + page.should have_selector "tr#li_#{li2.id}" end end diff --git a/spec/features/admin/reports_spec.rb b/spec/features/admin/reports_spec.rb index b1685be6db..309e0a3e81 100644 --- a/spec/features/admin/reports_spec.rb +++ b/spec/features/admin/reports_spec.rb @@ -211,8 +211,9 @@ feature %q{ end it "handles order cycles with nil opening or closing times" do - oc = create(:simple_order_cycle, name: "My Order Cycle", orders_open_at: Time.now, orders_close_at: nil) - o = create(:order, order_cycle: oc) + distributor = create(:distributor_enterprise) + oc = create(:simple_order_cycle, name: "My Order Cycle", distributors: [distributor], orders_open_at: Time.now, orders_close_at: nil) + o = create(:order, order_cycle: oc, distributor: distributor) login_to_admin_section visit spree.orders_and_fulfillment_admin_reports_path diff --git a/spec/javascripts/unit/bulk_order_management_spec.js.coffee b/spec/javascripts/unit/bulk_order_management_spec.js.coffee index 35b9e13d61..3377c799db 100644 --- a/spec/javascripts/unit/bulk_order_management_spec.js.coffee +++ b/spec/javascripts/unit/bulk_order_management_spec.js.coffee @@ -22,8 +22,8 @@ describe "AdminOrderMgmtCtrl", -> returnedOrderCycles = [ "oc1", "oc2", "oc3" ] httpBackend.expectGET("/api/users/authorise_api?token=API_KEY").respond success: "Use of API Authorised" httpBackend.expectGET("/api/enterprises/accessible?template=bulk_index&q[is_primary_producer_eq]=true").respond returnedSuppliers - httpBackend.expectGET("/api/enterprises/accessible?template=bulk_index&q[is_distributor_eq]=true").respond returnedDistributors - httpBackend.expectGET("/api/order_cycles/accessible").respond returnedOrderCycles + httpBackend.expectGET("/api/enterprises/accessible?template=bulk_index&q[sells_in][]=own&q[sells_in][]=any").respond returnedDistributors + httpBackend.expectGET("/api/order_cycles/accessible?as=distributor&q[orders_close_at_gt]=SomeDate").respond returnedOrderCycles spyOn(scope, "initialiseVariables").andCallThrough() spyOn(scope, "fetchOrders").andReturn "nothing" #spyOn(returnedSuppliers, "unshift") @@ -33,8 +33,8 @@ describe "AdminOrderMgmtCtrl", -> httpBackend.flush() expect(scope.suppliers).toEqual [{ id : '0', name : 'All' }, 'list of suppliers'] - expect(scope.distributors).toEqual [ { id : '0', name : 'All' }, 'list of distributors' ] - expect(scope.orderCycles).toEqual [ { id : '0', name : 'All' }, 'oc1', 'oc2', 'oc3' ] + expect(scope.distributors).toEqual [ { id : '0', name : 'All' }, 'list of distributors' ] + expect(scope.orderCycles).toEqual [ { id : '0', name : 'All' }, 'oc1', 'oc2', 'oc3' ] expect(scope.initialiseVariables.calls.length).toBe 1 expect(scope.fetchOrders.calls.length).toBe 1 @@ -43,7 +43,7 @@ describe "AdminOrderMgmtCtrl", -> describe "fetching orders", -> beforeEach -> scope.initialiseVariables() - httpBackend.expectGET("/api/orders/managed?template=bulk_index;page=1;per_page=500;q[completed_at_not_null]=true;q[completed_at_gt]=SomeDate;q[completed_at_lt]=SomeDate").respond "list of orders" + httpBackend.expectGET("/api/orders/managed?template=bulk_index;page=1;per_page=500;q[state_not_eq]=canceled;q[completed_at_not_null]=true;q[completed_at_gt]=SomeDate;q[completed_at_lt]=SomeDate").respond "list of orders" it "makes a call to dataFetcher, with current start and end date parameters", -> scope.fetchOrders() diff --git a/spec/lib/open_food_network/permissions_spec.rb b/spec/lib/open_food_network/permissions_spec.rb index 88611b857c..10552572f0 100644 --- a/spec/lib/open_food_network/permissions_spec.rb +++ b/spec/lib/open_food_network/permissions_spec.rb @@ -8,16 +8,71 @@ module OpenFoodNetwork let(:e1) { create(:enterprise) } let(:e2) { create(:enterprise) } + describe "finding managed and related enterprises granting a particular permission" do + describe "as super admin" do + before { allow(user).to receive(:admin?) { true } } + + it "returns all enterprises" do + expect(permissions.send(:managed_and_related_enterprises_granting, :some_permission)).to eq [e1, e2] + end + end + + describe "as an enterprise user" do + let(:e3) { create(:enterprise) } + before { allow(user).to receive(:admin?) { false } } + + it "returns only my managed enterprises any that have granting them P-OC" do + expect(permissions).to receive(:managed_enterprises) { Enterprise.where(id: e1) } + expect(permissions).to receive(:related_enterprises_granting).with(:some_permission) { Enterprise.where(id: e3) } + expect(permissions.send(:managed_and_related_enterprises_granting, :some_permission)).to eq [e1, e3] + end + end + end + + describe "finding managed and related enterprises granting or granted a particular permission" do + describe "as super admin" do + before { allow(user).to receive(:admin?) { true } } + + it "returns all enterprises" do + expect(permissions.send(:managed_and_related_enterprises_granting, :some_permission)).to eq [e1, e2] + end + end + + describe "as an enterprise user" do + let(:e3) { create(:enterprise) } + let(:e4) { create(:enterprise) } + before { allow(user).to receive(:admin?) { false } } + + it "returns only my managed enterprises any that have granting them P-OC" do + expect(permissions).to receive(:managed_enterprises) { Enterprise.where(id: e1) } + expect(permissions).to receive(:related_enterprises_granting).with(:some_permission) { Enterprise.where(id: e3) } + expect(permissions).to receive(:related_enterprises_granted).with(:some_permission) { Enterprise.where(id: e4) } + expect(permissions.send(:managed_and_related_enterprises_with, :some_permission)).to eq [e1, e3, e4] + end + end + end + + describe "finding enterprises that can be selected in order report filters" do + let(:e) { double(:enterprise) } + + it "returns managed and related enterprises with add_to_order_cycle permission" do + expect(permissions).to receive(:managed_and_related_enterprises_with). + with(:add_to_order_cycle). + and_return([e]) + + expect(permissions.visible_enterprises_for_order_reports).to eq [e] + end + end + describe "finding enterprises that can be added to an order cycle" do let(:e) { double(:enterprise) } it "returns managed and related enterprises with add_to_order_cycle permission" do - permissions. - should_receive(:managed_and_related_enterprises_with). + expect(permissions).to receive(:managed_and_related_enterprises_granting). with(:add_to_order_cycle). and_return([e]) - permissions.order_cycle_enterprises.should == [e] + expect(permissions.order_cycle_enterprises).to eq [e] end end @@ -26,7 +81,7 @@ module OpenFoodNetwork it "returns managed and related enterprises with edit_profile permission" do permissions. - should_receive(:managed_and_related_enterprises_with). + should_receive(:managed_and_related_enterprises_granting). with(:edit_profile). and_return([e]) @@ -55,6 +110,7 @@ module OpenFoodNetwork before do permissions.stub(:managed_enterprises) { Enterprise.where(id: hub.id) } + permissions.stub(:admin?) { false } end it "returns enterprises as hub_id => [producer, ...]" do @@ -133,7 +189,7 @@ module OpenFoodNetwork it "returns managed and related enterprises with manage_products permission" do permissions. - should_receive(:managed_and_related_enterprises_with). + should_receive(:managed_and_related_enterprises_granting). with(:manage_products). and_return([e]) @@ -148,30 +204,31 @@ module OpenFoodNetwork it "returns the enterprises" do permissions.stub(:managed_enterprises) { e2 } - permissions.send(:related_enterprises_with, permission).should == [e1] + permissions.send(:related_enterprises_granting, permission).should == [e1] end it "returns an empty array when there are none" do permissions.stub(:managed_enterprises) { e1 } - permissions.send(:related_enterprises_with, permission).should == [] + permissions.send(:related_enterprises_granting, permission).should == [] end end describe "finding enterprises that are managed or with a particular permission" do before do permissions.stub(:managed_enterprises) { Enterprise.where('1=0') } - permissions.stub(:related_enterprises_with) { Enterprise.where('1=0') } + permissions.stub(:related_enterprises_granting) { Enterprise.where('1=0') } + permissions.stub(:admin?) { false } end it "returns managed enterprises" do permissions.should_receive(:managed_enterprises) { Enterprise.where(id: e1) } - permissions.send(:managed_and_related_enterprises_with, permission).should == [e1] + permissions.send(:managed_and_related_enterprises_granting, permission).should == [e1] end it "returns permitted enterprises" do - permissions.should_receive(:related_enterprises_with).with(permission). + permissions.should_receive(:related_enterprises_granting).with(permission). and_return(Enterprise.where(id: e2)) - permissions.send(:managed_and_related_enterprises_with, permission).should == [e2] + permissions.send(:managed_and_related_enterprises_granting, permission).should == [e2] end end @@ -180,10 +237,141 @@ module OpenFoodNetwork let!(:p) { create(:simple_product, supplier: e) } it "returns supplied products" do - permissions.should_receive(:related_enterprises_with).with(:manage_products) { [e] } + permissions.should_receive(:related_enterprises_granting).with(:manage_products) { [e] } permissions.send(:related_enterprise_products).should == [p] end end + + describe "finding orders that are visible in reports" do + let(:distributor) { create(:distributor_enterprise) } + let(:coordinator) { create(:distributor_enterprise) } + let(:random_enterprise) { create(:distributor_enterprise) } + let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, distributors: [distributor]) } + let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor ) } + let!(:line_item) { create(:line_item, order: order) } + let!(:producer) { create(:supplier_enterprise) } + + before do + permissions.stub(:coordinated_order_cycles) { Enterprise.where("1=0") } + end + + context "as the hub through which the order was placed" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: distributor) } + end + + it "should let me see the order" do + expect(permissions.visible_orders).to include order + end + end + + context "as the coordinator of the order cycle through which the order was placed" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: coordinator) } + permissions.stub(:coordinated_order_cycles) { OrderCycle.where(id: order_cycle) } + end + + it "should let me see the order" do + expect(permissions.visible_orders).to include order + end + end + + context "as a producer which has granted P-OC to the distributor of an order" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: producer) } + create(:enterprise_relationship, parent: producer, child: distributor, permissions_list: [:add_to_order_cycle]) + end + + context "which contains my products" do + before do + line_item.product.supplier = producer + line_item.product.save + end + + it "should let me see the order" do + expect(permissions.visible_orders).to include order + end + end + + context "which does not contain my products" do + it "should not let me see the order" do + expect(permissions.visible_orders).to_not include order + end + end + end + + context "as an enterprise that is a distributor in the order cycle, but not the distributor of the order" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: random_enterprise) } + end + + it "should not let me see the order" do + expect(permissions.visible_orders).to_not include order + end + end + end + + describe "finding line items that are visible in reports" do + let(:distributor) { create(:distributor_enterprise) } + let(:coordinator) { create(:distributor_enterprise) } + let(:random_enterprise) { create(:distributor_enterprise) } + let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, distributors: [distributor]) } + let(:order) { create(:order, order_cycle: order_cycle, distributor: distributor ) } + let!(:line_item1) { create(:line_item, order: order) } + let!(:line_item2) { create(:line_item, order: order) } + let!(:producer) { create(:supplier_enterprise) } + + before do + permissions.stub(:coordinated_order_cycles) { Enterprise.where("1=0") } + end + + context "as the hub through which the parent order was placed" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: distributor) } + end + + it "should let me see the line_items" do + expect(permissions.visible_line_items).to include line_item1, line_item2 + end + end + + context "as the coordinator of the order cycle through which the parent order was placed" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: coordinator) } + permissions.stub(:coordinated_order_cycles) { OrderCycle.where(id: order_cycle) } + end + + it "should let me see the line_items" do + expect(permissions.visible_line_items).to include line_item1, line_item2 + end + end + + context "as the manager producer which has granted P-OC to the distributor of the parent order" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: producer) } + create(:enterprise_relationship, parent: producer, child: distributor, permissions_list: [:add_to_order_cycle]) + + line_item1.product.supplier = producer + line_item1.product.save + end + + it "should let me see the line_items pertaining to variants I produce" do + ps = permissions.visible_line_items + expect(ps).to include line_item1 + expect(ps).to_not include line_item2 + end + end + + context "as an enterprise that is a distributor in the order cycle, but not the distributor of the parent order" do + before do + permissions.stub(:managed_enterprises) { Enterprise.where(id: random_enterprise) } + end + + it "should not let me see the line_items" do + expect(permissions.visible_line_items).to_not include line_item1, line_item2 + end + end + end end end diff --git a/spec/models/enterprise_spec.rb b/spec/models/enterprise_spec.rb index 69ba68569f..df1b58aca6 100644 --- a/spec/models/enterprise_spec.rb +++ b/spec/models/enterprise_spec.rb @@ -558,35 +558,6 @@ describe Enterprise do enterprises.should include e2 end end - - describe "accessible_by" do - it "shows only enterprises that are invloved in order cycles which are common to those managed by the given user" do - user = create(:user) - user.spree_roles = [] - e1 = create(:enterprise) - e2 = create(:enterprise) - e3 = create(:enterprise) - e4 = create(:enterprise) - e1.enterprise_roles.build(user: user).save - oc = create(:simple_order_cycle, coordinator: e2, suppliers: [e1], distributors: [e3]) - - enterprises = Enterprise.accessible_by user - enterprises.length.should == 3 - enterprises.should include e1, e2, e3 - enterprises.should_not include e4 - end - - it "shows all enterprises for admin user" do - user = create(:admin_user) - e1 = create(:enterprise) - e2 = create(:enterprise) - - enterprises = Enterprise.managed_by user - enterprises.length.should == 2 - enterprises.should include e1 - enterprises.should include e2 - end - end end describe "callbacks" do