mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Report Refactor 3: Order Cycle Management
This commit is contained in:
committed by
Jean-Baptiste Bellet
parent
3808398807
commit
71aca960ee
@@ -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?
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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
|
||||
|
||||
81
lib/reporting/reports/order_cycle_management/base.rb
Normal file
81
lib/reporting/reports/order_cycle_management/base.rb
Normal 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
|
||||
35
lib/reporting/reports/order_cycle_management/delivery.rb
Normal file
35
lib/reporting/reports/order_cycle_management/delivery.rb
Normal 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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user