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.
This commit is contained in:
Cillian O'Ruanaidh
2020-06-05 16:43:38 +01:00
parent d436d18d19
commit 406309c577
22 changed files with 707 additions and 423 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,2 @@
= render "filters"
= render "report"

View File

@@ -0,0 +1 @@
= render "filters"

View File

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

View File

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

View File

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

View File

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