Report Refactor 3: BulkCoop

This commit is contained in:
Sebastian Castro
2022-04-07 11:05:24 +02:00
committed by Jean-Baptiste Bellet
parent 22fe652e89
commit 944d40e093
12 changed files with 516 additions and 636 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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