From 00927f7c6c19937a49bfaf58aa69d5bdba248c7f Mon Sep 17 00:00:00 2001 From: Lynne Davis Date: Mon, 1 Jun 2015 18:20:53 +0100 Subject: [PATCH] Refactoring to move bulk out of reports_controller_decorator Conflicts: app/controllers/spree/admin/reports_controller_decorator.rb --- .../admin/reports_controller_decorator.rb | 597 ++---------------- .../spree/admin/reports/bulk_coop.html.haml | 4 +- .../reports/orders_and_fulfillment.html.haml | 4 +- .../spree/admin/reports/payments.html.haml | 4 +- lib/open_food_network/bulk_coop_report.rb | 142 +++++ .../orders_and_fulfillments_report.rb | 256 ++++++++ lib/open_food_network/payments_report.rb | 101 +++ 7 files changed, 554 insertions(+), 554 deletions(-) create mode 100644 lib/open_food_network/bulk_coop_report.rb create mode 100644 lib/open_food_network/orders_and_fulfillments_report.rb create mode 100644 lib/open_food_network/payments_report.rb diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 852d35f5ce..236c676d95 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -9,6 +9,9 @@ require 'open_food_network/order_cycle_management_report' require 'open_food_network/packing_report' require 'open_food_network/sales_tax_report' require 'open_food_network/xero_invoices_report' +require 'open_food_network/bulk_coop_report' +require 'open_food_network/payments_report' +require 'open_food_network/orders_and_fulfillments_report' Spree::Admin::ReportsController.class_eval do @@ -73,17 +76,7 @@ Spree::Admin::ReportsController.class_eval do def order_cycle_management - # -- Prepare parameters - params[:q] ||= {} - if params[:q][:completed_at_gt].blank? - params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month - else - params[:q][:completed_at_gt] = Time.zone.parse(params[:q][:completed_at_gt]) rescue Time.zone.now.beginning_of_month - end - if params[:q] && !params[:q][:completed_at_lt].blank? - params[:q][:completed_at_lt] = Time.zone.parse(params[:q][:completed_at_lt]) rescue "" - end - params[:q][:meta_sort] ||= "completed_at.desc" + prepare_date_params params # -- Prepare form options my_distributors = Enterprise.is_distributor.managed_by(spree_current_user) @@ -107,17 +100,9 @@ Spree::Admin::ReportsController.class_eval do end def packing - # -- Prepare parameters - params[:q] ||= {} - if params[:q][:completed_at_gt].blank? - params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month - else - params[:q][:completed_at_gt] = Time.zone.parse(params[:q][:completed_at_gt]) rescue Time.zone.now.beginning_of_month - end - if params[:q] && !params[:q][:completed_at_lt].blank? - params[:q][:completed_at_lt] = Time.zone.parse(params[:q][:completed_at_lt]) rescue "" - end - params[:q][:meta_sort] ||= "completed_at.desc" + + # -- Prepare date parameters + prepare_date_params params # -- Prepare form options my_distributors = Enterprise.is_distributor.managed_by(spree_current_user) @@ -141,18 +126,8 @@ Spree::Admin::ReportsController.class_eval do end def orders_and_distributors - params[:q] ||= {} - if params[:q][:completed_at_gt].blank? - params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month - else - params[:q][:completed_at_gt] = Time.zone.parse(params[:q][:completed_at_gt]).beginning_of_day rescue Time.zone.now.beginning_of_month - end - - if params[:q] && !params[:q][:completed_at_lt].blank? - params[:q][:completed_at_lt] = Time.zone.parse(params[:q][:completed_at_lt]).end_of_day rescue "" - end - params[:q][:meta_sort] ||= "completed_at.desc" + prepare_date_params params @search = Spree::Order.complete.not_state(:canceled).managed_by(spree_current_user).search(params[:q]) orders = @search.result @@ -170,18 +145,8 @@ Spree::Admin::ReportsController.class_eval do end def sales_tax - params[:q] ||= {} - if params[:q][:completed_at_gt].blank? - params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month - else - params[:q][:completed_at_gt] = Time.zone.parse(params[:q][:completed_at_gt]).beginning_of_day rescue Time.zone.now.beginning_of_month - end - - if params[:q] && !params[:q][:completed_at_lt].blank? - params[:q][:completed_at_lt] = Time.zone.parse(params[:q][:completed_at_lt]).end_of_day rescue "" - end - params[:q][:meta_sort] ||= "completed_at.desc" + prepare_date_params params @search = Spree::Order.complete.not_state(:canceled).managed_by(spree_current_user).search(params[:q]) orders = @search.result @@ -200,300 +165,49 @@ Spree::Admin::ReportsController.class_eval do end def bulk_coop - params[:q] ||= {} - if params[:q][:completed_at_gt].blank? - params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month - else - params[:q][:completed_at_gt] = Time.zone.parse(params[:q][:completed_at_gt]).beginning_of_day rescue Time.zone.now.beginning_of_month - end - - if params[:q] && !params[:q][:completed_at_lt].blank? - params[:q][:completed_at_lt] = Time.zone.parse(params[:q][:completed_at_lt]).end_of_day rescue "" - end - params[:q][:meta_sort] ||= "completed_at.desc" - - @search = Spree::Order.complete.not_state(:canceled).managed_by(spree_current_user).search(params[:q]) - - orders = @search.result - @line_items = orders.map { |o| o.line_items.managed_by(spree_current_user) }.flatten + # -- Prepare date parameters + prepare_date_params params + # -- Prepare form options @distributors = Enterprise.is_distributor.managed_by(spree_current_user) @report_type = params[:report_type] - case params[:report_type] - when "bulk_coop_supplier_report" + # -- Build Report with Order Grouper + @report = OpenFoodNetwork::BulkCoopReport.new spree_current_user, params + order_grouper = OpenFoodNetwork::OrderGrouper.new @report.rules, @report.columns + @table = order_grouper.table(@report.table_items) + csv_file_name = "bulk_coop_#{params[:report_type]}_#{timestamp}.csv" - header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total", "Units Required", "Remainder"] - - columns = [ proc { |lis| lis.first.variant.product.supplier.name }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, - proc { |lis| lis.first.variant.full_name }, - proc { |lis| lis.first.variant.weight || 0 }, - proc { |lis| lis.sum { |li| li.quantity } }, - proc { |lis| lis.sum { |li| li.max_quantity || 0 } }, - proc { |lis| "" }, - proc { |lis| "" } ] - - rules = [ { group_by: proc { |li| li.variant.product.supplier }, - sort_by: proc { |supplier| supplier.name } }, - { group_by: proc { |li| li.variant.product }, - sort_by: proc { |product| product.name }, - summary_columns: [ proc { |lis| lis.first.variant.product.supplier.name }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, - proc { |lis| "" }, - proc { |lis| "" }, - proc { |lis| lis.sum { |li| (li.quantity || 0) * (li.variant.weight || 0) } }, - proc { |lis| lis.sum { |li| (li.max_quantity || 0) * (li.variant.weight || 0) } }, - proc { |lis| ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor }, - proc { |lis| lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max) * (li.variant.weight || 0) } - ( ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor * (lis.first.variant.product.group_buy_unit_size || 0) ) } ] }, - { group_by: proc { |li| li.variant }, - sort_by: proc { |variant| variant.full_name } } ] - - when "bulk_coop_allocation" - - header = ["Customer", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total", "Total Allocated", "Remainder"] - - columns = [ proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, - proc { |lis| lis.first.variant.full_name }, - proc { |lis| lis.first.variant.weight || 0 }, - proc { |lis| lis.sum { |li| li.quantity } }, - proc { |lis| lis.sum { |li| li.max_quantity || 0 } }, - proc { |lis| "" }, - proc { |lis| "" } ] - - rules = [ { group_by: proc { |li| li.variant.product }, - sort_by: proc { |product| product.name }, - summary_columns: [ proc { |lis| "TOTAL" }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, - proc { |lis| "" }, - proc { |lis| "" }, - proc { |lis| lis.sum { |li| li.quantity * (li.variant.weight || 0) } }, - proc { |lis| lis.sum { |li| (li.max_quantity || 0) * (li.variant.weight || 0) } }, - proc { |lis| ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor * (lis.first.variant.product.group_buy_unit_size || 0) }, - proc { |lis| lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } - ( ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor * (lis.first.variant.product.group_buy_unit_size || 0) ) } ] }, - { group_by: proc { |li| li.variant }, - sort_by: proc { |variant| variant.full_name } }, - { group_by: proc { |li| li.order }, - sort_by: proc { |order| order.to_s } } ] - - when "bulk_coop_packing_sheets" - - header = ["Customer", "Product", "Variant", "Sum Total"] - - columns = [ proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| lis.first.variant.full_name }, - proc { |lis| lis.sum { |li| li.quantity } } ] - - rules = [ { group_by: proc { |li| li.variant.product }, - sort_by: proc { |product| product.name } }, - { group_by: proc { |li| li.variant }, - sort_by: proc { |variant| variant.full_name } }, - { group_by: proc { |li| li.order }, - sort_by: proc { |order| order.to_s } } ] - - when "bulk_coop_customer_payments" - - header = ["Customer", "Date of Order", "Total Cost", "Amount Owing", "Amount Paid"] - - columns = [ proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, - proc { |lis| lis.first.order.completed_at.to_s }, - proc { |lis| lis.map { |li| li.order }.uniq.sum { |o| o.total } }, - proc { |lis| lis.map { |li| li.order }.uniq.sum { |o| o.outstanding_balance } }, - proc { |lis| lis.map { |li| li.order }.uniq.sum { |o| o.payment_total } } ] - - rules = [ { group_by: proc { |li| li.order }, - sort_by: proc { |order| order.completed_at } } ] - - else # List all line items - - header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total", "Units Required", "Remainder"] - - columns = [ proc { |lis| lis.first.variant.product.supplier.name }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, - proc { |lis| lis.first.variant.full_name }, - proc { |lis| lis.first.variant.weight || 0 }, - proc { |lis| lis.sum { |li| li.quantity } }, - proc { |lis| lis.sum { |li| li.max_quantity || 0 } }, - proc { |lis| "" }, - proc { |lis| "" } ] - - rules = [ { group_by: proc { |li| li.variant.product.supplier }, - sort_by: proc { |supplier| supplier.name } }, - { group_by: proc { |li| li.variant.product }, - sort_by: proc { |product| product.name }, - summary_columns: [ proc { |lis| lis.first.variant.product.supplier.name }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, - proc { |lis| "" }, - proc { |lis| "" }, - proc { |lis| lis.sum { |li| li.quantity * (li.variant.weight || 0) } }, - proc { |lis| lis.sum { |li| (li.max_quantity || 0) * (li.variant.weight || 0) } }, - proc { |lis| ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor }, - proc { |lis| lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } - ( ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor * (lis.first.variant.product.group_buy_unit_size || 0) ) } ] }, - { group_by: proc { |li| li.variant }, - sort_by: proc { |variant| variant.full_name } } ] - - end - - order_grouper = OpenFoodNetwork::OrderGrouper.new rules, columns - - @header = header - @table = order_grouper.table(@line_items) - csv_file_name = "bulk_coop_#{timestamp}.csv" - - render_report(@header, @table, params[:csv], csv_file_name) + render_report(@report.header, @table, params[:csv], csv_file_name) end def payments - params[:q] ||= {} - - if params[:q][:completed_at_gt].blank? - params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month - else - params[:q][:completed_at_gt] = Time.zone.parse(params[:q][:completed_at_gt]).beginning_of_day rescue Time.zone.now.beginning_of_month - end - - if params[:q] && !params[:q][:completed_at_lt].blank? - params[:q][:completed_at_lt] = Time.zone.parse(params[:q][:completed_at_lt]).end_of_day rescue "" - end - params[:q][:meta_sort] ||= "completed_at.desc" - - @search = Spree::Order.complete.not_state(:canceled).managed_by(spree_current_user).search(params[:q]) - - orders = @search.result - payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments + # -- Prepare Date Params + prepare_date_params params + # -- Prepare Form Options @distributors = Enterprise.is_distributor.managed_by(spree_current_user) @report_type = params[:report_type] - case params[:report_type] - when "payments_by_payment_type" - table_items = payments - - header = ["Payment State", "Distributor", "Payment Type", "Total (#{currency_symbol})"] - - columns = [ proc { |payments| payments.first.order.payment_state }, - proc { |payments| payments.first.order.distributor.name }, - proc { |payments| payments.first.payment_method.name }, - proc { |payments| payments.sum { |payment| payment.amount } } ] - - rules = [ { group_by: proc { |payment| payment.order.payment_state }, - sort_by: proc { |payment_state| payment_state } }, - { group_by: proc { |payment| payment.order.distributor }, - sort_by: proc { |distributor| distributor.name } }, - { group_by: proc { |payment| Spree::PaymentMethod.unscoped { payment.payment_method } }, - sort_by: proc { |method| method.name } } ] - - when "itemised_payment_totals" - table_items = orders - - header = ["Payment State", "Distributor", "Product Total (#{currency_symbol})", "Shipping Total (#{currency_symbol})", "Outstanding Balance (#{currency_symbol})", "Total (#{currency_symbol})"] - - columns = [ proc { |orders| orders.first.payment_state }, - proc { |orders| orders.first.distributor.name }, - proc { |orders| orders.sum { |o| o.item_total } }, - proc { |orders| orders.sum { |o| o.ship_total } }, - proc { |orders| orders.sum { |o| o.outstanding_balance } }, - proc { |orders| orders.sum { |o| o.total } } ] - - rules = [ { group_by: proc { |order| order.payment_state }, - sort_by: proc { |payment_state| payment_state } }, - { group_by: proc { |order| order.distributor }, - sort_by: proc { |distributor| distributor.name } } ] - - when "payment_totals" - table_items = orders - - header = ["Payment State", "Distributor", "Product Total (#{currency_symbol})", "Shipping Total (#{currency_symbol})", "Total (#{currency_symbol})", "EFT (#{currency_symbol})", "PayPal (#{currency_symbol})", "Outstanding Balance (#{currency_symbol})"] - - columns = [ proc { |orders| orders.first.payment_state }, - proc { |orders| orders.first.distributor.name }, - proc { |orders| orders.sum { |o| o.item_total } }, - proc { |orders| orders.sum { |o| o.ship_total } }, - proc { |orders| orders.sum { |o| o.total } }, - proc { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "EFT") }.sum { |payment| payment.amount } } }, - proc { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "PayPal") }.sum{ |payment| payment.amount } } }, - proc { |orders| orders.sum { |o| o.outstanding_balance } } ] - - rules = [ { group_by: proc { |order| order.payment_state }, - sort_by: proc { |payment_state| payment_state } }, - { group_by: proc { |order| order.distributor }, - sort_by: proc { |distributor| distributor.name } } ] - - else - table_items = payments - - header = ["Payment State", "Distributor", "Payment Type", "Total (#{currency_symbol})"] - - columns = [ proc { |payments| payments.first.order.payment_state }, - proc { |payments| payments.first.order.distributor.name }, - proc { |payments| payments.first.payment_method.name }, - proc { |payments| payments.sum { |payment| payment.amount } } ] - - rules = [ { group_by: proc { |payment| payment.order.payment_state }, - sort_by: proc { |payment_state| payment_state } }, - { group_by: proc { |payment| payment.order.distributor }, - sort_by: proc { |distributor| distributor.name } }, - { group_by: proc { |payment| payment.payment_method }, - sort_by: proc { |method| method.name } } ] - - end - - order_grouper = OpenFoodNetwork::OrderGrouper.new rules, columns - - @header = header - @table = order_grouper.table(table_items) + # -- Build Report with Order Grouper + @report = OpenFoodNetwork::BulkCoopReport.new spree_current_user, params + order_grouper = OpenFoodNetwork::OrderGrouper.new @report.rules, @report.columns + @table = order_grouper.table(@report.table_items) csv_file_name = "payments_#{timestamp}.csv" - render_report(@header, @table, params[:csv], csv_file_name) - + render_report(@report.header, @table, params[:csv], csv_file_name) end def orders_and_fulfillment - # -- Prepare parameters - params[:q] ||= {} - if params[:q][:completed_at_gt].blank? - params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month - else - params[:q][:completed_at_gt] = Time.zone.parse(params[:q][:completed_at_gt]) rescue Time.zone.now.beginning_of_month - end - - if params[:q] && !params[:q][:completed_at_lt].blank? - params[:q][:completed_at_lt] = Time.zone.parse(params[:q][:completed_at_lt]) rescue "" - end - params[:q][:meta_sort] ||= "completed_at.desc" + # -- Prepare Date Params + prepare_date_params params + # -- Prepare Form Options permissions = OpenFoodNetwork::Permissions.new(spree_current_user) - - # -- Search - - @search = Spree::Order.complete.not_state(:canceled).search(params[:q]) - orders = permissions.visible_orders.merge(@search.result) - - @line_items = permissions.visible_line_items.merge(Spree::LineItem.where(order_id: orders)) - @line_items = @line_items.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present? - - line_items_with_hidden_details = @line_items.where('"spree_line_items"."id" NOT IN (?)', permissions.editable_line_items) - @line_items.select{ |li| line_items_with_hidden_details.include? li }.each do |line_item| - # TODO We should really be hiding customer code here too, but until we - # have an actual association between order and customer, it's a bit tricky - line_item.order.bill_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil) - line_item.order.ship_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil) - line_item.order.assign_attributes(email: "HIDDEN") - end - # My distributors and any distributors distributing products I supply @distributors = permissions.visible_enterprises_for_order_reports.is_distributor - # My suppliers and any suppliers supplying products I distribute @suppliers = permissions.visible_enterprises_for_order_reports.is_primary_producer @@ -503,233 +217,15 @@ Spree::Admin::ReportsController.class_eval do @report_types = REPORT_TYPES[:orders_and_fulfillment] @report_type = params[:report_type] - # -- Format according to report type - case params[:report_type] - when "order_cycle_supplier_totals" - table_items = @line_items - @include_blank = 'All' + @include_blank = 'All' - header = ["Producer", "Product", "Variant", "Amount", "Total Units", "Curr. Cost per Unit", "Total Cost", "Status", "Incoming Transport"] - - columns = [ proc { |line_items| line_items.first.variant.product.supplier.name }, - proc { |line_items| line_items.first.variant.product.name }, - proc { |line_items| line_items.first.variant.full_name }, - proc { |line_items| line_items.sum { |li| li.quantity } }, - proc { |line_items| total_units(line_items) }, - proc { |line_items| line_items.first.price }, - proc { |line_items| line_items.sum { |li| li.amount } }, - proc { |line_items| "" }, - proc { |line_items| "incoming transport" } ] - - rules = [ { group_by: proc { |line_item| line_item.variant.product.supplier }, - sort_by: proc { |supplier| supplier.name } }, - { group_by: proc { |line_item| line_item.variant.product }, - sort_by: proc { |product| product.name } }, - { group_by: proc { |line_item| line_item.variant }, - sort_by: proc { |variant| variant.full_name } } ] - - when "order_cycle_supplier_totals_by_distributor" - table_items = @line_items - @include_blank = 'All' - - header = ["Producer", "Product", "Variant", "To Hub", "Amount", "Curr. Cost per Unit", "Total Cost", "Shipping Method"] - - columns = [ proc { |line_items| line_items.first.variant.product.supplier.name }, - proc { |line_items| line_items.first.variant.product.name }, - proc { |line_items| line_items.first.variant.full_name }, - proc { |line_items| line_items.first.order.distributor.name }, - proc { |line_items| line_items.sum { |li| li.quantity } }, - proc { |line_items| line_items.first.price }, - proc { |line_items| line_items.sum { |li| li.amount } }, - proc { |line_items| "shipping method" } ] - - rules = [ { group_by: proc { |line_item| line_item.variant.product.supplier }, - sort_by: proc { |supplier| supplier.name } }, - { group_by: proc { |line_item| line_item.variant.product }, - sort_by: proc { |product| product.name } }, - { group_by: proc { |line_item| line_item.variant }, - sort_by: proc { |variant| variant.full_name }, - summary_columns: [ proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "TOTAL" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| line_items.sum { |li| li.amount } }, - proc { |line_items| "" } ] }, - { group_by: proc { |line_item| line_item.order.distributor }, - sort_by: proc { |distributor| distributor.name } } ] - - when "order_cycle_distributor_totals_by_supplier" - table_items = @line_items - @include_blank = 'All' - - header = ["Hub", "Producer", "Product", "Variant", "Amount", "Curr. Cost per Unit", "Total Cost", "Total Shipping Cost", "Shipping Method"] - - columns = [ proc { |line_items| line_items.first.order.distributor.name }, - proc { |line_items| line_items.first.variant.product.supplier.name }, - proc { |line_items| line_items.first.variant.product.name }, - proc { |line_items| line_items.first.variant.full_name }, - proc { |line_items| line_items.sum { |li| li.quantity } }, - proc { |line_items| line_items.first.price }, - proc { |line_items| line_items.sum { |li| li.amount } }, - proc { |line_items| "" }, - proc { |line_items| "shipping method" } ] - - rules = [ { group_by: proc { |line_item| line_item.order.distributor }, - sort_by: proc { |distributor| distributor.name }, - summary_columns: [ proc { |line_items| "" }, - proc { |line_items| "TOTAL" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| line_items.sum { |li| li.amount } }, - proc { |line_items| line_items.map { |li| li.order }.uniq.sum { |o| o.ship_total } }, - proc { |line_items| "" } ] }, - { group_by: proc { |line_item| line_item.variant.product.supplier }, - sort_by: proc { |supplier| supplier.name } }, - { group_by: proc { |line_item| line_item.variant.product }, - sort_by: proc { |product| product.name } }, - { group_by: proc { |line_item| line_item.variant }, - sort_by: proc { |variant| variant.full_name } } ] - - when "order_cycle_customer_totals" - table_items = @line_items - @include_blank = 'All' - - header = ["Hub", "Customer", "Email", "Phone", "Producer", "Product", "Variant", - "Amount", "Item (#{currency_symbol})", "Item + Fees (#{currency_symbol})", "Admin & Handling (#{currency_symbol})", "Ship (#{currency_symbol})", "Total (#{currency_symbol})", "Paid?", - "Shipping", "Delivery?", - "Ship Street", "Ship Street 2", "Ship City", "Ship Postcode", "Ship State", - "Comments", "SKU", - "Order Cycle", "Payment Method", "Customer Code", "Tags", - "Billing Street 1", "Billing Street 2", "Billing City", "Billing Postcode", "Billing State" - ] - - rsa = proc { |line_items| line_items.first.order.shipping_method.andand.require_ship_address } - - columns = [ - proc { |line_items| line_items.first.order.distributor.name }, - proc { |line_items| line_items.first.order.bill_address.firstname + " " + line_items.first.order.bill_address.lastname }, - proc { |line_items| line_items.first.order.email }, - proc { |line_items| line_items.first.order.bill_address.phone }, - proc { |line_items| line_items.first.variant.product.supplier.name }, - proc { |line_items| line_items.first.variant.product.name }, - proc { |line_items| line_items.first.variant.full_name }, - - proc { |line_items| line_items.sum { |li| li.quantity } }, - proc { |line_items| line_items.sum { |li| li.amount } }, - proc { |line_items| line_items.sum { |li| li.amount_with_adjustments } }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - - proc { |line_items| line_items.first.order.shipping_method.andand.name }, - proc { |line_items| rsa.call(line_items) ? 'Y' : 'N' }, - - proc { |line_items| line_items.first.order.ship_address.andand.address1 if rsa.call(line_items) }, - proc { |line_items| line_items.first.order.ship_address.andand.address2 if rsa.call(line_items) }, - proc { |line_items| line_items.first.order.ship_address.andand.city if rsa.call(line_items) }, - proc { |line_items| line_items.first.order.ship_address.andand.zipcode if rsa.call(line_items) }, - proc { |line_items| line_items.first.order.ship_address.andand.state if rsa.call(line_items) }, - - proc { |line_items| "" }, - proc { |line_items| line_items.first.variant.product.sku }, - - proc { |line_items| line_items.first.order.order_cycle.andand.name }, - proc { |line_items| line_items.first.order.payments.first.andand.payment_method.andand.name }, - proc { |line_items| line_items.first.order.user.andand.customer_of(line_items.first.order.distributor).andand.code }, - proc { |line_items| "" }, - - proc { |line_items| line_items.first.order.bill_address.andand.address1 }, - proc { |line_items| line_items.first.order.bill_address.andand.address2 }, - proc { |line_items| line_items.first.order.bill_address.andand.city }, - proc { |line_items| line_items.first.order.bill_address.andand.zipcode }, - proc { |line_items| line_items.first.order.bill_address.andand.state } ] - - rules = [ { group_by: proc { |line_item| line_item.order.distributor }, - sort_by: proc { |distributor| distributor.name } }, - { group_by: proc { |line_item| line_item.order }, - sort_by: proc { |order| order.bill_address.lastname + " " + order.bill_address.firstname }, - summary_columns: [ - proc { |line_items| line_items.first.order.distributor.name }, - proc { |line_items| line_items.first.order.bill_address.firstname + " " + line_items.first.order.bill_address.lastname }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "TOTAL" }, - proc { |line_items| "" }, - - proc { |line_items| "" }, - proc { |line_items| line_items.sum { |li| li.amount } }, - proc { |line_items| line_items.sum { |li| li.amount_with_adjustments } }, - proc { |line_items| line_items.map { |li| li.order }.uniq.sum { |o| o.admin_and_handling_total } }, - proc { |line_items| line_items.map { |li| li.order }.uniq.sum { |o| o.ship_total } }, - proc { |line_items| line_items.map { |li| li.order }.uniq.sum { |o| o.total } }, - proc { |line_items| line_items.all? { |li| li.order.paid? } ? "Yes" : "No" }, - - proc { |line_items| "" }, - proc { |line_items| "" }, - - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - - proc { |line_items| line_items.first.order.special_instructions } , - proc { |line_items| "" }, - - proc { |line_items| line_items.first.order.order_cycle.andand.name }, - proc { |line_items| line_items.first.order.payments.first.andand.payment_method.andand.name }, - proc { |line_items| "" }, - proc { |line_items| "" }, - - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" }, - proc { |line_items| "" } - ] }, - - { group_by: proc { |line_item| line_item.variant.product }, - sort_by: proc { |product| product.name } }, - { group_by: proc { |line_item| line_item.variant }, - sort_by: proc { |variant| variant.full_name } } ] - - else - table_items = @line_items - @include_blank = 'All' - - header = ["Producer", "Product", "Variant", "Amount", "Curr. Cost per Unit", "Total Cost", "Status", "Incoming Transport"] - - columns = [ proc { |line_items| line_items.first.variant.product.supplier.name }, - proc { |line_items| line_items.first.variant.product.name }, - proc { |line_items| line_items.first.variant.full_name }, - proc { |line_items| line_items.sum { |li| li.quantity } }, - proc { |line_items| line_items.first.price }, - proc { |line_items| line_items.sum { |li| li.quantity * li.price } }, - proc { |line_items| "" }, - proc { |line_items| "incoming transport" } ] - - rules = [ { group_by: proc { |line_item| line_item.variant.product.supplier }, - sort_by: proc { |supplier| supplier.name } }, - { group_by: proc { |line_item| line_item.variant.product }, - sort_by: proc { |product| product.name } }, - { group_by: proc { |line_item| line_item.variant }, - sort_by: proc { |variant| variant.full_name } } ] - - end - - order_grouper = OpenFoodNetwork::OrderGrouper.new rules, columns - - @header = header - @table = order_grouper.table(table_items) + # -- Build Report with Order Grouper + @report = OpenFoodNetwork::OrdersAndFulfillmentsReport.new spree_current_user, params + order_grouper = OpenFoodNetwork::OrderGrouper.new @report.rules, @report.columns + @table = order_grouper.table(@report.table_items) csv_file_name = "#{params[:report_type]}_#{timestamp}.csv" - render_report(@header, @table, params[:csv], csv_file_name) + render_report(@report.header, @table, params[:csv], csv_file_name) end @@ -774,6 +270,20 @@ Spree::Admin::ReportsController.class_eval do private + def prepare_date_params(params) + # -- Prepare parameters + params[:q] ||= {} + if params[:q][:completed_at_gt].blank? + params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month + else + params[:q][:completed_at_gt] = Time.zone.parse(params[:q][:completed_at_gt]) rescue Time.zone.now.beginning_of_month + end + if params[:q] && !params[:q][:completed_at_lt].blank? + params[:q][:completed_at_lt] = Time.zone.parse(params[:q][:completed_at_lt]) rescue "" + end + params[:q][:meta_sort] ||= "completed_at.desc" + end + def load_data # Load distributors either owned by the user or selling their enterprises products. my_distributors = Enterprise.is_distributor.managed_by(spree_current_user) @@ -805,15 +315,6 @@ Spree::Admin::ReportsController.class_eval do reports.select { |action| can? action, :report } end - def total_units(line_items) - return " " if line_items.map{ |li| li.variant.unit_value.nil? }.any? - total_units = line_items.sum do |li| - scale_factor = ( li.product.variant_unit == 'weight' ? 1000 : 1 ) - li.quantity * li.variant.unit_value / scale_factor - end - total_units.round(3) - end - def timestamp Time.now.strftime("%Y%m%d") end diff --git a/app/views/spree/admin/reports/bulk_coop.html.haml b/app/views/spree/admin/reports/bulk_coop.html.haml index d80a449bb4..8d9a1234ce 100644 --- a/app/views/spree/admin/reports/bulk_coop.html.haml +++ b/app/views/spree/admin/reports/bulk_coop.html.haml @@ -1,4 +1,4 @@ -= form_for @search, :url => spree.bulk_coop_admin_reports_path do |f| += form_for @report.search, :url => spree.bulk_coop_admin_reports_path do |f| = render 'date_range_form', f: f .row @@ -20,7 +20,7 @@ %table#listing_orders.index %thead %tr{'data-hook' => "orders_header"} - - @header.each do |heading| + - @report.header.each do |heading| %th=heading %tbody - @table.each do |row| diff --git a/app/views/spree/admin/reports/orders_and_fulfillment.html.haml b/app/views/spree/admin/reports/orders_and_fulfillment.html.haml index 081cb43384..2465fe0ff2 100644 --- a/app/views/spree/admin/reports/orders_and_fulfillment.html.haml +++ b/app/views/spree/admin/reports/orders_and_fulfillment.html.haml @@ -1,4 +1,4 @@ -= form_for @search, :url => spree.orders_and_fulfillment_admin_reports_path do |f| += form_for @report.search, :url => spree.orders_and_fulfillment_admin_reports_path do |f| = render 'date_range_form', f: f .row @@ -30,7 +30,7 @@ %table#listing_orders.index %thead %tr{'data-hook' => "orders_header"} - - @header.each do |heading| + - @report.header.each do |heading| %th=heading %tbody - @table.each do |row| diff --git a/app/views/spree/admin/reports/payments.html.haml b/app/views/spree/admin/reports/payments.html.haml index 1a92d507db..909846f47f 100644 --- a/app/views/spree/admin/reports/payments.html.haml +++ b/app/views/spree/admin/reports/payments.html.haml @@ -1,4 +1,4 @@ -= form_for @search, :url => spree.payments_admin_reports_path do |f| += form_for @report.search, :url => spree.payments_admin_reports_path do |f| = render 'date_range_form', f: f .row @@ -20,7 +20,7 @@ %table#listing_orders.index %thead %tr{'data-hook' => "orders_header"} - - @header.each do |heading| + - @report.header.each do |heading| %th=heading %tbody - @table.each do |row| diff --git a/lib/open_food_network/bulk_coop_report.rb b/lib/open_food_network/bulk_coop_report.rb new file mode 100644 index 0000000000..1dc3be5a0e --- /dev/null +++ b/lib/open_food_network/bulk_coop_report.rb @@ -0,0 +1,142 @@ +module OpenFoodNetwork + class BulkCoopReport + attr_reader :params + def initialize(user, params = {}) + @params = params + @user = user + end + + def header + case params[:report_type] + when "bulk_coop_supplier_report" + ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total", "Units Required", "Remainder"] + when "bulk_coop_allocation" + ["Customer", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total", "Total Allocated", "Remainder"] + when "bulk_coop_packing_sheets" + ["Customer", "Product", "Variant", "Sum Total"] + when "bulk_coop_customer_payments" + ["Customer", "Date of Order", "Total Cost", "Amount Owing", "Amount Paid"] + else + ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total", "Units Required", "Remainder"] + end + end + + def search + Spree::Order.complete.not_state(:canceled).managed_by(@user).search(params[:q]) + end + + def table_items + orders = search.result + orders.map { |o| o.line_items.managed_by(@user) }.flatten + end + + def rules + case params[:report_type] + when "bulk_coop_supplier_report" + [ { group_by: proc { |li| li.variant.product.supplier }, + sort_by: proc { |supplier| supplier.name } }, + { group_by: proc { |li| li.variant.product }, + sort_by: proc { |product| product.name }, + summary_columns: [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, + proc { |lis| "" }, + proc { |lis| "" }, + proc { |lis| lis.sum { |li| (li.quantity || 0) * (li.variant.weight || 0) } }, + proc { |lis| lis.sum { |li| (li.max_quantity || 0) * (li.variant.weight || 0) } }, + proc { |lis| ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor }, + proc { |lis| lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max) * (li.variant.weight || 0) } - ( ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor * (lis.first.variant.product.group_buy_unit_size || 0) ) } ] }, + { group_by: proc { |li| li.variant }, + sort_by: proc { |variant| variant.full_name } } ] + when "bulk_coop_allocation" + [ { group_by: proc { |li| li.variant.product }, + sort_by: proc { |product| product.name }, + summary_columns: [ proc { |lis| "TOTAL" }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, + proc { |lis| "" }, + proc { |lis| "" }, + proc { |lis| lis.sum { |li| li.quantity * (li.variant.weight || 0) } }, + proc { |lis| lis.sum { |li| (li.max_quantity || 0) * (li.variant.weight || 0) } }, + proc { |lis| ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor * (lis.first.variant.product.group_buy_unit_size || 0) }, + proc { |lis| lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } - ( ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor * (lis.first.variant.product.group_buy_unit_size || 0) ) } ] }, + { group_by: proc { |li| li.variant }, + sort_by: proc { |variant| variant.full_name } }, + { group_by: proc { |li| li.order }, + sort_by: proc { |order| order.to_s } } ] + when "bulk_coop_packing_sheets" + [ { group_by: proc { |li| li.variant.product }, + sort_by: proc { |product| product.name } }, + { group_by: proc { |li| li.variant }, + sort_by: proc { |variant| variant.full_name } }, + { group_by: proc { |li| li.order }, + sort_by: proc { |order| order.to_s } } ] + when "bulk_coop_customer_payments" + [ { group_by: proc { |li| li.order }, + sort_by: proc { |order| order.completed_at } } ] + else + [ { group_by: proc { |li| li.variant.product.supplier }, + sort_by: proc { |supplier| supplier.name } }, + { group_by: proc { |li| li.variant.product }, + sort_by: proc { |product| product.name }, + summary_columns: [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, + proc { |lis| "" }, + proc { |lis| "" }, + proc { |lis| lis.sum { |li| li.quantity * (li.variant.weight || 0) } }, + proc { |lis| lis.sum { |li| (li.max_quantity || 0) * (li.variant.weight || 0) } }, + proc { |lis| ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor }, + proc { |lis| lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } - ( ( (lis.first.variant.product.group_buy_unit_size || 0).zero? ? 0 : ( lis.sum { |li| ( [li.max_quantity || 0, li.quantity || 0].max ) * (li.variant.weight || 0) } / lis.first.variant.product.group_buy_unit_size ) ).floor * (lis.first.variant.product.group_buy_unit_size || 0) ) } ] }, + { group_by: proc { |li| li.variant }, + sort_by: proc { |variant| variant.full_name } } ] + end + end + + def columns + case params[:report_type] + when "bulk_coop_supplier_report" + [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, + proc { |lis| lis.first.variant.full_name }, + proc { |lis| lis.first.variant.weight || 0 }, + proc { |lis| lis.sum { |li| li.quantity } }, + proc { |lis| lis.sum { |li| li.max_quantity || 0 } }, + proc { |lis| "" }, + proc { |lis| "" } ] + when "bulk_coop_allocation" + [ proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, + proc { |lis| lis.first.variant.full_name }, + proc { |lis| lis.first.variant.weight || 0 }, + proc { |lis| lis.sum { |li| li.quantity } }, + proc { |lis| lis.sum { |li| li.max_quantity || 0 } }, + proc { |lis| "" }, + proc { |lis| "" } ] + when "bulk_coop_packing_sheets" + [ proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| lis.first.variant.full_name }, + proc { |lis| lis.sum { |li| li.quantity } } ] + when "bulk_coop_customer_payments" + [ proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, + proc { |lis| lis.first.order.completed_at.to_s }, + proc { |lis| lis.map { |li| li.order }.uniq.sum { |o| o.total } }, + proc { |lis| lis.map { |li| li.order }.uniq.sum { |o| o.outstanding_balance } }, + proc { |lis| lis.map { |li| li.order }.uniq.sum { |o| o.payment_total } } ] + else + [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| lis.first.variant.product.group_buy ? (lis.first.variant.product.group_buy_unit_size || 0.0) : "" }, + proc { |lis| lis.first.variant.full_name }, + proc { |lis| lis.first.variant.weight || 0 }, + proc { |lis| lis.sum { |li| li.quantity } }, + proc { |lis| lis.sum { |li| li.max_quantity || 0 } }, + proc { |lis| "" }, + proc { |lis| "" } ] + end + end + end +end diff --git a/lib/open_food_network/orders_and_fulfillments_report.rb b/lib/open_food_network/orders_and_fulfillments_report.rb new file mode 100644 index 0000000000..2d4e1d1f1f --- /dev/null +++ b/lib/open_food_network/orders_and_fulfillments_report.rb @@ -0,0 +1,256 @@ +include Spree::ReportsHelper + +module OpenFoodNetwork + class OrdersAndFulfillmentsReport + attr_reader :params + def initialize(user, params = {}) + @params = params + @user = user + end + + def header + case params[:report_type] + when "order_cycle_supplier_totals" + ["Producer", "Product", "Variant", "Amount", "Total Units", "Curr. Cost per Unit", "Total Cost", "Status", "Incoming Transport"] + when "order_cycle_supplier_totals_by_distributor" + ["Producer", "Product", "Variant", "To Hub", "Amount", "Curr. Cost per Unit", "Total Cost", "Shipping Method"] + when "order_cycle_distributor_totals_by_supplier" + ["Hub", "Producer", "Product", "Variant", "Amount", "Curr. Cost per Unit", "Total Cost", "Total Shipping Cost", "Shipping Method"] + when "order_cycle_customer_totals" + ["Hub", "Customer", "Email", "Phone", "Producer", "Product", "Variant", + "Amount", "Item (#{currency_symbol})", "Item + Fees (#{currency_symbol})", "Admin & Handling (#{currency_symbol})", "Ship (#{currency_symbol})", "Total (#{currency_symbol})", "Paid?", + "Shipping", "Delivery?", + "Ship Street", "Ship Street 2", "Ship City", "Ship Postcode", "Ship State", + "Comments", "SKU", + "Order Cycle", "Payment Method", "Customer Code", "Tags", + "Billing Street 1", "Billing Street 2", "Billing City", "Billing Postcode", "Billing State" + ] + else + ["Producer", "Product", "Variant", "Amount", "Curr. Cost per Unit", "Total Cost", "Status", "Incoming Transport"] + end + + end + + def search + Spree::Order.complete.not_state(:canceled).search(params[:q]) + end + + def table_items + permissions = OpenFoodNetwork::Permissions.new(@user) + orders = permissions.visible_orders.merge(search.result) + + line_items = permissions.visible_line_items.merge(Spree::LineItem.where(order_id: orders)) + line_items = line_items.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present? + + line_items_with_hidden_details = line_items.where('"spree_line_items"."id" NOT IN (?)', permissions.editable_line_items) + line_items.select{ |li| line_items_with_hidden_details.include? li }.each do |line_item| + # TODO We should really be hiding customer code here too, but until we + # have an actual association between order and customer, it's a bit tricky + line_item.order.bill_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil) + line_item.order.ship_address.assign_attributes(firstname: "HIDDEN", lastname: "", phone: "", address1: "", address2: "", city: "", zipcode: "", state: nil) + line_item.order.assign_attributes(email: "HIDDEN") + end + line_items + end + + def rules + case params[:report_type] + when "order_cycle_supplier_totals" + [ { group_by: proc { |line_item| line_item.variant.product.supplier }, + sort_by: proc { |supplier| supplier.name } }, + { group_by: proc { |line_item| line_item.variant.product }, + sort_by: proc { |product| product.name } }, + { group_by: proc { |line_item| line_item.variant }, + sort_by: proc { |variant| variant.full_name } } ] + when "order_cycle_supplier_totals_by_distributor" + [ { group_by: proc { |line_item| line_item.variant.product.supplier }, + sort_by: proc { |supplier| supplier.name } }, + { group_by: proc { |line_item| line_item.variant.product }, + sort_by: proc { |product| product.name } }, + { group_by: proc { |line_item| line_item.variant }, + sort_by: proc { |variant| variant.full_name }, + summary_columns: [ proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "TOTAL" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| line_items.sum { |li| li.amount } }, + proc { |line_items| "" } ] }, + { group_by: proc { |line_item| line_item.order.distributor }, + sort_by: proc { |distributor| distributor.name } } ] + when "order_cycle_distributor_totals_by_supplier" + [ { group_by: proc { |line_item| line_item.order.distributor }, + sort_by: proc { |distributor| distributor.name }, + summary_columns: [ proc { |line_items| "" }, + proc { |line_items| "TOTAL" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| line_items.sum { |li| li.amount } }, + proc { |line_items| line_items.map { |li| li.order }.uniq.sum { |o| o.ship_total } }, + proc { |line_items| "" } ] }, + { group_by: proc { |line_item| line_item.variant.product.supplier }, + sort_by: proc { |supplier| supplier.name } }, + { group_by: proc { |line_item| line_item.variant.product }, + sort_by: proc { |product| product.name } }, + { group_by: proc { |line_item| line_item.variant }, + sort_by: proc { |variant| variant.full_name } } ] + when "order_cycle_customer_totals" + [ { group_by: proc { |line_item| line_item.order.distributor }, + sort_by: proc { |distributor| distributor.name } }, + { group_by: proc { |line_item| line_item.order }, + sort_by: proc { |order| order.bill_address.lastname + " " + order.bill_address.firstname }, + summary_columns: [ + proc { |line_items| line_items.first.order.distributor.name }, + proc { |line_items| line_items.first.order.bill_address.firstname + " " + line_items.first.order.bill_address.lastname }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "TOTAL" }, + proc { |line_items| "" }, + + proc { |line_items| "" }, + proc { |line_items| line_items.sum { |li| li.amount } }, + proc { |line_items| line_items.sum { |li| li.amount_with_adjustments } }, + proc { |line_items| line_items.map { |li| li.order }.uniq.sum { |o| o.admin_and_handling_total } }, + proc { |line_items| line_items.map { |li| li.order }.uniq.sum { |o| o.ship_total } }, + proc { |line_items| line_items.map { |li| li.order }.uniq.sum { |o| o.total } }, + proc { |line_items| line_items.all? { |li| li.order.paid? } ? "Yes" : "No" }, + + proc { |line_items| "" }, + proc { |line_items| "" }, + + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + + proc { |line_items| line_items.first.order.special_instructions } , + proc { |line_items| "" }, + + proc { |line_items| line_items.first.order.order_cycle.andand.name }, + proc { |line_items| line_items.first.order.payments.first.andand.payment_method.andand.name }, + proc { |line_items| "" }, + proc { |line_items| "" }, + + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" } + ] }, + + { group_by: proc { |line_item| line_item.variant.product }, + sort_by: proc { |product| product.name } }, + { group_by: proc { |line_item| line_item.variant }, + sort_by: proc { |variant| variant.full_name } } ] + else + [ { group_by: proc { |line_item| line_item.variant.product.supplier }, + sort_by: proc { |supplier| supplier.name } }, + { group_by: proc { |line_item| line_item.variant.product }, + sort_by: proc { |product| product.name } }, + { group_by: proc { |line_item| line_item.variant }, + sort_by: proc { |variant| variant.full_name } } ] + end + end + + def columns + case params[:report_type] + when "order_cycle_supplier_totals" + [ proc { |line_items| line_items.first.variant.product.supplier.name }, + proc { |line_items| line_items.first.variant.product.name }, + proc { |line_items| line_items.first.variant.full_name }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| total_units(line_items) }, + proc { |line_items| line_items.first.price }, + proc { |line_items| line_items.sum { |li| li.amount } }, + proc { |line_items| "" }, + proc { |line_items| "incoming transport" } ] + when "order_cycle_supplier_totals_by_distributor" + [ proc { |line_items| line_items.first.variant.product.supplier.name }, + proc { |line_items| line_items.first.variant.product.name }, + proc { |line_items| line_items.first.variant.full_name }, + proc { |line_items| line_items.first.order.distributor.name }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.first.price }, + proc { |line_items| line_items.sum { |li| li.amount } }, + proc { |line_items| "shipping method" } ] + when "order_cycle_distributor_totals_by_supplier" + [ proc { |line_items| line_items.first.order.distributor.name }, + proc { |line_items| line_items.first.variant.product.supplier.name }, + proc { |line_items| line_items.first.variant.product.name }, + proc { |line_items| line_items.first.variant.full_name }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.first.price }, + proc { |line_items| line_items.sum { |li| li.amount } }, + proc { |line_items| "" }, + proc { |line_items| "shipping method" } ] + when "order_cycle_customer_totals" + rsa = proc { |line_items| line_items.first.order.shipping_method.andand.require_ship_address } + [ + proc { |line_items| line_items.first.order.distributor.name }, + proc { |line_items| line_items.first.order.bill_address.firstname + " " + line_items.first.order.bill_address.lastname }, + proc { |line_items| line_items.first.order.email }, + proc { |line_items| line_items.first.order.bill_address.phone }, + proc { |line_items| line_items.first.variant.product.supplier.name }, + proc { |line_items| line_items.first.variant.product.name }, + proc { |line_items| line_items.first.variant.full_name }, + + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.sum { |li| li.amount } }, + proc { |line_items| line_items.sum { |li| li.amount_with_adjustments } }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + + proc { |line_items| line_items.first.order.shipping_method.andand.name }, + proc { |line_items| rsa.call(line_items) ? 'Y' : 'N' }, + + proc { |line_items| line_items.first.order.ship_address.andand.address1 if rsa.call(line_items) }, + proc { |line_items| line_items.first.order.ship_address.andand.address2 if rsa.call(line_items) }, + proc { |line_items| line_items.first.order.ship_address.andand.city if rsa.call(line_items) }, + proc { |line_items| line_items.first.order.ship_address.andand.zipcode if rsa.call(line_items) }, + proc { |line_items| line_items.first.order.ship_address.andand.state if rsa.call(line_items) }, + + proc { |line_items| "" }, + proc { |line_items| line_items.first.variant.product.sku }, + + proc { |line_items| line_items.first.order.order_cycle.andand.name }, + proc { |line_items| line_items.first.order.payments.first.andand.payment_method.andand.name }, + proc { |line_items| line_items.first.order.user.andand.customer_of(line_items.first.order.distributor).andand.code }, + proc { |line_items| "" }, + + proc { |line_items| line_items.first.order.bill_address.andand.address1 }, + proc { |line_items| line_items.first.order.bill_address.andand.address2 }, + proc { |line_items| line_items.first.order.bill_address.andand.city }, + proc { |line_items| line_items.first.order.bill_address.andand.zipcode }, + proc { |line_items| line_items.first.order.bill_address.andand.state } ] + else + [ proc { |line_items| line_items.first.variant.product.supplier.name }, + proc { |line_items| line_items.first.variant.product.name }, + proc { |line_items| line_items.first.variant.full_name }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.first.price }, + proc { |line_items| line_items.sum { |li| li.quantity * li.price } }, + proc { |line_items| "" }, + proc { |line_items| "incoming transport" } ] + end + end + + private + + def total_units(line_items) + return " " if line_items.map{ |li| li.variant.unit_value.nil? }.any? + total_units = line_items.sum do |li| + scale_factor = ( li.product.variant_unit == 'weight' ? 1000 : 1 ) + li.quantity * li.variant.unit_value / scale_factor + end + total_units.round(3) + end + + end +end diff --git a/lib/open_food_network/payments_report.rb b/lib/open_food_network/payments_report.rb new file mode 100644 index 0000000000..4872da6b2f --- /dev/null +++ b/lib/open_food_network/payments_report.rb @@ -0,0 +1,101 @@ +module OpenFoodNetwork + class PaymentsReport + attr_reader :params + def initialize(user, params = {}) + @params = params + @user = user + end + + def header + case params[:report_type] + when "payments_by_payment_type" + ["Payment State", "Distributor", "Payment Type", "Total (#{currency_symbol})"] + when "itemised_payment_totals" + ["Payment State", "Distributor", "Product Total (#{currency_symbol})", "Shipping Total (#{currency_symbol})", "Outstanding Balance (#{currency_symbol})", "Total (#{currency_symbol})"] + when "payment_totals" + ["Payment State", "Distributor", "Product Total (#{currency_symbol})", "Shipping Total (#{currency_symbol})", "Total (#{currency_symbol})", "EFT (#{currency_symbol})", "PayPal (#{currency_symbol})", "Outstanding Balance (#{currency_symbol})"] + else + ["Payment State", "Distributor", "Payment Type", "Total (#{currency_symbol})"] + end + end + + def search + Spree::Order.complete.not_state(:canceled).managed_by(@user).search(params[:q]) + end + + def table_items + orders = search.result + payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments + case params[:report_type] + when "payments_by_payment_type" + payments + when "itemised_payment_totals" + orders + when "payment_totals" + orders + else + payments + end + end + + def rules + case params[:report_type] + when "payments_by_payment_type" + [ { group_by: proc { |payment| payment.order.payment_state }, + sort_by: proc { |payment_state| payment_state } }, + { group_by: proc { |payment| payment.order.distributor }, + sort_by: proc { |distributor| distributor.name } }, + { group_by: proc { |payment| Spree::PaymentMethod.unscoped { payment.payment_method } }, + sort_by: proc { |method| method.name } } ] + when "itemised_payment_totals" + [ { group_by: proc { |order| order.payment_state }, + sort_by: proc { |payment_state| payment_state } }, + { group_by: proc { |order| order.distributor }, + sort_by: proc { |distributor| distributor.name } } ] + when "payment_totals" + [ { group_by: proc { |order| order.payment_state }, + sort_by: proc { |payment_state| payment_state } }, + { group_by: proc { |order| order.distributor }, + sort_by: proc { |distributor| distributor.name } } ] + else + [ { group_by: proc { |payment| payment.order.payment_state }, + sort_by: proc { |payment_state| payment_state } }, + { group_by: proc { |payment| payment.order.distributor }, + sort_by: proc { |distributor| distributor.name } }, + { group_by: proc { |payment| payment.payment_method }, + sort_by: proc { |method| method.name } } ] + end + end + + def columns + case params[:report_type] + when "payments_by_payment_type" + [ proc { |payments| payments.first.order.payment_state }, + proc { |payments| payments.first.order.distributor.name }, + proc { |payments| payments.first.payment_method.name }, + proc { |payments| payments.sum { |payment| payment.amount } } ] + when "itemised_payment_totals" + [ proc { |orders| orders.first.payment_state }, + proc { |orders| orders.first.distributor.name }, + proc { |orders| orders.sum { |o| o.item_total } }, + proc { |orders| orders.sum { |o| o.ship_total } }, + proc { |orders| orders.sum { |o| o.outstanding_balance } }, + proc { |orders| orders.sum { |o| o.total } } ] + when "payment_totals" + [ proc { |orders| orders.first.payment_state }, + proc { |orders| orders.first.distributor.name }, + proc { |orders| orders.sum { |o| o.item_total } }, + proc { |orders| orders.sum { |o| o.ship_total } }, + proc { |orders| orders.sum { |o| o.total } }, + proc { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "EFT") }.sum { |payment| payment.amount } } }, + proc { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "PayPal") }.sum{ |payment| payment.amount } } }, + proc { |orders| orders.sum { |o| o.outstanding_balance } } ] + else + [ proc { |payments| payments.first.order.payment_state }, + proc { |payments| payments.first.order.distributor.name }, + proc { |payments| payments.first.payment_method.name }, + proc { |payments| payments.sum { |payment| payment.amount } } ] + end + end + end +end