From 346113966e94b071d77f68ee49e8caae07eaa386 Mon Sep 17 00:00:00 2001 From: David Cook Date: Thu, 22 Aug 2013 11:31:07 +1000 Subject: [PATCH 1/5] Prevent exception when order has no payments --- lib/open_food_web/order_and_distributor_report.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/open_food_web/order_and_distributor_report.rb b/lib/open_food_web/order_and_distributor_report.rb index 04a3596441..6d9556cef7 100644 --- a/lib/open_food_web/order_and_distributor_report.rb +++ b/lib/open_food_web/order_and_distributor_report.rb @@ -21,7 +21,7 @@ module OpenFoodWeb order_and_distributor_details << [order.created_at, order.id, order.bill_address.full_name, order.email, order.bill_address.phone, order.bill_address.city, line_item.product.sku, line_item.product.name, line_item.variant.options_text, line_item.quantity, line_item.max_quantity, line_item.price * line_item.quantity, line_item.distribution_fee, - order.payments.first.payment_method.andand.name, + order.payments.first.andand.payment_method.andand.name, order.distributor.andand.name, order.distributor.address.address1, order.distributor.address.city, order.distributor.address.zipcode, order.special_instructions ] end end From 3a75f6b86a3e916283e2ea418f4e3e0f8bb54327 Mon Sep 17 00:00:00 2001 From: David Cook Date: Thu, 22 Aug 2013 11:49:18 +1000 Subject: [PATCH 2/5] Enterprise user can access all OFN reports --- .../spree/admin/base_controller_decorator.rb | 14 ++++++++++++++ app/models/spree/ability_decorator.rb | 4 +++- 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 app/controllers/spree/admin/base_controller_decorator.rb diff --git a/app/controllers/spree/admin/base_controller_decorator.rb b/app/controllers/spree/admin/base_controller_decorator.rb new file mode 100644 index 0000000000..8e876513fa --- /dev/null +++ b/app/controllers/spree/admin/base_controller_decorator.rb @@ -0,0 +1,14 @@ +Spree::Admin::BaseController.class_eval do + # Override Spree method + # It's a shame Spree doesn't just let CanCan handle this in it's own way + def authorize_admin + if respond_to?(:model_class, true) && model_class + record = model_class + else + # this line changed to allow specificity for each non-resource controller (to be consistent with "authorize_resource :class => false", see https://github.com/ryanb/cancan/blob/60cf6a67ef59c0c9b63bc27ea0101125c4193ea6/lib/cancan/controller_resource.rb#L146) + record = self.class.to_s.sub("Controller", "").underscore.split('/').last.singularize.to_sym + end + authorize! :admin, record + authorize! action, record + end +end \ No newline at end of file diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index ccd4252897..9b2875ce43 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -17,7 +17,7 @@ class AbilityDecorator can [:admin, :index, :read, :search], Spree::Taxon can [:admin, :index, :read, :create, :edit], Spree::Classification - #User can only access orders that they are a distributor for + #Enterprise User can only access orders that they are a distributor for can [:index, :create], Spree::Order can [:admin, :read, :update, :fire, :resend ], Spree::Order do |order| user.enterprises.include? order.distributor @@ -52,6 +52,8 @@ class AbilityDecorator user.enterprises.include? enterprise end + #Enterprise User can access reports page + can [:admin, :index, :orders_and_distributors, :group_buys, :bulk_coop, :payments, :order_cycles], :report end end end From f1c2582e65721c0dc28b22713e14b48e28cab123 Mon Sep 17 00:00:00 2001 From: David Cook Date: Thu, 22 Aug 2013 12:49:39 +1000 Subject: [PATCH 3/5] WIP: Test for enterprise user access in reports --- .../spree/admin/reports_controller_spec.rb | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 spec/controllers/spree/admin/reports_controller_spec.rb diff --git a/spec/controllers/spree/admin/reports_controller_spec.rb b/spec/controllers/spree/admin/reports_controller_spec.rb new file mode 100644 index 0000000000..89ac37dd12 --- /dev/null +++ b/spec/controllers/spree/admin/reports_controller_spec.rb @@ -0,0 +1,57 @@ +require 'spec_helper' + +describe Spree::Admin::ReportsController do + + # Given two distributors + let (:ba) { create(:address) } + let (:da) { create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234") } + let (:si) { "pick up on thursday please" } + let (:d1) { create(:distributor_enterprise, address: da) } + let (:d2) { create(:distributor_enterprise, address: da) } + let (:p1) { create(:product, price: 12.34, distributors: [d1]) } + let (:p2) { create(:product, price: 23.45, distributors: [d2]) } + + # Given two order cycles with both distributors + let (:ocA) { create(:order_cycle, distributors: [d1, d2], variants:[p1.master]) } + let (:ocB) { create(:order_cycle, distributors: [d1, d2], variants: [p2.master]) } + + let (:orderA1) do + order = create(:order, distributor: d1, bill_address: ba, special_instructions: si, order_cycle: ocA) + order.line_items << create(:line_item, variant: p1.master) + order.finalize! + order + end + let (:orderA2) do + order = create(:order, distributor: d2, bill_address: ba, special_instructions: si, order_cycle: ocA) + order.line_items << create(:line_item, variant: p2.master) + order.finalize! + order + end + let (:orderB1) do + order = create(:order, distributor: d1, bill_address: ba, special_instructions: si, order_cycle: ocB) + order.line_items << create(:line_item, variant: p1.master) + order.finalize! + order + end + let (:orderB2) do + order = create(:order, distributor: d2, bill_address: ba, special_instructions: si, order_cycle: ocB) + order.line_items << create(:line_item, variant: p2.master) + order.finalize! + order + end + + # Given Distributor Enterprise user for d1 + let (:user) do + user = create(:user) + user.spree_roles = [] + s1.enterprise_roles.build(user: user, enterprises: [d1]).save + user + end + + describe 'Orders and Distributors' do + spree_get :orders_and_distributors + + controller.search.result.should_include [orderA1, orderB1] + # assigns(:search).result.should_include [orderA1, orderB1] + end +end From 9de5a0061e683d82443490b28a49df93d787b88a Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 23 Aug 2013 16:09:37 +1000 Subject: [PATCH 4/5] Enterprise user can only view their own distributors in reports (and remove redundant feature test) --- .../admin/reports_controller_decorator.rb | 18 ++-- .../spree/admin/reports_controller_spec.rb | 98 +++++++++++++++---- spec/features/admin/reports_spec.rb | 46 --------- 3 files changed, 87 insertions(+), 75 deletions(-) diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index b4cf6c394c..d5453f774f 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -25,7 +25,7 @@ Spree::Admin::ReportsController.class_eval do end params[:q][:meta_sort] ||= "completed_at.desc" - @search = Spree::Order.complete.search(params[:q]) + @search = Spree::Order.complete.managed_by(spree_current_user).search(params[:q]) orders = @search.result @report = OpenFoodWeb::OrderAndDistributorReport.new orders @@ -54,10 +54,10 @@ Spree::Admin::ReportsController.class_eval do end params[:q][:meta_sort] ||= "completed_at.desc" - @search = Spree::Order.complete.search(params[:q]) + @search = Spree::Order.complete.managed_by(spree_current_user).search(params[:q]) orders = @search.result - @distributors = Enterprise.is_distributor + @distributors = Enterprise.is_distributor.managed_by(spree_current_user) @report = OpenFoodWeb::GroupBuyReport.new orders unless params[:csv] @@ -85,11 +85,11 @@ Spree::Admin::ReportsController.class_eval do end params[:q][:meta_sort] ||= "completed_at.desc" - @search = Spree::Order.complete.search(params[:q]) + @search = Spree::Order.complete.managed_by(spree_current_user).search(params[:q]) orders = @search.result line_items = orders.map { |o| o.line_items }.flatten - @distributors = Enterprise.is_distributor + @distributors = Enterprise.is_distributor.managed_by(spree_current_user) @report_type = params[:report_type] case params[:report_type] @@ -237,11 +237,11 @@ Spree::Admin::ReportsController.class_eval do end params[:q][:meta_sort] ||= "completed_at.desc" - @search = Spree::Order.complete.search(params[:q]) + @search = Spree::Order.complete.managed_by(spree_current_user).search(params[:q]) orders = @search.result payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments - @distributors = Enterprise.is_distributor + @distributors = Enterprise.is_distributor.managed_by(spree_current_user) @report_type = params[:report_type] case params[:report_type] @@ -341,12 +341,12 @@ Spree::Admin::ReportsController.class_eval do end params[:q][:meta_sort] ||= "completed_at.desc" - @search = Spree::Order.complete.search(params[:q]) + @search = Spree::Order.complete.managed_by(spree_current_user).search(params[:q]) orders = @search.result line_items = orders.map { |o| o.line_items }.flatten #payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments - @distributors = Enterprise.is_distributor + @distributors = Enterprise.is_distributor.managed_by(spree_current_user) #@suppliers = Enterprise.is_primary_producer @order_cycles = OrderCycle.active_or_complete.order('orders_close_at DESC') @report_type = params[:report_type] diff --git a/spec/controllers/spree/admin/reports_controller_spec.rb b/spec/controllers/spree/admin/reports_controller_spec.rb index 89ac37dd12..0705e8fa55 100644 --- a/spec/controllers/spree/admin/reports_controller_spec.rb +++ b/spec/controllers/spree/admin/reports_controller_spec.rb @@ -1,57 +1,115 @@ require 'spec_helper' describe Spree::Admin::ReportsController do - + # Given two distributors - let (:ba) { create(:address) } - let (:da) { create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234") } - let (:si) { "pick up on thursday please" } - let (:d1) { create(:distributor_enterprise, address: da) } - let (:d2) { create(:distributor_enterprise, address: da) } - let (:p1) { create(:product, price: 12.34, distributors: [d1]) } - let (:p2) { create(:product, price: 23.45, distributors: [d2]) } + let(:ba) { create(:address) } + let(:da) { create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234") } + let(:si) { "pick up on thursday please" } + let(:d1) { create(:distributor_enterprise, address: da) } + let(:d2) { create(:distributor_enterprise, address: da) } + let(:p1) { create(:product, price: 12.34, distributors: [d1]) } + let(:p2) { create(:product, price: 23.45, distributors: [d2]) } # Given two order cycles with both distributors - let (:ocA) { create(:order_cycle, distributors: [d1, d2], variants:[p1.master]) } - let (:ocB) { create(:order_cycle, distributors: [d1, d2], variants: [p2.master]) } + let(:ocA) { create(:order_cycle, distributors: [d1, d2], variants:[p1.master]) } + let(:ocB) { create(:order_cycle, distributors: [d1, d2], variants: [p2.master]) } - let (:orderA1) do + let!(:orderA1) do order = create(:order, distributor: d1, bill_address: ba, special_instructions: si, order_cycle: ocA) order.line_items << create(:line_item, variant: p1.master) order.finalize! + order.save order end - let (:orderA2) do + let!(:orderA2) do order = create(:order, distributor: d2, bill_address: ba, special_instructions: si, order_cycle: ocA) order.line_items << create(:line_item, variant: p2.master) order.finalize! + order.save order end - let (:orderB1) do + let!(:orderB1) do order = create(:order, distributor: d1, bill_address: ba, special_instructions: si, order_cycle: ocB) order.line_items << create(:line_item, variant: p1.master) order.finalize! + order.save order end - let (:orderB2) do + let!(:orderB2) do order = create(:order, distributor: d2, bill_address: ba, special_instructions: si, order_cycle: ocB) order.line_items << create(:line_item, variant: p2.master) order.finalize! + order.save order end # Given Distributor Enterprise user for d1 - let (:user) do + let(:user) do user = create(:user) user.spree_roles = [] - s1.enterprise_roles.build(user: user, enterprises: [d1]).save + d1.enterprise_roles.build(user: user).save user end - describe 'Orders and Distributors' do - spree_get :orders_and_distributors + before :each do + controller.stub :spree_current_user => user + end - controller.search.result.should_include [orderA1, orderB1] - # assigns(:search).result.should_include [orderA1, orderB1] + 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) + end + end + + describe 'Group Buys' do + it "only shows orders that I have access to" do + spree_get :group_buys + + assigns(:search).result.should include(orderA1, orderB1) + assigns(:search).result.should_not include(orderA2) + assigns(:search).result.should_not include(orderB2) + end + end + + 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) + end + end + + 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) + end + end + + describe 'Order Cycles' do + it "only shows orders that I have access to" do + spree_get :order_cycles + + assigns(:search).result.should include(orderA1, orderB1) + assigns(:search).result.should_not include(orderA2) + assigns(:search).result.should_not include(orderB2) + end + + it "only shows the selected order cycle" do + spree_get :order_cycles, q: {order_cycle_id_eq: ocA.id} + + assigns(:search).result.should include(orderA1) + assigns(:search).result.should_not include(orderB1) + end end end diff --git a/spec/features/admin/reports_spec.rb b/spec/features/admin/reports_spec.rb index 2a09ff29ba..7345a527b0 100644 --- a/spec/features/admin/reports_spec.rb +++ b/spec/features/admin/reports_spec.rb @@ -79,50 +79,4 @@ feature %q{ all('table#listing_orders tbody tr').count.should == 2 # Two rows per order end - scenario "Order cycle reports show only the selected order cycle" do - # Given two orders for two order cycles - @bill_address = create(:address) - @distributor_address = create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234") - d1 = create(:distributor_enterprise, :address => @distributor_address) - p1 = create(:product, price: 12.34) - p2 = create(:product, price: 23.45) - product_distribution = create(:product_distribution, :product => p1, :distributor => d1) - product_distribution = create(:product_distribution, :product => p2, :distributor => d1) - @shipping_instructions = "pick up on thursday please!" - - oc1 = create(:order_cycle, :distributors => [d1], :variants => [p1.master]) - oc2 = create(:order_cycle, :distributors => [d1], :variants => [p2.master]) - - # Given each order has one product, p1 for oc1; p2 for oc2 - @order11 = create(:order, :distributor => d1, :bill_address => @bill_address, :special_instructions => @shipping_instructions, :order_cycle => oc1) - @order12 = create(:order, :distributor => d1, :bill_address => @bill_address, :special_instructions => @shipping_instructions, :order_cycle => oc1) - @order21 = create(:order, :distributor => d1, :bill_address => @bill_address, :special_instructions => @shipping_instructions, :order_cycle => oc2) - @order22 = create(:order, :distributor => d1, :bill_address => @bill_address, :special_instructions => @shipping_instructions, :order_cycle => oc2) - - @order11.line_items << create(:line_item, variant: p1.master) - @order12.line_items << create(:line_item, variant: p1.master) - @order21.line_items << create(:line_item, variant: p2.master) - @order22.line_items << create(:line_item, variant: p2.master) - - @order11.finalize! - @order12.finalize! - @order21.finalize! - @order21.finalize! - - # When I select one order cycle - login_to_admin_section - click_link 'Reports' - click_link 'Order Cycle Reports' - - select oc1.name, from: 'q_order_cycle_id_eq' - select 'Order Cycle Supplier Totals', from: 'report_type' - click_button 'Search' - - # Then I should see the rows for order cycle 1 but not order cycle 2 - all('table#listing_orders tbody tr').count.should == 1 # One row per product - page.should have_content p1.price.to_s - page.should_not have_content p2.price.to_s - end - - end From 80bfc5ce53c36ec00c518e3a6c05bc0e32845fa6 Mon Sep 17 00:00:00 2001 From: David Cook Date: Fri, 30 Aug 2013 15:17:27 +1000 Subject: [PATCH 5/5] Ensure Supplier enterprise users can only view their own products in reports --- .../admin/reports_controller_decorator.rb | 18 +- app/models/spree/line_item_decorator.rb | 14 ++ app/models/spree/order_decorator.rb | 8 +- .../spree/admin/reports_controller_spec.rb | 185 +++++++++++------- 4 files changed, 149 insertions(+), 76 deletions(-) diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index d5453f774f..d7db956e20 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -87,7 +87,7 @@ Spree::Admin::ReportsController.class_eval do @search = Spree::Order.complete.managed_by(spree_current_user).search(params[:q]) orders = @search.result - line_items = orders.map { |o| o.line_items }.flatten + @line_items = orders.map { |o| o.line_items.managed_by(spree_current_user) }.flatten @distributors = Enterprise.is_distributor.managed_by(spree_current_user) @report_type = params[:report_type] @@ -217,7 +217,7 @@ Spree::Admin::ReportsController.class_eval do order_grouper = OpenFoodWeb::OrderGrouper.new rules, columns @header = header - @table = order_grouper.table(line_items) + @table = order_grouper.table(@line_items) csv_file_name = "bulk_coop.csv" render_report(@header, @table, params[:csv], csv_file_name) @@ -343,9 +343,9 @@ Spree::Admin::ReportsController.class_eval do @search = Spree::Order.complete.managed_by(spree_current_user).search(params[:q]) orders = @search.result - line_items = orders.map { |o| o.line_items }.flatten + @line_items = orders.map { |o| o.line_items.managed_by(spree_current_user) }.flatten #payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments - + @distributors = Enterprise.is_distributor.managed_by(spree_current_user) #@suppliers = Enterprise.is_primary_producer @order_cycles = OrderCycle.active_or_complete.order('orders_close_at DESC') @@ -353,7 +353,7 @@ Spree::Admin::ReportsController.class_eval do case params[:report_type] when "order_cycle_supplier_totals" - table_items = line_items + table_items = @line_items @include_blank = 'All' header = ["Supplier", "Product", "Variant", "Amount", "Cost per Unit", "Total Cost", "Status", "Incoming Transport"] @@ -375,7 +375,7 @@ Spree::Admin::ReportsController.class_eval do sort_by: proc { |variant| variant.options_text } } ] when "order_cycle_supplier_totals_by_distributor" - table_items = line_items + table_items = @line_items @include_blank = 'All' header = ["Supplier", "Product", "Variant", "To Distributor", "Amount", "Cost per Unit", "Total Cost", "Shipping Method"] @@ -407,7 +407,7 @@ Spree::Admin::ReportsController.class_eval do sort_by: proc { |distributor| distributor.name } } ] when "order_cycle_distributor_totals_by_supplier" - table_items = line_items + table_items = @line_items @include_blank = 'All' header = ["Distributor", "Supplier", "Product", "Variant", "Amount", "Cost per Unit", "Total Cost", "Total Shipping Cost", "Shipping Method"] @@ -441,7 +441,7 @@ Spree::Admin::ReportsController.class_eval do sort_by: proc { |variant| variant.options_text } } ] when "order_cycle_customer_totals" - table_items = line_items + table_items = @line_items @include_blank = 'All' header = ["Distributor", "Customer", "Email", "Phone", "Product", "Variant", "Amount", "Item ($)", "Ship ($)", "Total ($)", "Paid?", "Packed?", "Shipped?"] @@ -483,7 +483,7 @@ Spree::Admin::ReportsController.class_eval do sort_by: proc { |variant| variant.options_text } } ] else - table_items = line_items + table_items = @line_items @include_blank = 'All' header = ["Supplier", "Product", "Variant", "Amount", "Cost per Unit", "Total Cost", "Status", "Incoming Transport"] diff --git a/app/models/spree/line_item_decorator.rb b/app/models/spree/line_item_decorator.rb index 3b7ee891b8..21715e468f 100644 --- a/app/models/spree/line_item_decorator.rb +++ b/app/models/spree/line_item_decorator.rb @@ -1,3 +1,17 @@ Spree::LineItem.class_eval do attr_accessible :max_quantity + + # -- Scopes + scope :managed_by, lambda { |user| + if user.has_spree_role?('admin') + scoped + else + # User has a distributor on the Order or supplier that supplies a LineItem + joins('LEFT OUTER JOIN spree_variants ON (spree_variants.id = spree_line_items.variant_id)'). + joins('LEFT OUTER JOIN spree_products ON (spree_products.id = spree_variants.product_id)'). + joins(:order). + where('spree_orders.distributor_id IN (?) OR spree_products.supplier_id IN (?)', user.enterprises, user.enterprises). + select('spree_line_items.*') + end + } end diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index 5c28f5f510..8864860bf4 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -20,7 +20,13 @@ Spree::Order.class_eval do if user.has_spree_role?('admin') scoped else - where('distributor_id IN (?)', user.enterprises) + # User has a distributor on an Order or supplier that supplies a Product to an Order + # NOTE: supplier Orders should use LineItem.managed_by to ensure they only see their own LineItems! + joins('LEFT OUTER JOIN spree_line_items ON (spree_line_items.order_id = spree_orders.id)'). + joins('LEFT OUTER JOIN spree_variants ON (spree_variants.id = spree_line_items.variant_id)'). + joins('LEFT OUTER JOIN spree_products ON (spree_products.id = spree_variants.product_id)'). + where('spree_orders.distributor_id IN (?) OR spree_products.supplier_id IN (?)', user.enterprises, user.enterprises). + select('DISTINCT spree_orders.*') end } diff --git a/spec/controllers/spree/admin/reports_controller_spec.rb b/spec/controllers/spree/admin/reports_controller_spec.rb index 0705e8fa55..9446524873 100644 --- a/spec/controllers/spree/admin/reports_controller_spec.rb +++ b/spec/controllers/spree/admin/reports_controller_spec.rb @@ -2,26 +2,33 @@ require 'spec_helper' describe Spree::Admin::ReportsController do - # Given two distributors + # Given two distributors and two suppliers let(:ba) { create(:address) } - let(:da) { create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234") } let(:si) { "pick up on thursday please" } - let(:d1) { create(:distributor_enterprise, address: da) } - let(:d2) { create(:distributor_enterprise, address: da) } - let(:p1) { create(:product, price: 12.34, distributors: [d1]) } - let(:p2) { create(:product, price: 23.45, distributors: [d2]) } + 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(: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(:order_cycle, distributors: [d1, d2], variants:[p1.master]) } - let(:ocB) { create(:order_cycle, distributors: [d1, d2], variants: [p2.master]) } + 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]) } + # orderA1 can only be accessed by s1, s3 and d1 let!(:orderA1) do order = create(:order, distributor: d1, bill_address: ba, special_instructions: si, order_cycle: ocA) order.line_items << create(:line_item, variant: p1.master) + order.line_items << create(:line_item, variant: p3.master) order.finalize! order.save order end + # orderA2 can only be accessed by s2 and d2 let!(:orderA2) do order = create(:order, distributor: d2, bill_address: ba, special_instructions: si, order_cycle: ocA) order.line_items << create(:line_item, variant: p2.master) @@ -29,13 +36,16 @@ describe Spree::Admin::ReportsController do order.save order end + # orderB1 can only be accessed by s1, s3 and d1 let!(:orderB1) do order = create(:order, distributor: d1, bill_address: ba, special_instructions: si, order_cycle: ocB) order.line_items << create(:line_item, variant: p1.master) + order.line_items << create(:line_item, variant: p3.master) order.finalize! order.save order end + # orderB2 can only be accessed by s2 and d2 let!(:orderB2) do order = create(:order, distributor: d2, bill_address: ba, special_instructions: si, order_cycle: ocB) order.line_items << create(:line_item, variant: p2.master) @@ -44,72 +54,115 @@ describe Spree::Admin::ReportsController do order end - # Given Distributor Enterprise user for d1 - let(:user) do - user = create(:user) - user.spree_roles = [] - d1.enterprise_roles.build(user: user).save - user - end + # As a Distributor Enterprise user for d1 + context "Distributor Enterprise User" do + let(:user) do + user = create(:user) + user.spree_roles = [] + d1.enterprise_roles.build(user: user).save + user + end - before :each do - controller.stub :spree_current_user => user - end + before :each do + controller.stub :spree_current_user => user + end - 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) + 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) + end + end + + describe 'Group Buys' do + it "only shows orders that I have access to" do + spree_get :group_buys + + assigns(:search).result.should include(orderA1, orderB1) + assigns(:search).result.should_not include(orderA2) + assigns(:search).result.should_not include(orderB2) + end + end + + 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) + end + end + + 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) + end + end + + describe 'Order Cycles' do + it "only shows orders that I have access to" do + spree_get :order_cycles + + assigns(:search).result.should include(orderA1, orderB1) + assigns(:search).result.should_not include(orderA2) + assigns(:search).result.should_not include(orderB2) + end + + it "only shows the selected order cycle" do + spree_get :order_cycles, q: {order_cycle_id_eq: ocA.id} + + assigns(:search).result.should include(orderA1) + assigns(:search).result.should_not include(orderB1) + end end end - describe 'Group Buys' do - it "only shows orders that I have access to" do - spree_get :group_buys - - assigns(:search).result.should include(orderA1, orderB1) - assigns(:search).result.should_not include(orderA2) - assigns(:search).result.should_not include(orderB2) - end - end - - 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) - end - end - - 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) - end - end - - describe 'Order Cycles' do - it "only shows orders that I have access to" do - spree_get :order_cycles - - assigns(:search).result.should include(orderA1, orderB1) - assigns(:search).result.should_not include(orderA2) - assigns(:search).result.should_not include(orderB2) + # As a Supplier Enterprise user for s1 + context "Supplier" do + let(:user) do + user = create(:user) + user.spree_roles = [] + s1.enterprise_roles.build(user: user).save + user end - it "only shows the selected order cycle" do - spree_get :order_cycles, q: {order_cycle_id_eq: ocA.id} + before :each do + controller.stub :spree_current_user => user + end - assigns(:search).result.should include(orderA1) - assigns(:search).result.should_not include(orderB1) + describe 'Bulk Coop' 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) + end + end + + describe 'Order Cycles' do + it "only shows product line items that I am supplying" do + spree_get :order_cycles + + 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) + end + + it "only shows the selected order cycle" do + spree_get :order_cycles, q: {order_cycle_id_eq: ocA.id} + + assigns(:search).result.should include(orderA1) + assigns(:search).result.should_not include(orderB1) + end end end end