12776: add supplier report

This commit is contained in:
Ahmed Ejaz
2024-09-29 17:31:08 +05:00
committed by Rachel Arnould
parent 122a64e488
commit 7cb28fd064
5 changed files with 310 additions and 1 deletions

View File

@@ -0,0 +1,14 @@
= render 'admin/reports/date_range_form', f: f
.row
.alpha.two.columns= label_tag nil, t(:report_hubs)
.omega.fourteen.columns= f.collection_select(:distributor_id_in, @data.orders_distributors, :id, :name, {}, {class: "select2 fullwidth", multiple: true})
.row
.alpha.two.columns= label_tag nil, t(:report_producers)
.omega.fourteen.columns= select_tag(:supplier_id_in, options_from_collection_for_select(@data.orders_suppliers, :id, :name, params[:supplier_id_in]), {class: "select2 fullwidth", multiple: true})
.row
.alpha.two.columns= label_tag nil, t(:report_customers_cycle)
.omega.fourteen.columns
= f.select(:order_cycle_id_in, report_order_cycle_options(@data.order_cycles), {selected: params.dig(:q, :order_cycle_id_in)}, {class: "select2 fullwidth", multiple: true})

View File

@@ -3174,7 +3174,9 @@ See the %{link} to find out more about %{sitename}'s features and to start using
report_print: Print Report
report_render_options: Rendering Options
report_header_ofn_uid: OFN UID
report_header_order_cycle: Order Cycle
report_header_order_cycle: Order Cycle (OC)
report_header_order_cycle_start_date: OC Start Date
report_header_order_cycle_end_date: OC End Date
report_header_user: User
report_header_email: Email
report_header_status: Status
@@ -3195,6 +3197,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
report_header_hub_legal_name: "Hub Legal Name"
report_header_hub_contact_name: "Hub Contact Name"
report_header_hub_email: "Hub Public Email"
report_header_hub_contact_email: Hub Contact Email
report_header_hub_owner_email: Hub Owner Email
report_header_hub_phone: "Hub Phone Number"
report_header_hub_address_line1: "Hub Address Line 1"
@@ -3255,6 +3258,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
report_header_quantity: Quantity
report_header_max_quantity: Max Quantity
report_header_variant: Variant
report_header_variant_unit_name: Variant Unit Name
report_header_variant_value: Variant Value
report_header_variant_unit: Variant Unit
report_header_total_available: Total available
@@ -3266,6 +3270,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using
report_header_producer_suburb: Producer Suburb
report_header_producer_tax_status: Producer Tax Status
report_header_producer_charges_sales_tax?: GST/VAT Registered
report_header_producer_abn_acn: Producer ABN/ACN
report_header_producer_address: Producer Address
report_header_unit: Unit
report_header_group_buy_unit_quantity: Group Buy Unit Quantity
report_header_cost: Cost
@@ -3326,7 +3332,11 @@ See the %{link} to find out more about %{sitename}'s features and to start using
report_header_total_units: Total Units
report_header_sum_max_total: "Sum Max Total"
report_header_total_excl_vat: "Total excl. tax (%{currency_symbol})"
report_header_total_fees_excl_vat: "Total fees excl. tax (%{currency_symbol})"
report_header_total_vat_on_fees: "Total tax on fees (%{currency_symbol})"
report_header_total: "Total (%{currency_symbol})"
report_header_total_incl_vat: "Total incl. tax (%{currency_symbol})"
report_header_total_excl_vat_and_fees: "Total excl. fees and tax (%{currency_symbol})"
report_header_temp_controlled: TempControlled?
report_header_is_producer: Producer?
report_header_not_confirmed: Not Confirmed

View File

@@ -0,0 +1,100 @@
# frozen_string_literal: true
module Reporting
module Reports
module Suppliers
class Base < ReportTemplate
include Helpers::ColumnsHelper
def default_params
{
q: {
completed_at_gt: 1.month.ago.beginning_of_day,
completed_at_lt: 1.day.from_now.beginning_of_day
}
}
end
def search
report_line_items.orders
end
def query_result
report_line_items.list(line_item_includes).group_by { |e|
[e.variant_id, e.price, e.order.distributor_id]
}.values
end
def columns
{
producer:,
producer_address:,
producer_abn_acn:,
email:,
hub:,
hub_address:,
hub_contact_email:,
order_number:,
order_date:,
order_cycle:,
order_cycle_start_date:,
order_cycle_end_date:,
product:,
variant_unit_name:,
quantity:,
total_excl_vat_and_fees:,
total_excl_vat:,
total_fees_excl_vat:,
total_vat_on_fees:,
total_tax:,
total:,
}
end
def rules
[
{
group_by: :producer,
header: true,
summary_row: proc do |_key, items|
line_items = items.flatten
{
total_excl_vat_and_fees: total_excl_vat_and_fees.call(line_items),
total_excl_vat: total_excl_vat.call(line_items),
total_fees_excl_vat: total_fees_excl_vat.call(line_items),
total_vat_on_fees: total_vat_on_fees.call(line_items),
total_tax: total_tax.call(line_items),
total: total.call(line_items),
}
end
}
]
end
private
def order_permissions
return @order_permissions unless @order_permissions.nil?
@order_permissions = ::Permissions::Order.new(@user, ransack_params)
end
def report_line_items
@report_line_items ||= Reporting::LineItems.new(order_permissions, params)
end
def line_item_includes
[{
order: [
:distributor,
:adjustments,
{ shipments: { shipping_rates: :shipping_method } }
],
variant: [:product, :supplier]
}]
end
end
end
end
end

View File

@@ -0,0 +1,121 @@
# frozen_string_literal: true
module Reporting
module Reports
module Suppliers
module Helpers
module ColumnsHelper
include LineItemsAccessHelper
def producer
proc { |line_items| supplier(line_items).name }
end
def producer_address
proc { |line_items| supplier(line_items).address&.full_address }
end
def producer_abn_acn
proc do |line_items|
supplier = supplier(line_items)
supplier.abn.presence || supplier.acn
end
end
def email
proc { |line_items| supplier(line_items).email_address }
end
def hub
proc { |line_items| distributor(line_items).name }
end
def hub_address
proc { |line_items| distributor(line_items).address&.full_address }
end
def hub_contact_email
proc { |line_items| distributor(line_items).email_address }
end
def order_number
proc { |line_items| order(line_items).number }
end
def order_date
proc { |line_items| order(line_items).completed_at.strftime("%d/%m/%Y") }
end
def order_cycle
proc { |line_items| item_order_cycle(line_items).name }
end
def order_cycle_start_date
proc { |line_items| item_order_cycle(line_items).orders_open_at.strftime("%d/%m/%Y") }
end
def order_cycle_end_date
proc { |line_items| item_order_cycle(line_items).orders_close_at.strftime("%d/%m/%Y") }
end
def product
proc { |line_items| variant(line_items).product.name }
end
def variant_unit_name
proc { |line_items| variant(line_items).full_name }
end
def quantity
proc { |line_items| line_items.to_a.sum(&:quantity) }
end
def total_excl_vat_and_fees
proc do |line_items|
included_tax = adjustments_by_type(line_items, :tax, included: true)
line_items.sum(&:amount) - included_tax
end
end
def total_excl_vat
proc do |line_items|
total_fees = adjustments_by_type(line_items, :fees)
total_excl_vat_and_fees.call(line_items) + total_fees
end
end
def total_fees_excl_vat
proc do |line_items|
included_tax = tax_on_fees(line_items, included: true)
adjustments_by_type(line_items, :fees) - included_tax
end
end
def total_vat_on_fees
proc { |line_items| tax_on_fees(line_items) }
end
def total_tax
proc do |line_items|
excluded_tax = adjustments_by_type(line_items, :tax)
included_tax = adjustments_by_type(line_items, :tax, included: true)
excluded_tax + included_tax
end
end
def total
proc do |line_items|
total_price = total_excl_vat_and_fees.call(line_items)
total_fees = total_fees_excl_vat.call(line_items)
tax = total_tax.call(line_items)
total_price + total_fees + tax
end
end
end
end
end
end
end

View File

@@ -0,0 +1,64 @@
# frozen_string_literal: true
module Reporting
module Reports
module Suppliers
module Helpers
module LineItemsAccessHelper
def variant(line_items)
line_items.first.variant
end
def order(line_items)
line_items.first.order
end
def supplier(line_items)
variant(line_items).supplier
end
def distributor(line_items)
order(line_items).distributor
end
def item_order_cycle(line_items)
line_items.first.order_cycle
end
def adjustments_by_type(line_items, type, included: false)
total_amount = 0.0
adjustment_type = type == :tax ? 'Spree::TaxRate' : 'EnterpriseFee'
adjustments = line_items.flat_map(&:adjustments)
adjustments.each do |adjustment|
if adjustment.originator_type == adjustment_type
amount = included == adjustment.included ? adjustment.amount : 0.0
total_amount += amount
end
end
total_amount
end
def tax_on_fees(line_items, included: false)
total_amount = 0.0
adjustments = line_items.flat_map(&:adjustments)
adjustments.each do |adjustment|
next unless adjustment.originator_type == 'EnterpriseFee'
adjustment.adjustments.each do |fee_adjustment|
next unless adjustment.originator_type == 'Spree::TaxRate'
amount = included == fee_adjustment.included ? fee_adjustment.amount : 0.0
total_amount += amount
end
end
total_amount
end
end
end
end
end
end