diff --git a/lib/reporting/report_template.rb b/lib/reporting/report_template.rb index ca771fc269..9ba56b9e5b 100644 --- a/lib/reporting/report_template.rb +++ b/lib/reporting/report_template.rb @@ -9,11 +9,9 @@ module Reporting delegate :formatted_rules, :header_option?, :summary_row_option?, to: :ruler delegate :grouped_data, :rows, to: :grouper - OPTIONAL_HEADERS = [].freeze - - def initialize(user, params) + def initialize(user, params = {}) @user = user - @params = params || {} + @params = params @params = @params.permit!.to_h unless @params.is_a? Hash @ransack_params = @params[:q] || {} end diff --git a/lib/reporting/reports/bulk_coop/allocation.rb b/lib/reporting/reports/bulk_coop/allocation.rb new file mode 100644 index 0000000000..4805a90d73 --- /dev/null +++ b/lib/reporting/reports/bulk_coop/allocation.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module Reporting + module Reports + module BulkCoop + class Allocation < Base + def query_result + table_items.group_by(&:order).values + end + + def columns + { + customer: :order_billing_address_name, + product: :product_name, + bulk_unit_size: :product_group_buy_unit_size, + variant: :full_name, + variant_value: :option_value_value, + variant_unit: :option_value_unit, + weight: :weight_from_unit_value, + sum_total: :total_amount, + total_available: :empty_cell, + unallocated: :empty_cell, + max_quantity_excess: :empty_cell + } + end + + def rules + [ + { + group_by: :product, + header: true, + summary_row: proc do |_key, items, rows| + line_items = items.flatten + { + sum_total: rows.sum(&:sum_total), + total_available: total_available(line_items), + unallocated: remainder(line_items), + max_quantity_excess: max_quantity_excess(line_items) + } + end + } + ] + end + end + end + end +end diff --git a/lib/reporting/reports/bulk_coop/base.rb b/lib/reporting/reports/bulk_coop/base.rb new file mode 100644 index 0000000000..c09bc656d6 --- /dev/null +++ b/lib/reporting/reports/bulk_coop/base.rb @@ -0,0 +1,131 @@ +# frozen_string_literal: true + +module Reporting + module Reports + module BulkCoop + class Base < ReportObjectTemplate + def message + I18n.t("spree.admin.reports.customer_names_message.customer_names_tip") + end + + def search + report_line_items.orders + end + + def table_items + report_line_items.list(line_item_includes) + end + + private + + def line_item_includes + [ + { + order: [:bill_address], + variant: [{ option_values: :option_type }, { product: :supplier }] + }, + :option_values + ] + end + + def order_permissions + @order_permissions ||= ::Permissions::Order.new(@user) + end + + def report_line_items + @report_line_items ||= Reporting::LineItems.new( + order_permissions, + @params, + CompleteVisibleOrders.new(order_permissions).query + ) + end + + def empty_cell(_line_items) + "" + end + + def full_name(line_items) + line_items.first.full_name + end + + def group_buy_unit_size(line_items) + unit_size = line_items.first.variant.product.group_buy_unit_size || 0.0 + unit_size / (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 scaled_unit_value(variant) + (variant.unit_value || 0) / (variant.product.variant_unit_scale || 1) + end + + def option_value_value(line_items) + VariantUnits::OptionValueNamer.new(line_items.first).value + end + + def option_value_unit(line_items) + VariantUnits::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 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 remainder(line_items) + remainder = total_available(line_items) - total_amount(line_items) + remainder >= 0 ? remainder : '' + end + + def total_amount(line_items) + line_items.sum { |li| scaled_final_weight_volume(li) } + end + + def scaled_final_weight_volume(line_item) + (line_item.final_weight_volume || 0) / (line_item.product.variant_unit_scale || 1) + end + + def total_available(line_items) + units_required(line_items) * group_buy_unit_size(line_items) + 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 weight_from_unit_value(line_items) + line_items.first.weight_from_unit_value || 0 + end + end + end + end +end diff --git a/lib/reporting/reports/bulk_coop/bulk_coop_allocation_report.rb b/lib/reporting/reports/bulk_coop/bulk_coop_allocation_report.rb deleted file mode 100644 index 8295b04a93..0000000000 --- a/lib/reporting/reports/bulk_coop/bulk_coop_allocation_report.rb +++ /dev/null @@ -1,67 +0,0 @@ -# frozen_string_literal: true - -module Reporting - module Reports - module BulkCoop - class BulkCoopAllocationReport - def table_headers - [ - 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 diff --git a/lib/reporting/reports/bulk_coop/bulk_coop_report.rb b/lib/reporting/reports/bulk_coop/bulk_coop_report.rb deleted file mode 100644 index 62cb436868..0000000000 --- a/lib/reporting/reports/bulk_coop/bulk_coop_report.rb +++ /dev/null @@ -1,317 +0,0 @@ -# frozen_string_literal: true - -module Reporting - module Reports - module BulkCoop - class BulkCoopReport < ReportObjectTemplate - def initialize(user, params = {}) - super(user, params) - - @supplier_report = BulkCoopSupplierReport.new - @allocation_report = BulkCoopAllocationReport.new - @filter_canceled = false - end - - def message - I18n.t("spree.admin.reports.customer_names_message.customer_names_tip") - end - - def table_headers - case params[:report_subtype] - when "bulk_coop_supplier_report" - @supplier_report.table_headers - when "bulk_coop_allocation" - @allocation_report.table_headers - 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 - report_line_items.list(line_item_includes) - end - - def table_rows - order_grouper = Reporting::OrderGrouper.new rules, columns, self - order_grouper.table(table_items) - end - - def rules - case params[:report_subtype] - 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| - ( if (lis.first.product.group_buy_unit_size || 0).zero? - 0 - else - ( lis.sum { |li| - [li.max_quantity || 0, - li.quantity || 0].max * (li.weight_from_unit_value || 0) - } / lis.first.product.group_buy_unit_size ) - end ).floor - }, - proc { |lis| - lis.sum { |li| - [li.max_quantity || 0, - li.quantity || 0].max * (li.weight_from_unit_value || 0) - } - ( ( if (lis.first.product.group_buy_unit_size || 0).zero? - 0 - else - ( lis.sum { |li| - [li.max_quantity || 0, - li.quantity || 0].max * (li.weight_from_unit_value || 0) - } / lis.first.product.group_buy_unit_size ) - end ).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_subtype] - 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 - - attr_reader :filter_canceled - - def line_item_includes - [ - { - order: [:bill_address], - variant: [{ option_values: :option_type }, { product: :supplier }] - }, - :option_values - ] - end - - def order_permissions - @order_permissions ||= ::Permissions::Order.new(@user, filter_canceled) - end - - def report_line_items - @report_line_items ||= Reporting::LineItems.new( - order_permissions, - @params, - CompleteVisibleOrders.new(order_permissions).query - ) - end - - def customer_payments_total_cost(line_items) - unique_orders(line_items).sum(&:total) - end - - def customer_payments_amount_owed(line_items) - unique_orders(line_items).sum(&:new_outstanding_balance) - end - - def customer_payments_amount_paid(line_items) - unique_orders(line_items).sum(&:payment_total) - end - - def unique_orders(line_items) - line_items.map(&:order).uniq - end - - def empty_cell(_line_items) - "" - end - - def full_name(line_items) - line_items.first.full_name - end - - def group_buy_unit_size(line_items) - unit_size = line_items.first.variant.product.group_buy_unit_size || 0.0 - unit_size / (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) - VariantUnits::OptionValueNamer.new(line_items.first).value - end - - def option_value_unit(line_items) - VariantUnits::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(_line_items) - 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 diff --git a/lib/reporting/reports/bulk_coop/bulk_coop_supplier_report.rb b/lib/reporting/reports/bulk_coop/bulk_coop_supplier_report.rb deleted file mode 100644 index 1806105424..0000000000 --- a/lib/reporting/reports/bulk_coop/bulk_coop_supplier_report.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -module Reporting - module Reports - module BulkCoop - class BulkCoopSupplierReport - def table_headers - [ - 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 diff --git a/lib/reporting/reports/bulk_coop/customer_payments.rb b/lib/reporting/reports/bulk_coop/customer_payments.rb new file mode 100644 index 0000000000..1935f96a60 --- /dev/null +++ b/lib/reporting/reports/bulk_coop/customer_payments.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +module Reporting + module Reports + module BulkCoop + class CustomerPayments < Base + def query_result + table_items.group_by(&:order).values + end + + def columns + { + customer: :order_billing_address_name, + date_of_order: :order_completed_at, + total_cost: :customer_payments_total_cost, + amount_owing: :customer_payments_amount_owed, + amount_paid: :customer_payments_amount_paid + } + end + + def rules + [ + { + group_by: :customer, + header: true, + summary_row: proc do |_key, _items, rows| + { + total_cost: rows.sum(&:total_cost), + amount_owing: rows.sum(&:amount_owing), + amount_paid: rows.sum(&:amount_paid), + } + end + } + ] + end + + private + + def customer_payments_total_cost(line_items) + unique_orders(line_items).sum(&:total) + end + + def customer_payments_amount_owed(line_items) + unique_orders(line_items).sum(&:new_outstanding_balance) + end + + def customer_payments_amount_paid(line_items) + unique_orders(line_items).sum(&:payment_total) + end + + def unique_orders(line_items) + line_items.map(&:order).uniq + end + + def order_completed_at(line_items) + line_items.first.order.completed_at + end + end + end + end +end diff --git a/lib/reporting/reports/bulk_coop/packing_sheets.rb b/lib/reporting/reports/bulk_coop/packing_sheets.rb new file mode 100644 index 0000000000..3086cb3c42 --- /dev/null +++ b/lib/reporting/reports/bulk_coop/packing_sheets.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module Reporting + module Reports + module BulkCoop + class PackingSheets < Base + def query_result + table_items.group_by(&:order).values + end + + def columns + { + customer: :order_billing_address_name, + product: :product_name, + variant: :full_name, + sum_total: :total_quantity + } + end + + private + + def total_quantity(line_items) + line_items.sum(&:quantity) + end + end + end + end +end diff --git a/lib/reporting/reports/bulk_coop/supplier_report.rb b/lib/reporting/reports/bulk_coop/supplier_report.rb new file mode 100644 index 0000000000..6e797cd389 --- /dev/null +++ b/lib/reporting/reports/bulk_coop/supplier_report.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module Reporting + module Reports + module BulkCoop + class SupplierReport < Base + def query_result + table_items.group_by(&:variant).values + end + + def columns + { + supplier: :variant_product_supplier_name, + product: :variant_product_name, + bulk_unit_size: :variant_product_group_buy_unit_size_f, + variant: :full_name, + variant_value: :option_value_value, + variant_unit: :option_value_unit, + weight: :weight_from_unit_value, + sum_total: :total_amount, + units_required: :empty_cell, + unallocated: :empty_cell, + max_quantity_excess: :empty_cell + } + end + + def rules + [ + { + group_by: :supplier, + header: true, + summary_row: proc do |_key, items, rows| + line_items = items.flatten + { + sum_total: rows.sum(&:sum_total), + units_required: units_required(line_items), + unallocated: remainder(line_items), + max_quantity_excess: max_quantity_excess(line_items) + } + end + } + ] + end + + private + + def variant_product_supplier_name(line_items) + line_items.first.variant.product.supplier.name + end + end + end + end +end diff --git a/lib/reporting/reports/list.rb b/lib/reporting/reports/list.rb index e8055ca9d8..6a7400e5cd 100644 --- a/lib/reporting/reports/list.rb +++ b/lib/reporting/reports/list.rb @@ -89,15 +89,15 @@ module Reporting def bulk_coop_report_types [ - bulk_coop_item(:bulk_coop_supplier_report), - bulk_coop_item(:bulk_coop_allocation), - bulk_coop_item(:bulk_coop_packing_sheets), - bulk_coop_item(:bulk_coop_customer_payments) + bulk_coop_item(:supplier_report), + bulk_coop_item(:allocation), + bulk_coop_item(:packing_sheets), + bulk_coop_item(:customer_payments) ] end def bulk_coop_item(key) - [I18n.t("order_management.reports.bulk_coop.filters.#{key}"), key] + [I18n.t("order_management.reports.bulk_coop.filters.bulk_coop_#{key}"), key] end def i18n_translate(key) diff --git a/spec/lib/reports/bulk_coop_report_spec.rb b/spec/lib/reports/bulk_coop_report_spec.rb index 49ed7d861d..cca38b28d4 100644 --- a/spec/lib/reports/bulk_coop_report_spec.rb +++ b/spec/lib/reports/bulk_coop_report_spec.rb @@ -2,185 +2,196 @@ require 'spec_helper' -describe Reporting::Reports::BulkCoop::BulkCoopReport do - subject { Reporting::Reports::BulkCoop::BulkCoopReport.new user, params } - let(:user) { create(:admin_user) } +# rubocop:disable Metrics/ModuleLength +module Reporting + module Reports + module BulkCoop + describe Base do + subject { Base.new user, params } + let(:user) { create(:admin_user) } - describe '#table_items' do - let(:params) { {} } + describe '#query_result' do + let(:params) { {} } + let(:d1) { create(:distributor_enterprise) } + let(:oc1) { create(:simple_order_cycle) } + let(:o1) { create(:order, completed_at: 1.day.ago, order_cycle: oc1, distributor: d1) } + let(:li1) { build(:line_item_with_shipment) } - let(:d1) { create(:distributor_enterprise) } - let(:oc1) { create(:simple_order_cycle) } - let(:o1) { create(:order, completed_at: 1.day.ago, order_cycle: oc1, distributor: d1) } - let(:li1) { build(:line_item_with_shipment) } + before { o1.line_items << li1 } - before { o1.line_items << li1 } + context "as a site admin" do + context 'when searching' do + let(:params) { + { q: { completed_at_gt: '', completed_at_lt: '', distributor_id_in: [] } } + } - context "as a site admin" do - context 'when searching' do - let(:params) { { q: { completed_at_gt: '', completed_at_lt: '', distributor_id_in: [] } } } + it "fetches completed orders" do + o2 = create(:order, state: 'cart') + o2.line_items << build(:line_item) + expect(subject.table_items).to eq([li1]) + end - it "fetches completed orders" do - o2 = create(:order, state: 'cart') - o2.line_items << build(:line_item) - expect(subject.table_items).to eq([li1]) + it 'shows canceled orders' do + o2 = create(:order, state: 'canceled', completed_at: 1.day.ago, order_cycle: oc1, + distributor: d1) + line_item = build(:line_item_with_shipment) + o2.line_items << line_item + expect(subject.table_items).to include(line_item) + end + end + + context 'when not searching' do + let(:params) { {} } + + it "fetches completed orders" do + o2 = create(:order, state: 'cart') + o2.line_items << build(:line_item) + expect(subject.table_items).to eq([li1]) + end + + it 'shows canceled orders' do + o2 = create(:order, state: 'canceled', completed_at: 1.day.ago, order_cycle: oc1, + distributor: d1) + line_item = build(:line_item_with_shipment) + o2.line_items << line_item + expect(subject.table_items).to include(line_item) + end + end + end + + context "filtering by date" do + it do + user = create(:admin_user) + o2 = create(:order, completed_at: 3.days.ago, order_cycle: oc1, distributor: d1) + li2 = build(:line_item_with_shipment) + o2.line_items << li2 + + report = Base.new user, {} + expect(report.table_items).to match_array [li1, li2] + + report = Base.new( + user, { q: { completed_at_gt: 2.days.ago } } + ) + expect(report.table_items).to eq([li1]) + + report = Base.new( + user, { q: { completed_at_lt: 2.days.ago } } + ) + expect(report.table_items).to eq([li2]) + end + end + + context "filtering by distributor" do + it do + user = create(:admin_user) + d2 = create(:distributor_enterprise) + o2 = create(:order, distributor: d2, order_cycle: oc1, + completed_at: Time.zone.now) + li2 = build(:line_item_with_shipment) + o2.line_items << li2 + + report = Base.new user, {} + expect(report.table_items).to match_array [li1, li2] + + report = Base.new( + user, { q: { distributor_id_in: [d1.id] } } + ) + expect(report.table_items).to eq([li1]) + + report = Base.new( + user, { q: { distributor_id_in: [d2.id] } } + ) + expect(report.table_items).to eq([li2]) + end + end + + context "as a manager of a supplier" do + let!(:user) { create(:user) } + subject { Base.new user, {} } + + let(:s1) { create(:supplier_enterprise) } + + before do + s1.enterprise_roles.create!(user: user) + end + + context "that has granted P-OC to the distributor" do + let(:o2) do + create(:order, distributor: d1, completed_at: 1.day.ago, + bill_address: create(:address), + ship_address: create(:address)) + end + let(:li2) do + build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) + end + + before do + o2.line_items << li2 + create(:enterprise_relationship, parent: s1, child: d1, + permissions_list: [:add_to_order_cycle]) + end + + it "shows line items supplied by my producers, with names hidden" do + expect(subject.table_items).to eq([li2]) + expect(subject.table_items.first.order.bill_address.firstname).to eq("HIDDEN") + end + end + + context "that has not granted P-OC to the distributor" do + let(:o2) do + create(:order, distributor: d1, completed_at: 1.day.ago, + bill_address: create(:address), + ship_address: create(:address)) + end + let(:li2) do + build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) + end + + before do + o2.line_items << li2 + end + + it "does not show line items supplied by my producers" do + expect(subject.table_items).to eq([]) + end + end + end end - it 'shows canceled orders' do - o2 = create(:order, state: 'canceled', completed_at: 1.day.ago, order_cycle: oc1, - distributor: d1) - line_item = build(:line_item_with_shipment) - o2.line_items << line_item - expect(subject.table_items).to include(line_item) + describe '#columns' do + context 'when report type is bulk_coop_customer_payments' do + subject { CustomerPayments.new user } + + it 'returns' do + expect(subject.columns.values).to match_array( + [ + :order_billing_address_name, + :order_completed_at, + :customer_payments_total_cost, + :customer_payments_amount_owed, + :customer_payments_amount_paid, + ] + ) + end + end + end + + # Yes, I know testing a private method is bad practice but report's design, tighly coupling + # Reporting::OrderGrouper and Base, makes it + # very hard to make things testeable without ending up in a wormwhole. This is a trade-off. + describe '#customer_payments_amount_owed' do + let(:params) { {} } + let(:user) { build(:user) } + let!(:line_item) { create(:line_item) } + let(:order) { line_item.order } + + it 'calls #new_outstanding_balance' do + expect_any_instance_of(Spree::Order).to receive(:new_outstanding_balance) + CustomerPayments.new(user).__send__(:customer_payments_amount_owed, [line_item]) + end end end - - context 'when not searching' do - let(:params) { {} } - - it "fetches completed orders" do - o2 = create(:order, state: 'cart') - o2.line_items << build(:line_item) - expect(subject.table_items).to eq([li1]) - end - - it 'shows canceled orders' do - o2 = create(:order, state: 'canceled', completed_at: 1.day.ago, order_cycle: oc1, - distributor: d1) - line_item = build(:line_item_with_shipment) - o2.line_items << line_item - expect(subject.table_items).to include(line_item) - end - end - end - - context "filtering by date" do - it do - user = create(:admin_user) - o2 = create(:order, completed_at: 3.days.ago, order_cycle: oc1, distributor: d1) - li2 = build(:line_item_with_shipment) - o2.line_items << li2 - - report = Reporting::Reports::BulkCoop::BulkCoopReport.new user, {} - expect(report.table_items).to match_array [li1, li2] - - report = Reporting::Reports::BulkCoop::BulkCoopReport.new( - user, { q: { completed_at_gt: 2.days.ago } } - ) - expect(report.table_items).to eq([li1]) - - report = Reporting::Reports::BulkCoop::BulkCoopReport.new( - user, { q: { completed_at_lt: 2.days.ago } } - ) - expect(report.table_items).to eq([li2]) - end - end - - context "filtering by distributor" do - it do - user = create(:admin_user) - d2 = create(:distributor_enterprise) - o2 = create(:order, distributor: d2, order_cycle: oc1, - completed_at: Time.zone.now) - li2 = build(:line_item_with_shipment) - o2.line_items << li2 - - report = Reporting::Reports::BulkCoop::BulkCoopReport.new user, {} - expect(report.table_items).to match_array [li1, li2] - - report = Reporting::Reports::BulkCoop::BulkCoopReport.new( - user, { q: { distributor_id_in: [d1.id] } } - ) - expect(report.table_items).to eq([li1]) - - report = Reporting::Reports::BulkCoop::BulkCoopReport.new( - user, { q: { distributor_id_in: [d2.id] } } - ) - expect(report.table_items).to eq([li2]) - end - end - - context "as a manager of a supplier" do - let!(:user) { create(:user) } - subject { Reporting::Reports::BulkCoop::BulkCoopReport.new user, {} } - - let(:s1) { create(:supplier_enterprise) } - - before do - s1.enterprise_roles.create!(user: user) - end - - context "that has granted P-OC to the distributor" do - let(:o2) do - create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), - ship_address: create(:address)) - end - let(:li2) do - build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) - end - - before do - o2.line_items << li2 - create(:enterprise_relationship, parent: s1, child: d1, - permissions_list: [:add_to_order_cycle]) - end - - it "shows line items supplied by my producers, with names hidden" do - expect(subject.table_items).to eq([li2]) - expect(subject.table_items.first.order.bill_address.firstname).to eq("HIDDEN") - end - end - - context "that has not granted P-OC to the distributor" do - let(:o2) do - create(:order, distributor: d1, completed_at: 1.day.ago, bill_address: create(:address), - ship_address: create(:address)) - end - let(:li2) do - build(:line_item_with_shipment, product: create(:simple_product, supplier: s1)) - end - - before do - o2.line_items << li2 - end - - it "does not show line items supplied by my producers" do - expect(subject.table_items).to eq([]) - end - end - end - end - - describe '#columns' do - context 'when report type is bulk_coop_customer_payments' do - let(:params) { { report_subtype: 'bulk_coop_customer_payments' } } - - it 'returns' do - expect(subject.columns).to eq( - [ - :order_billing_address_name, - :order_completed_at, - :customer_payments_total_cost, - :customer_payments_amount_owed, - :customer_payments_amount_paid, - ] - ) - end - end - end - - # Yes, I know testing a private method is bad practice but report's design, tighly coupling - # Reporting::OrderGrouper and Reporting::Reports::BulkCoop::BulkCoopReport, makes it - # very hard to make things testeable without ending up in a wormwhole. This is a trade-off. - describe '#customer_payments_amount_owed' do - let(:params) { {} } - let(:user) { build(:user) } - let!(:line_item) { create(:line_item) } - let(:order) { line_item.order } - - it 'calls #new_outstanding_balance' do - expect_any_instance_of(Spree::Order).to receive(:new_outstanding_balance) - subject.__send__(:customer_payments_amount_owed, [line_item]) end end end +# rubocop:enable Metrics/ModuleLength diff --git a/spec/system/admin/reports_spec.rb b/spec/system/admin/reports_spec.rb index f6f1c776db..db6f7e9ba2 100644 --- a/spec/system/admin/reports_spec.rb +++ b/spec/system/admin/reports_spec.rb @@ -390,7 +390,7 @@ describe ' click_link 'Bulk Co-Op' end - xit "generating Bulk Co-op Supplier Report" do + it "generating Bulk Co-op Supplier Report" do select "Bulk Co-op Supplier Report", from: "report_subtype" click_button 'Go' @@ -406,10 +406,10 @@ describe ' "Units Required", "Unallocated", "Max Quantity Excess" - ] + ].map(&:upcase) end - xit "generating Bulk Co-op Allocation report" do + it "generating Bulk Co-op Allocation report" do select "Bulk Co-op Allocation", from: "report_subtype" click_button 'Go' @@ -425,10 +425,10 @@ describe ' "Total available", "Unallocated", "Max Quantity Excess" - ] + ].map(&:upcase) end - xit "generating Bulk Co-op Packing Sheets report" do + it "generating Bulk Co-op Packing Sheets report" do select "Bulk Co-op Packing Sheets", from: "report_subtype" click_button 'Go' @@ -437,10 +437,10 @@ describe ' "Product", "Variant", "Sum Total" - ] + ].map(&:upcase) end - xit "generating Bulk Co-op Customer Payments report" do + it "generating Bulk Co-op Customer Payments report" do select "Bulk Co-op Customer Payments", from: "report_subtype" click_button 'Go' @@ -450,7 +450,7 @@ describe ' "Total Cost", "Amount Owing", "Amount Paid" - ] + ].map(&:upcase) end end