mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
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:
1
Gemfile
1
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'
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
module OpenFoodNetwork::Reports
|
||||
class Row
|
||||
include Blockenspiel::DSL
|
||||
|
||||
def initialize
|
||||
@columns = []
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user