Ensure Supplier enterprise users can only view their own products in reports

This commit is contained in:
David Cook
2013-08-30 15:17:27 +10:00
parent 9de5a0061e
commit 80bfc5ce53
4 changed files with 149 additions and 76 deletions

View File

@@ -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"]

View File

@@ -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

View File

@@ -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
}

View File

@@ -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