Drop Blockenspiel and use :rules/:columns methods instead of :organise/:summary_columns DSL.

For https://github.com/openfoodfoundation/openfoodnetwork/issues/3231
This commit is contained in:
Cillian O'Ruanaidh
2020-05-28 19:04:18 +01:00
parent 2ae84ad710
commit 1fba998b9e
10 changed files with 117 additions and 249 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,7 +1,5 @@
module OpenFoodNetwork::Reports
class Row
include Blockenspiel::DSL
def initialize
@columns = []
end

View File

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

View File

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

View File

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