From 1fba998b9eaedfde6ab5ce7f85bf1f29e3887560 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Thu, 28 May 2020 19:04:18 +0100 Subject: [PATCH 01/19] Drop Blockenspiel and use :rules/:columns methods instead of :organise/:summary_columns DSL. For https://github.com/openfoodfoundation/openfoodnetwork/issues/3231 --- Gemfile | 1 - Gemfile.lock | 2 - .../reports/bulk_coop_allocation_report.rb | 77 ++++++++--------- .../reports/bulk_coop_report.rb | 86 +++++++++---------- .../reports/bulk_coop_supplier_report.rb | 76 ++++++++-------- lib/open_food_network/reports/report.rb | 10 --- lib/open_food_network/reports/row.rb | 2 - lib/open_food_network/reports/rule.rb | 11 --- .../open_food_network/reports/report_spec.rb | 83 ------------------ .../open_food_network/reports/rule_spec.rb | 18 ---- 10 files changed, 117 insertions(+), 249 deletions(-) diff --git a/Gemfile b/Gemfile index c2d772e8d3..861e193b16 100644 --- a/Gemfile +++ b/Gemfile @@ -65,7 +65,6 @@ gem 'unicorn' gem "active_model_serializers", "0.8.4" gem 'acts-as-taggable-on', '~> 3.4' gem 'angularjs-file-upload-rails', '~> 2.4.1' -gem 'blockenspiel' gem 'custom_error_message', github: 'jeremydurham/custom-err-msg' gem 'dalli' gem 'diffy' diff --git a/Gemfile.lock b/Gemfile.lock index 12760634af..dc1aa80cf5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -146,7 +146,6 @@ GEM bcrypt (3.1.13) bcrypt-ruby (3.1.5) bcrypt (>= 3.1.3) - blockenspiel (0.5.0) bugsnag (6.13.1) concurrent-ruby (~> 1.0) builder (3.0.4) @@ -698,7 +697,6 @@ DEPENDENCIES atomic awesome_print aws-sdk - blockenspiel bugsnag byebug (~> 11.0.0) capybara (>= 2.18.0) diff --git a/lib/open_food_network/reports/bulk_coop_allocation_report.rb b/lib/open_food_network/reports/bulk_coop_allocation_report.rb index f132e642df..c8b05c30a0 100644 --- a/lib/open_food_network/reports/bulk_coop_allocation_report.rb +++ b/lib/open_food_network/reports/bulk_coop_allocation_report.rb @@ -18,47 +18,46 @@ module OpenFoodNetwork::Reports ] end - organise do - group(&:product) - sort(&:name) - - summary_row do - column { |_lis| I18n.t('admin.reports.total') } - column { |lis| product_name(lis) } - column { |lis| group_buy_unit_size_f(lis) } - column { |_lis| "" } - column { |_lis| "" } - column { |_lis| "" } - column { |_lis| "" } - column { |lis| total_amount(lis) } - column { |lis| total_available(lis) } - column { |lis| remainder(lis) } - column { |lis| max_quantity_excess(lis) } - end - - organise do - group(&:full_name) - sort { |full_name| full_name } - - organise do - group(&:order) - sort(&:to_s) - end - end + def rules + [ + { + group_by: proc { |line_item| line_item.product }, + sort_by: proc { |product| product.name }, + summary_columns: [ + proc { |_lis| I18n.t('admin.reports.total') }, + proc { |lis| product_name(lis) }, + proc { |lis| group_buy_unit_size_f(lis) }, + proc { |_lis| "" }, + proc { |_lis| "" }, + proc { |_lis| "" }, + proc { |_lis| "" }, + proc { |lis| total_amount(lis) }, + proc { |lis| total_available(lis) }, + proc { |lis| remainder(lis) }, + proc { |lis| max_quantity_excess(lis) } + ] + }, + { + group_by: proc { |line_item| line_item.order }, + sort_by: proc { |order| order.to_s } + } + ] end - columns do - column { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname } - column { |lis| lis.first.product.name } - column { |lis| lis.first.product.group_buy_unit_size || 0.0 } - column { |lis| lis.first.full_name } - column { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).value } - column { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).unit } - column { |lis| lis.first.weight_from_unit_value || 0 } - column { |lis| total_amount(lis) } - column { |_lis| "" } - column { |_lis| "" } - column { |_lis| "" } + def columns + [ + proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, + proc { |lis| lis.first.product.name }, + proc { |lis| lis.first.product.group_buy_unit_size || 0.0 }, + proc { |lis| lis.first.full_name }, + proc { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).value }, + proc { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).unit }, + proc { |lis| lis.first.weight_from_unit_value || 0 }, + proc { |lis| total_amount(lis) }, + proc { |_lis| "" }, + proc { |_lis| "" }, + proc { |_lis| "" } + ] end end end diff --git a/lib/open_food_network/reports/bulk_coop_report.rb b/lib/open_food_network/reports/bulk_coop_report.rb index 0bbefcab35..a82605d634 100644 --- a/lib/open_food_network/reports/bulk_coop_report.rb +++ b/lib/open_food_network/reports/bulk_coop_report.rb @@ -4,63 +4,61 @@ module OpenFoodNetwork::Reports class BulkCoopReport < Report private - class << self - def supplier_name(lis) - lis.first.variant.product.supplier.name - end + def supplier_name(lis) + lis.first.variant.product.supplier.name + end - def product_name(lis) - lis.first.variant.product.name - end + def product_name(lis) + lis.first.variant.product.name + end - def group_buy_unit_size(lis) - (lis.first.variant.product.group_buy_unit_size || 0.0) / - (lis.first.product.variant_unit_scale || 1) - end + def group_buy_unit_size(lis) + (lis.first.variant.product.group_buy_unit_size || 0.0) / + (lis.first.product.variant_unit_scale || 1) + end - def group_buy_unit_size_f(lis) - group_buy_unit_size(lis) - end + def group_buy_unit_size_f(lis) + group_buy_unit_size(lis) + end - def total_amount(lis) - lis.sum { |li| scaled_final_weight_volume(li) } - end + def total_amount(lis) + lis.sum { |li| scaled_final_weight_volume(li) } + end - def units_required(lis) - if group_buy_unit_size(lis).zero? - 0 - else - ( total_amount(lis) / group_buy_unit_size(lis) ).ceil - end + def units_required(lis) + if group_buy_unit_size(lis).zero? + 0 + else + ( total_amount(lis) / group_buy_unit_size(lis) ).ceil end + end - def total_available(lis) - units_required(lis) * group_buy_unit_size(lis) - end + def total_available(lis) + units_required(lis) * group_buy_unit_size(lis) + end - def remainder(lis) - remainder = total_available(lis) - total_amount(lis) - remainder >= 0 ? remainder : '' - end + def remainder(lis) + remainder = total_available(lis) - total_amount(lis) + remainder >= 0 ? remainder : '' + end - def max_quantity_excess(lis) - max_quantity_amount(lis) - total_amount(lis) - end + def max_quantity_excess(lis) + max_quantity_amount(lis) - total_amount(lis) + end - def max_quantity_amount(lis) - lis.sum do |li| - max_quantity = [li.max_quantity || 0, li.quantity || 0].max - max_quantity * scaled_unit_value(li.variant) - end + def max_quantity_amount(lis) + lis.sum do |li| + max_quantity = [li.max_quantity || 0, li.quantity || 0].max + max_quantity * scaled_unit_value(li.variant) end + end - def scaled_final_weight_volume(li) - (li.final_weight_volume || 0) / (li.product.variant_unit_scale || 1) - end + def scaled_final_weight_volume(li) + (li.final_weight_volume || 0) / (li.product.variant_unit_scale || 1) + end - def scaled_unit_value(v) - (v.unit_value || 0) / (v.product.variant_unit_scale || 1) - end + def scaled_unit_value(v) + (v.unit_value || 0) / (v.product.variant_unit_scale || 1) end end end diff --git a/lib/open_food_network/reports/bulk_coop_supplier_report.rb b/lib/open_food_network/reports/bulk_coop_supplier_report.rb index ae4ed3da37..9ed4f7e175 100644 --- a/lib/open_food_network/reports/bulk_coop_supplier_report.rb +++ b/lib/open_food_network/reports/bulk_coop_supplier_report.rb @@ -18,47 +18,45 @@ module OpenFoodNetwork::Reports ] end - organise do - group { |li| li.product.supplier } - sort(&:name) - - organise do - group(&:product) - sort(&:name) - - summary_row do - column { |lis| supplier_name(lis) } - column { |lis| product_name(lis) } - column { |lis| group_buy_unit_size_f(lis) } - column { |_lis| "" } - column { |_lis| "" } - column { |_lis| "" } - column { |_lis| "" } - column { |lis| total_amount(lis) } - column { |lis| units_required(lis) } - column { |lis| remainder(lis) } - column { |lis| max_quantity_excess(lis) } - end - - organise do - group(&:full_name) - sort { |full_name| full_name } - end - end + def rules + [ + { group_by: proc { |line_item| line_item.product.supplier }, + sort_by: proc { |supplier| supplier.name } }, + { group_by: proc { |line_item| line_item.product }, + sort_by: proc { |product| product.name }, + summary_columns: [ + proc { |lis| supplier_name(lis) }, + proc { |lis| product_name(lis) }, + proc { |lis| group_buy_unit_size_f(lis) }, + proc { |_lis| "" }, + proc { |_lis| "" }, + proc { |_lis| "" }, + proc { |_lis| "" }, + proc { |lis| total_amount(lis) }, + proc { |lis| units_required(lis) }, + proc { |lis| remainder(lis) }, + proc { |lis| max_quantity_excess(lis) } + ] + }, + { group_by: proc { |line_item| line_item.full_name }, + sort_by: proc { |full_name| full_name } } + ] end - columns do - column { |lis| supplier_name(lis) } - column { |lis| product_name(lis) } - column { |lis| group_buy_unit_size_f(lis) } - column { |lis| lis.first.full_name } - column { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).value } - column { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).unit } - column { |lis| lis.first.weight_from_unit_value || 0 } - column { |lis| total_amount(lis) } - column { |_lis| '' } - column { |_lis| '' } - column { |_lis| '' } + def columns + [ + proc { |lis| supplier_name(lis) }, + proc { |lis| product_name(lis) }, + proc { |lis| group_buy_unit_size_f(lis) }, + proc { |lis| lis.first.full_name }, + proc { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).value }, + proc { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).unit }, + proc { |lis| lis.first.weight_from_unit_value || 0 }, + proc { |lis| total_amount(lis) }, + proc { |_lis| '' }, + proc { |_lis| '' }, + proc { |_lis| '' } + ] end end end diff --git a/lib/open_food_network/reports/report.rb b/lib/open_food_network/reports/report.rb index 2933b7cec6..2c4e5900f2 100644 --- a/lib/open_food_network/reports/report.rb +++ b/lib/open_food_network/reports/report.rb @@ -31,15 +31,5 @@ module OpenFoodNetwork::Reports def self.header(*columns) self._header = columns end - - def self.columns(&block) - self._columns = Row.new - Blockenspiel.invoke block, _columns - end - - def self.organise(&block) - self._rules_head = Rule.new - Blockenspiel.invoke block, _rules_head - end end end diff --git a/lib/open_food_network/reports/row.rb b/lib/open_food_network/reports/row.rb index 01c8dd192e..35b4bffe33 100644 --- a/lib/open_food_network/reports/row.rb +++ b/lib/open_food_network/reports/row.rb @@ -1,7 +1,5 @@ module OpenFoodNetwork::Reports class Row - include Blockenspiel::DSL - def initialize @columns = [] end diff --git a/lib/open_food_network/reports/rule.rb b/lib/open_food_network/reports/rule.rb index 372c52b249..cfb8b7e67f 100644 --- a/lib/open_food_network/reports/rule.rb +++ b/lib/open_food_network/reports/rule.rb @@ -2,7 +2,6 @@ require 'open_food_network/reports/row' module OpenFoodNetwork::Reports class Rule - include Blockenspiel::DSL attr_reader :next def group(&block) @@ -13,16 +12,6 @@ module OpenFoodNetwork::Reports @sort = block end - def summary_row(&block) - @summary_row = Row.new - Blockenspiel.invoke block, @summary_row - end - - def organise(&block) - @next = Rule.new - Blockenspiel.invoke block, @next - end - def to_h h = { group_by: @group, sort_by: @sort } h[:summary_columns] = @summary_row.to_a if @summary_row diff --git a/spec/lib/open_food_network/reports/report_spec.rb b/spec/lib/open_food_network/reports/report_spec.rb index 64baf06ba6..86e76bcec5 100644 --- a/spec/lib/open_food_network/reports/report_spec.rb +++ b/spec/lib/open_food_network/reports/report_spec.rb @@ -1,98 +1,15 @@ require 'open_food_network/reports/report' module OpenFoodNetwork::Reports - P1 = proc { |o| o[:one] } - P2 = proc { |o| o[:two] } - P3 = proc { |o| o[:three] } - P4 = proc { |o| o[:four] } - class TestReport < Report header 'One', 'Two', 'Three', 'Four' - - columns do - column(&P1) - column(&P2) - column(&P3) - column(&P4) - end - - organise do - group(&P1) - sort(&P2) - - organise do - group(&P3) - sort(&P4) - - summary_row do - column(&P1) - column(&P4) - end - end - end - end - - class HelperReport < Report - columns do - column { |o| my_helper(o) } - end - - private - - def self.my_helper(o) - o[:one] - end end describe Report do let(:report) { TestReport.new } - let(:helper_report) { HelperReport.new } - let(:rules_head) { TestReport._rules_head } - let(:data) { { one: 1, two: 2, three: 3, four: 4 } } it "returns the header" do expect(report.header).to eq(%w(One Two Three Four)) end - - it "returns columns as an array of procs" do - expect(report.columns[0].call(data)).to eq(1) - expect(report.columns[1].call(data)).to eq(2) - expect(report.columns[2].call(data)).to eq(3) - expect(report.columns[3].call(data)).to eq(4) - end - - it "supports helpers when outputting columns" do - expect(helper_report.columns[0].call(data)).to eq(1) - end - - describe "rules" do - let(:group_by) { rules_head.to_h[:group_by] } - let(:sort_by) { rules_head.to_h[:sort_by] } - let(:next_group_by) { rules_head.next.to_h[:group_by] } - let(:next_sort_by) { rules_head.next.to_h[:sort_by] } - let(:next_summary_columns) { rules_head.next.to_h[:summary_columns] } - - it "constructs the head of the rules list" do - expect(group_by.call(data)).to eq(1) - expect(sort_by.call(data)).to eq(2) - end - - it "constructs nested rules" do - expect(next_group_by.call(data)).to eq(3) - expect(next_sort_by.call(data)).to eq(4) - end - - it "constructs summary columns for rules" do - expect(next_summary_columns[0].call(data)).to eq(1) - expect(next_summary_columns[1].call(data)).to eq(4) - end - end - - describe "outputting rules" do - it "outputs the rules" do - expect(report.rules).to eq([{ group_by: P1, sort_by: P2 }, - { group_by: P3, sort_by: P4, summary_columns: [P1, P4] }]) - end - end end end diff --git a/spec/lib/open_food_network/reports/rule_spec.rb b/spec/lib/open_food_network/reports/rule_spec.rb index d800f6e818..eae5b26045 100644 --- a/spec/lib/open_food_network/reports/rule_spec.rb +++ b/spec/lib/open_food_network/reports/rule_spec.rb @@ -17,23 +17,5 @@ module OpenFoodNetwork::Reports rule.sort(&proc) expect(rule.to_h).to eq(group_by: nil, sort_by: proc) end - - it "can define a nested rule" do - rule.organise(&proc) - expect(rule.next).to be_a Rule - end - - it "can define a summary row and return it in a hash" do - rule.summary_row do - column {} - column {} - column {} - end - - expect(rule.to_h[:summary_columns].count).to eq(3) - expect(rule.to_h[:summary_columns][0]).to be_a Proc - expect(rule.to_h[:summary_columns][1]).to be_a Proc - expect(rule.to_h[:summary_columns][2]).to be_a Proc - end end end From d02f64da064f5725b46730856de6c7873ac45036 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 29 May 2020 10:55:55 +0100 Subject: [PATCH 02/19] Define bulk coop report summary row and columns with lists of method names instead of Procs. --- .../spree/admin/reports_controller.rb | 2 +- lib/open_food_network/bulk_coop_report.rb | 164 ++++++++++++++++-- lib/open_food_network/order_grouper.rb | 27 ++- .../reports/bulk_coop_allocation_report.rb | 48 +++-- .../reports/bulk_coop_report.rb | 64 ------- .../reports/bulk_coop_supplier_report.rb | 48 +++-- 6 files changed, 217 insertions(+), 136 deletions(-) delete mode 100644 lib/open_food_network/reports/bulk_coop_report.rb diff --git a/app/controllers/spree/admin/reports_controller.rb b/app/controllers/spree/admin/reports_controller.rb index 9583fe7134..6fd19ae734 100644 --- a/app/controllers/spree/admin/reports_controller.rb +++ b/app/controllers/spree/admin/reports_controller.rb @@ -260,7 +260,7 @@ module Spree end def order_grouper_table - order_grouper = OpenFoodNetwork::OrderGrouper.new @report.rules, @report.columns + order_grouper = OpenFoodNetwork::OrderGrouper.new @report.rules, @report.columns, @report order_grouper.table(@report.table_items) end diff --git a/lib/open_food_network/bulk_coop_report.rb b/lib/open_food_network/bulk_coop_report.rb index 019dcddbb7..74802dbbe2 100644 --- a/lib/open_food_network/bulk_coop_report.rb +++ b/lib/open_food_network/bulk_coop_report.rb @@ -96,26 +96,32 @@ module OpenFoodNetwork when "bulk_coop_allocation" @allocation_report.columns when "bulk_coop_packing_sheets" - [proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, - proc { |lis| lis.first.product.name }, - proc { |lis| lis.first.full_name }, - proc { |lis| lis.sum(&:quantity) }] + [ + :order_billing_address_name, + :product_name, + :full_name, + :total_quantity + ] when "bulk_coop_customer_payments" - [proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, - proc { |lis| lis.first.order.completed_at.to_s }, - proc { |lis| lis.map(&:order).uniq.sum(&:total) }, - proc { |lis| lis.map(&:order).uniq.sum(&:outstanding_balance) }, - proc { |lis| lis.map(&:order).uniq.sum(&:payment_total) }] + [ + :order_billing_address_name, + :order_completed_at, + :customer_payments_total_cost, + :customer_payments_amount_owed, + :customer_payments_amount_paid + ] else - [proc { |lis| lis.first.product.supplier.name }, - proc { |lis| lis.first.product.name }, - proc { |lis| lis.first.product.group_buy_unit_size || 0.0 }, - proc { |lis| lis.first.full_name }, - proc { |lis| lis.first.weight_from_unit_value || 0 }, - proc { |lis| lis.sum(&:quantity) }, - proc { |lis| lis.sum { |li| li.max_quantity || 0 } }, - proc { |_lis| "" }, - proc { |_lis| "" }] + [ + :product_supplier_name, + :product_name, + :product_group_buy_unit_size, + :full_name, + :weight_from_unit_value, + :total_quantity, + :total_max_quantity, + :empty_cell, + :empty_cell + ] end end @@ -134,5 +140,127 @@ module OpenFoodNetwork def report_line_items @report_line_items ||= Reports::LineItems.new(order_permissions, @params) end + + def customer_payments_total_cost(line_items) + line_items.map(&:order).uniq.sum(&:total) + end + + def customer_payments_amount_owed(line_items) + line_items.map(&:order).uniq.sum(&:outstanding_balance) + end + + def customer_payments_amount_paid(line_items) + line_items.map(&:order).uniq.sum(&:payment_total) + end + + def empty_cell(line_items) + "" + end + + def full_name(line_items) + line_items.first.full_name + end + + def group_buy_unit_size(line_items) + (line_items.first.variant.product.group_buy_unit_size || 0.0) / + (line_items.first.product.variant_unit_scale || 1) + end + + def max_quantity_excess(line_items) + max_quantity_amount(line_items) - total_amount(line_items) + end + + def max_quantity_amount(line_items) + line_items.sum do |line_item| + max_quantity = [line_item.max_quantity || 0, line_item.quantity || 0].max + max_quantity * scaled_unit_value(line_item.variant) + end + end + + def option_value_value(line_items) + OpenFoodNetwork::OptionValueNamer.new(line_items.first).value + end + + def option_value_unit(line_items) + OpenFoodNetwork::OptionValueNamer.new(line_items.first).unit + end + + def order_billing_address_name(line_items) + billing_address = line_items.first.order.bill_address + billing_address.firstname + " " + billing_address.lastname + end + + def order_completed_at(line_items) + line_items.first.order.completed_at.to_s + end + + def product_group_buy_unit_size(line_items) + line_items.first.product.group_buy_unit_size || 0.0 + end + + def product_name(line_items) + line_items.first.product.name + end + + def product_supplier_name(line_items) + line_items.first.product.supplier.name + end + + def remainder(line_items) + remainder = total_available(line_items) - total_amount(line_items) + remainder >= 0 ? remainder : '' + end + + def scaled_final_weight_volume(li) + (li.final_weight_volume || 0) / (li.product.variant_unit_scale || 1) + end + + def scaled_unit_value(v) + (v.unit_value || 0) / (v.product.variant_unit_scale || 1) + end + + def total_amount(line_items) + line_items.sum { |li| scaled_final_weight_volume(li) } + end + + def total_available(line_items) + units_required(line_items) * group_buy_unit_size(line_items) + end + + def total_max_quantity(line_items) + line_items.sum { |line_item| line_item.max_quantity || 0 } + end + + def total_quantity(line_items) + line_items.sum(&:quantity) + end + + def total_label(line_items) + I18n.t('admin.reports.total') + end + + def units_required(line_items) + if group_buy_unit_size(line_items).zero? + 0 + else + ( total_amount(line_items) / group_buy_unit_size(line_items) ).ceil + end + end + + def variant_product_group_buy_unit_size_f(line_items) + group_buy_unit_size(line_items) + end + + def variant_product_name(line_items) + line_items.first.variant.product.name + end + + def variant_product_supplier_name(line_items) + line_items.first.variant.product.supplier.name + end + + def weight_from_unit_value(line_items) + line_items.first.weight_from_unit_value || 0 + end end end diff --git a/lib/open_food_network/order_grouper.rb b/lib/open_food_network/order_grouper.rb index 5b792bd5d4..b4e4861a79 100644 --- a/lib/open_food_network/order_grouper.rb +++ b/lib/open_food_network/order_grouper.rb @@ -1,8 +1,9 @@ module OpenFoodNetwork class OrderGrouper - def initialize(rules, column_constructors) + def initialize(rules, column_constructors, report=nil) @rules = rules @column_constructors = column_constructors + @report = report end def build_tree(items, remaining_rules) @@ -38,11 +39,11 @@ module OpenFoodNetwork def build_table(groups) rows = [] if is_leaf_node(groups) - rows << @column_constructors.map { |column_constructor| column_constructor.call(groups) } + rows << build_row(groups) else groups.each do |key, group| if key == :summary_row - rows << group[:columns].map { |cols| cols.call(group[:items]) } + rows << build_summary_row(group[:columns], group[:items]) else build_table(group).each { |g| rows << g } end @@ -59,6 +60,26 @@ module OpenFoodNetwork private + def build_cell(column_constructor, items) + if column_constructor.is_a?(Symbol) + @report.send(column_constructor, items) + else + column_constructor.call(items) + end + end + + def build_row(groups) + @column_constructors.map do |column_constructor| + build_cell(column_constructor, groups) + end + end + + def build_summary_row(summary_row_column_constructors, items) + summary_row_column_constructors.map do |summary_row_column_constructor| + build_cell(summary_row_column_constructor, items) + end + end + def is_leaf_node(node) node.is_a? Array end diff --git a/lib/open_food_network/reports/bulk_coop_allocation_report.rb b/lib/open_food_network/reports/bulk_coop_allocation_report.rb index c8b05c30a0..316648dbf6 100644 --- a/lib/open_food_network/reports/bulk_coop_allocation_report.rb +++ b/lib/open_food_network/reports/bulk_coop_allocation_report.rb @@ -1,7 +1,5 @@ -require 'open_food_network/reports/bulk_coop_report' - module OpenFoodNetwork::Reports - class BulkCoopAllocationReport < BulkCoopReport + class BulkCoopAllocationReport def header [ I18n.t(:report_header_customer), @@ -24,17 +22,17 @@ module OpenFoodNetwork::Reports group_by: proc { |line_item| line_item.product }, sort_by: proc { |product| product.name }, summary_columns: [ - proc { |_lis| I18n.t('admin.reports.total') }, - proc { |lis| product_name(lis) }, - proc { |lis| group_buy_unit_size_f(lis) }, - proc { |_lis| "" }, - proc { |_lis| "" }, - proc { |_lis| "" }, - proc { |_lis| "" }, - proc { |lis| total_amount(lis) }, - proc { |lis| total_available(lis) }, - proc { |lis| remainder(lis) }, - proc { |lis| max_quantity_excess(lis) } + :total_label, + :variant_product_name, + :variant_product_group_buy_unit_size_f, + :empty_cell, + :empty_cell, + :empty_cell, + :empty_cell, + :total_amount, + :total_available, + :remainder, + :max_quantity_excess ] }, { @@ -46,17 +44,17 @@ module OpenFoodNetwork::Reports def columns [ - proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, - proc { |lis| lis.first.product.name }, - proc { |lis| lis.first.product.group_buy_unit_size || 0.0 }, - proc { |lis| lis.first.full_name }, - proc { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).value }, - proc { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).unit }, - proc { |lis| lis.first.weight_from_unit_value || 0 }, - proc { |lis| total_amount(lis) }, - proc { |_lis| "" }, - proc { |_lis| "" }, - proc { |_lis| "" } + :order_billing_address_name, + :product_name, + :product_group_buy_unit_size, + :full_name, + :option_value_value, + :option_value_unit, + :weight_from_unit_value, + :total_amount, + :empty_cell, + :empty_cell, + :empty_cell ] end end diff --git a/lib/open_food_network/reports/bulk_coop_report.rb b/lib/open_food_network/reports/bulk_coop_report.rb deleted file mode 100644 index a82605d634..0000000000 --- a/lib/open_food_network/reports/bulk_coop_report.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'open_food_network/reports/report' - -module OpenFoodNetwork::Reports - class BulkCoopReport < Report - private - - def supplier_name(lis) - lis.first.variant.product.supplier.name - end - - def product_name(lis) - lis.first.variant.product.name - end - - def group_buy_unit_size(lis) - (lis.first.variant.product.group_buy_unit_size || 0.0) / - (lis.first.product.variant_unit_scale || 1) - end - - def group_buy_unit_size_f(lis) - group_buy_unit_size(lis) - end - - def total_amount(lis) - lis.sum { |li| scaled_final_weight_volume(li) } - end - - def units_required(lis) - if group_buy_unit_size(lis).zero? - 0 - else - ( total_amount(lis) / group_buy_unit_size(lis) ).ceil - end - end - - def total_available(lis) - units_required(lis) * group_buy_unit_size(lis) - end - - def remainder(lis) - remainder = total_available(lis) - total_amount(lis) - remainder >= 0 ? remainder : '' - end - - def max_quantity_excess(lis) - max_quantity_amount(lis) - total_amount(lis) - end - - def max_quantity_amount(lis) - lis.sum do |li| - max_quantity = [li.max_quantity || 0, li.quantity || 0].max - max_quantity * scaled_unit_value(li.variant) - end - end - - def scaled_final_weight_volume(li) - (li.final_weight_volume || 0) / (li.product.variant_unit_scale || 1) - end - - def scaled_unit_value(v) - (v.unit_value || 0) / (v.product.variant_unit_scale || 1) - end - end -end diff --git a/lib/open_food_network/reports/bulk_coop_supplier_report.rb b/lib/open_food_network/reports/bulk_coop_supplier_report.rb index 9ed4f7e175..0c1c86e3b2 100644 --- a/lib/open_food_network/reports/bulk_coop_supplier_report.rb +++ b/lib/open_food_network/reports/bulk_coop_supplier_report.rb @@ -1,7 +1,5 @@ -require 'open_food_network/reports/bulk_coop_report' - module OpenFoodNetwork::Reports - class BulkCoopSupplierReport < BulkCoopReport + class BulkCoopSupplierReport def header [ I18n.t(:report_header_supplier), @@ -25,17 +23,17 @@ module OpenFoodNetwork::Reports { group_by: proc { |line_item| line_item.product }, sort_by: proc { |product| product.name }, summary_columns: [ - proc { |lis| supplier_name(lis) }, - proc { |lis| product_name(lis) }, - proc { |lis| group_buy_unit_size_f(lis) }, - proc { |_lis| "" }, - proc { |_lis| "" }, - proc { |_lis| "" }, - proc { |_lis| "" }, - proc { |lis| total_amount(lis) }, - proc { |lis| units_required(lis) }, - proc { |lis| remainder(lis) }, - proc { |lis| max_quantity_excess(lis) } + :variant_product_supplier_name, + :variant_product_name, + :variant_product_group_buy_unit_size_f, + :empty_cell, + :empty_cell, + :empty_cell, + :empty_cell, + :total_amount, + :units_required, + :remainder, + :max_quantity_excess ] }, { group_by: proc { |line_item| line_item.full_name }, @@ -45,17 +43,17 @@ module OpenFoodNetwork::Reports def columns [ - proc { |lis| supplier_name(lis) }, - proc { |lis| product_name(lis) }, - proc { |lis| group_buy_unit_size_f(lis) }, - proc { |lis| lis.first.full_name }, - proc { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).value }, - proc { |lis| OpenFoodNetwork::OptionValueNamer.new(lis.first).unit }, - proc { |lis| lis.first.weight_from_unit_value || 0 }, - proc { |lis| total_amount(lis) }, - proc { |_lis| '' }, - proc { |_lis| '' }, - proc { |_lis| '' } + :variant_product_supplier_name, + :variant_product_name, + :variant_product_group_buy_unit_size_f, + :full_name, + :option_value_value, + :option_value_unit, + :weight_from_unit_value, + :total_amount, + :empty_cell, + :empty_cell, + :empty_cell ] end end From d436d18d19c0233093995b82b508451d394d09fd Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 5 Jun 2020 10:13:06 +0100 Subject: [PATCH 03/19] Fix code climate violations in removal of Blockenspiel dependency. --- lib/open_food_network/bulk_coop_report.rb | 12 ++++++------ lib/open_food_network/order_grouper.rb | 4 ++-- .../reports/bulk_coop_allocation_report.rb | 2 ++ 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/open_food_network/bulk_coop_report.rb b/lib/open_food_network/bulk_coop_report.rb index 74802dbbe2..9eb8cf07c6 100644 --- a/lib/open_food_network/bulk_coop_report.rb +++ b/lib/open_food_network/bulk_coop_report.rb @@ -153,7 +153,7 @@ module OpenFoodNetwork line_items.map(&:order).uniq.sum(&:payment_total) end - def empty_cell(line_items) + def empty_cell(*) "" end @@ -211,12 +211,12 @@ module OpenFoodNetwork remainder >= 0 ? remainder : '' end - def scaled_final_weight_volume(li) - (li.final_weight_volume || 0) / (li.product.variant_unit_scale || 1) + def scaled_final_weight_volume(line_item) + (line_item.final_weight_volume || 0) / (line_item.product.variant_unit_scale || 1) end - def scaled_unit_value(v) - (v.unit_value || 0) / (v.product.variant_unit_scale || 1) + def scaled_unit_value(variant) + (variant.unit_value || 0) / (variant.product.variant_unit_scale || 1) end def total_amount(line_items) @@ -235,7 +235,7 @@ module OpenFoodNetwork line_items.sum(&:quantity) end - def total_label(line_items) + def total_label(*) I18n.t('admin.reports.total') end diff --git a/lib/open_food_network/order_grouper.rb b/lib/open_food_network/order_grouper.rb index b4e4861a79..8d810254d5 100644 --- a/lib/open_food_network/order_grouper.rb +++ b/lib/open_food_network/order_grouper.rb @@ -1,6 +1,6 @@ module OpenFoodNetwork class OrderGrouper - def initialize(rules, column_constructors, report=nil) + def initialize(rules, column_constructors, report = nil) @rules = rules @column_constructors = column_constructors @report = report @@ -62,7 +62,7 @@ module OpenFoodNetwork def build_cell(column_constructor, items) if column_constructor.is_a?(Symbol) - @report.send(column_constructor, items) + @report.__send__(column_constructor, items) else column_constructor.call(items) end diff --git a/lib/open_food_network/reports/bulk_coop_allocation_report.rb b/lib/open_food_network/reports/bulk_coop_allocation_report.rb index 316648dbf6..bcc068c0c5 100644 --- a/lib/open_food_network/reports/bulk_coop_allocation_report.rb +++ b/lib/open_food_network/reports/bulk_coop_allocation_report.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module OpenFoodNetwork::Reports class BulkCoopAllocationReport def header From 406309c577d7fe702bd79701d544cca38ab172da Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 5 Jun 2020 16:43:38 +0100 Subject: [PATCH 04/19] Move BulkCoop reports out of deprecated lib/ directory into OrderManagement engine. The BulkCoop reports are not generated the same way as the EnterpriseFeeSummary report is generated yet so that may need to be updated. --- .../spree/admin/reports_controller.rb | 8 +- .../spree/admin/reports/bulk_coop.html.haml | 19 -- .../reports/bulk_coop_controller.rb | 64 ++++ .../reports/bulk_coop/authorizer.rb | 16 + .../bulk_coop/bulk_coop_allocation_report.rb | 67 +++++ .../reports/bulk_coop/bulk_coop_report.rb | 275 ++++++++++++++++++ .../bulk_coop/bulk_coop_supplier_report.rb | 64 ++++ .../reports/bulk_coop/parameters.rb | 55 ++++ .../reports/bulk_coop/permissions.rb | 11 + .../bulk_coop/renderers/csv_renderer.rb | 30 ++ .../bulk_coop/renderers/html_renderer.rb | 22 ++ .../reports/bulk_coop/report_service.rb | 27 ++ .../enterprise_fee_summary/authorizer.rb | 13 - .../app/services/reports/authorizer.rb | 15 + .../reports/bulk_coop/_filters.html.haml | 31 ++ .../reports/bulk_coop/_report.html.haml | 20 ++ .../reports/bulk_coop/create.html.haml | 2 + .../reports/bulk_coop/new.html.haml | 1 + engines/order_management/config/routes.rb | 1 + lib/open_food_network/bulk_coop_report.rb | 266 ----------------- .../reports/bulk_coop_allocation_report.rb | 63 ---- .../reports/bulk_coop_supplier_report.rb | 60 ---- 22 files changed, 707 insertions(+), 423 deletions(-) delete mode 100644 app/views/spree/admin/reports/bulk_coop.html.haml create mode 100644 engines/order_management/app/controllers/order_management/reports/bulk_coop_controller.rb create mode 100644 engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb create mode 100644 engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_allocation_report.rb create mode 100644 engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb create mode 100644 engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_supplier_report.rb create mode 100644 engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb create mode 100644 engines/order_management/app/services/order_management/reports/bulk_coop/permissions.rb create mode 100644 engines/order_management/app/services/order_management/reports/bulk_coop/renderers/csv_renderer.rb create mode 100644 engines/order_management/app/services/order_management/reports/bulk_coop/renderers/html_renderer.rb create mode 100644 engines/order_management/app/services/order_management/reports/bulk_coop/report_service.rb create mode 100644 engines/order_management/app/views/order_management/reports/bulk_coop/_filters.html.haml create mode 100644 engines/order_management/app/views/order_management/reports/bulk_coop/_report.html.haml create mode 100644 engines/order_management/app/views/order_management/reports/bulk_coop/create.html.haml create mode 100644 engines/order_management/app/views/order_management/reports/bulk_coop/new.html.haml delete mode 100644 lib/open_food_network/bulk_coop_report.rb delete mode 100644 lib/open_food_network/reports/bulk_coop_allocation_report.rb delete mode 100644 lib/open_food_network/reports/bulk_coop_supplier_report.rb diff --git a/app/controllers/spree/admin/reports_controller.rb b/app/controllers/spree/admin/reports_controller.rb index 6fd19ae734..ce3ec90c57 100644 --- a/app/controllers/spree/admin/reports_controller.rb +++ b/app/controllers/spree/admin/reports_controller.rb @@ -12,7 +12,6 @@ require 'open_food_network/order_cycle_management_report' require 'open_food_network/packing_report' require 'open_food_network/sales_tax_report' require 'open_food_network/xero_invoices_report' -require 'open_food_network/bulk_coop_report' require 'open_food_network/payments_report' require 'open_food_network/orders_and_fulfillments_report' @@ -21,6 +20,11 @@ module Spree class ReportsController < Spree::Admin::BaseController include Spree::ReportsHelper + ORDER_MANAGEMENT_ENGINE_REPORTS = [ + :bulk_coop, + :enterprise_fee_summary + ] + helper_method :render_content? before_filter :cache_search_state @@ -309,7 +313,7 @@ module Spree # List of reports that have been moved to the Order Management engine def report_in_order_management_engine?(report) - report == :enterprise_fee_summary + ORDER_MANAGEMENT_ENGINE_REPORTS.include?(report) end def timestamp diff --git a/app/views/spree/admin/reports/bulk_coop.html.haml b/app/views/spree/admin/reports/bulk_coop.html.haml deleted file mode 100644 index c644e8dd6e..0000000000 --- a/app/views/spree/admin/reports/bulk_coop.html.haml +++ /dev/null @@ -1,19 +0,0 @@ -= form_for @report.search, :url => spree.bulk_coop_admin_reports_path do |f| - = render 'date_range_form', f: f - - .row - .four.columns.alpha - = label_tag nil, t(:report_distributor) - = f.collection_select(:distributor_id_eq, @distributors, :id, :name, {:include_blank => t(:all)}, {:class => "select2 fullwidth"}) - = label_tag nil, t(:report_type) - %br - = select_tag(:report_type, options_for_select([:bulk_coop_supplier_report, :bulk_coop_allocation, :bulk_coop_packing_sheets, :bulk_coop_customer_payments].map{ |e| [t(".#{e}"), e] }, @report_type)) - %br - %br - = check_box_tag :csv - = label_tag :csv, t(:report_customers_csv) - %br - %br - = button t(:search) - -= render "table", id: "listing_orders", msg_option: t(:search) diff --git a/engines/order_management/app/controllers/order_management/reports/bulk_coop_controller.rb b/engines/order_management/app/controllers/order_management/reports/bulk_coop_controller.rb new file mode 100644 index 0000000000..26397e40bf --- /dev/null +++ b/engines/order_management/app/controllers/order_management/reports/bulk_coop_controller.rb @@ -0,0 +1,64 @@ +module OrderManagement + module Reports + class BulkCoopController < Spree::Admin::BaseController + before_filter :load_report_parameters + before_filter :load_permissions + + def new; end + + def create + return respond_to_invalid_parameters unless @report_parameters.valid? + + @report_parameters.authorize!(@permissions) + + @report = report_klass::ReportService.new(@permissions, params[:report], spree_current_user) + renderer.render(self) + rescue ::Reports::Authorizer::ParameterNotAllowedError => e + flash[:error] = e.message + render_report_form + end + + private + + def respond_to_invalid_parameters + flash[:error] = I18n.t("invalid_filter_parameters", scope: i18n_scope) + render_report_form + end + + def i18n_scope + "order_management.reports.enterprise_fee_summary" + end + + def render_report_form + render action: :new + end + + def report_klass + OrderManagement::Reports::BulkCoop + end + + def load_report_parameters + @report_parameters = report_klass::Parameters.new(params[:report] || {}) + end + + def load_permissions + @permissions = report_klass::Permissions.new(spree_current_user) + end + + def report_renderer_klass + case params[:report_format] + when "csv" + report_klass::Renderers::CsvRenderer + when nil, "", "html" + report_klass::Renderers::HtmlRenderer + else + raise Reports::UnsupportedReportFormatException + end + end + + def renderer + @renderer ||= report_renderer_klass.new(@report) + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb new file mode 100644 index 0000000000..39562e6da2 --- /dev/null +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb @@ -0,0 +1,16 @@ +module OrderManagement + module Reports + module BulkCoop + class Authorizer < ::Reports::Authorizer + def self.parameter_not_allowed_error_message + i18n_scope = "order_management.reports.enterprise_fee_summary" + I18n.t("parameter_not_allowed_error", scope: i18n_scope) + end + + def authorize! + require_ids_allowed(parameters.distributor_ids, permissions.allowed_distributors) + end + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_allocation_report.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_allocation_report.rb new file mode 100644 index 0000000000..9513f51e9b --- /dev/null +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_allocation_report.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +module OrderManagement + module Reports + module BulkCoop + class BulkCoopAllocationReport + def header + [ + I18n.t(:report_header_customer), + I18n.t(:report_header_product), + I18n.t(:report_header_bulk_unit_size), + I18n.t(:report_header_variant), + I18n.t(:report_header_variant_value), + I18n.t(:report_header_variant_unit), + I18n.t(:report_header_weight), + I18n.t(:report_header_sum_total), + I18n.t(:report_header_total_available), + I18n.t(:report_header_unallocated), + I18n.t(:report_header_max_quantity_excess), + ] + end + + def rules + [ + { + group_by: proc { |line_item| line_item.product }, + sort_by: proc { |product| product.name }, + summary_columns: [ + :total_label, + :variant_product_name, + :variant_product_group_buy_unit_size_f, + :empty_cell, + :empty_cell, + :empty_cell, + :empty_cell, + :total_amount, + :total_available, + :remainder, + :max_quantity_excess + ] + }, + { + group_by: proc { |line_item| line_item.order }, + sort_by: proc { |order| order.to_s } + } + ] + end + + def columns + [ + :order_billing_address_name, + :product_name, + :product_group_buy_unit_size, + :full_name, + :option_value_value, + :option_value_unit, + :weight_from_unit_value, + :total_amount, + :empty_cell, + :empty_cell, + :empty_cell + ] + end + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb new file mode 100644 index 0000000000..3d776c31f5 --- /dev/null +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb @@ -0,0 +1,275 @@ +require "open_food_network/reports/line_items" + +module OrderManagement + module Reports + module BulkCoop + class BulkCoopReport + REPORT_TYPES = [ + :bulk_coop_supplier_report, + :bulk_coop_allocation, + :bulk_coop_packing_sheets, + :bulk_coop_customer_payments + ] + + attr_reader :params + def initialize(user, params = {}, render_table = false) + @params = params + @user = user + @render_table = render_table + + @supplier_report = BulkCoopSupplierReport.new + @allocation_report = BulkCoopAllocationReport.new + end + + def header + case params[:report_type] + when "bulk_coop_supplier_report" + @supplier_report.header + when "bulk_coop_allocation" + @allocation_report.header + when "bulk_coop_packing_sheets" + [I18n.t(:report_header_customer), + I18n.t(:report_header_product), + I18n.t(:report_header_variant), + I18n.t(:report_header_sum_total)] + when "bulk_coop_customer_payments" + [I18n.t(:report_header_customer), + I18n.t(:report_header_date_of_order), + I18n.t(:report_header_total_cost), + I18n.t(:report_header_amount_owing), + I18n.t(:report_header_amount_paid)] + else + [I18n.t(:report_header_supplier), + I18n.t(:report_header_product), + I18n.t(:report_header_product), + I18n.t(:report_header_bulk_unit_size), + I18n.t(:report_header_variant), + I18n.t(:report_header_weight), + I18n.t(:report_header_sum_total), + I18n.t(:report_header_sum_max_total), + I18n.t(:report_header_units_required), + I18n.t(:report_header_remainder)] + end + end + + def search + report_line_items.orders + end + + def table_items + return [] unless @render_table + report_line_items.list(line_item_includes) + end + + def rules + case params[:report_type] + when "bulk_coop_supplier_report" + @supplier_report.rules + when "bulk_coop_allocation" + @allocation_report.rules + when "bulk_coop_packing_sheets" + [{ group_by: proc { |li| li.product }, + sort_by: proc { |product| product.name } }, + { group_by: proc { |li| li.full_name }, + sort_by: proc { |full_name| full_name } }, + { group_by: proc { |li| li.order }, + sort_by: proc { |order| order.to_s } }] + when "bulk_coop_customer_payments" + [{ group_by: proc { |li| li.order }, + sort_by: proc { |order| order.completed_at } }] + else + [{ group_by: proc { |li| li.product.supplier }, + sort_by: proc { |supplier| supplier.name } }, + { group_by: proc { |li| li.product }, + sort_by: proc { |product| product.name }, + summary_columns: [proc { |lis| lis.first.product.supplier.name }, + proc { |lis| lis.first.product.name }, + proc { |lis| lis.first.product.group_buy_unit_size || 0.0 }, + proc { |_lis| "" }, + proc { |_lis| "" }, + proc { |lis| lis.sum { |li| li.quantity * (li.weight_from_unit_value || 0) } }, + proc { |lis| lis.sum { |li| (li.max_quantity || 0) * (li.weight_from_unit_value || 0) } }, + proc { |lis| ( (lis.first.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| [li.max_quantity || 0, li.quantity || 0].max * (li.weight_from_unit_value || 0) } / lis.first.product.group_buy_unit_size ) ).floor }, + proc { |lis| lis.sum { |li| [li.max_quantity || 0, li.quantity || 0].max * (li.weight_from_unit_value || 0) } - ( ( (lis.first.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| [li.max_quantity || 0, li.quantity || 0].max * (li.weight_from_unit_value || 0) } / lis.first.product.group_buy_unit_size ) ).floor * (lis.first.product.group_buy_unit_size || 0) ) }] }, + { group_by: proc { |li| li.full_name }, + sort_by: proc { |full_name| full_name } }] + end + end + + def columns + case params[:report_type] + when "bulk_coop_supplier_report" + @supplier_report.columns + when "bulk_coop_allocation" + @allocation_report.columns + when "bulk_coop_packing_sheets" + [ + :order_billing_address_name, + :product_name, + :full_name, + :total_quantity + ] + when "bulk_coop_customer_payments" + [ + :order_billing_address_name, + :order_completed_at, + :customer_payments_total_cost, + :customer_payments_amount_owed, + :customer_payments_amount_paid + ] + else + [ + :product_supplier_name, + :product_name, + :product_group_buy_unit_size, + :full_name, + :weight_from_unit_value, + :total_quantity, + :total_max_quantity, + :empty_cell, + :empty_cell + ] + end + end + + private + + def line_item_includes + [{ order: [:bill_address], + variant: [{ option_values: :option_type }, { product: :supplier }] }] + end + + def order_permissions + return @order_permissions unless @order_permissions.nil? + @order_permissions = ::Permissions::Order.new(@user, @params[:q]) + end + + def report_line_items + @report_line_items ||= OpenFoodNetwork::Reports::LineItems.new(order_permissions, @params) + end + + def customer_payments_total_cost(line_items) + line_items.map(&:order).uniq.sum(&:total) + end + + def customer_payments_amount_owed(line_items) + line_items.map(&:order).uniq.sum(&:outstanding_balance) + end + + def customer_payments_amount_paid(line_items) + line_items.map(&:order).uniq.sum(&:payment_total) + end + + def empty_cell(*) + "" + end + + def full_name(line_items) + line_items.first.full_name + end + + def group_buy_unit_size(line_items) + (line_items.first.variant.product.group_buy_unit_size || 0.0) / + (line_items.first.product.variant_unit_scale || 1) + end + + def max_quantity_excess(line_items) + max_quantity_amount(line_items) - total_amount(line_items) + end + + def max_quantity_amount(line_items) + line_items.sum do |line_item| + max_quantity = [line_item.max_quantity || 0, line_item.quantity || 0].max + max_quantity * scaled_unit_value(line_item.variant) + end + end + + def option_value_value(line_items) + OpenFoodNetwork::OptionValueNamer.new(line_items.first).value + end + + def option_value_unit(line_items) + OpenFoodNetwork::OptionValueNamer.new(line_items.first).unit + end + + def order_billing_address_name(line_items) + billing_address = line_items.first.order.bill_address + billing_address.firstname + " " + billing_address.lastname + end + + def order_completed_at(line_items) + line_items.first.order.completed_at.to_s + end + + def product_group_buy_unit_size(line_items) + line_items.first.product.group_buy_unit_size || 0.0 + end + + def product_name(line_items) + line_items.first.product.name + end + + def product_supplier_name(line_items) + line_items.first.product.supplier.name + end + + def remainder(line_items) + remainder = total_available(line_items) - total_amount(line_items) + remainder >= 0 ? remainder : '' + end + + def scaled_final_weight_volume(line_item) + (line_item.final_weight_volume || 0) / (line_item.product.variant_unit_scale || 1) + end + + def scaled_unit_value(variant) + (variant.unit_value || 0) / (variant.product.variant_unit_scale || 1) + end + + def total_amount(line_items) + line_items.sum { |li| scaled_final_weight_volume(li) } + end + + def total_available(line_items) + units_required(line_items) * group_buy_unit_size(line_items) + end + + def total_max_quantity(line_items) + line_items.sum { |line_item| line_item.max_quantity || 0 } + end + + def total_quantity(line_items) + line_items.sum(&:quantity) + end + + def total_label(*) + I18n.t('admin.reports.total') + end + + def units_required(line_items) + if group_buy_unit_size(line_items).zero? + 0 + else + ( total_amount(line_items) / group_buy_unit_size(line_items) ).ceil + end + end + + def variant_product_group_buy_unit_size_f(line_items) + group_buy_unit_size(line_items) + end + + def variant_product_name(line_items) + line_items.first.variant.product.name + end + + def variant_product_supplier_name(line_items) + line_items.first.variant.product.supplier.name + end + + def weight_from_unit_value(line_items) + line_items.first.weight_from_unit_value || 0 + end + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_supplier_report.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_supplier_report.rb new file mode 100644 index 0000000000..076a0a63c9 --- /dev/null +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_supplier_report.rb @@ -0,0 +1,64 @@ +module OrderManagement + module Reports + module BulkCoop + class BulkCoopSupplierReport + def header + [ + I18n.t(:report_header_supplier), + I18n.t(:report_header_product), + I18n.t(:report_header_bulk_unit_size), + I18n.t(:report_header_variant), + I18n.t(:report_header_variant_value), + I18n.t(:report_header_variant_unit), + I18n.t(:report_header_weight), + I18n.t(:report_header_sum_total), + I18n.t(:report_header_units_required), + I18n.t(:report_header_unallocated), + I18n.t(:report_header_max_quantity_excess), + ] + end + + def rules + [ + { group_by: proc { |line_item| line_item.product.supplier }, + sort_by: proc { |supplier| supplier.name } }, + { group_by: proc { |line_item| line_item.product }, + sort_by: proc { |product| product.name }, + summary_columns: [ + :variant_product_supplier_name, + :variant_product_name, + :variant_product_group_buy_unit_size_f, + :empty_cell, + :empty_cell, + :empty_cell, + :empty_cell, + :total_amount, + :units_required, + :remainder, + :max_quantity_excess + ] + }, + { group_by: proc { |line_item| line_item.full_name }, + sort_by: proc { |full_name| full_name } } + ] + end + + def columns + [ + :variant_product_supplier_name, + :variant_product_name, + :variant_product_group_buy_unit_size_f, + :full_name, + :option_value_value, + :option_value_unit, + :weight_from_unit_value, + :total_amount, + :empty_cell, + :empty_cell, + :empty_cell + ] + end + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb new file mode 100644 index 0000000000..16ed31a744 --- /dev/null +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb @@ -0,0 +1,55 @@ +module OrderManagement + module Reports + module BulkCoop + class Parameters < ::Reports::Parameters::Base + extend ActiveModel::Naming + extend ActiveModel::Translation + include ActiveModel::Validations + + attr_accessor :start_at, :end_at, :distributor_ids, :report_type + + before_validation :cleanup_arrays + + validates :start_at, :end_at, date_time_string: true + validates :distributor_ids, integer_array: true + validates_inclusion_of :report_type, in: OrderManagement::Reports::BulkCoop::BulkCoopReport::REPORT_TYPES.map(&:to_s) + + validate :require_valid_datetime_range + + def self.date_end_before_start_error_message + i18n_scope = "order_management.reports.enterprise_fee_summary" + I18n.t("date_end_before_start_error", scope: i18n_scope) + end + + def initialize(attributes = {}) + self.distributor_ids = [] + + super(attributes) + end + + def authorize!(permissions) + authorizer = Authorizer.new(self, permissions) + authorizer.authorize! + end + + protected + + def require_valid_datetime_range + return if start_at.blank? || end_at.blank? + + error_message = self.class.date_end_before_start_error_message + errors.add(:end_at, error_message) unless start_at < end_at + end + + # Remove the blank strings that Rails multiple selects add by default to + # make sure that blank lists are still submitted to the server as arrays + # instead of nil. + # + # https://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html#method-i-select + def cleanup_arrays + distributor_ids.reject!(&:blank?) + end + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/permissions.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/permissions.rb new file mode 100644 index 0000000000..23eb0aaca0 --- /dev/null +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/permissions.rb @@ -0,0 +1,11 @@ +module OrderManagement + module Reports + module BulkCoop + class Permissions < ::Reports::Permissions + def allowed_distributors + @allowed_distributors ||= Enterprise.is_distributor.managed_by(user) + end + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/csv_renderer.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/csv_renderer.rb new file mode 100644 index 0000000000..ca19e0a873 --- /dev/null +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/csv_renderer.rb @@ -0,0 +1,30 @@ +module OrderManagement + module Reports + module BulkCoop + module Renderers + class CsvRenderer < ::Reports::Renderers::Base + def render(context) + context.send_data(generate, filename: filename) + end + + def generate + CSV.generate do |csv| + csv << report_data.header + + report_data.list.each do |data| + csv << data + end + end + end + + private + + def filename + timestamp = Time.zone.now.strftime("%Y%m%d") + "#{report_data.parameters[:report_type]}_#{timestamp}.csv" + end + end + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/html_renderer.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/html_renderer.rb new file mode 100644 index 0000000000..edbda863e1 --- /dev/null +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/html_renderer.rb @@ -0,0 +1,22 @@ +module OrderManagement + module Reports + module BulkCoop + module Renderers + class HtmlRenderer < ::Reports::Renderers::Base + def render(context) + context.instance_variable_set :@renderer, self + context.render(action: :create, renderer: self) + end + + def header + report_data.header + end + + def data_rows + report_data.list + end + end + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/report_service.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/report_service.rb new file mode 100644 index 0000000000..c74e40934e --- /dev/null +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/report_service.rb @@ -0,0 +1,27 @@ +require 'open_food_network/order_grouper' + +module OrderManagement + module Reports + module BulkCoop + class ReportService + attr_accessor :permissions, :parameters, :user + + def initialize(permissions, parameters, user) + @permissions = permissions + @parameters = parameters + @user = user + @report = BulkCoopReport.new(user, parameters, true) + end + + def header + @report.header + end + + def list + order_grouper = OpenFoodNetwork::OrderGrouper.new @report.rules, @report.columns, @report + order_grouper.table(@report.table_items) + end + end + end + end +end diff --git a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/authorizer.rb b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/authorizer.rb index e129905dc6..51b1393630 100644 --- a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/authorizer.rb +++ b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/authorizer.rb @@ -2,11 +2,6 @@ module OrderManagement module Reports module EnterpriseFeeSummary class Authorizer < ::Reports::Authorizer - def self.parameter_not_allowed_error_message - i18n_scope = "order_management.reports.enterprise_fee_summary" - I18n.t("parameter_not_allowed_error", scope: i18n_scope) - end - def authorize! authorize_by_distribution! authorize_by_fee! @@ -25,14 +20,6 @@ module OrderManagement require_ids_allowed(parameters.shipping_method_ids, permissions.allowed_shipping_methods) require_ids_allowed(parameters.payment_method_ids, permissions.allowed_payment_methods) end - - def require_ids_allowed(array, allowed_objects) - error_klass = ::Reports::Authorizer::ParameterNotAllowedError - error_message = self.class.parameter_not_allowed_error_message - ids_allowed = (array - allowed_objects.map(&:id).map(&:to_s)).blank? - - raise error_klass, error_message unless ids_allowed - end end end end diff --git a/engines/order_management/app/services/reports/authorizer.rb b/engines/order_management/app/services/reports/authorizer.rb index 279952249a..5871e7e395 100644 --- a/engines/order_management/app/services/reports/authorizer.rb +++ b/engines/order_management/app/services/reports/authorizer.rb @@ -8,5 +8,20 @@ module Reports @parameters = parameters @permissions = permissions end + + def self.parameter_not_allowed_error_message + i18n_scope = "order_management.reports.shared" + I18n.t("parameter_not_allowed_error", scope: i18n_scope) + end + + private + + def require_ids_allowed(array, allowed_objects) + error_klass = ::Reports::Authorizer::ParameterNotAllowedError + error_message = self.class.parameter_not_allowed_error_message + ids_allowed = (array - allowed_objects.map(&:id).map(&:to_s)).blank? + + raise error_klass, error_message unless ids_allowed + end end end diff --git a/engines/order_management/app/views/order_management/reports/bulk_coop/_filters.html.haml b/engines/order_management/app/views/order_management/reports/bulk_coop/_filters.html.haml new file mode 100644 index 0000000000..012d910070 --- /dev/null +++ b/engines/order_management/app/views/order_management/reports/bulk_coop/_filters.html.haml @@ -0,0 +1,31 @@ += form_for @report_parameters, as: :report, url: main_app.order_management_reports_bulk_coop_path, method: :post do |f| + .row.date-range-filter + .sixteen.columns.alpha + = label_tag nil, t(".date_range") + %br + + = f.label :start_at, class: "inline" + = f.text_field :start_at, class: "datetimepicker datepicker-from" + + %span.range-divider + %i.icon-arrow-right + + = f.text_field :end_at, class: "datetimepicker datepicker-to" + = f.label :end_at, class: "inline" + + .row + .sixteen.columns.alpha + = f.label :distributor_ids + = f.collection_select(:distributor_ids, @permissions.allowed_distributors, :id, :name, {}, {class: "select2 fullwidth", multiple: true}) + + .row + .sixteen.columns.alpha + = f.label :report_type + = f.collection_select(:report_type, OrderManagement::Reports::BulkCoop::BulkCoopReport::REPORT_TYPES.map { |report_type| [t(".#{report_type}"), report_type] }, :last, :first, {}, {class: "select2 fullwidth", multiple: false}) + + .row + .sixteen.columns.alpha + = check_box_tag :report_format, "csv", false, id: "report_format_csv" + = label_tag :report_format_csv, t(".report_format_csv") + + = button t(".generate_report") diff --git a/engines/order_management/app/views/order_management/reports/bulk_coop/_report.html.haml b/engines/order_management/app/views/order_management/reports/bulk_coop/_report.html.haml new file mode 100644 index 0000000000..c4e2e5fc76 --- /dev/null +++ b/engines/order_management/app/views/order_management/reports/bulk_coop/_report.html.haml @@ -0,0 +1,20 @@ +- if @report.present? + %table#bulk_coop_report.report__table + %thead + %tr + - @renderer.header.each do |heading| + %th= heading + + %tbody + - @renderer.data_rows.each do |row| + %tr + - row.each do |cell_value| + %td= cell_value + + - if @renderer.data_rows.empty? + %tr + %td{colspan: @renderer.header.length}= t('.none') +- else + %p.report__message + = t(".select_and_search") + diff --git a/engines/order_management/app/views/order_management/reports/bulk_coop/create.html.haml b/engines/order_management/app/views/order_management/reports/bulk_coop/create.html.haml new file mode 100644 index 0000000000..6d8f0c79ab --- /dev/null +++ b/engines/order_management/app/views/order_management/reports/bulk_coop/create.html.haml @@ -0,0 +1,2 @@ += render "filters" += render "report" diff --git a/engines/order_management/app/views/order_management/reports/bulk_coop/new.html.haml b/engines/order_management/app/views/order_management/reports/bulk_coop/new.html.haml new file mode 100644 index 0000000000..790853ca1f --- /dev/null +++ b/engines/order_management/app/views/order_management/reports/bulk_coop/new.html.haml @@ -0,0 +1 @@ += render "filters" diff --git a/engines/order_management/config/routes.rb b/engines/order_management/config/routes.rb index 79706c635a..405219634b 100644 --- a/engines/order_management/config/routes.rb +++ b/engines/order_management/config/routes.rb @@ -1,6 +1,7 @@ Openfoodnetwork::Application.routes.prepend do namespace :order_management do namespace :reports do + resource :bulk_coop, only: [:new, :create], controller: :bulk_coop resource :enterprise_fee_summary, only: [:new, :create] end end diff --git a/lib/open_food_network/bulk_coop_report.rb b/lib/open_food_network/bulk_coop_report.rb deleted file mode 100644 index 9eb8cf07c6..0000000000 --- a/lib/open_food_network/bulk_coop_report.rb +++ /dev/null @@ -1,266 +0,0 @@ -require 'open_food_network/reports/bulk_coop_supplier_report' -require 'open_food_network/reports/bulk_coop_allocation_report' -require "open_food_network/reports/line_items" - -module OpenFoodNetwork - class BulkCoopReport - attr_reader :params - def initialize(user, params = {}, render_table = false) - @params = params - @user = user - @render_table = render_table - - @supplier_report = Reports::BulkCoopSupplierReport.new - @allocation_report = Reports::BulkCoopAllocationReport.new - end - - def header - case params[:report_type] - when "bulk_coop_supplier_report" - @supplier_report.header - when "bulk_coop_allocation" - @allocation_report.header - when "bulk_coop_packing_sheets" - [I18n.t(:report_header_customer), - I18n.t(:report_header_product), - I18n.t(:report_header_variant), - I18n.t(:report_header_sum_total)] - when "bulk_coop_customer_payments" - [I18n.t(:report_header_customer), - I18n.t(:report_header_date_of_order), - I18n.t(:report_header_total_cost), - I18n.t(:report_header_amount_owing), - I18n.t(:report_header_amount_paid)] - else - [I18n.t(:report_header_supplier), - I18n.t(:report_header_product), - I18n.t(:report_header_product), - I18n.t(:report_header_bulk_unit_size), - I18n.t(:report_header_variant), - I18n.t(:report_header_weight), - I18n.t(:report_header_sum_total), - I18n.t(:report_header_sum_max_total), - I18n.t(:report_header_units_required), - I18n.t(:report_header_remainder)] - end - end - - def search - report_line_items.orders - end - - def table_items - return [] unless @render_table - report_line_items.list(line_item_includes) - end - - def rules - case params[:report_type] - when "bulk_coop_supplier_report" - @supplier_report.rules - when "bulk_coop_allocation" - @allocation_report.rules - when "bulk_coop_packing_sheets" - [{ group_by: proc { |li| li.product }, - sort_by: proc { |product| product.name } }, - { group_by: proc { |li| li.full_name }, - sort_by: proc { |full_name| full_name } }, - { group_by: proc { |li| li.order }, - sort_by: proc { |order| order.to_s } }] - when "bulk_coop_customer_payments" - [{ group_by: proc { |li| li.order }, - sort_by: proc { |order| order.completed_at } }] - else - [{ group_by: proc { |li| li.product.supplier }, - sort_by: proc { |supplier| supplier.name } }, - { group_by: proc { |li| li.product }, - sort_by: proc { |product| product.name }, - summary_columns: [proc { |lis| lis.first.product.supplier.name }, - proc { |lis| lis.first.product.name }, - proc { |lis| lis.first.product.group_buy_unit_size || 0.0 }, - proc { |_lis| "" }, - proc { |_lis| "" }, - proc { |lis| lis.sum { |li| li.quantity * (li.weight_from_unit_value || 0) } }, - proc { |lis| lis.sum { |li| (li.max_quantity || 0) * (li.weight_from_unit_value || 0) } }, - proc { |lis| ( (lis.first.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| [li.max_quantity || 0, li.quantity || 0].max * (li.weight_from_unit_value || 0) } / lis.first.product.group_buy_unit_size ) ).floor }, - proc { |lis| lis.sum { |li| [li.max_quantity || 0, li.quantity || 0].max * (li.weight_from_unit_value || 0) } - ( ( (lis.first.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| [li.max_quantity || 0, li.quantity || 0].max * (li.weight_from_unit_value || 0) } / lis.first.product.group_buy_unit_size ) ).floor * (lis.first.product.group_buy_unit_size || 0) ) }] }, - { group_by: proc { |li| li.full_name }, - sort_by: proc { |full_name| full_name } }] - end - end - - def columns - case params[:report_type] - when "bulk_coop_supplier_report" - @supplier_report.columns - when "bulk_coop_allocation" - @allocation_report.columns - when "bulk_coop_packing_sheets" - [ - :order_billing_address_name, - :product_name, - :full_name, - :total_quantity - ] - when "bulk_coop_customer_payments" - [ - :order_billing_address_name, - :order_completed_at, - :customer_payments_total_cost, - :customer_payments_amount_owed, - :customer_payments_amount_paid - ] - else - [ - :product_supplier_name, - :product_name, - :product_group_buy_unit_size, - :full_name, - :weight_from_unit_value, - :total_quantity, - :total_max_quantity, - :empty_cell, - :empty_cell - ] - end - end - - private - - def line_item_includes - [{ order: [:bill_address], - variant: [{ option_values: :option_type }, { product: :supplier }] }] - end - - def order_permissions - return @order_permissions unless @order_permissions.nil? - @order_permissions = ::Permissions::Order.new(@user, @params[:q]) - end - - def report_line_items - @report_line_items ||= Reports::LineItems.new(order_permissions, @params) - end - - def customer_payments_total_cost(line_items) - line_items.map(&:order).uniq.sum(&:total) - end - - def customer_payments_amount_owed(line_items) - line_items.map(&:order).uniq.sum(&:outstanding_balance) - end - - def customer_payments_amount_paid(line_items) - line_items.map(&:order).uniq.sum(&:payment_total) - end - - def empty_cell(*) - "" - end - - def full_name(line_items) - line_items.first.full_name - end - - def group_buy_unit_size(line_items) - (line_items.first.variant.product.group_buy_unit_size || 0.0) / - (line_items.first.product.variant_unit_scale || 1) - end - - def max_quantity_excess(line_items) - max_quantity_amount(line_items) - total_amount(line_items) - end - - def max_quantity_amount(line_items) - line_items.sum do |line_item| - max_quantity = [line_item.max_quantity || 0, line_item.quantity || 0].max - max_quantity * scaled_unit_value(line_item.variant) - end - end - - def option_value_value(line_items) - OpenFoodNetwork::OptionValueNamer.new(line_items.first).value - end - - def option_value_unit(line_items) - OpenFoodNetwork::OptionValueNamer.new(line_items.first).unit - end - - def order_billing_address_name(line_items) - billing_address = line_items.first.order.bill_address - billing_address.firstname + " " + billing_address.lastname - end - - def order_completed_at(line_items) - line_items.first.order.completed_at.to_s - end - - def product_group_buy_unit_size(line_items) - line_items.first.product.group_buy_unit_size || 0.0 - end - - def product_name(line_items) - line_items.first.product.name - end - - def product_supplier_name(line_items) - line_items.first.product.supplier.name - end - - def remainder(line_items) - remainder = total_available(line_items) - total_amount(line_items) - remainder >= 0 ? remainder : '' - end - - def scaled_final_weight_volume(line_item) - (line_item.final_weight_volume || 0) / (line_item.product.variant_unit_scale || 1) - end - - def scaled_unit_value(variant) - (variant.unit_value || 0) / (variant.product.variant_unit_scale || 1) - end - - def total_amount(line_items) - line_items.sum { |li| scaled_final_weight_volume(li) } - end - - def total_available(line_items) - units_required(line_items) * group_buy_unit_size(line_items) - end - - def total_max_quantity(line_items) - line_items.sum { |line_item| line_item.max_quantity || 0 } - end - - def total_quantity(line_items) - line_items.sum(&:quantity) - end - - def total_label(*) - I18n.t('admin.reports.total') - end - - def units_required(line_items) - if group_buy_unit_size(line_items).zero? - 0 - else - ( total_amount(line_items) / group_buy_unit_size(line_items) ).ceil - end - end - - def variant_product_group_buy_unit_size_f(line_items) - group_buy_unit_size(line_items) - end - - def variant_product_name(line_items) - line_items.first.variant.product.name - end - - def variant_product_supplier_name(line_items) - line_items.first.variant.product.supplier.name - end - - def weight_from_unit_value(line_items) - line_items.first.weight_from_unit_value || 0 - end - end -end diff --git a/lib/open_food_network/reports/bulk_coop_allocation_report.rb b/lib/open_food_network/reports/bulk_coop_allocation_report.rb deleted file mode 100644 index bcc068c0c5..0000000000 --- a/lib/open_food_network/reports/bulk_coop_allocation_report.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: true - -module OpenFoodNetwork::Reports - class BulkCoopAllocationReport - def header - [ - I18n.t(:report_header_customer), - I18n.t(:report_header_product), - I18n.t(:report_header_bulk_unit_size), - I18n.t(:report_header_variant), - I18n.t(:report_header_variant_value), - I18n.t(:report_header_variant_unit), - I18n.t(:report_header_weight), - I18n.t(:report_header_sum_total), - I18n.t(:report_header_total_available), - I18n.t(:report_header_unallocated), - I18n.t(:report_header_max_quantity_excess), - ] - end - - def rules - [ - { - group_by: proc { |line_item| line_item.product }, - sort_by: proc { |product| product.name }, - summary_columns: [ - :total_label, - :variant_product_name, - :variant_product_group_buy_unit_size_f, - :empty_cell, - :empty_cell, - :empty_cell, - :empty_cell, - :total_amount, - :total_available, - :remainder, - :max_quantity_excess - ] - }, - { - group_by: proc { |line_item| line_item.order }, - sort_by: proc { |order| order.to_s } - } - ] - end - - def columns - [ - :order_billing_address_name, - :product_name, - :product_group_buy_unit_size, - :full_name, - :option_value_value, - :option_value_unit, - :weight_from_unit_value, - :total_amount, - :empty_cell, - :empty_cell, - :empty_cell - ] - end - end -end diff --git a/lib/open_food_network/reports/bulk_coop_supplier_report.rb b/lib/open_food_network/reports/bulk_coop_supplier_report.rb deleted file mode 100644 index 0c1c86e3b2..0000000000 --- a/lib/open_food_network/reports/bulk_coop_supplier_report.rb +++ /dev/null @@ -1,60 +0,0 @@ -module OpenFoodNetwork::Reports - class BulkCoopSupplierReport - def header - [ - I18n.t(:report_header_supplier), - I18n.t(:report_header_product), - I18n.t(:report_header_bulk_unit_size), - I18n.t(:report_header_variant), - I18n.t(:report_header_variant_value), - I18n.t(:report_header_variant_unit), - I18n.t(:report_header_weight), - I18n.t(:report_header_sum_total), - I18n.t(:report_header_units_required), - I18n.t(:report_header_unallocated), - I18n.t(:report_header_max_quantity_excess), - ] - end - - def rules - [ - { group_by: proc { |line_item| line_item.product.supplier }, - sort_by: proc { |supplier| supplier.name } }, - { group_by: proc { |line_item| line_item.product }, - sort_by: proc { |product| product.name }, - summary_columns: [ - :variant_product_supplier_name, - :variant_product_name, - :variant_product_group_buy_unit_size_f, - :empty_cell, - :empty_cell, - :empty_cell, - :empty_cell, - :total_amount, - :units_required, - :remainder, - :max_quantity_excess - ] - }, - { group_by: proc { |line_item| line_item.full_name }, - sort_by: proc { |full_name| full_name } } - ] - end - - def columns - [ - :variant_product_supplier_name, - :variant_product_name, - :variant_product_group_buy_unit_size_f, - :full_name, - :option_value_value, - :option_value_unit, - :weight_from_unit_value, - :total_amount, - :empty_cell, - :empty_cell, - :empty_cell - ] - end - end -end From 9172606780806734217691428067b95e71b36a93 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 5 Jun 2020 16:51:43 +0100 Subject: [PATCH 05/19] Allow the order management report partial to be reused on different reports. --- .../reports/{enterprise_fee_summaries => }/_report.html.haml | 0 .../views/order_management/reports/bulk_coop/create.html.haml | 2 +- .../reports/enterprise_fee_summaries/create.html.haml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename engines/order_management/app/views/order_management/reports/{enterprise_fee_summaries => }/_report.html.haml (100%) diff --git a/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_report.html.haml b/engines/order_management/app/views/order_management/reports/_report.html.haml similarity index 100% rename from engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_report.html.haml rename to engines/order_management/app/views/order_management/reports/_report.html.haml diff --git a/engines/order_management/app/views/order_management/reports/bulk_coop/create.html.haml b/engines/order_management/app/views/order_management/reports/bulk_coop/create.html.haml index 6d8f0c79ab..06938dd67d 100644 --- a/engines/order_management/app/views/order_management/reports/bulk_coop/create.html.haml +++ b/engines/order_management/app/views/order_management/reports/bulk_coop/create.html.haml @@ -1,2 +1,2 @@ = render "filters" -= render "report" += render "order_management/reports/report" diff --git a/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/create.html.haml b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/create.html.haml index 6d8f0c79ab..06938dd67d 100644 --- a/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/create.html.haml +++ b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/create.html.haml @@ -1,2 +1,2 @@ = render "filters" -= render "report" += render "order_management/reports/report" From e58852289ffa44069374424f282137f596bb143c Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 5 Jun 2020 16:58:56 +0100 Subject: [PATCH 06/19] Move the :require_valid_datetime_range method to OrderManagement::Reports::Parameters::Base so it can be reused on multiple reports. --- config/locales/en.yml | 5 +++-- .../reports/bulk_coop/parameters.rb | 12 ------------ .../reports/enterprise_fee_summary/parameters.rb | 12 ------------ .../app/services/reports/parameters/base.rb | 14 ++++++++++++++ 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 1aee3bfa2c..ef9dfe332d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2827,6 +2827,9 @@ See the %{link} to find out more about %{sitename}'s features and to start using order_management: reports: + base: + date_end_before_start_error: "must be after start" + parameter_not_allowed_error: "You are not authorized to use one or more selected filters for this report." enterprise_fee_summaries: filters: date_range: "Date Range" @@ -2836,8 +2839,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using none: "None" select_and_search: "Select filters and click on GENERATE REPORT to access your data." enterprise_fee_summary: - date_end_before_start_error: "must be after start" - parameter_not_allowed_error: "You are not authorized to use one or more selected filters for this report." fee_calculated_on_transfer_through_all: "All" fee_calculated_on_transfer_through_entire_orders: "Entire Orders through %{distributor}" tax_category_various: "Various" diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb index 16ed31a744..5fe2b0e5fb 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb @@ -16,11 +16,6 @@ module OrderManagement validate :require_valid_datetime_range - def self.date_end_before_start_error_message - i18n_scope = "order_management.reports.enterprise_fee_summary" - I18n.t("date_end_before_start_error", scope: i18n_scope) - end - def initialize(attributes = {}) self.distributor_ids = [] @@ -34,13 +29,6 @@ module OrderManagement protected - def require_valid_datetime_range - return if start_at.blank? || end_at.blank? - - error_message = self.class.date_end_before_start_error_message - errors.add(:end_at, error_message) unless start_at < end_at - end - # Remove the blank strings that Rails multiple selects add by default to # make sure that blank lists are still submitted to the server as arrays # instead of nil. diff --git a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/parameters.rb b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/parameters.rb index cc12d9be1f..938feeea75 100644 --- a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/parameters.rb +++ b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/parameters.rb @@ -19,11 +19,6 @@ module OrderManagement validate :require_valid_datetime_range - def self.date_end_before_start_error_message - i18n_scope = "order_management.reports.enterprise_fee_summary" - I18n.t("date_end_before_start_error", scope: i18n_scope) - end - def initialize(attributes = {}) self.distributor_ids = [] self.producer_ids = [] @@ -42,13 +37,6 @@ module OrderManagement protected - def require_valid_datetime_range - return if start_at.blank? || end_at.blank? - - error_message = self.class.date_end_before_start_error_message - errors.add(:end_at, error_message) unless start_at < end_at - end - # Remove the blank strings that Rails multiple selects add by default to # make sure that blank lists are still submitted to the server as arrays # instead of nil. diff --git a/engines/order_management/app/services/reports/parameters/base.rb b/engines/order_management/app/services/reports/parameters/base.rb index 8debc06b1d..c25a2e9969 100644 --- a/engines/order_management/app/services/reports/parameters/base.rb +++ b/engines/order_management/app/services/reports/parameters/base.rb @@ -12,8 +12,22 @@ module Reports end end + def self.date_end_before_start_error_message + i18n_scope = "order_management.reports.base" + I18n.t("date_end_before_start_error", scope: i18n_scope) + end + # The parameters are never persisted. def to_key; end + + protected + + def require_valid_datetime_range + return if start_at.blank? || end_at.blank? + + error_message = self.class.date_end_before_start_error_message + errors.add(:end_at, error_message) unless start_at < end_at + end end end end From bafa8beab361b745a5df48d977ebb6e69452e4b1 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 5 Jun 2020 17:05:26 +0100 Subject: [PATCH 07/19] Use :parameter_not_allowed_error_message to from base Reports::Authorizer. --- .../order_management/reports/bulk_coop/authorizer.rb | 5 ----- engines/order_management/app/services/reports/authorizer.rb | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb index 39562e6da2..98e499d3c1 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb @@ -2,11 +2,6 @@ module OrderManagement module Reports module BulkCoop class Authorizer < ::Reports::Authorizer - def self.parameter_not_allowed_error_message - i18n_scope = "order_management.reports.enterprise_fee_summary" - I18n.t("parameter_not_allowed_error", scope: i18n_scope) - end - def authorize! require_ids_allowed(parameters.distributor_ids, permissions.allowed_distributors) end diff --git a/engines/order_management/app/services/reports/authorizer.rb b/engines/order_management/app/services/reports/authorizer.rb index 5871e7e395..3fd3d2fc4f 100644 --- a/engines/order_management/app/services/reports/authorizer.rb +++ b/engines/order_management/app/services/reports/authorizer.rb @@ -10,7 +10,7 @@ module Reports end def self.parameter_not_allowed_error_message - i18n_scope = "order_management.reports.shared" + i18n_scope = "order_management.reports.base" I18n.t("parameter_not_allowed_error", scope: i18n_scope) end From f90969134d5191e379865bf639bc77c9afd33e4c Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Fri, 5 Jun 2020 20:03:17 +0100 Subject: [PATCH 08/19] Fix a couple of Rubocop violations. --- .../order_management/reports/bulk_coop/bulk_coop_report.rb | 3 ++- .../services/order_management/reports/bulk_coop/parameters.rb | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb index 3d776c31f5..67229fdbc4 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb @@ -9,7 +9,7 @@ module OrderManagement :bulk_coop_allocation, :bulk_coop_packing_sheets, :bulk_coop_customer_payments - ] + ].freeze attr_reader :params def initialize(user, params = {}, render_table = false) @@ -141,6 +141,7 @@ module OrderManagement def order_permissions return @order_permissions unless @order_permissions.nil? + @order_permissions = ::Permissions::Order.new(@user, @params[:q]) end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb index 5fe2b0e5fb..7de25375e4 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb @@ -12,7 +12,7 @@ module OrderManagement validates :start_at, :end_at, date_time_string: true validates :distributor_ids, integer_array: true - validates_inclusion_of :report_type, in: OrderManagement::Reports::BulkCoop::BulkCoopReport::REPORT_TYPES.map(&:to_s) + validates_inclusion_of :report_type, in: BulkCoopReport::REPORT_TYPES.map(&:to_s) validate :require_valid_datetime_range From ed82c7e3db199c0b4d76b3ea9a6b37ad4a66e75a Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 12:51:29 +0100 Subject: [PATCH 09/19] BulkCoopReport has been moved to the engines/order_management so move it's spec there too. --- .../bulk_coop/bulk_coop_report_spec.rb | 95 ++++++++++++++++++ .../bulk_coop_report_spec.rb | 98 ------------------- 2 files changed, 95 insertions(+), 98 deletions(-) create mode 100644 engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb delete mode 100644 spec/lib/open_food_network/bulk_coop_report_spec.rb diff --git a/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb new file mode 100644 index 0000000000..46f774a576 --- /dev/null +++ b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb @@ -0,0 +1,95 @@ +require 'spec_helper' + +include AuthenticationWorkflow + +describe OrderManagement::Reports::BulkCoop::BulkCoopReport do + describe "fetching orders" do + let(:d1) { create(:distributor_enterprise) } + let(:oc1) { create(:simple_order_cycle) } + let(:o1) { create(:order, completed_at: 1.day.ago, order_cycle: oc1, distributor: d1) } + let(:li1) { build(:line_item_with_shipment) } + + before { o1.line_items << li1 } + + context "as a site admin" do + let(:user) { create(:admin_user) } + subject { OrderManagement::Reports::BulkCoop::BulkCoopReport.new user, {}, true } + + it "fetches completed orders" do + o2 = create(:order) + o2.line_items << build(:line_item) + expect(subject.table_items).to eq([li1]) + end + + it "does not show cancelled orders" do + o2 = create(:order, state: "canceled", completed_at: 1.day.ago) + o2.line_items << build(:line_item_with_shipment) + expect(subject.table_items).to eq([li1]) + end + end + + context "as a manager of a supplier" do + let!(:user) { create(:user) } + subject { OrderManagement::Reports::BulkCoop::BulkCoopReport.new user, {}, true } + + let(:s1) { create(:supplier_enterprise) } + + before do + s1.enterprise_roles.create!(user: user) + end + + context "that has granted P-OC to the distributor" do + let(:o2) { create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), ship_address: create(:address)) } + let(:li2) { build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) } + + before do + o2.line_items << li2 + create(:enterprise_relationship, parent: s1, child: d1, permissions_list: [:add_to_order_cycle]) + end + + it "shows line items supplied by my producers, with names hidden" do + expect(subject.table_items).to eq([li2]) + expect(subject.table_items.first.order.bill_address.firstname).to eq("HIDDEN") + end + end + + context "that has not granted P-OC to the distributor" do + let(:o2) { create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), ship_address: create(:address)) } + let(:li2) { build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) } + + before do + o2.line_items << li2 + end + + it "does not show line items supplied by my producers" do + expect(subject.table_items).to eq([]) + end + end + end + + context "as a manager of a distributor" do + let!(:user) { create(:user) } + subject { PackingReport.new user, {}, true } + + before do + d1.enterprise_roles.create!(user: user) + end + + it "only shows line items distributed by enterprises managed by the current user" do + d2 = create(:distributor_enterprise) + d2.enterprise_roles.create!(user: create(:user)) + o2 = create(:order, distributor: d2, completed_at: 1.day.ago) + o2.line_items << build(:line_item_with_shipment) + expect(subject.table_items).to eq([li1]) + end + + it "only shows the selected order cycle" do + oc2 = create(:simple_order_cycle) + o2 = create(:order, distributor: d1, order_cycle: oc2) + o2.line_items << build(:line_item) + allow(subject).to receive(:params).and_return(order_cycle_id_in: oc1.id) + expect(subject.table_items).to eq([li1]) + end + end + end +end diff --git a/spec/lib/open_food_network/bulk_coop_report_spec.rb b/spec/lib/open_food_network/bulk_coop_report_spec.rb deleted file mode 100644 index 5b43ba0283..0000000000 --- a/spec/lib/open_food_network/bulk_coop_report_spec.rb +++ /dev/null @@ -1,98 +0,0 @@ -require 'spec_helper' -require 'open_food_network/bulk_coop_report' - -include AuthenticationWorkflow - -module OpenFoodNetwork - describe BulkCoopReport do - describe "fetching orders" do - let(:d1) { create(:distributor_enterprise) } - let(:oc1) { create(:simple_order_cycle) } - let(:o1) { create(:order, completed_at: 1.day.ago, order_cycle: oc1, distributor: d1) } - let(:li1) { build(:line_item_with_shipment) } - - before { o1.line_items << li1 } - - context "as a site admin" do - let(:user) { create(:admin_user) } - subject { BulkCoopReport.new user, {}, true } - - it "fetches completed orders" do - o2 = create(:order) - o2.line_items << build(:line_item) - expect(subject.table_items).to eq([li1]) - end - - it "does not show cancelled orders" do - o2 = create(:order, state: "canceled", completed_at: 1.day.ago) - o2.line_items << build(:line_item_with_shipment) - expect(subject.table_items).to eq([li1]) - end - end - - context "as a manager of a supplier" do - let!(:user) { create(:user) } - subject { BulkCoopReport.new user, {}, true } - - let(:s1) { create(:supplier_enterprise) } - - before do - s1.enterprise_roles.create!(user: user) - end - - context "that has granted P-OC to the distributor" do - let(:o2) { create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), ship_address: create(:address)) } - let(:li2) { build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) } - - before do - o2.line_items << li2 - create(:enterprise_relationship, parent: s1, child: d1, permissions_list: [:add_to_order_cycle]) - end - - it "shows line items supplied by my producers, with names hidden" do - expect(subject.table_items).to eq([li2]) - expect(subject.table_items.first.order.bill_address.firstname).to eq("HIDDEN") - end - end - - context "that has not granted P-OC to the distributor" do - let(:o2) { create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), ship_address: create(:address)) } - let(:li2) { build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) } - - before do - o2.line_items << li2 - end - - it "does not show line items supplied by my producers" do - expect(subject.table_items).to eq([]) - end - end - end - - context "as a manager of a distributor" do - let!(:user) { create(:user) } - subject { PackingReport.new user, {}, true } - - before do - d1.enterprise_roles.create!(user: user) - end - - it "only shows line items distributed by enterprises managed by the current user" do - d2 = create(:distributor_enterprise) - d2.enterprise_roles.create!(user: create(:user)) - o2 = create(:order, distributor: d2, completed_at: 1.day.ago) - o2.line_items << build(:line_item_with_shipment) - expect(subject.table_items).to eq([li1]) - end - - it "only shows the selected order cycle" do - oc2 = create(:simple_order_cycle) - o2 = create(:order, distributor: d1, order_cycle: oc2) - o2.line_items << build(:line_item) - allow(subject).to receive(:params).and_return(order_cycle_id_in: oc1.id) - expect(subject.table_items).to eq([li1]) - end - end - end - end -end From bfc6daf07689649afb0e411c79ea889e26f03d5f Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 12:57:14 +0100 Subject: [PATCH 10/19] Remove duplicate PackingReport tests from the BulkCoopReport spec. These tests already exist in spec/lib/open_food_network/packing_report_spec.rb:72 --- .../bulk_coop/bulk_coop_report_spec.rb | 25 ------------------- 1 file changed, 25 deletions(-) diff --git a/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb index 46f774a576..cc8d874cc1 100644 --- a/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb +++ b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb @@ -66,30 +66,5 @@ describe OrderManagement::Reports::BulkCoop::BulkCoopReport do end end end - - context "as a manager of a distributor" do - let!(:user) { create(:user) } - subject { PackingReport.new user, {}, true } - - before do - d1.enterprise_roles.create!(user: user) - end - - it "only shows line items distributed by enterprises managed by the current user" do - d2 = create(:distributor_enterprise) - d2.enterprise_roles.create!(user: create(:user)) - o2 = create(:order, distributor: d2, completed_at: 1.day.ago) - o2.line_items << build(:line_item_with_shipment) - expect(subject.table_items).to eq([li1]) - end - - it "only shows the selected order cycle" do - oc2 = create(:simple_order_cycle) - o2 = create(:order, distributor: d1, order_cycle: oc2) - o2.line_items << build(:line_item) - allow(subject).to receive(:params).and_return(order_cycle_id_in: oc1.id) - expect(subject.table_items).to eq([li1]) - end - end end end From 293e8949a998fc4626fda0eeccc0865347c81e56 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 12:59:23 +0100 Subject: [PATCH 11/19] Remove unused AuthenticationWorkflow module from the BulkCoopReport specs. --- .../order_management/reports/bulk_coop/bulk_coop_report_spec.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb index cc8d874cc1..9cd9629c74 100644 --- a/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb +++ b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb @@ -1,7 +1,5 @@ require 'spec_helper' -include AuthenticationWorkflow - describe OrderManagement::Reports::BulkCoop::BulkCoopReport do describe "fetching orders" do let(:d1) { create(:distributor_enterprise) } From 6dbb6f3f09941d28dd9689cb0655a36196e0711f Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 13:09:09 +0100 Subject: [PATCH 12/19] Add an underscore before unused method arguments rather than an empty splat operator so it's easier to understand what is being passed in. --- .../order_management/reports/bulk_coop/bulk_coop_report.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb index 67229fdbc4..c31c3edfc3 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb @@ -161,7 +161,7 @@ module OrderManagement line_items.map(&:order).uniq.sum(&:payment_total) end - def empty_cell(*) + def empty_cell(_line_items) "" end @@ -243,7 +243,7 @@ module OrderManagement line_items.sum(&:quantity) end - def total_label(*) + def total_label(_line_items) I18n.t('admin.reports.total') end From bcf79ef8032741ec19bc239f23632a8e33600e2c Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 13:27:44 +0100 Subject: [PATCH 13/19] Fix code climate violations related to removing blockenspiel. --- app/controllers/spree/admin/reports_controller.rb | 2 +- .../order_management/reports/bulk_coop_controller.rb | 2 ++ .../order_management/reports/bulk_coop/authorizer.rb | 2 ++ .../order_management/reports/bulk_coop/bulk_coop_report.rb | 3 +++ .../reports/bulk_coop/bulk_coop_supplier_report.rb | 5 +++-- .../order_management/reports/bulk_coop/parameters.rb | 2 ++ .../order_management/reports/bulk_coop/permissions.rb | 2 ++ .../reports/bulk_coop/renderers/csv_renderer.rb | 2 ++ .../reports/bulk_coop/renderers/html_renderer.rb | 2 ++ .../order_management/reports/bulk_coop/report_service.rb | 2 ++ .../reports/bulk_coop/bulk_coop_report_spec.rb | 2 ++ 11 files changed, 23 insertions(+), 3 deletions(-) diff --git a/app/controllers/spree/admin/reports_controller.rb b/app/controllers/spree/admin/reports_controller.rb index ce3ec90c57..e8878308de 100644 --- a/app/controllers/spree/admin/reports_controller.rb +++ b/app/controllers/spree/admin/reports_controller.rb @@ -23,7 +23,7 @@ module Spree ORDER_MANAGEMENT_ENGINE_REPORTS = [ :bulk_coop, :enterprise_fee_summary - ] + ].freeze helper_method :render_content? diff --git a/engines/order_management/app/controllers/order_management/reports/bulk_coop_controller.rb b/engines/order_management/app/controllers/order_management/reports/bulk_coop_controller.rb index 26397e40bf..5a308fbdab 100644 --- a/engines/order_management/app/controllers/order_management/reports/bulk_coop_controller.rb +++ b/engines/order_management/app/controllers/order_management/reports/bulk_coop_controller.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module OrderManagement module Reports class BulkCoopController < Spree::Admin::BaseController diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb index 98e499d3c1..b0e398e0a0 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/authorizer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module OrderManagement module Reports module BulkCoop diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb index c31c3edfc3..8adaef7f33 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "open_food_network/reports/line_items" module OrderManagement @@ -58,6 +60,7 @@ module OrderManagement def table_items return [] unless @render_table + report_line_items.list(line_item_includes) end diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_supplier_report.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_supplier_report.rb index 076a0a63c9..0f57c58f6a 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_supplier_report.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_supplier_report.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module OrderManagement module Reports module BulkCoop @@ -36,8 +38,7 @@ module OrderManagement :units_required, :remainder, :max_quantity_excess - ] - }, + ] }, { group_by: proc { |line_item| line_item.full_name }, sort_by: proc { |full_name| full_name } } ] diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb index 7de25375e4..2f5a48d296 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/parameters.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module OrderManagement module Reports module BulkCoop diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/permissions.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/permissions.rb index 23eb0aaca0..ca2a38467c 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/permissions.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/permissions.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module OrderManagement module Reports module BulkCoop diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/csv_renderer.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/csv_renderer.rb index ca19e0a873..f848edbe71 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/csv_renderer.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/csv_renderer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module OrderManagement module Reports module BulkCoop diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/html_renderer.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/html_renderer.rb index edbda863e1..03f7934e06 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/html_renderer.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/renderers/html_renderer.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + module OrderManagement module Reports module BulkCoop diff --git a/engines/order_management/app/services/order_management/reports/bulk_coop/report_service.rb b/engines/order_management/app/services/order_management/reports/bulk_coop/report_service.rb index c74e40934e..ac7f965218 100644 --- a/engines/order_management/app/services/order_management/reports/bulk_coop/report_service.rb +++ b/engines/order_management/app/services/order_management/reports/bulk_coop/report_service.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'open_food_network/order_grouper' module OrderManagement diff --git a/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb index 9cd9629c74..4378eb5b9b 100644 --- a/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb +++ b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' describe OrderManagement::Reports::BulkCoop::BulkCoopReport do From 3abcb5b23c0cfc6f40675d584cb5bd5a559e54c2 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 15:37:44 +0100 Subject: [PATCH 14/19] Don't move the :parameter_not_allowed_error translation to a different scope yet. It will make it harder to merge and deploy this PR if every translation locale file has to be updated too. --- config/locales/en.yml | 5 ++--- engines/order_management/app/services/reports/authorizer.rb | 2 +- .../order_management/app/services/reports/parameters/base.rb | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index ef9dfe332d..1aee3bfa2c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2827,9 +2827,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using order_management: reports: - base: - date_end_before_start_error: "must be after start" - parameter_not_allowed_error: "You are not authorized to use one or more selected filters for this report." enterprise_fee_summaries: filters: date_range: "Date Range" @@ -2839,6 +2836,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using none: "None" select_and_search: "Select filters and click on GENERATE REPORT to access your data." enterprise_fee_summary: + date_end_before_start_error: "must be after start" + parameter_not_allowed_error: "You are not authorized to use one or more selected filters for this report." fee_calculated_on_transfer_through_all: "All" fee_calculated_on_transfer_through_entire_orders: "Entire Orders through %{distributor}" tax_category_various: "Various" diff --git a/engines/order_management/app/services/reports/authorizer.rb b/engines/order_management/app/services/reports/authorizer.rb index 3fd3d2fc4f..1f232b0160 100644 --- a/engines/order_management/app/services/reports/authorizer.rb +++ b/engines/order_management/app/services/reports/authorizer.rb @@ -10,7 +10,7 @@ module Reports end def self.parameter_not_allowed_error_message - i18n_scope = "order_management.reports.base" + i18n_scope = "order_management.reports.enterprise_fee_summary" I18n.t("parameter_not_allowed_error", scope: i18n_scope) end diff --git a/engines/order_management/app/services/reports/parameters/base.rb b/engines/order_management/app/services/reports/parameters/base.rb index c25a2e9969..31148fd47c 100644 --- a/engines/order_management/app/services/reports/parameters/base.rb +++ b/engines/order_management/app/services/reports/parameters/base.rb @@ -13,7 +13,7 @@ module Reports end def self.date_end_before_start_error_message - i18n_scope = "order_management.reports.base" + i18n_scope = "order_management.reports.enterprise_fee_summary" I18n.t("date_end_before_start_error", scope: i18n_scope) end From c1e57fcc128f9c060d0bb5c2e1f1e3fa8ed27926 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 15:41:09 +0100 Subject: [PATCH 15/19] Adjust CanCan ability to reflect that the bulk coop report now runs from the order management engine. --- app/models/spree/ability_decorator.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index dccfd4d756..baac52a54d 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -185,9 +185,10 @@ class AbilityDecorator can [:admin, :index, :guide, :import, :save, :save_data, :validate_data, :reset_absent_products], ProductImport::ProductImporter # Reports page - can [:admin, :index, :customers, :orders_and_distributors, :group_buys, :bulk_coop, :payments, + can [:admin, :index, :customers, :orders_and_distributors, :group_buys, :payments, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management, :packing], Spree::Admin::ReportsController + add_bulk_coop_abilities add_enterprise_fee_summary_abilities end @@ -267,6 +268,7 @@ class AbilityDecorator can [:admin, :index, :customers, :group_buys, :bulk_coop, :sales_tax, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management, :xero_invoices], Spree::Admin::ReportsController + add_bulk_coop_abilities add_enterprise_fee_summary_abilities can [:create], Customer @@ -291,6 +293,13 @@ class AbilityDecorator end end + def add_bulk_coop_abilities + # Reveal the report link in spree/admin/reports#index + can [:bulk_coop], Spree::Admin::ReportsController + # Allow direct access to the report resource + can [:admin, :new, :create], :bulk_coop + end + def add_enterprise_fee_summary_abilities # Reveal the report link in spree/admin/reports#index can [:enterprise_fee_summary], Spree::Admin::ReportsController From ba126d5afc7f72857973096046b682a82cf19793 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 15:42:26 +0100 Subject: [PATCH 16/19] Move the bulk coop controller specs to the order management engine. Also deleting old :bulk_coop_report action from the Spree::Admin::ReportsController. --- .../spree/admin/reports_controller.rb | 13 --- .../reports/bulk_coop_controller_spec.rb | 95 +++++++++++++++++++ .../spree/admin/reports_controller_spec.rb | 37 -------- 3 files changed, 95 insertions(+), 50 deletions(-) create mode 100644 engines/order_management/spec/controllers/order_management/reports/bulk_coop_controller_spec.rb diff --git a/app/controllers/spree/admin/reports_controller.rb b/app/controllers/spree/admin/reports_controller.rb index e8878308de..a931606ed0 100644 --- a/app/controllers/spree/admin/reports_controller.rb +++ b/app/controllers/spree/admin/reports_controller.rb @@ -95,19 +95,6 @@ module Spree render_report(@report.header, @report.table, params[:csv], "sales_tax.csv") end - def bulk_coop - # -- Prepare form options - @distributors = my_distributors - @report_type = params[:report_type] - - # -- Build Report with Order Grouper - @report = OpenFoodNetwork::BulkCoopReport.new spree_current_user, params, render_content? - @table = order_grouper_table - csv_file_name = "bulk_coop_#{params[:report_type]}_#{timestamp}.csv" - - render_report(@report.header, @table, params[:csv], csv_file_name) - end - def payments # -- Prepare Form Options @distributors = my_distributors diff --git a/engines/order_management/spec/controllers/order_management/reports/bulk_coop_controller_spec.rb b/engines/order_management/spec/controllers/order_management/reports/bulk_coop_controller_spec.rb new file mode 100644 index 0000000000..e292325ff8 --- /dev/null +++ b/engines/order_management/spec/controllers/order_management/reports/bulk_coop_controller_spec.rb @@ -0,0 +1,95 @@ +require "spec_helper" + +describe OrderManagement::Reports::BulkCoopController, type: :controller do + let(:report_klass) { OrderManagement::Reports::BulkCoop } + + let!(:distributor) { create(:distributor_enterprise) } + + let(:current_user) { distributor.owner } + + before do + allow(controller).to receive(:spree_current_user) { current_user } + end + + describe "#new" do + it "renders the report form" do + get :new + + expect(response).to be_success + expect(response).to render_template(new_template_path) + end + end + + describe "#create" do + context "when the parameters are valid" do + it "sends the generated report in the correct format" do + post :create, report: { + start_at: "2018-10-09 07:30:00", + report_type: "bulk_coop_supplier_report" + }, report_format: "csv" + + expect(response).to be_success + expect(response.body).not_to be_blank + expect(response.header["Content-Type"]).to eq("text/csv") + end + end + + context "when the parameters are invalid" do + it "renders the report form with an error" do + post :create, report: { + start_at: "invalid_date", + report_type: "bulk_coop_supplier_report" + }, report_format: "csv" + + expect(flash[:error]).to eq(I18n.t("invalid_filter_parameters", scope: i18n_scope)) + expect(response).to render_template(new_template_path) + end + end + + context "when some parameters are now allowed" do + let!(:distributor) { create(:distributor_enterprise) } + let!(:other_distributor) { create(:distributor_enterprise) } + + let(:current_user) { distributor.owner } + + it "renders the report form with an error" do + post :create, report: { + distributor_ids: [other_distributor.id], + report_type: "bulk_coop_supplier_report" + }, report_format: "csv" + + expect(flash[:error]).to eq(report_klass::Authorizer.parameter_not_allowed_error_message) + expect(response).to render_template(new_template_path) + end + end + + describe "filtering results based on permissions" do + let!(:distributor) { create(:distributor_enterprise) } + let!(:other_distributor) { create(:distributor_enterprise) } + + let(:current_user) { distributor.owner } + + it "applies permissions to report" do + post :create, report: {}, report_format: "csv" + + expect(assigns(:permissions).allowed_distributors.to_a).to eq([distributor]) + end + end + end + + private + + def default_report_params + { + report_type: "bulk_coop_supplier_report" + } + end + + def i18n_scope + "order_management.reports.enterprise_fee_summary" + end + + def new_template_path + "order_management/reports/bulk_coop/new" + end +end diff --git a/spec/controllers/spree/admin/reports_controller_spec.rb b/spec/controllers/spree/admin/reports_controller_spec.rb index e339e09fd1..9c4e2d65ff 100644 --- a/spec/controllers/spree/admin/reports_controller_spec.rb +++ b/spec/controllers/spree/admin/reports_controller_spec.rb @@ -93,18 +93,6 @@ describe Spree::Admin::ReportsController, type: :controller do end end - describe 'Bulk Coop' do - let!(:present_objects) { [orderA1, orderA2, orderB1, orderB2] } - - it "only shows orders that I have access to" do - spree_post :bulk_coop, q: {} - - expect(resulting_orders).to include(orderA1, orderB1) - expect(resulting_orders).not_to include(orderA2) - expect(resulting_orders).not_to include(orderB2) - end - end - describe 'Payments' do let!(:present_objects) { [orderA1, orderA2, orderB1, orderB2] } @@ -156,31 +144,6 @@ describe Spree::Admin::ReportsController, type: :controller do end end - describe 'Bulk Coop' do - context "where I have granted P-OC to the distributor" do - let!(:present_objects) { [orderA1, orderA2] } - - before do - create(:enterprise_relationship, parent: supplier1, child: distributor1, permissions_list: [:add_to_order_cycle]) - end - - it "only shows product line items that I am supplying" do - spree_post :bulk_coop, q: {} - - expect(resulting_products).to include product1 - expect(resulting_products).not_to include product2, product3 - end - end - - context "where I have not granted P-OC to the distributor" do - it "shows product line items that I am supplying" do - spree_post :bulk_coop - - expect(resulting_products).not_to include product1, product2, product3 - end - end - end - describe 'Orders & Fulfillment' do let!(:present_objects) { [orderA1, orderA2] } From fdf0d923667395a7ccb70b67d7c764bc63ab7524 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 15:52:42 +0100 Subject: [PATCH 17/19] Move feature spec for bulk coop report to the order management engine. --- .../order_management/reports/bulk_coop_spec.rb | 17 +++++++++++++++++ spec/features/admin/reports_spec.rb | 9 --------- 2 files changed, 17 insertions(+), 9 deletions(-) create mode 100644 engines/order_management/spec/features/order_management/reports/bulk_coop_spec.rb diff --git a/engines/order_management/spec/features/order_management/reports/bulk_coop_spec.rb b/engines/order_management/spec/features/order_management/reports/bulk_coop_spec.rb new file mode 100644 index 0000000000..90d3599628 --- /dev/null +++ b/engines/order_management/spec/features/order_management/reports/bulk_coop_spec.rb @@ -0,0 +1,17 @@ +require "spec_helper" + +feature "bulk coop" do + include AuthenticationWorkflow + include WebHelper + + scenario "bulk co-op report" do + quick_login_as_admin + visit spree.admin_reports_path + click_link 'Bulk Co-Op' + click_button 'Generate Report' + + expect(page).to have_content 'Supplier' + end +end + + diff --git a/spec/features/admin/reports_spec.rb b/spec/features/admin/reports_spec.rb index 97b677ed98..5ebd118fd7 100644 --- a/spec/features/admin/reports_spec.rb +++ b/spec/features/admin/reports_spec.rb @@ -155,15 +155,6 @@ feature ' expect(page).to have_content 'Order date' end - scenario "bulk co-op report" do - quick_login_as_admin - visit spree.admin_reports_path - click_link 'Bulk Co-Op' - click_button 'Search' - - expect(page).to have_content 'Supplier' - end - scenario "payments reports" do quick_login_as_admin visit spree.admin_reports_path From 0ef3a7e24f614d6670cb4d8445aae1c0eaf93e8d Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 16:23:11 +0100 Subject: [PATCH 18/19] Fix some more code climate violations for bulk coop specs which have been moved to the order management engine. --- .../reports/bulk_coop_controller_spec.rb | 2 ++ .../reports/bulk_coop_spec.rb | 4 ++-- .../bulk_coop/bulk_coop_report_spec.rb | 21 ++++++++++++++----- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/engines/order_management/spec/controllers/order_management/reports/bulk_coop_controller_spec.rb b/engines/order_management/spec/controllers/order_management/reports/bulk_coop_controller_spec.rb index e292325ff8..4476edd9cf 100644 --- a/engines/order_management/spec/controllers/order_management/reports/bulk_coop_controller_spec.rb +++ b/engines/order_management/spec/controllers/order_management/reports/bulk_coop_controller_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" describe OrderManagement::Reports::BulkCoopController, type: :controller do diff --git a/engines/order_management/spec/features/order_management/reports/bulk_coop_spec.rb b/engines/order_management/spec/features/order_management/reports/bulk_coop_spec.rb index 90d3599628..29caf17a15 100644 --- a/engines/order_management/spec/features/order_management/reports/bulk_coop_spec.rb +++ b/engines/order_management/spec/features/order_management/reports/bulk_coop_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require "spec_helper" feature "bulk coop" do @@ -13,5 +15,3 @@ feature "bulk coop" do expect(page).to have_content 'Supplier' end end - - diff --git a/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb index 4378eb5b9b..8f45355ee6 100644 --- a/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb +++ b/engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb @@ -39,12 +39,18 @@ describe OrderManagement::Reports::BulkCoop::BulkCoopReport do end context "that has granted P-OC to the distributor" do - let(:o2) { create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), ship_address: create(:address)) } - let(:li2) { build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) } + let(:o2) do + create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), + ship_address: create(:address)) + end + let(:li2) do + build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) + end before do o2.line_items << li2 - create(:enterprise_relationship, parent: s1, child: d1, permissions_list: [:add_to_order_cycle]) + create(:enterprise_relationship, parent: s1, child: d1, + permissions_list: [:add_to_order_cycle]) end it "shows line items supplied by my producers, with names hidden" do @@ -54,8 +60,13 @@ describe OrderManagement::Reports::BulkCoop::BulkCoopReport do end context "that has not granted P-OC to the distributor" do - let(:o2) { create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), ship_address: create(:address)) } - let(:li2) { build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) } + let(:o2) do + create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), + ship_address: create(:address)) + end + let(:li2) do + build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) + end before do o2.line_items << li2 From 430e5ea9cc43ae0e7f72cdf7b20597f465e13712 Mon Sep 17 00:00:00 2001 From: Cillian O'Ruanaidh Date: Sat, 13 Jun 2020 16:57:43 +0100 Subject: [PATCH 19/19] Permission to view :bulk_coop report is now added in the #add_bulk_coop_abilities method. --- app/models/spree/ability_decorator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index baac52a54d..f416a9d53f 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -265,7 +265,7 @@ class AbilityDecorator end # Reports page - can [:admin, :index, :customers, :group_buys, :bulk_coop, :sales_tax, :payments, + can [:admin, :index, :customers, :group_buys, :sales_tax, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management, :xero_invoices], Spree::Admin::ReportsController add_bulk_coop_abilities