mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-04-04 07:09:14 +00:00
Replace data loading with new Reports::QueryInterface
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reports
|
||||
module Reporting
|
||||
module Errors
|
||||
class Base < StandardError
|
||||
def i18n_error_scope
|
||||
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reports
|
||||
module Reporting
|
||||
class FrontendData
|
||||
def initialize(current_user)
|
||||
@current_user = current_user
|
||||
52
lib/reporting/queries/joins.rb
Normal file
52
lib/reporting/queries/joins.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
module Queries
|
||||
module Joins
|
||||
def joins_order
|
||||
reflect query.join(association(Spree::LineItem, :order))
|
||||
end
|
||||
|
||||
def joins_order_distributor
|
||||
reflect query.join(association(Spree::Order, :distributor, distributor_alias))
|
||||
end
|
||||
|
||||
def joins_variant
|
||||
reflect query.join(association(Spree::LineItem, :variant))
|
||||
end
|
||||
|
||||
def joins_variant_product
|
||||
reflect query.join(association(Spree::Variant, :product))
|
||||
end
|
||||
|
||||
def joins_product_supplier
|
||||
reflect query.join(association(Spree::Product, :supplier, supplier_alias))
|
||||
end
|
||||
|
||||
def joins_product_shipping_category
|
||||
reflect query.join(association(Spree::Product, :shipping_category))
|
||||
end
|
||||
|
||||
def joins_order_and_distributor
|
||||
reflect query.
|
||||
join(association(Spree::LineItem, :order)).
|
||||
join(association(Spree::Order, :distributor, distributor_alias))
|
||||
end
|
||||
|
||||
def joins_order_customer
|
||||
reflect query.join(association(Spree::Order, :customer))
|
||||
end
|
||||
|
||||
def joins_order_bill_address
|
||||
reflect query.join(association(Spree::Order, :bill_address, bill_address_alias))
|
||||
end
|
||||
|
||||
def join_line_item_option_values
|
||||
reflect query.
|
||||
join(association(Spree::LineItem, :option_values)).
|
||||
join(association(Spree::OptionValuesLineItem, :option_value)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
88
lib/reporting/queries/query_builder.rb
Normal file
88
lib/reporting/queries/query_builder.rb
Normal file
@@ -0,0 +1,88 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
module Queries
|
||||
class QueryBuilder < QueryInterface
|
||||
include Joins
|
||||
include Tables
|
||||
|
||||
attr_reader :grouping_fields
|
||||
|
||||
def initialize(model, grouping_fields = [])
|
||||
@grouping_fields = instance_exec(&grouping_fields)
|
||||
|
||||
super model.arel_table
|
||||
end
|
||||
|
||||
def selecting(lambda)
|
||||
fields = instance_exec(&lambda).map{ |key, value| value.public_send(:as, key.to_s) }
|
||||
|
||||
reflect query.project(*fields)
|
||||
end
|
||||
|
||||
def scoped_to_orders(orders_relation)
|
||||
reflect query.where(
|
||||
line_item_table[:order_id].in(Arel.sql(orders_relation.to_sql))
|
||||
)
|
||||
end
|
||||
|
||||
def with_managed_orders(orders_relation)
|
||||
reflect query.
|
||||
outer_join(managed_orders_alias).
|
||||
on(
|
||||
managed_orders_alias[:id].eq(line_item_table[:order_id]).
|
||||
and(managed_orders_alias[:distributor_id].in(Arel.sql(orders_relation.to_sql)))
|
||||
)
|
||||
end
|
||||
|
||||
def grouped_in_sets(group_sets)
|
||||
reflect query.group(*instance_exec(&group_sets))
|
||||
end
|
||||
|
||||
def ordered_by(ordering_fields)
|
||||
reflect query.order(*instance_exec(&ordering_fields))
|
||||
end
|
||||
|
||||
def masked(field, message = nil, mask_rule = nil)
|
||||
Case.new.
|
||||
when(mask_rule || default_mask_rule).
|
||||
then(field).
|
||||
else(quoted(message || I18n.t("hidden_field", scope: i18n_scope)))
|
||||
end
|
||||
|
||||
def distinct_results(fields = nil)
|
||||
return reflect query.distinct if fields.blank?
|
||||
|
||||
reflect query.distinct_on(fields)
|
||||
end
|
||||
|
||||
def variant_full_name
|
||||
display_name = variant_table[:display_name]
|
||||
display_as = variant_table[:display_as]
|
||||
options_text = option_value_table[:presentation]
|
||||
|
||||
unit_to_display = coalesce(nullify_empty_strings(display_as), options_text)
|
||||
combined_description = sql_concat(display_name, raw("' ('"), unit_to_display, raw("')'"))
|
||||
|
||||
Case.new.
|
||||
when(nullify_empty_strings(display_name).eq(nil)).then(unit_to_display).
|
||||
when(nullify_empty_strings(unit_to_display).not_eq(nil)).then(combined_description).
|
||||
else(display_name)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def default_mask_rule
|
||||
line_item_table[:order_id].in(raw("#{managed_orders_alias.name}.id"))
|
||||
end
|
||||
|
||||
def summary_row_title
|
||||
I18n.t("total_items", scope: i18n_scope)
|
||||
end
|
||||
|
||||
def i18n_scope
|
||||
"admin.reports"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
125
lib/reporting/queries/query_interface.rb
Normal file
125
lib/reporting/queries/query_interface.rb
Normal file
@@ -0,0 +1,125 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "arel-helpers"
|
||||
|
||||
module Reporting
|
||||
module Queries
|
||||
class QueryInterface < ::ArelHelpers::QueryBuilder
|
||||
include Arel::Nodes
|
||||
|
||||
def coalesce(field, default = 0)
|
||||
NamedFunction.new("COALESCE", [field, default])
|
||||
end
|
||||
|
||||
def sum_values(field, default = 0)
|
||||
NamedFunction.new("SUM", [coalesce(field, default)])
|
||||
end
|
||||
|
||||
def sum_grouped(field, default = 0)
|
||||
Case.new(sql_grouping(grouping_fields)).when(0).then(field.maximum).else(field.sum)
|
||||
end
|
||||
|
||||
def sum_new(field, default = 0)
|
||||
Case.new(sql_grouping(grouping_fields)).when(0).then(field.maximum).else(sum_values(field))
|
||||
end
|
||||
|
||||
def round(field, places: 2)
|
||||
NamedFunction.new("ROUND", [field, places])
|
||||
end
|
||||
|
||||
def association(base_class, association, alias_node = nil, join_type = InnerJoin)
|
||||
options = alias_node.present? ? { aliases: [alias_node] } : {}
|
||||
|
||||
Arel.sql(base_class.join_association(association, join_type, options).first.to_sql)
|
||||
end
|
||||
|
||||
def arel_join(join)
|
||||
Arel.sql(join.first.to_sql)
|
||||
end
|
||||
|
||||
def join_source(join_association)
|
||||
join_association[0].right
|
||||
end
|
||||
|
||||
def default_value(field)
|
||||
field.maximum
|
||||
end
|
||||
|
||||
def default_blank(field)
|
||||
Case.new(sql_grouping(grouping_fields)).when(0).then(field.maximum).else(empty_string)
|
||||
end
|
||||
|
||||
def default_string(field, string)
|
||||
Case.new(sql_grouping(grouping_fields)).when(0).then(field.maximum).else(quoted(string))
|
||||
end
|
||||
|
||||
def default_summary(field)
|
||||
Case.new(sql_grouping(grouping_fields)).when(0).then(field.maximum).else(empty_string)
|
||||
end
|
||||
|
||||
def boolean_blank(field, true_string = I18n.t(:yes), false_string = I18n.t(:no))
|
||||
Case.new(sql_grouping(grouping_fields)).when(0).
|
||||
then(pretty_boolean(field, true_string, false_string).maximum).
|
||||
else(empty_string)
|
||||
end
|
||||
|
||||
def pretty_boolean(field, true_string, false_string)
|
||||
Case.new(field).when(true).
|
||||
then(Arel.sql("'#{true_string}'")).
|
||||
else(Arel.sql("'#{false_string}'"))
|
||||
end
|
||||
|
||||
def cast(field, type)
|
||||
NamedFunction.new("CAST", [field.as(type)])
|
||||
end
|
||||
|
||||
def null_if(field, nullif)
|
||||
NamedFunction.new("NULLIF", [field, nullif])
|
||||
end
|
||||
|
||||
def parenthesise(args)
|
||||
Grouping.new(args)
|
||||
end
|
||||
|
||||
def nullify_empty_strings(field)
|
||||
null_if(field, empty_string)
|
||||
end
|
||||
|
||||
def empty_string
|
||||
raw("''")
|
||||
end
|
||||
|
||||
def sql_concat(*args)
|
||||
NamedFunction.new("CONCAT", args)
|
||||
end
|
||||
|
||||
def raw(string)
|
||||
SqlLiteral.new(string)
|
||||
end
|
||||
|
||||
def quoted(string)
|
||||
Quoted.new(string)
|
||||
end
|
||||
|
||||
def sql_grouping(groupings = grouping_fields)
|
||||
NamedFunction.new("GROUPING", [groupings])
|
||||
end
|
||||
|
||||
def grouping_sets(groupings)
|
||||
GroupingSet.new(groupings)
|
||||
end
|
||||
|
||||
def sql_case(expression)
|
||||
Case.new(expression)
|
||||
end
|
||||
|
||||
def rollup(groupings)
|
||||
RollUp.new(groupings)
|
||||
end
|
||||
|
||||
def raw_result
|
||||
ActiveRecord::Base.connection.exec_query(query.to_sql)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
51
lib/reporting/queries/tables.rb
Normal file
51
lib/reporting/queries/tables.rb
Normal file
@@ -0,0 +1,51 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
module Queries
|
||||
module Tables
|
||||
def order_table
|
||||
Spree::Order.arel_table
|
||||
end
|
||||
|
||||
def line_item_table
|
||||
Spree::LineItem.arel_table
|
||||
end
|
||||
|
||||
def product_table
|
||||
Spree::Product.arel_table
|
||||
end
|
||||
|
||||
def variant_table
|
||||
Spree::Variant.arel_table
|
||||
end
|
||||
|
||||
def customer_table
|
||||
::Customer.arel_table
|
||||
end
|
||||
|
||||
def distributor_alias
|
||||
Enterprise.arel_table.alias(:order_distributor)
|
||||
end
|
||||
|
||||
def supplier_alias
|
||||
Enterprise.arel_table.alias(:product_supplier)
|
||||
end
|
||||
|
||||
def bill_address_alias
|
||||
Spree::Address.arel_table.alias(:bill_address)
|
||||
end
|
||||
|
||||
def managed_orders_alias
|
||||
Spree::Order.arel_table.alias(:managed_orders)
|
||||
end
|
||||
|
||||
def option_value_table
|
||||
Spree::OptionValue.arel_table
|
||||
end
|
||||
|
||||
def shipping_category_table
|
||||
Spree::ShippingCategory.arel_table
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reports
|
||||
module Reporting
|
||||
class ReportLoader
|
||||
delegate :report_subtypes, to: :base_class
|
||||
|
||||
@@ -12,7 +12,7 @@ module Reports
|
||||
def report_class
|
||||
"#{report_module}::#{report_subtype_class}".constantize
|
||||
rescue NameError
|
||||
raise Reports::Errors::ReportNotFound
|
||||
raise Reporting::Errors::ReportNotFound
|
||||
end
|
||||
|
||||
def default_report_subtype
|
||||
@@ -24,7 +24,7 @@ module Reports
|
||||
attr_reader :report_type, :report_subtype
|
||||
|
||||
def report_module
|
||||
"Reports::#{report_type.camelize}"
|
||||
"Reporting::Reports::#{report_type.camelize}"
|
||||
end
|
||||
|
||||
def report_subtype_class
|
||||
@@ -34,7 +34,7 @@ module Reports
|
||||
def base_class
|
||||
"#{report_module}::Base".constantize
|
||||
rescue NameError
|
||||
raise Reports::Errors::ReportNotFound
|
||||
raise Reporting::Errors::ReportNotFound
|
||||
end
|
||||
end
|
||||
end
|
||||
39
lib/reporting/report_renderer.rb
Normal file
39
lib/reporting/report_renderer.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spreadsheet_architect'
|
||||
|
||||
module Reporting
|
||||
class ReportRenderer
|
||||
def initialize(report)
|
||||
@report = report
|
||||
end
|
||||
|
||||
def table_headers
|
||||
@report.report_data.columns
|
||||
end
|
||||
|
||||
def table_rows
|
||||
@report.report_data.rows
|
||||
end
|
||||
|
||||
def as_json
|
||||
@report.report_data.as_json
|
||||
end
|
||||
|
||||
def as_arrays
|
||||
@as_arrays ||= [table_headers] + table_rows
|
||||
end
|
||||
|
||||
def to_csv
|
||||
SpreadsheetArchitect.to_csv(headers: table_headers, data: table_rows)
|
||||
end
|
||||
|
||||
def to_ods
|
||||
SpreadsheetArchitect.to_ods(headers: table_headers, data: table_rows)
|
||||
end
|
||||
|
||||
def to_xlsx
|
||||
SpreadsheetArchitect.to_xlsx(headers: table_headers, data: table_rows)
|
||||
end
|
||||
end
|
||||
end
|
||||
52
lib/reporting/report_template.rb
Normal file
52
lib/reporting/report_template.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
class ReportTemplate
|
||||
delegate :as_json, :as_arrays, :table_headers, :table_rows,
|
||||
:to_csv, :to_xlsx, :to_ods, :to_json, to: :renderer
|
||||
|
||||
attr_reader :options
|
||||
|
||||
SUBTYPES = []
|
||||
|
||||
def self.report_subtypes
|
||||
self::SUBTYPES
|
||||
end
|
||||
|
||||
def initialize(current_user, ransack_params, options = {})
|
||||
@current_user = current_user
|
||||
@ransack_params = ransack_params.with_indifferent_access
|
||||
@options = ( options || {} ).with_indifferent_access
|
||||
end
|
||||
|
||||
def report_data
|
||||
@report_data ||= report_query.raw_result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :current_user, :ransack_params
|
||||
|
||||
def renderer
|
||||
@renderer ||= ReportRenderer.new(self)
|
||||
end
|
||||
|
||||
def scoped_orders_relation
|
||||
visible_orders_relation.ransack(ransack_params).result
|
||||
end
|
||||
|
||||
def visible_orders_relation
|
||||
::Permissions::Order.new(current_user).
|
||||
visible_orders.complete.not_state(:canceled).
|
||||
select(:id).distinct
|
||||
end
|
||||
|
||||
def managed_orders_relation
|
||||
::Enterprise.managed_by(current_user).select(:id).distinct
|
||||
end
|
||||
|
||||
def i18n_scope
|
||||
"admin.reports"
|
||||
end
|
||||
end
|
||||
end
|
||||
41
lib/reporting/reports/packing/base.rb
Normal file
41
lib/reporting/reports/packing/base.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
module Reports
|
||||
module Packing
|
||||
class Base < ReportTemplate
|
||||
SUBTYPES = ["customer", "supplier"]
|
||||
|
||||
def primary_model
|
||||
Spree::LineItem
|
||||
end
|
||||
|
||||
def report_query
|
||||
Queries::QueryBuilder.new(primary_model, grouping_fields).
|
||||
scoped_to_orders(scoped_orders_relation).
|
||||
with_managed_orders(managed_orders_relation).
|
||||
joins_order_and_distributor.
|
||||
joins_order_customer.
|
||||
joins_order_bill_address.
|
||||
joins_variant.
|
||||
joins_variant_product.
|
||||
joins_product_supplier.
|
||||
joins_product_shipping_category.
|
||||
join_line_item_option_values.
|
||||
selecting(select_fields).
|
||||
grouped_in_sets(group_sets).
|
||||
ordered_by(ordering_fields)
|
||||
end
|
||||
|
||||
def grouping_fields
|
||||
lambda do
|
||||
[
|
||||
order_table[:id],
|
||||
line_item_table[:id]
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
49
lib/reporting/reports/packing/customer.rb
Normal file
49
lib/reporting/reports/packing/customer.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
module Reports
|
||||
module Packing
|
||||
class Customer < Base
|
||||
def select_fields
|
||||
lambda do
|
||||
{
|
||||
hub: default_blank(distributor_alias[:name]),
|
||||
customer_code: default_blank(masked(customer_table[:code])),
|
||||
first_name: default_blank(masked(bill_address_alias[:firstname])),
|
||||
last_name: default_blank(masked(bill_address_alias[:lastname])),
|
||||
supplier: default_blank(supplier_alias[:name]),
|
||||
product: default_string(product_table[:name], summary_row_title),
|
||||
variant: default_blank(variant_full_name),
|
||||
quantity: sum_values(line_item_table[:quantity]),
|
||||
temp_controlled: boolean_blank(shipping_category_table[:temperature_controlled]),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def ordering_fields
|
||||
lambda do
|
||||
[
|
||||
distributor_alias[:name],
|
||||
bill_address_alias[:lastname],
|
||||
order_table[:id],
|
||||
sql_grouping(grouping_fields),
|
||||
Arel.sql("supplier"),
|
||||
Arel.sql("product"),
|
||||
Arel.sql("variant"),
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
def group_sets
|
||||
lambda do
|
||||
[
|
||||
distributor_alias[:name],
|
||||
bill_address_alias[:lastname],
|
||||
grouping_sets([parenthesise(order_table[:id]), parenthesise(grouping_fields)])
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
48
lib/reporting/reports/packing/supplier.rb
Normal file
48
lib/reporting/reports/packing/supplier.rb
Normal file
@@ -0,0 +1,48 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
module Reports
|
||||
module Packing
|
||||
class Supplier < Base
|
||||
def select_fields
|
||||
lambda do
|
||||
{
|
||||
hub: default_blank(distributor_alias[:name]),
|
||||
supplier: default_blank(supplier_alias[:name]),
|
||||
customer_code: default_blank(customer_table[:code]),
|
||||
first_name: default_blank(bill_address_alias[:firstname]),
|
||||
last_name: default_blank(bill_address_alias[:lastname]),
|
||||
product: default_string(product_table[:name], summary_row_title),
|
||||
variant: default_blank(variant_full_name),
|
||||
quantity: sum_values(line_item_table[:quantity]),
|
||||
temp_controlled: boolean_blank(shipping_category_table[:temperature_controlled]),
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def group_sets
|
||||
lambda do
|
||||
[
|
||||
distributor_alias[:name],
|
||||
supplier_alias[:name],
|
||||
grouping_sets([parenthesise(supplier_alias[:name]), parenthesise(grouping_fields)])
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
def ordering_fields
|
||||
lambda do
|
||||
[
|
||||
distributor_alias[:name],
|
||||
supplier_alias[:name],
|
||||
sql_grouping(grouping_fields),
|
||||
Arel.sql("product"),
|
||||
Arel.sql("variant"),
|
||||
Arel.sql("supplier"),
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,17 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reports
|
||||
module Packing
|
||||
class Base < ReportTemplate
|
||||
SUBTYPES = ["customer", "supplier"]
|
||||
|
||||
|
||||
|
||||
private
|
||||
|
||||
def i18n_scope
|
||||
"admin.reports"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reports
|
||||
module Packing
|
||||
class Customer < Base
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reports
|
||||
module Packing
|
||||
class Supplier < Base
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,67 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spreadsheet_architect'
|
||||
|
||||
module Reports
|
||||
class ReportRenderer
|
||||
def initialize(report)
|
||||
@report = report
|
||||
end
|
||||
|
||||
def table_headers
|
||||
as_arrays.first
|
||||
end
|
||||
|
||||
def table_rows
|
||||
as_arrays.drop(1)
|
||||
end
|
||||
|
||||
def as_hashes
|
||||
report_rows
|
||||
end
|
||||
|
||||
def as_arrays
|
||||
@as_arrays ||= rows_as_arrays
|
||||
end
|
||||
|
||||
def to_csv
|
||||
SpreadsheetArchitect.to_csv(headers: table_headers, data: table_rows)
|
||||
end
|
||||
|
||||
def to_ods
|
||||
SpreadsheetArchitect.to_ods(headers: table_headers, data: table_rows)
|
||||
end
|
||||
|
||||
def to_xlsx
|
||||
SpreadsheetArchitect.to_xlsx(headers: table_headers, data: table_rows)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def report_rows
|
||||
@report.report_rows
|
||||
end
|
||||
|
||||
def rows_as_arrays
|
||||
report_array = [header_row]
|
||||
|
||||
report_rows.each do |row|
|
||||
report_array << row_or_summary(row)
|
||||
end
|
||||
|
||||
report_array
|
||||
end
|
||||
|
||||
def header_row
|
||||
report_rows.first.keys - [:summary_row_title]
|
||||
end
|
||||
|
||||
def row_or_summary(row)
|
||||
summary_row_title = row.delete :summary_row_title
|
||||
row_values = row.values
|
||||
row_values[0] = summary_row_title if summary_row_title
|
||||
|
||||
row_values
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,42 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reports
|
||||
class ReportTemplate
|
||||
delegate :as_hashes, :as_arrays, :table_headers, :table_rows,
|
||||
:to_csv, :to_xlsx, :to_ods, :to_json, to: :report_renderer
|
||||
|
||||
attr_reader :options
|
||||
attr_accessor :report_rows
|
||||
|
||||
SUBTYPES = []
|
||||
|
||||
def self.report_subtypes
|
||||
self::SUBTYPES
|
||||
end
|
||||
|
||||
def initialize(current_user, ransack_params, options = {})
|
||||
@current_user = current_user
|
||||
@ransack_params = ransack_params.with_indifferent_access
|
||||
@options = ( options || {} ).with_indifferent_access
|
||||
@report_rows = []
|
||||
|
||||
build_report
|
||||
end
|
||||
|
||||
def headers
|
||||
report_rows.first&.keys || []
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :current_user, :ransack_params
|
||||
|
||||
def build_report
|
||||
# TODO
|
||||
end
|
||||
|
||||
def report_renderer
|
||||
@report_renderer ||= ReportRenderer.new(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user