Report Refactor 3: Order Cycle Management

This commit is contained in:
Sebastian Castro
2022-04-03 20:53:43 +02:00
committed by Jean-Baptiste Bellet
parent 3808398807
commit 71aca960ee
9 changed files with 162 additions and 180 deletions

View File

@@ -105,6 +105,10 @@ module Spree
render_address([city, zipcode, state&.name])
end
def address_and_city
[address1, address2, city].select(&:present?).join(' ')
end
private
def require_zipcode?

View File

@@ -11,8 +11,8 @@
.row
.alpha.two.columns= label_tag nil, t(:report_payment)
.omega.fourteen.columns= select_tag(:payment_method_in, options_for_select(report_payment_method_options(@report.orders), params[:payment_method_in]), {class: "select2 fullwidth", multiple: true})
.omega.fourteen.columns= select_tag(:payment_method_in, options_for_select(report_payment_method_options(@report.query_result), params[:payment_method_in]), {class: "select2 fullwidth", multiple: true})
.row
.alpha.two.columns= label_tag nil, "#{t(:shipping_methods)}: "
.omega.fourteen.columns= select_tag(:shipping_method_in, options_for_select(report_shipping_method_options(@report.orders), params[:shipping_method_in]), {class: "select2 fullwidth", multiple: true})
.alpha.two.columns= label_tag nil, t(:shipping_methods)
.omega.fourteen.columns= select_tag(:shipping_method_in, options_for_select(report_shipping_method_options(@report.query_result), params[:shipping_method_in]), {class: "select2 fullwidth", multiple: true})

View File

@@ -8,20 +8,14 @@ module Reporting
{
first_name: proc { |order| order.billing_address.firstname },
last_name: proc { |order| order.billing_address.lastname },
billing_address: proc { |order| address_from(order.billing_address) },
billing_address: proc { |order| order.billing_address.address_and_city },
email: proc { |order| order.email },
phone: proc { |order| order.billing_address.phone },
hub: proc { |order| order.distributor&.name },
hub_address: proc { |order| address_from(order.distributor&.address) },
hub_address: proc { |order| order.distributor&.address&.address_and_city },
shipping_method: proc { |order| order.shipping_method&.name },
}
end
private
def address_from(address)
[address&.address1, address&.address2, address&.city].join(" ")
end
end
end
end

View File

@@ -0,0 +1,81 @@
# frozen_string_literal: true
module Reporting
module Reports
module OrderCycleManagement
class Base < ReportObjectTemplate
DEFAULT_DATE_INTERVAL = { from: -1.month, to: 1.day }.freeze
def initialize(user, params = {})
super(user, params)
params[:q] ||= {}
params[:q][:completed_at_gt] ||= Time.zone.today + DEFAULT_DATE_INTERVAL[:from]
params[:q][:completed_at_lt] ||= Time.zone.today + DEFAULT_DATE_INTERVAL[:to]
end
def search
Spree::Order.
finalized.
not_state(:canceled).
distributed_by_user(@user).
managed_by(@user).
ransack(params[:q])
end
# This result is used in _order_cucle_management.html so caching it
def query_result
@query_result ||= orders
end
def orders
search_result = search.result.order(:completed_at)
orders = OutstandingBalance.new(search_result).query.select('spree_orders.*')
filter(orders)
end
def filter(orders)
filter_to_payment_method filter_to_shipping_method filter_to_order_cycle orders
end
private
def filter_to_payment_method(orders)
if params[:payment_method_in].present?
orders
.joins(payments: :payment_method)
.where(spree_payments: { payment_method_id: params[:payment_method_in] })
else
orders
end
end
def filter_to_shipping_method(orders)
if params[:shipping_method_in].present?
orders
.joins(shipments: :shipping_rates)
.where(spree_shipping_rates: {
selected: true,
shipping_method_id: params[:shipping_method_in]
})
else
orders
end
end
def filter_to_order_cycle(orders)
if params[:order_cycle_id].present?
orders.where(order_cycle_id: params[:order_cycle_id])
else
orders
end
end
def customer_code(email)
customer = Customer.where(email: email).first
customer.nil? ? "" : customer.code
end
end
end
end
end

View File

@@ -0,0 +1,35 @@
# frozen_string_literal: true
module Reporting
module Reports
module OrderCycleManagement
class Delivery < Base
# rubocop:disable Metrics/AbcSize
def columns
{
first_name: proc { |order| order.shipping_address.firstname },
last_name: proc { |order| order.shipping_address.lastname },
hub: proc { |order| order.distributor&.name },
customer_code: proc { |order| customer_code(order.email) },
delivery_address: proc { |order| order.shipping_address.address_and_city },
delivery_postcode: proc { |order| order.shipping_address.zipcode },
phone: proc { |order| order.shipping_address.phone },
shipping_method: proc { |order| order.shipping_method&.name },
payment_method: proc { |order| order.payments.first&.payment_method&.name },
amount: proc { |order| order.total },
balance: proc { |order| order.balance_value },
temp_controlled_items: proc { |order| has_temperature_controlled_items?(order) },
special_instructions: proc { |order| order.special_instructions },
}
end
# rubocop:enable Metrics/AbcSize
def has_temperature_controlled_items?(order)
order.line_items.any? { |line_item|
line_item.product.shipping_category&.temperature_controlled
}
end
end
end
end
end

View File

@@ -1,160 +0,0 @@
# frozen_string_literal: true
module Reporting
module Reports
module OrderCycleManagement
class OrderCycleManagementReport < ReportObjectTemplate
DEFAULT_DATE_INTERVAL = { from: -1.month, to: 1.day }.freeze
def initialize(user, params = {})
super(user, params)
params[:q] ||= {}
params[:q][:completed_at_gt] ||= Time.zone.today + DEFAULT_DATE_INTERVAL[:from]
params[:q][:completed_at_lt] ||= Time.zone.today + DEFAULT_DATE_INTERVAL[:to]
end
def table_headers
if is_payment_methods?
[
I18n.t(:report_header_first_name),
I18n.t(:report_header_last_name),
I18n.t(:report_header_hub),
I18n.t(:report_header_hub_code),
I18n.t(:report_header_email),
I18n.t(:report_header_phone),
I18n.t(:report_header_shipping_method),
I18n.t(:report_header_payment_method),
I18n.t(:report_header_amount),
I18n.t(:report_header_balance),
]
else
[
I18n.t(:report_header_first_name),
I18n.t(:report_header_last_name),
I18n.t(:report_header_hub),
I18n.t(:report_header_hub_code),
I18n.t(:report_header_delivery_address),
I18n.t(:report_header_delivery_postcode),
I18n.t(:report_header_phone),
I18n.t(:report_header_shipping_method),
I18n.t(:report_header_payment_method),
I18n.t(:report_header_amount),
I18n.t(:report_header_balance),
I18n.t(:report_header_temp_controlled_items),
I18n.t(:report_header_special_instructions),
]
end
end
def search
Spree::Order.
finalized.
not_state(:canceled).
distributed_by_user(@user).
managed_by(@user).
ransack(params[:q])
end
def orders
search_result = search.result.order(:completed_at)
orders_with_balance = OutstandingBalance.new(search_result).
query.
select('spree_orders.*')
filter(orders_with_balance)
end
def table_rows
if is_payment_methods?
orders.map { |o| payment_method_row o }
else
orders.map { |o| delivery_row o }
end
end
def filter(search_result)
filter_to_payment_method filter_to_shipping_method filter_to_order_cycle search_result
end
private
# This method relies on `balance_value` as a computed DB column. See `CompleteOrdersWithBalance`
# for reference.
def balance(order)
order.balance_value
end
def payment_method_row(order)
ba = order.billing_address
[ba&.firstname,
ba&.lastname,
order.distributor&.name,
customer_code(order.email),
order.email,
ba&.phone,
order.shipping_method&.name,
order.payments.last&.payment_method&.name,
order.total,
balance(order)]
end
def delivery_row(order)
sa = order.shipping_address
[sa.firstname,
sa.lastname,
order.distributor&.name,
customer_code(order.email),
"#{sa.address1} #{sa.address2} #{sa.city}",
sa.zipcode,
sa.phone,
order.shipping_method&.name,
order.payments.first&.payment_method&.name,
order.total,
balance(order),
has_temperature_controlled_items?(order),
order.special_instructions]
end
def filter_to_payment_method(orders)
if params[:payment_method_in].present?
orders.joins(payments: :payment_method).where(spree_payments: { payment_method_id: params[:payment_method_in] })
else
orders
end
end
def filter_to_shipping_method(orders)
if params[:shipping_method_in].present?
orders.joins(shipments: :shipping_rates).where(spree_shipping_rates: { selected: true,
shipping_method_id: params[:shipping_method_in] })
else
orders
end
end
def filter_to_order_cycle(orders)
if params[:order_cycle_id].present?
orders.where(order_cycle_id: params[:order_cycle_id])
else
orders
end
end
def has_temperature_controlled_items?(order)
order.line_items.any? { |line_item|
line_item.product.shipping_category&.temperature_controlled
}
end
def is_payment_methods?
params[:report_subtype] == "payment_methods"
end
def customer_code(email)
customer = Customer.where(email: email).first
customer.nil? ? "" : customer.code
end
end
end
end
end

View File

@@ -0,0 +1,28 @@
# frozen_string_literal: true
module Reporting
module Reports
module OrderCycleManagement
class PaymentMethods < Base
# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/CyclomaticComplexity
def columns
{
first_name: proc { |order| order.billing_address&.firstname },
last_name: proc { |order| order.billing_address&.lastname },
hub: proc { |order| order.distributor&.name },
customer_code: proc { |order| customer_code(order.email) },
email: proc { |order| order.email },
phone: proc { |order| order.billing_address&.phone },
shipping_method: proc { |order| order.shipping_method&.name },
payment_method: proc { |order| order.payments.last&.payment_method&.name },
amount: proc { |order| order.total },
balance: proc { |order| order.balance_value },
}
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/CyclomaticComplexity
end
end
end
end

View File

@@ -5,9 +5,9 @@ require 'spec_helper'
module Reporting
module Reports
module OrderCycleManagement
describe OrderCycleManagementReport do
describe Base do
context "as a site admin" do
subject { OrderCycleManagementReport.new(user, params) }
subject { Base.new(user, params) }
let(:params) { {} }
let(:user) do
@@ -63,7 +63,7 @@ module Reporting
context "as an enterprise user" do
let!(:user) { create(:user) }
subject { OrderCycleManagementReport.new user, {} }
subject { Base.new user, {} }
describe "fetching orders" do
let(:supplier) { create(:supplier_enterprise) }
@@ -148,13 +148,13 @@ module Reporting
end
describe '#table_rows' do
subject { OrderCycleManagementReport.new(user, params) }
subject { Base.new(user, params) }
let(:distributor) { create(:distributor_enterprise) }
before { distributor.enterprise_roles.create!(user: user) }
context 'when the report type is payment_methods' do
let(:params) { { report_subtype: 'payment_methods' } }
subject { PaymentMethods.new(user) }
let!(:order) do
create(
@@ -180,8 +180,8 @@ module Reporting
end
end
context 'when the report type is not payment_methods' do
let(:params) { {} }
context 'when the report type is delivery' do
subject { Delivery.new(user) }
let!(:order) do
create(
:completed_order_with_totals,

View File

@@ -73,7 +73,7 @@ describe '
rows = find("table.report__table").all("thead tr")
table = rows.map { |r| r.all("th").map { |c| c.text.strip } }
expect(table.sort).to eq([
["First Name", "Last Name", "Hub", "Hub Code", "Email", "Phone", "Shipping Method",
["First Name", "Last Name", "Hub", "Customer Code", "Email", "Phone", "Shipping Method",
"Payment Method", "Amount", "Balance"].map(&:upcase)
].sort)
end
@@ -84,7 +84,7 @@ describe '
rows = find("table.report__table").all("thead tr")
table = rows.map { |r| r.all("th").map { |c| c.text.strip } }
expect(table.sort).to eq([
["First Name", "Last Name", "Hub", "Hub Code", "Delivery Address", "Delivery Postcode",
["First Name", "Last Name", "Hub", "Customer Code", "Delivery Address", "Delivery Postcode",
"Phone", "Shipping Method", "Payment Method", "Amount", "Balance",
"Temp Controlled Items?", "Special Instructions"].map(&:upcase)
].sort)