mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-27 01:43:22 +00:00
Merge pull request #12879 from chahmedejaz/task/12776-pay-suppliers-report
[Flower Farms] - Pay Suppliers Report
This commit is contained in:
@@ -244,7 +244,7 @@ module Spree
|
||||
can [:admin, :index, :show, :create], ::Admin::ReportsController
|
||||
can [:admin, :show, :create, :customers, :orders_and_distributors, :group_buys, :payments,
|
||||
:orders_and_fulfillment, :products_and_inventory, :order_cycle_management,
|
||||
:packing, :enterprise_fee_summary, :bulk_coop], :report
|
||||
:packing, :enterprise_fee_summary, :bulk_coop, :suppliers], :report
|
||||
end
|
||||
|
||||
def add_order_cycle_management_abilities(user)
|
||||
|
||||
14
app/views/admin/reports/filters/_suppliers.html.haml
Normal file
14
app/views/admin/reports/filters/_suppliers.html.haml
Normal 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})
|
||||
@@ -1768,6 +1768,7 @@ en:
|
||||
pack_by_customer: Pack By Customer
|
||||
pack_by_supplier: Pack By Supplier
|
||||
pack_by_product: Pack By Product
|
||||
pay_your_suppliers: Pay your suppliers
|
||||
display:
|
||||
report_is_big: "This report is big and may slow down your device."
|
||||
display_anyway: "Display anyway"
|
||||
@@ -1814,6 +1815,8 @@ en:
|
||||
enterprise_fee_summary:
|
||||
name: "Enterprise Fee Summary"
|
||||
description: "Summary of Enterprise Fees collected"
|
||||
suppliers:
|
||||
name: Suppliers
|
||||
enterprise_fees_with_tax_report_by_order: "Enterprise Fees With Tax Report By Order"
|
||||
enterprise_fees_with_tax_report_by_producer: "Enterprise Fees With Tax Report By Producer"
|
||||
errors:
|
||||
@@ -3172,6 +3175,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
report_render_options: Rendering Options
|
||||
report_header_ofn_uid: OFN UID
|
||||
report_header_order_cycle: Order Cycle
|
||||
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
|
||||
@@ -3192,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"
|
||||
@@ -3252,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
|
||||
@@ -3263,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
|
||||
@@ -3323,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_tax: "Total fees excl. tax (%{currency_symbol})"
|
||||
report_header_total_tax_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_fees_and_tax: "Total excl. fees and tax (%{currency_symbol})"
|
||||
report_header_temp_controlled: TempControlled?
|
||||
report_header_is_producer: Producer?
|
||||
report_header_not_confirmed: Not Confirmed
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
module Reporting
|
||||
module Reports
|
||||
class List
|
||||
include ReportTypes
|
||||
|
||||
def self.all
|
||||
new.all
|
||||
end
|
||||
@@ -22,98 +24,9 @@ module Reporting
|
||||
xero_invoices: xero_report_types,
|
||||
packing: packing_report_types,
|
||||
revenues_by_hub: [],
|
||||
suppliers: suppliers_report_types,
|
||||
}
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def orders_and_fulfillment_report_types
|
||||
[
|
||||
[i18n_translate("supplier_totals"), :order_cycle_supplier_totals],
|
||||
[i18n_translate("supplier_totals_by_distributor"),
|
||||
:order_cycle_supplier_totals_by_distributor],
|
||||
[i18n_translate("totals_by_supplier"), :order_cycle_distributor_totals_by_supplier],
|
||||
[i18n_translate("customer_totals"), :order_cycle_customer_totals]
|
||||
]
|
||||
end
|
||||
|
||||
def products_and_inventory_report_types
|
||||
[
|
||||
[i18n_translate("all_products"), :all_products],
|
||||
[i18n_translate("inventory"), :inventory, { deprecated: true }],
|
||||
[i18n_translate("lettuce_share"), :lettuce_share]
|
||||
]
|
||||
end
|
||||
|
||||
def payments_report_types
|
||||
[
|
||||
[I18n.t(:report_payment_by), :payments_by_payment_type],
|
||||
[I18n.t(:report_itemised_payment), :itemised_payment_totals],
|
||||
[I18n.t(:report_payment_totals), :payment_totals]
|
||||
]
|
||||
end
|
||||
|
||||
def enterprise_fee_summary
|
||||
[
|
||||
[i18n_translate('enterprise_fee_summary.name'), :fee_summary],
|
||||
[
|
||||
i18n_translate('enterprise_fees_with_tax_report_by_order'),
|
||||
:enterprise_fees_with_tax_report_by_order
|
||||
],
|
||||
[
|
||||
i18n_translate('enterprise_fees_with_tax_report_by_producer'),
|
||||
:enterprise_fees_with_tax_report_by_producer
|
||||
],
|
||||
]
|
||||
end
|
||||
|
||||
def order_cycle_management_report_types
|
||||
[
|
||||
[i18n_translate("payment_methods"), :payment_methods],
|
||||
[i18n_translate("delivery"), :delivery]
|
||||
]
|
||||
end
|
||||
|
||||
def sales_tax_report_types
|
||||
[
|
||||
[i18n_translate("tax_types"), :tax_types],
|
||||
[i18n_translate("tax_rates"), :tax_rates],
|
||||
[i18n_translate("sales_tax_totals_by_producer"), :sales_tax_totals_by_producer],
|
||||
[i18n_translate("sales_tax_totals_by_order"), :sales_tax_totals_by_order]
|
||||
]
|
||||
end
|
||||
|
||||
def packing_report_types
|
||||
[
|
||||
[i18n_translate("pack_by_customer"), :customer],
|
||||
[i18n_translate("pack_by_supplier"), :supplier],
|
||||
[i18n_translate("pack_by_product"), :product]
|
||||
]
|
||||
end
|
||||
|
||||
def xero_report_types
|
||||
[
|
||||
[I18n.t(:summary), 'summary'],
|
||||
[I18n.t(:detailed), 'detailed']
|
||||
]
|
||||
end
|
||||
|
||||
def bulk_coop_report_types
|
||||
[
|
||||
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.bulk_coop_#{key}"), key]
|
||||
end
|
||||
|
||||
def i18n_translate(key)
|
||||
I18n.t(key, scope: "admin.reports")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
103
lib/reporting/reports/report_types.rb
Normal file
103
lib/reporting/reports/report_types.rb
Normal file
@@ -0,0 +1,103 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
module Reports
|
||||
module ReportTypes
|
||||
protected
|
||||
|
||||
def orders_and_fulfillment_report_types
|
||||
[
|
||||
[i18n_translate("supplier_totals"), :order_cycle_supplier_totals],
|
||||
[i18n_translate("supplier_totals_by_distributor"),
|
||||
:order_cycle_supplier_totals_by_distributor],
|
||||
[i18n_translate("totals_by_supplier"), :order_cycle_distributor_totals_by_supplier],
|
||||
[i18n_translate("customer_totals"), :order_cycle_customer_totals]
|
||||
]
|
||||
end
|
||||
|
||||
def products_and_inventory_report_types
|
||||
[
|
||||
[i18n_translate("all_products"), :all_products],
|
||||
[i18n_translate("inventory"), :inventory, { deprecated: true }],
|
||||
[i18n_translate("lettuce_share"), :lettuce_share]
|
||||
]
|
||||
end
|
||||
|
||||
def payments_report_types
|
||||
[
|
||||
[I18n.t(:report_payment_by), :payments_by_payment_type],
|
||||
[I18n.t(:report_itemised_payment), :itemised_payment_totals],
|
||||
[I18n.t(:report_payment_totals), :payment_totals]
|
||||
]
|
||||
end
|
||||
|
||||
def enterprise_fee_summary
|
||||
[
|
||||
[i18n_translate('enterprise_fee_summary.name'), :fee_summary],
|
||||
[
|
||||
i18n_translate('enterprise_fees_with_tax_report_by_order'),
|
||||
:enterprise_fees_with_tax_report_by_order
|
||||
],
|
||||
[
|
||||
i18n_translate('enterprise_fees_with_tax_report_by_producer'),
|
||||
:enterprise_fees_with_tax_report_by_producer
|
||||
],
|
||||
]
|
||||
end
|
||||
|
||||
def order_cycle_management_report_types
|
||||
[
|
||||
[i18n_translate("payment_methods"), :payment_methods],
|
||||
[i18n_translate("delivery"), :delivery]
|
||||
]
|
||||
end
|
||||
|
||||
def sales_tax_report_types
|
||||
[
|
||||
[i18n_translate("tax_types"), :tax_types],
|
||||
[i18n_translate("tax_rates"), :tax_rates],
|
||||
[i18n_translate("sales_tax_totals_by_producer"), :sales_tax_totals_by_producer],
|
||||
[i18n_translate("sales_tax_totals_by_order"), :sales_tax_totals_by_order]
|
||||
]
|
||||
end
|
||||
|
||||
def packing_report_types
|
||||
[
|
||||
[i18n_translate("pack_by_customer"), :customer],
|
||||
[i18n_translate("pack_by_supplier"), :supplier],
|
||||
[i18n_translate("pack_by_product"), :product]
|
||||
]
|
||||
end
|
||||
|
||||
def xero_report_types
|
||||
[
|
||||
[I18n.t(:summary), 'summary'],
|
||||
[I18n.t(:detailed), 'detailed']
|
||||
]
|
||||
end
|
||||
|
||||
def bulk_coop_report_types
|
||||
[
|
||||
bulk_coop_item(:supplier_report),
|
||||
bulk_coop_item(:allocation),
|
||||
bulk_coop_item(:packing_sheets),
|
||||
bulk_coop_item(:customer_payments)
|
||||
]
|
||||
end
|
||||
|
||||
def suppliers_report_types
|
||||
[
|
||||
[i18n_translate(:pay_your_suppliers), :pay_your_suppliers]
|
||||
]
|
||||
end
|
||||
|
||||
def bulk_coop_item(key)
|
||||
[I18n.t("order_management.reports.bulk_coop.filters.bulk_coop_#{key}"), key]
|
||||
end
|
||||
|
||||
def i18n_translate(key)
|
||||
I18n.t(key, scope: "admin.reports")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
99
lib/reporting/reports/suppliers/base.rb
Normal file
99
lib/reporting/reports/suppliers/base.rb
Normal file
@@ -0,0 +1,99 @@
|
||||
# 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)
|
||||
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_fees_and_tax:,
|
||||
total_excl_vat:,
|
||||
total_fees_excl_tax:,
|
||||
total_tax_on_fees:,
|
||||
total_tax:,
|
||||
total:,
|
||||
}
|
||||
end
|
||||
|
||||
def rules
|
||||
[
|
||||
{
|
||||
group_by: :producer,
|
||||
header: true,
|
||||
summary_row: proc do |_key, line_items|
|
||||
summary_hash = Hash.new(0)
|
||||
|
||||
line_items.each do |line_item|
|
||||
summary_hash[:total_excl_fees_and_tax] += total_excl_fees_and_tax.call(line_item)
|
||||
summary_hash[:total_excl_vat] += total_excl_vat.call(line_item)
|
||||
summary_hash[:total_fees_excl_tax] += total_fees_excl_tax.call(line_item)
|
||||
summary_hash[:total_tax_on_fees] += total_tax_on_fees.call(line_item)
|
||||
summary_hash[:total_tax] += total_tax.call(line_item)
|
||||
summary_hash[:total] += total.call(line_item)
|
||||
end
|
||||
|
||||
summary_hash
|
||||
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,
|
||||
],
|
||||
variant: [:product, :supplier]
|
||||
}]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
122
lib/reporting/reports/suppliers/helpers/columns_helper.rb
Normal file
122
lib/reporting/reports/suppliers/helpers/columns_helper.rb
Normal file
@@ -0,0 +1,122 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
module Reports
|
||||
module Suppliers
|
||||
module Helpers
|
||||
module ColumnsHelper
|
||||
include LineItemsAccessHelper
|
||||
|
||||
def producer
|
||||
proc { |line_item| supplier(line_item).name }
|
||||
end
|
||||
|
||||
def producer_address
|
||||
proc { |line_item| supplier(line_item).address&.full_address }
|
||||
end
|
||||
|
||||
def producer_abn_acn
|
||||
proc do |line_items|
|
||||
supplier = supplier(line_items)
|
||||
# return nil if both abn and acn are nil so that it can be converted to "none"
|
||||
[supplier.abn, supplier.acn].compact_blank.join("/").presence
|
||||
end
|
||||
end
|
||||
|
||||
def email
|
||||
proc { |line_item| supplier(line_item).email_address }
|
||||
end
|
||||
|
||||
def hub
|
||||
proc { |line_item| distributor(line_item).name }
|
||||
end
|
||||
|
||||
def hub_address
|
||||
proc { |line_item| distributor(line_item).address&.full_address }
|
||||
end
|
||||
|
||||
def hub_contact_email
|
||||
proc { |line_item| distributor(line_item).email_address }
|
||||
end
|
||||
|
||||
def order_number
|
||||
proc { |line_item| order(line_item).number }
|
||||
end
|
||||
|
||||
def order_date
|
||||
proc { |line_item| order(line_item).completed_at.to_date }
|
||||
end
|
||||
|
||||
def order_cycle
|
||||
proc { |line_item| item_order_cycle(line_item).name }
|
||||
end
|
||||
|
||||
def order_cycle_start_date
|
||||
proc { |line_item| item_order_cycle(line_item).orders_open_at.to_date }
|
||||
end
|
||||
|
||||
def order_cycle_end_date
|
||||
proc { |line_item| item_order_cycle(line_item).orders_close_at.to_date }
|
||||
end
|
||||
|
||||
def product
|
||||
proc { |line_item| variant(line_item).product.name }
|
||||
end
|
||||
|
||||
def variant_unit_name
|
||||
proc { |line_item| variant(line_item).full_name }
|
||||
end
|
||||
|
||||
def quantity
|
||||
proc { |line_item| line_item.quantity }
|
||||
end
|
||||
|
||||
def total_excl_fees_and_tax
|
||||
proc do |line_item|
|
||||
included_tax = adjustments_by_type(line_item, :tax, included: true)
|
||||
line_item.amount - included_tax
|
||||
end
|
||||
end
|
||||
|
||||
def total_excl_vat
|
||||
proc do |line_item|
|
||||
total_fees = adjustments_by_type(line_item, :fees)
|
||||
total_excl_fees_and_tax.call(line_item) + total_fees
|
||||
end
|
||||
end
|
||||
|
||||
def total_fees_excl_tax
|
||||
proc do |line_item|
|
||||
included_tax = tax_on_fees(line_item, included: true)
|
||||
adjustments_by_type(line_item, :fees) - included_tax
|
||||
end
|
||||
end
|
||||
|
||||
def total_tax_on_fees
|
||||
proc { |line_item| tax_on_fees(line_item) + tax_on_fees(line_item, included: true) }
|
||||
end
|
||||
|
||||
def total_tax
|
||||
proc do |line_item|
|
||||
excluded_tax = adjustments_by_type(line_item, :tax)
|
||||
included_tax = adjustments_by_type(line_item, :tax, included: true)
|
||||
|
||||
excluded_tax + included_tax
|
||||
end
|
||||
end
|
||||
|
||||
def total
|
||||
proc do |line_item|
|
||||
total_price = total_excl_fees_and_tax.call(line_item)
|
||||
total_fees = total_fees_excl_tax.call(line_item)
|
||||
total_fees_tax = total_tax_on_fees.call(line_item)
|
||||
tax = total_tax.call(line_item)
|
||||
|
||||
total_price + total_fees + total_fees_tax + tax
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,66 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Reporting
|
||||
module Reports
|
||||
module Suppliers
|
||||
module Helpers
|
||||
module LineItemsAccessHelper
|
||||
def variant(line_item)
|
||||
line_item.variant
|
||||
end
|
||||
|
||||
def order(line_item)
|
||||
line_item.order
|
||||
end
|
||||
|
||||
def supplier(line_item)
|
||||
variant(line_item).supplier
|
||||
end
|
||||
|
||||
def distributor(line_item)
|
||||
order(line_item).distributor
|
||||
end
|
||||
|
||||
def item_order_cycle(line_item)
|
||||
line_item.order_cycle
|
||||
end
|
||||
|
||||
def suppliers_adjustments(line_item, adjustment_type = 'EnterpriseFee')
|
||||
adjustments = line_item.adjustments
|
||||
return adjustments.tax if adjustment_type == 'Spree::TaxRate'
|
||||
|
||||
supplier_id = line_item.supplier_id
|
||||
adjustments.enterprise_fee.select do |adjustment|
|
||||
label = adjustment.label
|
||||
adjustment_enterprise_id = adjustment.originator.enterprise_id
|
||||
label.include?('supplier') && adjustment_enterprise_id == supplier_id
|
||||
end
|
||||
end
|
||||
|
||||
def adjustments_by_type(line_item, type, included: false)
|
||||
total_amount = 0.0
|
||||
adjustment_type = type == :tax ? 'Spree::TaxRate' : 'EnterpriseFee'
|
||||
suppliers_adjustments(line_item, adjustment_type).each do |adjustment|
|
||||
amount = included == adjustment.included ? adjustment.amount : 0.0
|
||||
total_amount += amount
|
||||
end
|
||||
|
||||
total_amount
|
||||
end
|
||||
|
||||
def tax_on_fees(line_item, included: false)
|
||||
total_amount = 0.0
|
||||
suppliers_adjustments(line_item).each do |adjustment|
|
||||
adjustment.adjustments.tax.each do |fee_adjustment|
|
||||
amount = included == fee_adjustment.included ? fee_adjustment.amount : 0.0
|
||||
total_amount += amount
|
||||
end
|
||||
end
|
||||
|
||||
total_amount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
105
spec/lib/reports/suppliers/pay_your_suppliers_report_spec.rb
Normal file
105
spec/lib/reports/suppliers/pay_your_suppliers_report_spec.rb
Normal file
@@ -0,0 +1,105 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe "Pay Your Suppliers Report" do
|
||||
let(:hub) { create(:distributor_enterprise) }
|
||||
let(:order_cycle) { create(:open_order_cycle, distributors: [hub]) }
|
||||
let(:product) { order.products.first }
|
||||
let(:variant) { product.variants.first }
|
||||
let(:supplier) { variant.supplier }
|
||||
let(:current_user) { hub.owner }
|
||||
let!(:order) do
|
||||
create(:completed_order_with_totals, distributor: hub, order_cycle:, line_items_count: 1)
|
||||
end
|
||||
let(:params) { { display_summary_row: true } }
|
||||
let(:report) { Reporting::Reports::Suppliers::Base.new(current_user, { q: params }) }
|
||||
let(:report_table_rows) { report.rows }
|
||||
|
||||
context "without fees and taxes" do
|
||||
it "Generates the report" do
|
||||
expect(report_table_rows.length).to eq(1)
|
||||
table_row = report_table_rows.first
|
||||
|
||||
expect(table_row.producer).to eq(supplier.name)
|
||||
expect(table_row.producer_address).to eq(supplier.address.full_address)
|
||||
expect(table_row.producer_abn_acn).to eq("none")
|
||||
expect(table_row.email).to eq("none")
|
||||
expect(table_row.hub).to eq(hub.name)
|
||||
expect(table_row.hub_address).to eq(hub.address.full_address)
|
||||
expect(table_row.hub_contact_email).to eq("none")
|
||||
expect(table_row.order_number).to eq(order.number)
|
||||
expect(table_row.order_date).to eq(order.completed_at.to_date.to_s)
|
||||
expect(table_row.order_cycle).to eq(order_cycle.name)
|
||||
expect(table_row.order_cycle_start_date).to eq(
|
||||
order_cycle.orders_open_at.to_date.to_s
|
||||
)
|
||||
expect(table_row.order_cycle_end_date).to eq(order_cycle.orders_close_at.to_date.to_s)
|
||||
expect(table_row.product).to eq(product.name)
|
||||
expect(table_row.variant_unit_name).to eq(variant.full_name)
|
||||
expect(table_row.quantity).to eq(1)
|
||||
expect(table_row.total_excl_fees_and_tax.to_f).to eq(10.0)
|
||||
expect(table_row.total_excl_vat.to_f).to eq(10.0)
|
||||
expect(table_row.total_fees_excl_tax.to_f).to eq(0.0)
|
||||
expect(table_row.total_tax_on_fees.to_f).to eq(0.0)
|
||||
expect(table_row.total_tax.to_f).to eq(0.0)
|
||||
expect(table_row.total.to_f).to eq(10.0)
|
||||
end
|
||||
end
|
||||
|
||||
context "with taxes and fees" do
|
||||
let(:line_item) { order.line_items.first }
|
||||
let(:tax_category) {
|
||||
create(
|
||||
:tax_category,
|
||||
tax_rates: [
|
||||
create(
|
||||
:tax_rate,
|
||||
zone: create(:zone_with_member)
|
||||
)
|
||||
]
|
||||
)
|
||||
}
|
||||
let!(:enterprise_fee) do
|
||||
create(
|
||||
:enterprise_fee,
|
||||
enterprise: supplier,
|
||||
fee_type: 'sales',
|
||||
amount: 0.1,
|
||||
tax_category:
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
# Prepare order or line_item to have respective tax adjustments
|
||||
hub.update!(charges_sales_tax: true)
|
||||
supplier.update!(charges_sales_tax: true)
|
||||
line_item.variant.update!(tax_category:)
|
||||
line_item.copy_tax_category
|
||||
|
||||
exchange = order_cycle.exchanges.take
|
||||
exchange.enterprise_fees << enterprise_fee
|
||||
exchange.exchange_variants.build(variant: line_item.variant)
|
||||
exchange.incoming = true
|
||||
exchange.save!
|
||||
|
||||
OpenFoodNetwork::EnterpriseFeeCalculator
|
||||
.new(hub, order_cycle)
|
||||
.create_line_item_adjustments_for(line_item)
|
||||
|
||||
order.create_tax_charge!
|
||||
end
|
||||
|
||||
it "Generates the report" do
|
||||
expect(report_table_rows.length).to eq(1)
|
||||
table_row = report_table_rows.first
|
||||
|
||||
expect(table_row.total_excl_fees_and_tax.to_f).to eq(10.0)
|
||||
expect(table_row.total_excl_vat.to_f).to eq(10.1)
|
||||
expect(table_row.total_fees_excl_tax.to_f).to eq(0.1)
|
||||
expect(table_row.total_tax_on_fees.to_f).to eq(0.01)
|
||||
expect(table_row.total_tax.to_f).to eq(1.0)
|
||||
expect(table_row.total.to_f).to eq(11.11)
|
||||
end
|
||||
end
|
||||
end
|
||||
141
spec/system/admin/reports/pay_your_suppliers_spec.rb
Normal file
141
spec/system/admin/reports/pay_your_suppliers_spec.rb
Normal file
@@ -0,0 +1,141 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "system_helper"
|
||||
|
||||
RSpec.describe "Pay Your Suppliers Report" do
|
||||
include ReportsHelper
|
||||
|
||||
let(:owner) { create(:user) }
|
||||
let(:hub1) { create(:enterprise, owner:) }
|
||||
let(:order_cycle1) { create(:open_order_cycle, distributors: [hub1]) }
|
||||
let!(:order1) do
|
||||
create(
|
||||
:completed_order_with_totals,
|
||||
distributor: hub1,
|
||||
order_cycle: order_cycle1,
|
||||
line_items_count: 2
|
||||
)
|
||||
end
|
||||
|
||||
let(:hub2) { create(:enterprise, owner:) }
|
||||
let(:product2) { order1.products.first }
|
||||
let(:variant2) { product2.variants.first }
|
||||
let(:supplier2) { variant2.supplier }
|
||||
let(:order_cycle2) { create(:open_order_cycle, distributors: [hub2]) }
|
||||
let!(:order2) do
|
||||
create(
|
||||
:completed_order_with_totals,
|
||||
distributor: hub2,
|
||||
order_cycle: order_cycle2,
|
||||
line_items_count: 3
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
login_as owner
|
||||
visit admin_reports_path
|
||||
end
|
||||
|
||||
context "on Reports page" do
|
||||
it "should generate 'Pay Your Suppliers' report" do
|
||||
click_on 'Pay your suppliers'
|
||||
expect(page).to have_button("Go")
|
||||
run_report
|
||||
|
||||
expect(page.find("table.report__table thead tr").text).to have_content([
|
||||
"Producer",
|
||||
"Producer Address",
|
||||
"Producer ABN/ACN",
|
||||
"Email",
|
||||
"Hub",
|
||||
"Hub Address",
|
||||
"Hub Contact Email",
|
||||
"Order number",
|
||||
"Order date",
|
||||
"Order Cycle",
|
||||
"OC Start Date",
|
||||
"OC End Date",
|
||||
"Product",
|
||||
"Variant Unit Name",
|
||||
"Quantity",
|
||||
"Total excl. fees and tax ($)",
|
||||
"Total excl. tax ($)",
|
||||
"Total fees excl. tax ($)",
|
||||
"Total tax on fees ($)",
|
||||
"Total Tax ($)",
|
||||
"Total ($)"
|
||||
].join(" "))
|
||||
|
||||
lines = page.all('table.report__table tbody tr').map(&:text)
|
||||
# 5 line_item rows + 1 summary row = 6 rows
|
||||
expect(lines.count).to be(6)
|
||||
|
||||
hub1_rows = lines.select { |line| line.include?(hub1.name) }
|
||||
order1.line_items.each_with_index do |line_item, index|
|
||||
variant = line_item.variant
|
||||
supplier = line_item.supplier
|
||||
product = line_item.variant.product
|
||||
line = hub1_rows[index]
|
||||
|
||||
expect(line).to have_content([
|
||||
supplier.name,
|
||||
supplier.address.full_address,
|
||||
"none",
|
||||
"none",
|
||||
hub1.name,
|
||||
hub1.address.full_address,
|
||||
"none",
|
||||
order1.number,
|
||||
order1.completed_at.to_date.to_s,
|
||||
order_cycle1.name,
|
||||
order_cycle1.orders_open_at.to_date.to_s,
|
||||
order_cycle1.orders_close_at.to_date.to_s,
|
||||
product.name,
|
||||
variant.full_name,
|
||||
1,
|
||||
10.0,
|
||||
10.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
10.0,
|
||||
].compact.join(" "))
|
||||
end
|
||||
|
||||
hub2_rows = lines.select { |line| line.include?(hub2.name) }
|
||||
order2.line_items.each_with_index do |line_item, index|
|
||||
variant = line_item.variant
|
||||
supplier = line_item.supplier
|
||||
product = line_item.variant.product
|
||||
line = hub2_rows[index]
|
||||
|
||||
expect(line).to have_content([
|
||||
supplier.name,
|
||||
supplier.address.full_address,
|
||||
"none",
|
||||
"none",
|
||||
hub2.name,
|
||||
hub2.address.full_address,
|
||||
"none",
|
||||
order2.number,
|
||||
order2.completed_at.to_date.to_s,
|
||||
order_cycle2.name,
|
||||
order_cycle2.orders_open_at.to_date.to_s,
|
||||
order_cycle2.orders_close_at.to_date.to_s,
|
||||
product.name,
|
||||
variant.full_name,
|
||||
1,
|
||||
10.0,
|
||||
10.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
10.0,
|
||||
].compact.join(" "))
|
||||
end
|
||||
|
||||
# summary row
|
||||
expect(lines.last).to have_content("TOTAL 50.0 50.0 0.0 0.0 0.0 50.0")
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user