mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Add filtering to enterprise fee summary
This commit is contained in:
@@ -17,7 +17,7 @@ module OrderManagement
|
||||
end
|
||||
|
||||
def enterprise_fees_by_customer
|
||||
Scope.new.all
|
||||
Scope.new.apply_filters(parameters).result
|
||||
end
|
||||
|
||||
def enterprise_fee_type_totals
|
||||
|
||||
@@ -2,11 +2,22 @@ module OrderManagement
|
||||
module Reports
|
||||
module EnterpriseFeeSummary
|
||||
class Scope
|
||||
attr_accessor :parameters
|
||||
|
||||
def initialize
|
||||
setup_default_scope
|
||||
end
|
||||
|
||||
def all
|
||||
def apply_filters(params)
|
||||
filter_by_date(params)
|
||||
filter_by_distribution(params)
|
||||
filter_by_fee(params)
|
||||
|
||||
self
|
||||
end
|
||||
|
||||
def result
|
||||
group_data.select_attributes
|
||||
@scope.all
|
||||
end
|
||||
|
||||
@@ -275,6 +286,30 @@ module OrderManagement
|
||||
)
|
||||
end
|
||||
|
||||
def filter_by_date(params)
|
||||
filter_scope("spree_orders.completed_at >= ?", params.start_at) \
|
||||
if params.start_at.present?
|
||||
filter_scope("spree_orders.completed_at <= ?", params.end_at) if params.end_at.present?
|
||||
end
|
||||
|
||||
def filter_by_distribution(params)
|
||||
filter_scope(spree_orders: { distributor_id: params.distributor_ids }) \
|
||||
if params.distributor_ids.present?
|
||||
filter_scope(spree_products: { supplier_id: params.producer_ids }) \
|
||||
if params.producer_ids.present?
|
||||
filter_scope(spree_orders: { order_cycle_id: params.order_cycle_ids }) \
|
||||
if params.order_cycle_ids.present?
|
||||
end
|
||||
|
||||
def filter_by_fee(params)
|
||||
filter_scope(enterprise_fees: { id: params.enterprise_fee_ids }) \
|
||||
if params.enterprise_fee_ids.present?
|
||||
filter_scope(spree_shipping_methods: { id: params.shipping_method_ids }) \
|
||||
if params.shipping_method_ids.present?
|
||||
filter_scope(spree_payment_methods: { id: params.payment_method_ids }) \
|
||||
if params.payment_method_ids.present?
|
||||
end
|
||||
|
||||
def group_data
|
||||
chain_to_scope do
|
||||
group("enterprise_fees.id", "enterprises.id", "customers.id", "hubs.id",
|
||||
@@ -314,6 +349,12 @@ module OrderManagement
|
||||
joins(join_string)
|
||||
end
|
||||
end
|
||||
|
||||
def filter_scope(*args)
|
||||
chain_to_scope do
|
||||
where(*args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,6 +4,8 @@ require "order_management/reports/enterprise_fee_summary/report_service"
|
||||
require "order_management/reports/enterprise_fee_summary/parameters"
|
||||
|
||||
describe OrderManagement::Reports::EnterpriseFeeSummary::ReportService do
|
||||
let(:report_klass) { OrderManagement::Reports::EnterpriseFeeSummary }
|
||||
|
||||
let!(:shipping_method) do
|
||||
create(:shipping_method, name: "Sample Shipping Method", calculator: per_item_calculator(1.0))
|
||||
end
|
||||
@@ -75,9 +77,9 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::ReportService do
|
||||
let!(:another_customer) { create(:customer, name: "Another Customer") }
|
||||
|
||||
describe "grouping and sorting of entries" do
|
||||
let!(:customer_order) { prepare_completed_order(customer: customer) }
|
||||
let!(:second_customer_order) { prepare_completed_order(customer: customer) }
|
||||
let!(:other_customer_order) { prepare_completed_order(customer: another_customer) }
|
||||
let!(:customer_order) { prepare_order(customer: customer) }
|
||||
let!(:second_customer_order) { prepare_order(customer: customer) }
|
||||
let!(:other_customer_order) { prepare_order(customer: another_customer) }
|
||||
|
||||
let(:parameters) { OrderManagement::Reports::EnterpriseFeeSummary::Parameters.new }
|
||||
let(:service) { described_class.new(parameters, nil) }
|
||||
@@ -138,6 +140,241 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::ReportService do
|
||||
end
|
||||
end
|
||||
|
||||
describe "filters entries correctly" do
|
||||
let(:parameters) { report_klass::Parameters.new(parameters_attributes) }
|
||||
let(:service) { described_class.new(parameters, nil) }
|
||||
|
||||
context "filtering by completion date" do
|
||||
let(:timestamp) { Time.zone.local(2018, 1, 5, 14, 30, 5) }
|
||||
|
||||
let!(:customer_a) { create(:customer, name: "Customer A") }
|
||||
let!(:customer_b) { create(:customer, name: "Customer B") }
|
||||
let!(:customer_c) { create(:customer, name: "Customer C") }
|
||||
|
||||
let!(:order_placed_before_timestamp) do
|
||||
prepare_order(customer: customer_a).tap do |order|
|
||||
order.update_column(:completed_at, timestamp - 1.second)
|
||||
end
|
||||
end
|
||||
|
||||
let!(:order_placed_during_timestamp) do
|
||||
prepare_order(customer: customer_b).tap do |order|
|
||||
order.update_column(:completed_at, timestamp)
|
||||
end
|
||||
end
|
||||
|
||||
let!(:order_placed_after_timestamp) do
|
||||
prepare_order(customer: customer_c).tap do |order|
|
||||
order.update_column(:completed_at, timestamp + 1.second)
|
||||
end
|
||||
end
|
||||
|
||||
context "on or after start_at" do
|
||||
let(:parameters_attributes) { { start_at: timestamp } }
|
||||
|
||||
it "filters entries" do
|
||||
totals = service.enterprise_fee_type_totals.list
|
||||
|
||||
expect_total_matches(totals, 0, fee_type: "Shipment", customer_name: "Customer A")
|
||||
expect_total_matches(totals, 1, fee_type: "Shipment", customer_name: "Customer B")
|
||||
expect_total_matches(totals, 1, fee_type: "Shipment", customer_name: "Customer C")
|
||||
end
|
||||
end
|
||||
|
||||
context "on or before end_at" do
|
||||
let(:parameters_attributes) { { end_at: timestamp } }
|
||||
|
||||
it "filters entries" do
|
||||
totals = service.enterprise_fee_type_totals.list
|
||||
|
||||
expect_total_matches(totals, 1, fee_type: "Shipment", customer_name: "Customer A")
|
||||
expect_total_matches(totals, 1, fee_type: "Shipment", customer_name: "Customer B")
|
||||
expect_total_matches(totals, 0, fee_type: "Shipment", customer_name: "Customer C")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "for specified shops" do
|
||||
let!(:distributor_a) do
|
||||
create(:distributor_enterprise, name: "Distributor A", payment_methods: [payment_method],
|
||||
shipping_methods: [shipping_method])
|
||||
end
|
||||
let!(:distributor_b) do
|
||||
create(:distributor_enterprise, name: "Distributor B", payment_methods: [payment_method],
|
||||
shipping_methods: [shipping_method])
|
||||
end
|
||||
let!(:distributor_c) do
|
||||
create(:distributor_enterprise, name: "Distributor C", payment_methods: [payment_method],
|
||||
shipping_methods: [shipping_method])
|
||||
end
|
||||
|
||||
let!(:order_a) { prepare_order(distributor: distributor_a) }
|
||||
let!(:order_b) { prepare_order(distributor: distributor_b) }
|
||||
let!(:order_c) { prepare_order(distributor: distributor_c) }
|
||||
|
||||
let(:parameters_attributes) { { distributor_ids: [distributor_a.id, distributor_b.id] } }
|
||||
|
||||
it "filters entries" do
|
||||
totals = service.enterprise_fee_type_totals.list
|
||||
|
||||
expect_total_matches(totals, 1, fee_type: "Shipment", enterprise_name: "Distributor A")
|
||||
expect_total_matches(totals, 1, fee_type: "Shipment", enterprise_name: "Distributor B")
|
||||
expect_total_matches(totals, 0, fee_type: "Shipment", enterprise_name: "Distributor C")
|
||||
end
|
||||
end
|
||||
|
||||
describe "for specified suppliers" do
|
||||
let!(:producer_a) { create(:supplier_enterprise, name: "Producer A") }
|
||||
let!(:producer_b) { create(:supplier_enterprise, name: "Producer B") }
|
||||
let!(:producer_c) { create(:supplier_enterprise, name: "Producer C") }
|
||||
|
||||
let!(:fee_a) { create(:enterprise_fee, name: "Fee A", enterprise: producer_a) }
|
||||
let!(:fee_b) { create(:enterprise_fee, name: "Fee B", enterprise: producer_b) }
|
||||
let!(:fee_c) { create(:enterprise_fee, name: "Fee C", enterprise: producer_c) }
|
||||
|
||||
let!(:product_a) { create(:product, supplier: producer_a) }
|
||||
let!(:product_b) { create(:product, supplier: producer_b) }
|
||||
let!(:product_c) { create(:product, supplier: producer_c) }
|
||||
|
||||
let!(:variant_a) do
|
||||
prepare_variant(product: product_a, producer: producer_a, incoming_exchange_fees: [fee_a])
|
||||
end
|
||||
let!(:variant_b) do
|
||||
prepare_variant(product: product_b, producer: producer_b, incoming_exchange_fees: [fee_b])
|
||||
end
|
||||
let!(:variant_c) do
|
||||
prepare_variant(product: product_c, producer: producer_c, incoming_exchange_fees: [fee_c])
|
||||
end
|
||||
|
||||
let!(:order_a) { prepare_order(variant: variant_a) }
|
||||
let!(:order_b) { prepare_order(variant: variant_b) }
|
||||
let!(:order_c) { prepare_order(variant: variant_c) }
|
||||
|
||||
let(:parameters_attributes) { { producer_ids: [producer_a.id, producer_b.id] } }
|
||||
|
||||
it "filters entries" do
|
||||
totals = service.enterprise_fee_type_totals.list
|
||||
|
||||
expect_total_matches(totals, 1, fee_name: "Fee A", enterprise_name: "Producer A")
|
||||
expect_total_matches(totals, 1, fee_name: "Fee B", enterprise_name: "Producer B")
|
||||
expect_total_matches(totals, 0, fee_name: "Fee C", enterprise_name: "Producer C")
|
||||
end
|
||||
end
|
||||
|
||||
describe "for specified order cycles" do
|
||||
let!(:distributor_a) do
|
||||
create(:distributor_enterprise, name: "Distributor A", payment_methods: [payment_method],
|
||||
shipping_methods: [shipping_method])
|
||||
end
|
||||
let!(:distributor_b) do
|
||||
create(:distributor_enterprise, name: "Distributor B", payment_methods: [payment_method],
|
||||
shipping_methods: [shipping_method])
|
||||
end
|
||||
let!(:distributor_c) do
|
||||
create(:distributor_enterprise, name: "Distributor C", payment_methods: [payment_method],
|
||||
shipping_methods: [shipping_method])
|
||||
end
|
||||
|
||||
let!(:order_cycle_a) { create(:simple_order_cycle, coordinator: coordinator) }
|
||||
let!(:order_cycle_b) { create(:simple_order_cycle, coordinator: coordinator) }
|
||||
let!(:order_cycle_c) { create(:simple_order_cycle, coordinator: coordinator) }
|
||||
|
||||
let!(:variant_a) { prepare_variant(distributor: distributor_a, order_cycle: order_cycle_a) }
|
||||
let!(:variant_b) { prepare_variant(distributor: distributor_b, order_cycle: order_cycle_b) }
|
||||
let!(:variant_c) { prepare_variant(distributor: distributor_c, order_cycle: order_cycle_c) }
|
||||
|
||||
let!(:order_a) { prepare_order(order_cycle: order_cycle_a, distributor: distributor_a) }
|
||||
let!(:order_b) { prepare_order(order_cycle: order_cycle_b, distributor: distributor_b) }
|
||||
let!(:order_c) { prepare_order(order_cycle: order_cycle_c, distributor: distributor_c) }
|
||||
|
||||
let(:parameters_attributes) { { order_cycle_ids: [order_cycle_a.id, order_cycle_b.id] } }
|
||||
|
||||
it "filters entries" do
|
||||
totals = service.enterprise_fee_type_totals.list
|
||||
|
||||
expect_total_matches(totals, 1, fee_type: "Shipment", enterprise_name: "Distributor A")
|
||||
expect_total_matches(totals, 1, fee_type: "Shipment", enterprise_name: "Distributor B")
|
||||
expect_total_matches(totals, 0, fee_type: "Shipment", enterprise_name: "Distributor C")
|
||||
end
|
||||
end
|
||||
|
||||
describe "for specified enterprise fees" do
|
||||
let!(:fee_a) { create(:enterprise_fee, name: "Fee A", enterprise: distributor) }
|
||||
let!(:fee_b) { create(:enterprise_fee, name: "Fee B", enterprise: distributor) }
|
||||
let!(:fee_c) { create(:enterprise_fee, name: "Fee C", enterprise: distributor) }
|
||||
|
||||
let!(:variant) { prepare_variant(outgoing_exchange_fees: [fee_a, fee_b, fee_c]) }
|
||||
|
||||
let!(:order) { prepare_order(variant: variant) }
|
||||
|
||||
let(:parameters_attributes) { { enterprise_fee_ids: [fee_a.id, fee_b.id] } }
|
||||
|
||||
it "filters entries" do
|
||||
totals = service.enterprise_fee_type_totals.list
|
||||
|
||||
expect_total_matches(totals, 1, fee_name: "Fee A")
|
||||
expect_total_matches(totals, 1, fee_name: "Fee B")
|
||||
expect_total_matches(totals, 0, fee_name: "Fee C")
|
||||
end
|
||||
end
|
||||
|
||||
describe "for specified shipping methods" do
|
||||
let!(:shipping_method_a) do
|
||||
create(:shipping_method, name: "Shipping A", distributors: [distributor])
|
||||
end
|
||||
let!(:shipping_method_b) do
|
||||
create(:shipping_method, name: "Shipping B", distributors: [distributor])
|
||||
end
|
||||
let!(:shipping_method_c) do
|
||||
create(:shipping_method, name: "Shipping C", distributors: [distributor])
|
||||
end
|
||||
|
||||
let!(:order_a) { prepare_order(shipping_method: shipping_method_a) }
|
||||
let!(:order_b) { prepare_order(shipping_method: shipping_method_b) }
|
||||
let!(:order_c) { prepare_order(shipping_method: shipping_method_c) }
|
||||
|
||||
let(:parameters_attributes) do
|
||||
{ shipping_method_ids: [shipping_method_a.id, shipping_method_b.id] }
|
||||
end
|
||||
|
||||
it "filters entries" do
|
||||
totals = service.enterprise_fee_type_totals.list
|
||||
|
||||
expect_total_matches(totals, 1, fee_name: "Shipping A")
|
||||
expect_total_matches(totals, 1, fee_name: "Shipping B")
|
||||
expect_total_matches(totals, 0, fee_name: "Shipping C")
|
||||
end
|
||||
end
|
||||
|
||||
describe "for specified payment methods" do
|
||||
let!(:payment_method_a) do
|
||||
create(:payment_method, name: "Payment A", distributors: [distributor])
|
||||
end
|
||||
let!(:payment_method_b) do
|
||||
create(:payment_method, name: "Payment B", distributors: [distributor])
|
||||
end
|
||||
let!(:payment_method_c) do
|
||||
create(:payment_method, name: "Payment C", distributors: [distributor])
|
||||
end
|
||||
|
||||
let!(:order_a) { prepare_order(payment_method: payment_method_a) }
|
||||
let!(:order_b) { prepare_order(payment_method: payment_method_b) }
|
||||
let!(:order_c) { prepare_order(payment_method: payment_method_c) }
|
||||
|
||||
let(:parameters_attributes) do
|
||||
{ payment_method_ids: [payment_method_a.id, payment_method_b.id] }
|
||||
end
|
||||
|
||||
it "filters entries" do
|
||||
totals = service.enterprise_fee_type_totals.list
|
||||
|
||||
expect_total_matches(totals, 1, fee_name: "Payment A")
|
||||
expect_total_matches(totals, 1, fee_name: "Payment B")
|
||||
expect_total_matches(totals, 0, fee_name: "Payment C")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Helper methods for example group
|
||||
|
||||
def expect_total_attributes(total, expected_attribute_list)
|
||||
@@ -148,6 +385,10 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::ReportService do
|
||||
expect(actual_attribute_list).to eq(expected_attribute_list)
|
||||
end
|
||||
|
||||
def expect_total_matches(totals, count, attributes)
|
||||
expect(count_totals(totals, attributes)).to eq(count)
|
||||
end
|
||||
|
||||
def prepare_tax_category(name)
|
||||
create(:tax_category, name: name)
|
||||
end
|
||||
@@ -157,7 +398,7 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::ReportService do
|
||||
shipping_method: shipping_method, variant: variant }
|
||||
end
|
||||
|
||||
def prepare_order(options = {})
|
||||
def setup_order(options = {})
|
||||
target = default_order_options.merge(options)
|
||||
|
||||
create(:order, customer: target[:customer], distributor: target[:distributor],
|
||||
@@ -168,8 +409,8 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::ReportService do
|
||||
end
|
||||
end
|
||||
|
||||
def prepare_completed_order(options = {})
|
||||
order = prepare_order(options)
|
||||
def prepare_order(options = {})
|
||||
order = setup_order(options)
|
||||
complete_order(order, options)
|
||||
order.reload
|
||||
end
|
||||
@@ -182,16 +423,38 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::ReportService do
|
||||
while !order.completed? do break unless order.next! end
|
||||
end
|
||||
|
||||
def prepare_variant(options = {})
|
||||
variant = create(:variant, product: product, is_master: false)
|
||||
exchange = create(:exchange, incoming: true, order_cycle: order_cycle, sender: producer,
|
||||
receiver: coordinator, variants: [variant])
|
||||
attach_enterprise_fees(exchange, options[:incoming_exchange_fees] || [])
|
||||
def default_variant_options
|
||||
{ product: product, producer: producer, coordinator: coordinator, distributor: distributor,
|
||||
order_cycle: order_cycle }
|
||||
end
|
||||
|
||||
exchange = create(:exchange, incoming: false, order_cycle: order_cycle, sender: coordinator,
|
||||
receiver: distributor, variants: [variant])
|
||||
attach_enterprise_fees(exchange, options[:outgoing_exchange_fees] || [])
|
||||
variant
|
||||
def prepare_variant(options = {})
|
||||
target = default_variant_options.merge(options)
|
||||
|
||||
create(:variant, product: target[:product], is_master: false).tap do |variant|
|
||||
exchange_options = { producer: target[:producer], coordinator: target[:coordinator],
|
||||
distributor: target[:distributor],
|
||||
incoming_exchange_fees: target[:incoming_exchange_fees],
|
||||
outgoing_exchange_fees: target[:outgoing_exchange_fees] }
|
||||
setup_exchanges(target[:order_cycle], variant, exchange_options)
|
||||
end
|
||||
end
|
||||
|
||||
def setup_exchanges(order_cycle, variant, options)
|
||||
setup_exchange(order_cycle, variant, true, sender: options[:producer],
|
||||
receiver: options[:coordinator],
|
||||
enterprise_fees: options[:incoming_exchange_fees])
|
||||
setup_exchange(order_cycle, variant, false, sender: options[:coordinator],
|
||||
receiver: options[:distributor],
|
||||
enterprise_fees: options[:outgoing_exchange_fees])
|
||||
end
|
||||
|
||||
def setup_exchange(order_cycle, variant, incoming, options)
|
||||
exchange_attributes = { order_cycle_id: order_cycle.id, incoming: incoming,
|
||||
sender_id: options[:sender].id, receiver_id: options[:receiver].id }
|
||||
exchange = Exchange.where(exchange_attributes).first || create(:exchange, exchange_attributes)
|
||||
exchange.variants << variant
|
||||
attach_enterprise_fees(exchange, options[:enterprise_fees] || [])
|
||||
end
|
||||
|
||||
def attach_enterprise_fees(exchange, enterprise_fees)
|
||||
@@ -203,4 +466,12 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::ReportService do
|
||||
def per_item_calculator(amount)
|
||||
Spree::Calculator::PerItem.new(preferred_amount: amount)
|
||||
end
|
||||
|
||||
def count_totals(totals, attributes)
|
||||
totals.count do |data|
|
||||
attributes.all? do |attribute_name, attribute_value|
|
||||
data.public_send(attribute_name) == attribute_value
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user