diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index 0804602b70..903227ac50 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -148,7 +148,6 @@ Metrics/LineLength: - lib/open_food_network/order_cycle_form_applicator.rb - lib/open_food_network/order_cycle_management_report.rb - lib/open_food_network/order_grouper.rb - - lib/open_food_network/orders_and_fulfillments_report.rb - lib/open_food_network/payments_report.rb - lib/open_food_network/permalink_generator.rb - lib/open_food_network/products_cache.rb @@ -454,7 +453,6 @@ Metrics/AbcSize: - lib/open_food_network/order_cycle_form_applicator.rb - lib/open_food_network/order_cycle_management_report.rb - lib/open_food_network/order_cycle_permissions.rb - - lib/open_food_network/orders_and_fulfillments_report.rb - lib/open_food_network/packing_report.rb - lib/open_food_network/payments_report.rb - lib/open_food_network/permissions.rb @@ -532,7 +530,6 @@ Metrics/CyclomaticComplexity: - lib/discourse/single_sign_on.rb - lib/open_food_network/bulk_coop_report.rb - lib/open_food_network/enterprise_issue_validator.rb - - lib/open_food_network/orders_and_fulfillments_report.rb - lib/spree/core/controller_helpers/order_decorator.rb - lib/spree/core/controller_helpers/respond_with_decorator.rb - lib/spree/localized_number.rb @@ -557,7 +554,6 @@ Metrics/PerceivedComplexity: - lib/discourse/single_sign_on.rb - lib/open_food_network/bulk_coop_report.rb - lib/open_food_network/enterprise_issue_validator.rb - - lib/open_food_network/orders_and_fulfillments_report.rb - lib/spree/core/controller_helpers/order_decorator.rb - lib/spree/core/controller_helpers/respond_with_decorator.rb - lib/spree/localized_number.rb @@ -627,7 +623,6 @@ Metrics/MethodLength: - lib/open_food_network/order_cycle_management_report.rb - lib/open_food_network/order_cycle_permissions.rb - lib/open_food_network/order_grouper.rb - - lib/open_food_network/orders_and_fulfillments_report.rb - lib/open_food_network/packing_report.rb - lib/open_food_network/payments_report.rb - lib/open_food_network/permissions.rb @@ -671,7 +666,6 @@ Metrics/ClassLength: - lib/open_food_network/order_cycle_form_applicator.rb - lib/open_food_network/order_cycle_management_report.rb - lib/open_food_network/order_cycle_permissions.rb - - lib/open_food_network/orders_and_fulfillments_report.rb - lib/open_food_network/packing_report.rb - lib/open_food_network/payments_report.rb - lib/open_food_network/permissions.rb diff --git a/lib/open_food_network/orders_and_fulfillments_report.rb b/lib/open_food_network/orders_and_fulfillments_report.rb index 0eaf26b54a..f5b810fb18 100644 --- a/lib/open_food_network/orders_and_fulfillments_report.rb +++ b/lib/open_food_network/orders_and_fulfillments_report.rb @@ -1,295 +1,53 @@ require "open_food_network/reports/line_items" +require "open_food_network/orders_and_fulfillments_report/supplier_totals_report" +require "open_food_network/orders_and_fulfillments_report/supplier_totals_by_distributor_report" +require "open_food_network/orders_and_fulfillments_report/distributor_totals_by_supplier_report" +require "open_food_network/orders_and_fulfillments_report/customer_totals_report" require 'open_food_network/orders_and_fulfillments_report/default_report' include Spree::ReportsHelper module OpenFoodNetwork class OrdersAndFulfillmentsReport - attr_reader :params - def initialize(permissions, params = {}, render_table = false) - @params = params + attr_reader :options, :report_type + + delegate :header, :rules, :columns, to: :report + + def initialize(permissions, options = {}, render_table = false) + @options = options + @report_type = options[:report_type] @permissions = permissions @render_table = render_table end - def header - case params[:report_type] - - when "order_cycle_supplier_totals" - [I18n.t(:report_header_producer), I18n.t(:report_header_product), I18n.t(:report_header_variant), I18n.t(:report_header_amount), - I18n.t(:report_header_total_units), I18n.t(:report_header_curr_cost_per_unit), I18n.t(:report_header_total_cost), - I18n.t(:report_header_status), I18n.t(:report_header_incoming_transport)] - when "order_cycle_supplier_totals_by_distributor" - [I18n.t(:report_header_producer), I18n.t(:report_header_product), I18n.t(:report_header_variant), I18n.t(:report_header_to_hub), - I18n.t(:report_header_amount), I18n.t(:report_header_curr_cost_per_unit), I18n.t(:report_header_total_cost), - I18n.t(:report_header_shipping_method)] - when "order_cycle_distributor_totals_by_supplier" - [I18n.t(:report_header_hub), I18n.t(:report_header_producer), I18n.t(:report_header_product), I18n.t(:report_header_variant), - I18n.t(:report_header_amount), I18n.t(:report_header_curr_cost_per_unit), I18n.t(:report_header_total_cost), - I18n.t(:report_header_total_shipping_cost), I18n.t(:report_header_shipping_method)] - when "order_cycle_customer_totals" - [I18n.t(:report_header_hub), I18n.t(:report_header_customer), I18n.t(:report_header_email), I18n.t(:report_header_phone), - I18n.t(:report_header_producer), I18n.t(:report_header_product), I18n.t(:report_header_variant), I18n.t(:report_header_amount), - I18n.t(:report_header_item_price, currency: currency_symbol), - I18n.t(:report_header_item_fees_price, currency: currency_symbol), - I18n.t(:report_header_admin_handling_fees, currency: currency_symbol), - I18n.t(:report_header_ship_price, currency: currency_symbol), - I18n.t(:report_header_pay_fee_price, currency: currency_symbol), - I18n.t(:report_header_total_price, currency: currency_symbol), - I18n.t(:report_header_paid), I18n.t(:report_header_shipping), I18n.t(:report_header_delivery), - I18n.t(:report_header_ship_street), I18n.t(:report_header_ship_street_2), I18n.t(:report_header_ship_city), I18n.t(:report_header_ship_postcode), I18n.t(:report_header_ship_state), - I18n.t(:report_header_comments), I18n.t(:report_header_sku), - I18n.t(:report_header_order_cycle), I18n.t(:report_header_payment_method), I18n.t(:report_header_customer_code), I18n.t(:report_header_tags), - I18n.t(:report_header_billing_street), I18n.t(:report_header_billing_street_2), I18n.t(:report_header_billing_city), I18n.t(:report_header_billing_postcode), I18n.t(:report_header_billing_state),] - else - DefaultReport.new(self).header - end - end - def search - Reports::LineItems.search_orders(permissions, params) + Reports::LineItems.search_orders(permissions, options) end def table_items return [] unless @render_table - Reports::LineItems.list(permissions, params) - end - - def rules - case params[:report_type] - when "order_cycle_supplier_totals" - [ - { - group_by: proc { |line_item| line_item.variant.product.supplier }, - sort_by: proc { |supplier| supplier.name } - }, - { - group_by: proc { |line_item| line_item.variant.product }, - sort_by: proc { |product| product.name } - }, - { - group_by: proc { |line_item| line_item.variant.full_name }, - sort_by: proc { |full_name| full_name } - } - ] - when "order_cycle_supplier_totals_by_distributor" - [ - { - group_by: proc { |line_item| line_item.variant.product.supplier }, - sort_by: proc { |supplier| supplier.name } - }, - { - group_by: proc { |line_item| line_item.variant.product }, - sort_by: proc { |product| product.name } - }, - { - group_by: proc { |line_item| line_item.variant.full_name }, - sort_by: proc { |full_name| full_name }, - summary_columns: [ - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| I18n.t('admin.reports.total') }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |line_items| line_items.sum(&:amount) }, - proc { |_line_items| "" } - ] - }, - { - group_by: proc { |line_item| line_item.order.distributor }, - sort_by: proc { |distributor| distributor.name } - } - ] - when "order_cycle_distributor_totals_by_supplier" - [ - { - group_by: proc { |line_item| line_item.order.distributor }, - sort_by: proc { |distributor| distributor.name }, - summary_columns: [ - proc { |_line_items| "" }, - proc { |_line_items| I18n.t('admin.reports.total') }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |line_items| line_items.sum(&:amount) }, - proc { |line_items| line_items.map(&:order).uniq.sum(&:ship_total) }, - proc { |_line_items| "" } - ] - }, - { - group_by: proc { |line_item| line_item.variant.product.supplier }, - sort_by: proc { |supplier| supplier.name } - }, - { - group_by: proc { |line_item| line_item.variant.product }, - sort_by: proc { |product| product.name } - }, - { - group_by: proc { |line_item| line_item.variant.full_name }, - sort_by: proc { |full_name| full_name } - } - ] - when "order_cycle_customer_totals" - [ - { - group_by: proc { |line_item| line_item.order.distributor }, - sort_by: proc { |distributor| distributor.name } - }, - { - group_by: proc { |line_item| line_item.order }, - sort_by: proc { |order| order.bill_address.full_name_reverse }, - summary_columns: [ - proc { |line_items| line_items.first.order.distributor.name }, - proc { |line_items| line_items.first.order.bill_address.full_name }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| I18n.t('admin.reports.total') }, - proc { |_line_items| "" }, - - proc { |_line_items| "" }, - proc { |line_items| line_items.sum(&:amount) }, - proc { |line_items| line_items.sum(&:amount_with_adjustments) }, - proc { |line_items| line_items.first.order.admin_and_handling_total }, - proc { |line_items| line_items.first.order.ship_total }, - proc { |line_items| line_items.first.order.payment_fee }, - proc { |line_items| line_items.first.order.total }, - proc { |line_items| line_items.first.order.paid? ? I18n.t(:yes) : I18n.t(:no) }, - - proc { |_line_items| "" }, - proc { |_line_items| "" }, - - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - - proc { |line_items| line_items.first.order.special_instructions }, - proc { |_line_items| "" }, - - proc { |line_items| line_items.first.order.order_cycle.andand.name }, - proc { |line_items| - line_items.first.order.payments.first.andand.payment_method.andand.name - }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" } - ] - }, - { - group_by: proc { |line_item| line_item.variant.product }, - sort_by: proc { |product| product.name } - }, - { - group_by: proc { |line_item| line_item.variant }, - sort_by: proc { |variant| variant.full_name } - }, - { - group_by: line_item_name, - sort_by: proc { |full_name| full_name } - } - ] - else - DefaultReport.new(self).rules - end - end - - # Returns a proc for each column displayed in each report type containing - # the logic to compute the value for each cell. - def columns - case params[:report_type] - when "order_cycle_supplier_totals" - [ - supplier_name, - product_name, - line_items_name, - proc { |line_items| line_items.sum(&:quantity) }, - proc { |line_items| total_units(line_items) }, - proc { |line_items| line_items.first.price }, - proc { |line_items| line_items.sum(&:amount) }, - proc { |_line_items| "" }, - proc { |_line_items| I18n.t(:report_header_incoming_transport) } - ] - when "order_cycle_supplier_totals_by_distributor" - [ - supplier_name, - proc { |line_items| line_items.first.variant.product.name }, - proc { |line_items| line_items.first.variant.full_name }, - proc { |line_items| line_items.first.order.distributor.name }, - proc { |line_items| line_items.sum(&:quantity) }, - proc { |line_items| line_items.first.price }, - proc { |line_items| line_items.sum(&:amount) }, - proc { |_line_items| I18n.t(:report_header_shipping_method) } - ] - when "order_cycle_distributor_totals_by_supplier" - [proc { |line_items| line_items.first.order.distributor.name }, - proc { |line_items| line_items.first.variant.product.supplier.name }, - proc { |line_items| line_items.first.variant.product.name }, - proc { |line_items| line_items.first.variant.full_name }, - proc { |line_items| line_items.sum(&:quantity) }, - proc { |line_items| line_items.first.price }, - proc { |line_items| line_items.sum(&:amount) }, - proc { |_line_items| "" }, - proc { |_line_items| I18n.t(:report_header_shipping_method) }] - when "order_cycle_customer_totals" - rsa = proc { |line_items| line_items.first.order.shipping_method.andand.delivery? } - [ - proc { |line_items| line_items.first.order.distributor.name }, - proc { |line_items| line_items.first.order.bill_address.firstname + " " + line_items.first.order.bill_address.lastname }, - proc { |line_items| line_items.first.order.email }, - proc { |line_items| line_items.first.order.bill_address.phone }, - proc { |line_items| line_items.first.variant.product.supplier.name }, - proc { |line_items| line_items.first.variant.product.name }, - proc { |line_items| line_items.first.variant.full_name }, - - proc { |line_items| line_items.sum(&:quantity) }, - proc { |line_items| line_items.sum(&:amount) }, - proc { |line_items| line_items.sum(&:amount_with_adjustments) }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |_line_items| "" }, - proc { |line_items| line_items.all? { |li| li.order.paid? } ? I18n.t(:yes) : I18n.t(:no) }, - - proc { |line_items| line_items.first.order.shipping_method.andand.name }, - proc { |line_items| rsa.call(line_items) ? I18n.t(:yes) : I18n.t(:no) }, - - proc { |line_items| line_items.first.order.ship_address.andand.address1 if rsa.call(line_items) }, - proc { |line_items| line_items.first.order.ship_address.andand.address2 if rsa.call(line_items) }, - proc { |line_items| line_items.first.order.ship_address.andand.city if rsa.call(line_items) }, - proc { |line_items| line_items.first.order.ship_address.andand.zipcode if rsa.call(line_items) }, - proc { |line_items| line_items.first.order.ship_address.andand.state if rsa.call(line_items) }, - - proc { |_line_items| "" }, - proc { |line_items| line_items.first.variant.sku }, - - proc { |line_items| line_items.first.order.order_cycle.andand.name }, - proc { |line_items| line_items.first.order.payments.first.andand.payment_method.andand.name }, - proc { |line_items| line_items.first.order.user.andand.customer_of(line_items.first.order.distributor).andand.code }, - proc { |line_items| line_items.first.order.user.andand.customer_of(line_items.first.order.distributor).andand.tags.andand.join(', ') }, - - proc { |line_items| line_items.first.order.bill_address.andand.address1 }, - proc { |line_items| line_items.first.order.bill_address.andand.address2 }, - proc { |line_items| line_items.first.order.bill_address.andand.city }, - proc { |line_items| line_items.first.order.bill_address.andand.zipcode }, - proc { |line_items| line_items.first.order.bill_address.andand.state } - ] - else - DefaultReport.new(self).columns - end + Reports::LineItems.list(permissions, options) end private attr_reader :permissions + def report + @report ||= report_klass.new(self) + end + + def report_klass + case report_type + when SupplierTotalsReport::REPORT_TYPE then SupplierTotalsReport + when SupplierTotalsByDistributorReport::REPORT_TYPE then SupplierTotalsByDistributorReport + when DistributorTotalsBySupplierReport::REPORT_TYPE then DistributorTotalsBySupplierReport + when CustomerTotalsReport::REPORT_TYPE then CustomerTotalsReport + else + DefaultReport + end + end + def supplier_name proc { |line_items| line_items.first.variant.product.supplier.name } end diff --git a/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb b/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb new file mode 100644 index 0000000000..24a5769a57 --- /dev/null +++ b/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb @@ -0,0 +1,194 @@ +# rubocop:disable Metrics/ClassLength +module OpenFoodNetwork + class OrdersAndFulfillmentsReport + class CustomerTotalsReport + REPORT_TYPE = "order_cycle_customer_totals".freeze + + attr_reader :context + + delegate :line_item_name, to: :context + + def initialize(context) + @context = context + end + + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength + def header + [I18n.t(:report_header_hub), I18n.t(:report_header_customer), I18n.t(:report_header_email), + I18n.t(:report_header_phone), I18n.t(:report_header_producer), + I18n.t(:report_header_product), I18n.t(:report_header_variant), + I18n.t(:report_header_amount), + I18n.t(:report_header_item_price, currency: currency_symbol), + I18n.t(:report_header_item_fees_price, currency: currency_symbol), + I18n.t(:report_header_admin_handling_fees, currency: currency_symbol), + I18n.t(:report_header_ship_price, currency: currency_symbol), + I18n.t(:report_header_pay_fee_price, currency: currency_symbol), + I18n.t(:report_header_total_price, currency: currency_symbol), + I18n.t(:report_header_paid), I18n.t(:report_header_shipping), + I18n.t(:report_header_delivery), I18n.t(:report_header_ship_street), + I18n.t(:report_header_ship_street_2), I18n.t(:report_header_ship_city), + I18n.t(:report_header_ship_postcode), I18n.t(:report_header_ship_state), + I18n.t(:report_header_comments), I18n.t(:report_header_sku), + I18n.t(:report_header_order_cycle), I18n.t(:report_header_payment_method), + I18n.t(:report_header_customer_code), I18n.t(:report_header_tags), + I18n.t(:report_header_billing_street), I18n.t(:report_header_billing_street_2), + I18n.t(:report_header_billing_city), I18n.t(:report_header_billing_postcode), + I18n.t(:report_header_billing_state)] + end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/MethodLength + + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength + def rules + [ + { + group_by: proc { |line_item| line_item.order.distributor }, + sort_by: proc { |distributor| distributor.name } + }, + { + group_by: proc { |line_item| line_item.order }, + sort_by: proc { |order| order.bill_address.full_name_reverse }, + summary_columns: [ + proc { |line_items| line_items.first.order.distributor.name }, + proc { |line_items| line_items.first.order.bill_address.full_name }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| I18n.t('admin.reports.total') }, + proc { |_line_items| "" }, + + proc { |_line_items| "" }, + proc { |line_items| line_items.sum(&:amount) }, + proc { |line_items| line_items.sum(&:amount_with_adjustments) }, + proc { |line_items| line_items.first.order.admin_and_handling_total }, + proc { |line_items| line_items.first.order.ship_total }, + proc { |line_items| line_items.first.order.payment_fee }, + proc { |line_items| line_items.first.order.total }, + proc { |line_items| line_items.first.order.paid? ? I18n.t(:yes) : I18n.t(:no) }, + + proc { |_line_items| "" }, + proc { |_line_items| "" }, + + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + + proc { |line_items| line_items.first.order.special_instructions }, + proc { |_line_items| "" }, + + proc { |line_items| line_items.first.order.order_cycle.andand.name }, + proc { |line_items| + line_items.first.order.payments.first.andand.payment_method.andand.name + }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" } + ] + }, + { + group_by: proc { |line_item| line_item.variant.product }, + sort_by: proc { |product| product.name } + }, + { + group_by: proc { |line_item| line_item.variant }, + sort_by: proc { |variant| variant.full_name } + }, + { + group_by: line_item_name, + sort_by: proc { |full_name| full_name } + } + ] + end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/MethodLength + + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/CyclomaticComplexity + # rubocop:disable Metrics/MethodLength + # rubocop:disable Metrics/PerceivedComplexity + def columns + rsa = proc { |line_items| line_items.first.order.shipping_method.andand.delivery? } + [ + proc { |line_items| line_items.first.order.distributor.name }, + proc { |line_items| + bill_address = line_items.first.order.bill_address + bill_address.firstname + " " + bill_address.lastname + }, + proc { |line_items| line_items.first.order.email }, + proc { |line_items| line_items.first.order.bill_address.phone }, + proc { |line_items| line_items.first.variant.product.supplier.name }, + proc { |line_items| line_items.first.variant.product.name }, + proc { |line_items| line_items.first.variant.full_name }, + + proc { |line_items| line_items.sum(&:quantity) }, + proc { |line_items| line_items.sum(&:amount) }, + proc { |line_items| line_items.sum(&:amount_with_adjustments) }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |line_items| + line_items.all? { |li| li.order.paid? } ? I18n.t(:yes) : I18n.t(:no) + }, + + proc { |line_items| line_items.first.order.shipping_method.andand.name }, + proc { |line_items| rsa.call(line_items) ? I18n.t(:yes) : I18n.t(:no) }, + + proc { |line_items| + line_items.first.order.ship_address.andand.address1 if rsa.call(line_items) + }, + proc { |line_items| + line_items.first.order.ship_address.andand.address2 if rsa.call(line_items) + }, + proc { |line_items| + line_items.first.order.ship_address.andand.city if rsa.call(line_items) + }, + proc { |line_items| + line_items.first.order.ship_address.andand.zipcode if rsa.call(line_items) + }, + proc { |line_items| + line_items.first.order.ship_address.andand.state if rsa.call(line_items) + }, + + proc { |_line_items| "" }, + proc { |line_items| line_items.first.variant.sku }, + + proc { |line_items| line_items.first.order.order_cycle.andand.name }, + proc { |line_items| + payment = line_items.first.order.payments.first + payment.andand.payment_method.andand.name + }, + proc { |line_items| + distributor = line_items.first.order.distributor + user = line_items.first.order.user + user.andand.customer_of(distributor).andand.code + }, + proc { |line_items| + distributor = line_items.first.order.distributor + user = line_items.first.order.user + user.andand.customer_of(distributor).andand.tags.andand.join(', ') + }, + + proc { |line_items| line_items.first.order.bill_address.andand.address1 }, + proc { |line_items| line_items.first.order.bill_address.andand.address2 }, + proc { |line_items| line_items.first.order.bill_address.andand.city }, + proc { |line_items| line_items.first.order.bill_address.andand.zipcode }, + proc { |line_items| line_items.first.order.bill_address.andand.state } + ] + end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/CyclomaticComplexity + # rubocop:enable Metrics/MethodLength + # rubocop:enable Metrics/PerceivedComplexity + end + end +end +# rubocop:enable Metrics/ClassLength diff --git a/lib/open_food_network/orders_and_fulfillments_report/distributor_totals_by_supplier_report.rb b/lib/open_food_network/orders_and_fulfillments_report/distributor_totals_by_supplier_report.rb new file mode 100644 index 0000000000..e9ee219ac8 --- /dev/null +++ b/lib/open_food_network/orders_and_fulfillments_report/distributor_totals_by_supplier_report.rb @@ -0,0 +1,71 @@ +module OpenFoodNetwork + class OrdersAndFulfillmentsReport + class DistributorTotalsBySupplierReport + REPORT_TYPE = "order_cycle_distributor_totals_by_supplier".freeze + + attr_reader :context + + def initialize(context) + @context = context + end + + def header + [I18n.t(:report_header_hub), I18n.t(:report_header_producer), + I18n.t(:report_header_product), I18n.t(:report_header_variant), + I18n.t(:report_header_amount), I18n.t(:report_header_curr_cost_per_unit), + I18n.t(:report_header_total_cost), I18n.t(:report_header_total_shipping_cost), + I18n.t(:report_header_shipping_method)] + end + + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength + def rules + [ + { + group_by: proc { |line_item| line_item.order.distributor }, + sort_by: proc { |distributor| distributor.name }, + summary_columns: [ + proc { |_line_items| "" }, + proc { |_line_items| I18n.t('admin.reports.total') }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |line_items| line_items.sum(&:amount) }, + proc { |line_items| line_items.map(&:order).uniq.sum(&:ship_total) }, + proc { |_line_items| "" } + ] + }, + { + group_by: proc { |line_item| line_item.variant.product.supplier }, + sort_by: proc { |supplier| supplier.name } + }, + { + group_by: proc { |line_item| line_item.variant.product }, + sort_by: proc { |product| product.name } + }, + { + group_by: proc { |line_item| line_item.variant.full_name }, + sort_by: proc { |full_name| full_name } + } + ] + end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/MethodLength + + # rubocop:disable Metrics/AbcSize + def columns + [proc { |line_items| line_items.first.order.distributor.name }, + proc { |line_items| line_items.first.variant.product.supplier.name }, + proc { |line_items| line_items.first.variant.product.name }, + proc { |line_items| line_items.first.variant.full_name }, + proc { |line_items| line_items.sum(&:quantity) }, + proc { |line_items| line_items.first.price }, + proc { |line_items| line_items.sum(&:amount) }, + proc { |_line_items| "" }, + proc { |_line_items| I18n.t(:report_header_shipping_method) }] + end + # rubocop:enable Metrics/AbcSize + end + end +end diff --git a/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_by_distributor_report.rb b/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_by_distributor_report.rb new file mode 100644 index 0000000000..dd578058e2 --- /dev/null +++ b/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_by_distributor_report.rb @@ -0,0 +1,72 @@ +module OpenFoodNetwork + class OrdersAndFulfillmentsReport + class SupplierTotalsByDistributorReport + REPORT_TYPE = "order_cycle_supplier_totals_by_distributor".freeze + + attr_reader :context + + delegate :supplier_name, to: :context + + def initialize(context) + @context = context + end + + def header + [I18n.t(:report_header_producer), I18n.t(:report_header_product), + I18n.t(:report_header_variant), I18n.t(:report_header_to_hub), + I18n.t(:report_header_amount), I18n.t(:report_header_curr_cost_per_unit), + I18n.t(:report_header_total_cost), I18n.t(:report_header_shipping_method)] + end + + # rubocop:disable Metrics/AbcSize + # rubocop:disable Metrics/MethodLength + def rules + [ + { + group_by: proc { |line_item| line_item.variant.product.supplier }, + sort_by: proc { |supplier| supplier.name } + }, + { + group_by: proc { |line_item| line_item.variant.product }, + sort_by: proc { |product| product.name } + }, + { + group_by: proc { |line_item| line_item.variant.full_name }, + sort_by: proc { |full_name| full_name }, + summary_columns: [ + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |_line_items| I18n.t('admin.reports.total') }, + proc { |_line_items| "" }, + proc { |_line_items| "" }, + proc { |line_items| line_items.sum(&:amount) }, + proc { |_line_items| "" } + ] + }, + { + group_by: proc { |line_item| line_item.order.distributor }, + sort_by: proc { |distributor| distributor.name } + } + ] + end + # rubocop:enable Metrics/AbcSize + # rubocop:enable Metrics/MethodLength + + # rubocop:disable Metrics/AbcSize + def columns + [ + supplier_name, + proc { |line_items| line_items.first.variant.product.name }, + proc { |line_items| line_items.first.variant.full_name }, + proc { |line_items| line_items.first.order.distributor.name }, + proc { |line_items| line_items.sum(&:quantity) }, + proc { |line_items| line_items.first.price }, + proc { |line_items| line_items.sum(&:amount) }, + proc { |_line_items| I18n.t(:report_header_shipping_method) } + ] + end + # rubocop:enable Metrics/AbcSize + end + end +end diff --git a/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_report.rb b/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_report.rb new file mode 100644 index 0000000000..666cc1473e --- /dev/null +++ b/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_report.rb @@ -0,0 +1,58 @@ +module OpenFoodNetwork + class OrdersAndFulfillmentsReport + class SupplierTotalsReport + REPORT_TYPE = "order_cycle_supplier_totals".freeze + + attr_reader :context + + delegate :supplier_name, :product_name, :line_items_name, :total_units, to: :context + + def initialize(context) + @context = context + end + + def header + [I18n.t(:report_header_producer), I18n.t(:report_header_product), + I18n.t(:report_header_variant), I18n.t(:report_header_amount), + I18n.t(:report_header_total_units), I18n.t(:report_header_curr_cost_per_unit), + I18n.t(:report_header_total_cost), I18n.t(:report_header_status), + I18n.t(:report_header_incoming_transport)] + end + + # rubocop:disable Metrics/MethodLength + def rules + [ + { + group_by: proc { |line_item| line_item.variant.product.supplier }, + sort_by: proc { |supplier| supplier.name } + }, + { + group_by: proc { |line_item| line_item.variant.product }, + sort_by: proc { |product| product.name } + }, + { + group_by: proc { |line_item| line_item.variant.full_name }, + sort_by: proc { |full_name| full_name } + } + ] + end + # rubocop:enable Metrics/MethodLength + + # rubocop:disable Metrics/MethodLength + def columns + [ + supplier_name, + product_name, + line_items_name, + proc { |line_items| line_items.sum(&:quantity) }, + proc { |line_items| total_units(line_items) }, + proc { |line_items| line_items.first.price }, + proc { |line_items| line_items.sum(&:amount) }, + proc { |_line_items| "" }, + proc { |_line_items| I18n.t(:report_header_incoming_transport) } + ] + end + # rubocop:enable Metrics/MethodLength + end + end +end diff --git a/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb b/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb new file mode 100644 index 0000000000..c53398e2c6 --- /dev/null +++ b/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb @@ -0,0 +1,39 @@ +require "spec_helper" + +RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::CustomerTotalsReport do + let!(:distributor) { create(:distributor_enterprise) } + + let!(:customer) { create(:customer, enterprise: distributor) } + + let!(:order) do + create(:completed_order_with_totals, line_items_count: 1, user: customer.user, + customer: customer, distributor: distributor) + end + + let(:current_user) { distributor.owner } + let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) } + + let(:report) do + report_options = { report_type: described_class::REPORT_TYPE } + OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true) + end + + let(:report_table) do + OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items) + end + + it "generates the report" do + expect(report_table.length).to eq(2) + end + + it "has a line item row" do + distributor_name_field = report_table.first[0] + expect(distributor_name_field).to eq distributor.name + + customer_name_field = report_table.first[1] + expect(customer_name_field).to eq order.bill_address.full_name + + total_field = report_table.last[5] + expect(total_field).to eq I18n.t("admin.reports.total") + end +end diff --git a/spec/lib/open_food_network/orders_and_fulfillments_report/distributor_totals_by_supplier_report_spec.rb b/spec/lib/open_food_network/orders_and_fulfillments_report/distributor_totals_by_supplier_report_spec.rb new file mode 100644 index 0000000000..4b0b721caf --- /dev/null +++ b/spec/lib/open_food_network/orders_and_fulfillments_report/distributor_totals_by_supplier_report_spec.rb @@ -0,0 +1,37 @@ +require "spec_helper" + +RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::DistributorTotalsBySupplierReport do + let!(:distributor) { create(:distributor_enterprise) } + + let!(:order) do + create(:completed_order_with_totals, line_items_count: 1, distributor: distributor) + end + + let(:current_user) { distributor.owner } + let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) } + + let(:report) do + report_options = { report_type: described_class::REPORT_TYPE } + OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true) + end + + let(:report_table) do + OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items) + end + + it "generates the report" do + expect(report_table.length).to eq(2) + end + + it "has a variant row under the distributor" do + distributor_name_field = report_table.first[0] + expect(distributor_name_field).to eq distributor.name + + supplier = order.line_items.first.variant.product.supplier + supplier_name_field = report_table.first[1] + expect(supplier_name_field).to eq supplier.name + + total_field = report_table.last[1] + expect(total_field).to eq I18n.t("admin.reports.total") + end +end diff --git a/spec/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_by_distributor_report_spec.rb b/spec/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_by_distributor_report_spec.rb new file mode 100644 index 0000000000..f22ec80bae --- /dev/null +++ b/spec/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_by_distributor_report_spec.rb @@ -0,0 +1,37 @@ +require "spec_helper" + +RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::SupplierTotalsByDistributorReport do + let!(:distributor) { create(:distributor_enterprise) } + + let!(:order) do + create(:completed_order_with_totals, line_items_count: 1, distributor: distributor) + end + + let(:current_user) { distributor.owner } + let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) } + + let(:report) do + report_options = { report_type: described_class::REPORT_TYPE } + OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true) + end + + let(:report_table) do + OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items) + end + + it "generates the report" do + expect(report_table.length).to eq(2) + end + + it "has a variant row under the distributor" do + supplier = order.line_items.first.variant.product.supplier + supplier_name_field = report_table.first[0] + expect(supplier_name_field).to eq supplier.name + + distributor_name_field = report_table.first[3] + expect(distributor_name_field).to eq distributor.name + + total_field = report_table.last[3] + expect(total_field).to eq I18n.t("admin.reports.total") + end +end diff --git a/spec/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_report_spec.rb b/spec/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_report_spec.rb new file mode 100644 index 0000000000..143bc953e5 --- /dev/null +++ b/spec/lib/open_food_network/orders_and_fulfillments_report/supplier_totals_report_spec.rb @@ -0,0 +1,31 @@ +require "spec_helper" + +RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::SupplierTotalsReport do + let!(:distributor) { create(:distributor_enterprise) } + + let!(:order) do + create(:completed_order_with_totals, line_items_count: 1, distributor: distributor) + end + + let(:current_user) { distributor.owner } + let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) } + + let(:report) do + report_options = { report_type: described_class::REPORT_TYPE } + OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true) + end + + let(:report_table) do + OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items) + end + + it "generates the report" do + expect(report_table.length).to eq(1) + end + + it "has a variant row" do + supplier = order.line_items.first.variant.product.supplier + supplier_name_field = report_table.first[0] + expect(supplier_name_field).to eq supplier.name + end +end