mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-03 02:21:33 +00:00
Merge branch 'enterprise-reports'
Conflicts: app/models/spree/ability_decorator.rb
This commit is contained in:
14
app/controllers/spree/admin/base_controller_decorator.rb
Normal file
14
app/controllers/spree/admin/base_controller_decorator.rb
Normal file
@@ -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
|
||||
@@ -27,7 +27,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
|
||||
@@ -56,10 +56,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]
|
||||
@@ -87,11 +87,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
|
||||
@line_items = orders.map { |o| o.line_items.managed_by(spree_current_user) }.flatten
|
||||
|
||||
@distributors = Enterprise.is_distributor
|
||||
@distributors = Enterprise.is_distributor.managed_by(spree_current_user)
|
||||
@report_type = params[:report_type]
|
||||
|
||||
case params[:report_type]
|
||||
@@ -219,7 +219,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)
|
||||
@@ -239,11 +239,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]
|
||||
@@ -343,19 +343,19 @@ 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
|
||||
@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
|
||||
|
||||
@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]
|
||||
|
||||
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"]
|
||||
@@ -377,7 +377,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"]
|
||||
@@ -409,7 +409,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"]
|
||||
@@ -443,7 +443,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?"]
|
||||
@@ -485,7 +485,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"]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
168
spec/controllers/spree/admin/reports_controller_spec.rb
Normal file
168
spec/controllers/spree/admin/reports_controller_spec.rb
Normal file
@@ -0,0 +1,168 @@
|
||||
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(: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]) }
|
||||
|
||||
# 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)
|
||||
order.finalize!
|
||||
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)
|
||||
order.finalize!
|
||||
order.save
|
||||
order
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
before :each do
|
||||
controller.stub :spree_current_user => user
|
||||
end
|
||||
|
||||
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
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user