mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Merge branch 'group-buy-report'
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
require 'csv'
|
||||
require 'open_food_web/order_and_distributor_report'
|
||||
require 'open_food_web/group_buy_report'
|
||||
|
||||
Spree::Admin::ReportsController.class_eval do
|
||||
|
||||
Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:orders_and_distributors => {:name => "Orders And Distributors", :description => "Orders with distributor details"}})
|
||||
Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:group_buys => {:name => "Group Buys", :description => "Orders by supplier and variant"}})
|
||||
|
||||
def orders_and_distributors
|
||||
params[:q] = {} unless params[:q]
|
||||
@@ -23,7 +25,7 @@ Spree::Admin::ReportsController.class_eval do
|
||||
orders = @search.result
|
||||
|
||||
@report = OpenFoodWeb::OrderAndDistributorReport.new orders
|
||||
if(!params[:csv])
|
||||
unless params[:csv]
|
||||
render :html => @report
|
||||
else
|
||||
csv_string = CSV.generate do |csv|
|
||||
@@ -34,4 +36,35 @@ Spree::Admin::ReportsController.class_eval do
|
||||
end
|
||||
end
|
||||
|
||||
def group_buys
|
||||
params[:q] = {} unless params[:q]
|
||||
|
||||
if params[:q][:created_at_gt].blank?
|
||||
params[:q][:created_at_gt] = Time.zone.now.beginning_of_month
|
||||
else
|
||||
params[:q][:created_at_gt] = Time.zone.parse(params[:q][:created_at_gt]).beginning_of_day rescue Time.zone.now.beginning_of_month
|
||||
end
|
||||
|
||||
if params[:q] && !params[:q][:created_at_lt].blank?
|
||||
params[:q][:created_at_lt] = Time.zone.parse(params[:q][:created_at_lt]).end_of_day rescue ""
|
||||
end
|
||||
params[:q][:meta_sort] ||= "created_at.desc"
|
||||
|
||||
@search = Spree::Order.complete.search(params[:q])
|
||||
orders = @search.result
|
||||
|
||||
@distributors = Spree::Distributor.all
|
||||
|
||||
@report = OpenFoodWeb::GroupBuyReport.new orders
|
||||
unless params[:csv]
|
||||
render :html => @report
|
||||
else
|
||||
csv_string = CSV.generate do |csv|
|
||||
csv << @report.header
|
||||
@report.table.each { |row| csv << row }
|
||||
end
|
||||
send_data csv_string, :filename => "group_buy.csv"
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
37
app/views/spree/admin/reports/group_buys.html.haml
Normal file
37
app/views/spree/admin/reports/group_buys.html.haml
Normal file
@@ -0,0 +1,37 @@
|
||||
= form_for @search, :url => spree.group_buys_admin_reports_path do |f|
|
||||
= label_tag nil, t(:date_range)
|
||||
%br
|
||||
.date-range-filter
|
||||
%div{"class" => "left sub-field"}
|
||||
= f.text_field :created_at_gt, :class => 'datepicker'
|
||||
%br
|
||||
= label_tag nil, t(:start), :class => 'sub'
|
||||
%div{"class" => "right sub-field"}
|
||||
= f.text_field :created_at_lt, :class => 'datepicker'
|
||||
%br
|
||||
= label_tag nil, t(:stop)
|
||||
%br
|
||||
= label_tag nil, "Distributor: "
|
||||
= f.collection_select(:distributor_id_eq, @distributors, :id, :name)
|
||||
%br
|
||||
%br
|
||||
= check_box_tag :csv
|
||||
= label_tag :csv, "Download as csv"
|
||||
%br
|
||||
= button t(:search)
|
||||
%br
|
||||
%br
|
||||
%table#listing_orders.index
|
||||
%thead
|
||||
%tr{'data-hook' => "orders_header"}
|
||||
- @report.header.each do |heading|
|
||||
%th=heading
|
||||
%tbody
|
||||
- @report.table.each do |row|
|
||||
%tr
|
||||
- row.each do |column|
|
||||
%td= column
|
||||
- if @report.table.empty?
|
||||
%tr
|
||||
%td{:colspan => "2"}= t(:none)
|
||||
|
||||
@@ -19,4 +19,6 @@ Spree::Core::Engine.routes.prepend do
|
||||
end
|
||||
|
||||
match '/admin/reports/orders_and_distributors' => 'admin/reports#orders_and_distributors', :as => "orders_and_distributors_admin_reports", :via => [:get, :post]
|
||||
match '/admin/reports/group_buys' => 'admin/reports#group_buys', :as => "group_buys_admin_reports", :via => [:get, :post]
|
||||
|
||||
end
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
module OpenFoodWeb
|
||||
|
||||
GroupBuyVariantRow = Struct.new(:variant, :sum_quantities, :sum_max_quantities) do
|
||||
def to_row
|
||||
[variant.product.supplier.name,variant.product.name,"UNITSIZE",variant.options_text,variant.weight,sum_quantities,sum_max_quantities]
|
||||
end
|
||||
end
|
||||
|
||||
GroupBuyProductRow = Struct.new(:product, :sum_quantities, :sum_max_quantities) do
|
||||
def to_row
|
||||
[product.supplier.name,product.name,"UNITSIZE","TOTAL","",sum_quantities,sum_max_quantities]
|
||||
end
|
||||
end
|
||||
|
||||
class GroupBuyReport
|
||||
def initialize orders
|
||||
@orders = orders
|
||||
@@ -7,5 +20,38 @@ module OpenFoodWeb
|
||||
def header
|
||||
["Supplier", "Product", "Unit Size", "Variant", "Weight", "Total Ordered", "Total Max"]
|
||||
end
|
||||
|
||||
def variants_and_quantities
|
||||
variants_and_quantities = []
|
||||
line_items = @orders.map { |o| o.line_items }.flatten
|
||||
supplier_groups = line_items.group_by{ |li| li.variant.product.supplier }
|
||||
supplier_groups.each do |supplier,line_items_by_supplier|
|
||||
product_groups = line_items_by_supplier.group_by{ |li| li.variant.product }
|
||||
product_groups.each do |product,line_items_by_product|
|
||||
|
||||
# Cycle thorugh variant of a product
|
||||
variant_groups = line_items_by_product.group_by{ |li| li.variant }
|
||||
variant_groups.each do |variant,line_items_by_variant|
|
||||
sum_quantities = line_items_by_variant.sum { |li| li.quantity }
|
||||
sum_max_quantities = line_items_by_variant.sum { |li| li.max_quantity || 0 }
|
||||
variants_and_quantities << GroupBuyVariantRow.new(variant,sum_quantities,sum_max_quantities)
|
||||
end
|
||||
|
||||
# Sum quantities for each product (Total line)
|
||||
sum_quantities = line_items_by_product.sum { |li| li.variant.weight * li.quantity }
|
||||
sum_max_quantities = line_items_by_product.sum { |li| li.variant.weight * (li.max_quantity || 0) }
|
||||
variants_and_quantities << GroupBuyProductRow.new(product, sum_quantities, sum_max_quantities)
|
||||
end
|
||||
end
|
||||
variants_and_quantities
|
||||
end
|
||||
|
||||
def table
|
||||
table = []
|
||||
variants_and_quantities.each do |vr|
|
||||
table << vr.to_row
|
||||
end
|
||||
table
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
97
spec/lib/open_food_web/group_buy_report_spec.rb
Normal file
97
spec/lib/open_food_web/group_buy_report_spec.rb
Normal file
@@ -0,0 +1,97 @@
|
||||
require 'spec_helper'
|
||||
|
||||
module OpenFoodWeb
|
||||
describe GroupBuyReport do
|
||||
|
||||
before(:each) do
|
||||
@orders = []
|
||||
bill_address = create(:address)
|
||||
distributor_address = create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234")
|
||||
distributor = create(:distributor, :pickup_address => distributor_address)
|
||||
|
||||
@supplier1 = create(:supplier)
|
||||
@variant1 = create(:variant)
|
||||
@variant1.product.supplier = @supplier1
|
||||
@variant1.product.save!
|
||||
shipping_method = create(:shipping_method)
|
||||
product_distribution = create(:product_distribution, :product => @variant1.product, :distributor => distributor, :shipping_method => create(:shipping_method))
|
||||
shipping_instructions = "pick up on thursday please!"
|
||||
|
||||
order1 = create(:order, :distributor => distributor, :bill_address => bill_address, :special_instructions => shipping_instructions)
|
||||
line_item11 = create(:line_item, :variant => @variant1, :order => order1)
|
||||
order1.line_items << line_item11
|
||||
@orders << order1
|
||||
|
||||
order2 = create(:order, :distributor => distributor, :bill_address => bill_address, :special_instructions => shipping_instructions)
|
||||
line_item21 = create(:line_item, :variant => @variant1, :order => order2)
|
||||
order2.line_items << line_item21
|
||||
|
||||
@variant2 = create(:variant)
|
||||
@variant2.product.supplier = @supplier1
|
||||
@variant2.product.save!
|
||||
product_distribution = create(:product_distribution, :product => @variant2.product, :distributor => distributor, :shipping_method => create(:shipping_method))
|
||||
|
||||
line_item22 = create(:line_item, :variant => @variant2, :order => order2)
|
||||
order2.line_items << line_item22
|
||||
@orders << order2
|
||||
|
||||
@supplier2 = create(:supplier)
|
||||
@variant3 = create(:variant)
|
||||
@variant3.product.supplier = @supplier2
|
||||
@variant3.product.save!
|
||||
product_distribution = create(:product_distribution, :product => @variant3.product, :distributor => distributor, :shipping_method => create(:shipping_method))
|
||||
|
||||
order3 = create(:order, :distributor => distributor, :bill_address => bill_address, :special_instructions => shipping_instructions)
|
||||
line_item31 = create(:line_item, :variant => @variant3, :order => order3)
|
||||
order3.line_items << line_item31
|
||||
@orders << order3
|
||||
end
|
||||
|
||||
it "should return a header row describing the report" do
|
||||
subject = GroupBuyReport.new [@order1]
|
||||
header = subject.header
|
||||
header.should == ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Total Ordered", "Total Max"]
|
||||
end
|
||||
|
||||
it "should provide the required variant and quantity information in a table" do
|
||||
subject = GroupBuyReport.new @orders
|
||||
|
||||
table = subject.table
|
||||
|
||||
line_items = @orders.map{ |o| o.line_items }.flatten.select{ |li| li.product.supplier == @supplier1 && li.variant == @variant1 }
|
||||
|
||||
sum_quantities = line_items.map { |li| li.quantity }.sum
|
||||
sum_max_quantities = line_items.map { |li| li.max_quantity || 0 }.sum
|
||||
|
||||
table[0].should == [@variant1.product.supplier.name,@variant1.product.name,"UNITSIZE",@variant1.options_text,@variant1.weight,sum_quantities,sum_max_quantities]
|
||||
end
|
||||
|
||||
it "should return a table wherein each rows contains the same number of columns as the heading" do
|
||||
subject = GroupBuyReport.new @orders
|
||||
|
||||
table = subject.table
|
||||
columns = subject.header.length
|
||||
|
||||
table.each do |r|
|
||||
r.length.should == columns
|
||||
end
|
||||
end
|
||||
|
||||
it "should split and group line items from multiple suppliers and of multiple variants" do
|
||||
subject = GroupBuyReport.new @orders
|
||||
|
||||
table_row_objects = subject.variants_and_quantities
|
||||
|
||||
variant_rows = table_row_objects.select{ |r| r.class == OpenFoodWeb::GroupBuyVariantRow }
|
||||
product_rows = table_row_objects.select{ |r| r.class == OpenFoodWeb::GroupBuyProductRow }
|
||||
|
||||
supplier_groups = variant_rows.group_by { |r| r.variant.product.supplier }
|
||||
variant_groups = variant_rows.group_by{ |r| r.variant }
|
||||
product_groups = product_rows.group_by{ |r| r.product }
|
||||
|
||||
supplier_groups.length.should == 2
|
||||
variant_groups.length.should == 3
|
||||
product_groups.length.should == 3
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,29 +0,0 @@
|
||||
require 'spec_helper'
|
||||
|
||||
module OpenFoodWeb
|
||||
describe GroupBuyReport do
|
||||
|
||||
before(:each) do
|
||||
@bill_address = create(:address)
|
||||
@distributor_address = create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234")
|
||||
@distributor = create(:distributor, :pickup_address => @distributor_address)
|
||||
product = create(:product)
|
||||
product_distribution = create(:product_distribution, :product => product, :distributor => @distributor, :shipping_method => create(:shipping_method))
|
||||
@shipping_instructions = "pick up on thursday please!"
|
||||
@order = create(:order, :distributor => @distributor, :bill_address => @bill_address, :special_instructions => @shipping_instructions)
|
||||
@payment_method = create(:payment_method)
|
||||
payment = create(:payment, :payment_method => @payment_method, :order => @order )
|
||||
@order.payments << payment
|
||||
@line_item = create(:line_item, :product => product, :order => @order)
|
||||
@order.line_items << @line_item
|
||||
end
|
||||
|
||||
it "should return a header row describing the report" do
|
||||
subject = GroupBuyReport.new [@order]
|
||||
|
||||
header = subject.header
|
||||
header.should == ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Total Ordered", "Total Max"]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user