From ddb01e4ccb59063b4218b2ed546eb29606fb3808 Mon Sep 17 00:00:00 2001 From: Rob H Date: Sun, 21 Oct 2012 13:12:48 +1100 Subject: [PATCH 01/18] WIP: Create report grouper, write reports for bulk co-ops and payments --- .../admin/reports_controller_decorator.rb | 136 +++++++- .../spree/admin/reports/bulk_coop.html.haml | 41 +++ .../spree/admin/reports/payments.html.haml | 41 +++ lib/open_food_web/order_grouper.rb | 56 ++++ spec/lib/open_food_web/order_grouper_spec.rb | 298 ++++++++++++++++++ 5 files changed, 571 insertions(+), 1 deletion(-) create mode 100644 app/views/spree/admin/reports/bulk_coop.html.haml create mode 100644 app/views/spree/admin/reports/payments.html.haml create mode 100644 lib/open_food_web/order_grouper.rb create mode 100644 spec/lib/open_food_web/order_grouper_spec.rb diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 10c09b7bdb..ed2d7a0c7c 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -1,11 +1,14 @@ require 'csv' require 'open_food_web/order_and_distributor_report' require 'open_food_web/group_buy_report' +require 'open_food_web/order_grouper' 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"}}) + Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:bulk_coop => {:name => "Bulk Co-Op", :description => "Reports for Bulk Co-Op orders"}}) + Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:payments => {:name => "Payment Reports", :description => "Reports for Payments"}}) def orders_and_distributors params[:q] = {} unless params[:q] @@ -52,7 +55,7 @@ Spree::Admin::ReportsController.class_eval do @search = Spree::Order.complete.search(params[:q]) orders = @search.result - + @distributors = Spree::Distributor.all @report = OpenFoodWeb::GroupBuyReport.new orders @@ -67,4 +70,135 @@ Spree::Admin::ReportsController.class_eval do end end + def bulk_coop + 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.select { |o| o.completed? } # Only select complete orders + line_items = orders.map { |o| o.line_items }.flatten + + # Ignore supplier conditions if "All" selected + #if params[:supplier_id] && params[:supplier_id] != "All" + # line_items = line_items.select { |li| li.variant.product.supplier_id == params[:supplier_id] } + #end + + #[Distributor.new(:id => nil, :name => 'All')]+ + @distributors = Spree::Distributor.all + @report_type = params[:report_type] + + case params[:report_type] + when "bulk_coop_supplier_report" + rules = [ { group_by: Proc.new { |li| li.variant.product.supplier }, sort_by: Proc.new { |supplier| supplier.name } }, { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name }, summary_columns: [ Proc.new { |lis| lis.first.variant.product.supplier.name }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| "" }, Proc.new { |lis| "" }, Proc.new { |lis| lis.sum { |li| li.quantity * li.variant.weight } }, Proc.new { |lis| lis.sum { |li| (li.max_quantity || 0) * li.variant.weight } } ] }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } } ] + columns = [ Proc.new { |lis| lis.first.variant.product.supplier.name }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + header = ["Supplier","Product","Unit Size","Variant","Weight","Sum Total","Sum Max Total"] + when "bulk_coop_allocation" + rules = [ { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } }, { group_by: Proc.new { |li| li.order.user }, sort_by: Proc.new { |user| user.to_s } } ] + columns = [ Proc.new { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + header = ["Customer","Product","Unit Size","Variant","Weight","Sum Total","Sum Max Total"] + when "bulk_coop_packing_sheets" + rules = [ { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } }, { group_by: Proc.new { |li| li.order.user }, sort_by: Proc.new { |user| user.to_s } } ] + columns = [ Proc.new { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.sum { |li| li.quantity } } ] + header = ["Customer","Product","Variant","Sum Total"] + when "bulk_coop_customer_payments" + rules = [ { group_by: Proc.new { |li| li.order.user }, sort_by: Proc.new { |user| user.to_s } }, { group_by: Proc.new { |li| li.order }, sort_by: Proc.new { |order| order.created_at } } ] + columns = [ Proc.new { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, Proc.new { |lis| lis.first.order.created_at.to_s }, Proc.new { |lis| lis.map { |li| li.order }.to_set.to_a.sum { |o| o.total } }, Proc.new { |lis| lis.map { |li| li.order }.to_set.to_a.sum { |o| o.outstanding_balance } }, Proc.new { |lis| lis.map { |li| li.order }.to_set.to_a.sum { |o| o.payment_total } } ] + header = ["Customer","Date of Order","Total Cost","Amount Owing","Amount Paid"] + else # List all line items + rules = [ { group_by: Proc.new { |li| li.variant.product.supplier }, sort_by: Proc.new { |supplier| supplier.name } }, { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } } ] + columns = [ Proc.new { |lis| lis.first.variant.product.supplier.name }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + header = ["Supplier","Product","Unit Size","Variant","Weight","Sum Total","Sum Max Total"] + end + + order_grouper = OpenFoodWeb::OrderGrouper.new rules, columns + + @header = header + @table = order_grouper.table(line_items) + + unless params[:csv] + render :html => @table + else + csv_string = CSV.generate do |csv| + csv << @header + @table.each { |row| csv << row } + end + send_data csv_string, :filename => "bulk_coop.csv" + end + end + + def payments + 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.select { |o| o.complete? } # Only select complete orders + payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments + + # Ignore supplier conditions if "All" selected + #if params[:supplier_id] && params[:supplier_id] != "All" + # line_items = line_items.select { |li| li.variant.product.supplier_id == params[:supplier_id] } + #end + + #[Distributor.new(:id => nil, :name => 'All')]+ + @distributors = Spree::Distributor.all + @report_type = params[:report_type] + + case params[:report_type] + when "payments_by_payment_type" + table_items = payments + rules = [ { group_by: Proc.new { |payment| payment.order.payment_state }, sort_by: Proc.new { |payment_state| payment_state } }, { group_by: Proc.new { |payment| payment.order.distributor }, sort_by: Proc.new { |distributor| distributor.name } }, { group_by: Proc.new { |payment| payment.payment_method }, sort_by: Proc.new { |method| method.name } } ] + columns = [ Proc.new { |payments| payments.first.order.payment_state }, Proc.new { |payments| payments.first.order.distributor.name }, Proc.new { |payments| payments.first.payment_method.name }, Proc.new { |payments| payments.sum { |payment| payment.amount } } ] + header = ["Payment State", "Distributor", "Payment Type", "Total ($)"] + when "itemised_payment_totals" + table_items = orders + rules = [ { group_by: Proc.new { |order| order.payment_state }, sort_by: Proc.new { |payment_state| payment_state } }, { group_by: Proc.new { |order| order.distributor }, sort_by: Proc.new { |distributor| distributor.name } } ] + columns = [ Proc.new { |orders| orders.first.payment_state }, Proc.new { |orders| orders.first.distributor.name }, Proc.new { |orders| orders.sum { |o| o.item_total } }, Proc.new { |orders| orders.sum { |o| o.ship_total } }, Proc.new { |orders| orders.sum { |o| o.outstanding_balance } }, Proc.new { |orders| orders.sum { |o| o.total } } ] + header = ["Payment State", "Distributor", "Product Total ($)", "Shipping Total ($)", "Outstanding Balance ($)", "Total ($)"] + when "payment_totals" + table_items = orders + rules = [ { group_by: Proc.new { |order| order.payment_state }, sort_by: Proc.new { |payment_state| payment_state } }, { group_by: Proc.new { |order| order.distributor }, sort_by: Proc.new { |distributor| distributor.name } } ] + columns = [ Proc.new { |orders| orders.first.payment_state }, Proc.new { |orders| orders.first.distributor.name }, Proc.new { |orders| orders.sum { |o| o.item_total } }, Proc.new { |orders| orders.sum { |o| o.ship_total } }, Proc.new { |orders| orders.sum { |o| o.total } }, Proc.new { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "EFT") }.sum { |payment| payment.amount } } }, Proc.new { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "PayPal") }.sum{ |payment| payment.amount } } }, Proc.new { |orders| orders.sum { |o| o.outstanding_balance } } ] + header = ["Payment State", "Distributor", "Product Total ($)", "Shipping Total ($)", "Total ($)", "EFT ($)", "PayPal ($)", "Outstanding Balance ($)"] + else + table_items = payments + rules = [ { group_by: Proc.new { |payment| payment.order.payment_state }, sort_by: Proc.new { |payment_state| payment_state } }, { group_by: Proc.new { |payment| payment.order.distributor }, sort_by: Proc.new { |distributor| distributor.name } }, { group_by: Proc.new { |payment| payment.payment_method }, sort_by: Proc.new { |method| method.name } } ] + columns = [ Proc.new { |payments| payments.first.order.payment_state }, Proc.new { |payments| payments.first.order.distributor.name }, Proc.new { |payments| payments.first.payment_method.name }, Proc.new { |payments| payments.sum { |payment| payment.amount } } ] + header = ["Payment State", "Distributor", "Payment Type", "Total ($)"] + end + + order_grouper = OpenFoodWeb::OrderGrouper.new rules, columns + + @header = header + @table = order_grouper.table(table_items) + + unless params[:csv] + render :html => @table + else + csv_string = CSV.generate do |csv| + csv << @header + @table.each { |row| csv << row } + end + send_data csv_string, :filename => "payments.csv" + end + end end \ No newline at end of file diff --git a/app/views/spree/admin/reports/bulk_coop.html.haml b/app/views/spree/admin/reports/bulk_coop.html.haml new file mode 100644 index 0000000000..b1b4824d1a --- /dev/null +++ b/app/views/spree/admin/reports/bulk_coop.html.haml @@ -0,0 +1,41 @@ += form_for @search, :url => spree.bulk_coop_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, :include_blank => 'All') + /= label_tag nil, "Supplier: " + /= collection_select(:supplier, :supplier_id, @suppliers, :id, :name, :prompt => 'All') + %br + = label_tag nil, "Report Type: " + = select_tag(:report_type, options_for_select([['Bulk Co-op - Totals by Supplier',:bulk_coop_supplier_report],['Bulk Co-op - Allocation',:bulk_coop_allocation],['Bulk Co-op - Packing Sheets',:bulk_coop_packing_sheets],['Bulk Co-op - Customer Payments',:bulk_coop_customer_payments]], @report_type)) + %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"} + - @header.each do |heading| + %th=heading + %tbody + - @table.each do |row| + %tr + - row.each do |column| + %td= column + - if @table.empty? + %tr + %td{:colspan => "2"}= t(:none) \ No newline at end of file diff --git a/app/views/spree/admin/reports/payments.html.haml b/app/views/spree/admin/reports/payments.html.haml new file mode 100644 index 0000000000..559e456a8f --- /dev/null +++ b/app/views/spree/admin/reports/payments.html.haml @@ -0,0 +1,41 @@ += form_for @search, :url => spree.payments_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, :include_blank => 'All') + /= label_tag nil, "Supplier: " + /= collection_select(:supplier, :supplier_id, @suppliers, :id, :name, :prompt => 'All') + %br + = label_tag nil, "Report Type: " + = select_tag(:report_type, options_for_select([['Payments By Type',:payments_by_payment_type],['Itemised Payment Totals',:itemised_payment_totals],['Payment Totals',:payment_totals]], @report_type)) + %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"} + - @header.each do |heading| + %th=heading + %tbody + - @table.each do |row| + %tr + - row.each do |column| + %td= column + - if @table.empty? + %tr + %td{:colspan => "2"}= t(:none) \ No newline at end of file diff --git a/lib/open_food_web/order_grouper.rb b/lib/open_food_web/order_grouper.rb new file mode 100644 index 0000000000..43587ae83b --- /dev/null +++ b/lib/open_food_web/order_grouper.rb @@ -0,0 +1,56 @@ +module OpenFoodWeb + + class OrderGrouper + def initialize rules, column_constructors + @rules = rules + @column_constructors = column_constructors + end + + def build_tree items, remaining_rules + rules = remaining_rules.clone + unless rules.empty? + rule = rules.delete_at(0) # Remove current rule for subsequent groupings + group_and_sort(rule, rules, items) + else + items + end + end + + def group_and_sort rule, remaining_rules, items + branch = {} + groups = items.group_by { |item| rule[:group_by].call(item) } + sorted_groups = groups.sort_by { |key, value| rule[:sort_by].call(key) } + sorted_groups.each do |property,items_by_property| + branch[property] = build_tree(items_by_property, remaining_rules) + branch[property][:summary_row] = { items: items_by_property, columns: rule[:summary_columns] } unless rule[:summary_columns] == nil || branch[property].class == Array + end + branch + end + + def build_table groups + rows = [] + unless groups.class == Array + groups.each do |key, group| + unless key == :summary_row + build_table(group).each { |g| rows << g } + else + row = Array.new + group[:columns].each { |cols| row << cols.call(group[:items]) } + rows << row + end + end + else + row = Array.new + @column_constructors.each { |column_constructor| row << column_constructor.call(groups) } + rows << row + end + rows + end + + def table items + tree = build_tree(items,@rules) + table = build_table(tree) + table + end + end +end \ No newline at end of file diff --git a/spec/lib/open_food_web/order_grouper_spec.rb b/spec/lib/open_food_web/order_grouper_spec.rb new file mode 100644 index 0000000000..010fd319e2 --- /dev/null +++ b/spec/lib/open_food_web/order_grouper_spec.rb @@ -0,0 +1,298 @@ +#require 'spec_helper' + +#module OpenFoodWeb +# describe OrderGrouper do +# +# before(:each) do +# @orders = [] +# 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!" +# +# bill_address1 = create(:address) +# order1 = create(:order, :distributor => distributor, :bill_address => bill_address1, :special_instructions => shipping_instructions) +# line_item11 = create(:line_item, :variant => @variant1, :order => order1) +# order1.line_items << line_item11 +# @orders << order1 +# +# bill_address2 = create(:address) +# order2 = create(:order, :distributor => distributor, :bill_address => bill_address2, :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)) + +# bill_address3 = create(:address) +# order3 = create(:order, :distributor => distributor, :bill_address => bill_address3, :special_instructions => shipping_instructions) +# line_item31 = create(:line_item, :variant => @variant3, :order => order3) +# order3.line_items << line_item31 +# @orders << order3 +# end + +# context "when grouping by supplier, then product, then variant" do +# group_rules = [ { group_by: Proc.new { |li| li.variant.product.supplier }, sort_by: Proc.new { |supplier| supplier.name } }, { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } } ] +# column_properties = [ Proc.new { |lis| lis.first.variant.product.supplier.name }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + +# it "should return a Hash with one key for each supplier represented by the orders" do +# subject = OrderGrouper.new group_rules, column_properties + +# line_items = @orders.map { |o| o.line_items }.flatten + +# groups = subject.grouper_sorter(line_items, group_rules) +# groups.class.should == Hash +# groups.length.should == 2 +# end + +# it "should group items over multiple levels according to group by rules" do +# subject = OrderGrouper.new group_rules, column_properties + +# line_items = @orders.map { |o| o.line_items }.flatten + +# groups = subject.grouper_sorter(line_items, group_rules) +# groups[@supplier1].length.should == 2 +# groups[@supplier2].length.should == 1 +# end + +# it "should return a table as an array" do +# subject = OrderGrouper.new group_rules, column_properties +# +# line_items = @orders.map { |o| o.line_items }.flatten + +# subject.table(line_items).class.should == Array +# end +# end + +# context "when grouping by customers" do +# group_rules = [ { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } }, { group_by: Proc.new { |li| li.order.bill_address }, sort_by: Proc.new { |bill_address| bill_address.firstname + " " + bill_address.lastname } } ] +# column_properties = [ Proc.new { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + +# it "should return a table as an array" do +# subject = OrderGrouper.new group_rules, column_properties + +# line_items = @orders.map { |o| o.line_items }.flatten + +# subject.table(line_items).class.should == Array +# end +# end +# end +#end + +require 'spec_helper' + +module OpenFoodWeb + describe OrderGrouper do + + before(:each) do + @items = [1, 2, 3, 4] + end + + context "constructing the table" do + it "should build a tree then build a table" do + rules = [ { group_by: Proc.new { |sentence| sentence.paragraph.chapter }, sort_by: Proc.new { |chapter| chapter.name }, summary_columns: [Proc.new { |is| is.first.paragraph.chapter.name }, Proc.new { |is| "TOTAL" }, Proc.new { |is| "" }, Proc.new { |is| is.sum {|i| i.property1 } } ] }, + { group_by: Proc.new { |sentence| sentence.paragraph }, sort_by: Proc.new { |paragraph| paragraph.name } } ] + columns = [Proc.new { |is| is.first.paragraph.chapter.name }, Proc.new { |is| is.first.paragraph.name }, Proc.new { |is| is.first.name }, Proc.new { |is| is.sum {|i| i.property1 } }] + + subject = OrderGrouper.new rules, columns + + tree = double(:tree) + subject.should_receive(:build_tree).with(@items, rules).and_return(tree) + subject.should_receive(:build_table).with(tree) + + subject.table(@items) + end + + end + + context "grouping items without rules" do + it "returns the original array when no rules are provided" do + rules = [] + column1 = double(:col1) + column2 = double(:col2) + columns = [column1, column2] + subject = OrderGrouper.new rules, columns + + rules.should_receive(:clone).and_return(rules) + subject.build_tree(@items, rules).should == @items + end + end + + context "grouping items with rules" do + it "builds branches by removing a rule from \"rules\" and running group_and_sort" do + rule1 = double(:rule1) + rule2 = double(:rule2) + rules = [rule1, rule2] + column1 = double(:col1) + column2 = double(:col2) + columns = [column1, column2] + + subject = OrderGrouper.new rules, columns + + #rules = [ { group_by: Proc.new { |sentence| sentence.paragraph.chapter }, sort_by: Proc.new { |chapter| chapter.name }, summary_columns: [Proc.new { |is| is.first.paragraph.chapter.name }, Proc.new { |is| "TOTAL" }, Proc.new { |is| "" }, Proc.new { |is| is.sum {|i| i.property1 } } ] }, + #{ group_by: Proc.new { |sentence| sentence.paragraph }, sort_by: Proc.new { |paragraph| paragraph.name } } ] + #columns = [Proc.new { |is| is.first.paragraph.chapter.name }, Proc.new { |is| is.first.paragraph.name }, Proc.new { |is| is.first.name }, Proc.new { |is| is.sum {|i| i.property1 } }] + rules.should_receive(:clone).and_return(rules) + rules.should_receive(:delete_at).with(0) + grouped_tree = double(:grouped_tree) + subject.should_receive(:group_and_sort).and_return(grouped_tree) + + subject.build_tree(@items, rules).should == grouped_tree + end + + it "separates the first rule from rules before sending to group_and_sort" do + rule1 = double(:rule1) + rule2 = double(:rule2) + rules = [rule1, rule2] + column1 = double(:col1) + column2 = double(:col2) + columns = [column1, column2] + + subject = OrderGrouper.new rules, columns + + grouped_tree = double(:grouped_tree) + subject.should_receive(:group_and_sort).with(rule1, rules[1..-1], @items).and_return(grouped_tree) + + subject.build_tree(@items, rules).should == grouped_tree + end + + it "should group, then sort, send each group to build_tree, and return a branch" do + rule1 = double(:rule1) + rule2 = double(:rule2) + rules = [rule1, rule2] + remaining_rules = [rule2] + column1 = double(:col1) + column2 = double(:col2) + columns = [column1, column2] + + summary_columns_object = double(:summary_columns) + rule1.stub(:[]).with(:summary_columns) { summary_columns_object } + + subject = OrderGrouper.new rules, columns + + number_of_categories = 3 + groups = double(:groups) + @items.should_receive(:group_by).and_return(groups) + sorted_groups = {} + 1.upto(number_of_categories) { |i| sorted_groups[i] = double(:group, name: "Group "+ i.to_s ) } + groups.should_receive(:sort_by).and_return(sorted_groups) + group = { group1: 1, group2: 2, group3: 3 } + subject.should_receive(:build_tree).exactly(number_of_categories).times.and_return(group) + + group_tree = {} + 1.upto(number_of_categories) { |i| group_tree[i] = group } + 1.upto(number_of_categories) { |i| group_tree[i][:summary_row] = summary_columns_object } + subject.group_and_sort(rule1, remaining_rules, @items).should == group_tree + end + end + + context "building the table Array" do + it "should return columns when given an Array" do + rule1 = double(:rule1) + rule2 = double(:rule2) + rules = [rule1, rule2] + column1 = double(:col1) + column2 = double(:col2) + columns = [column1, column2] + column1.stub(:call) { "Column1" } + column2.stub(:call) { "Column2" } + + item1 = double(:item1) + item2 = double(:item2) + item3 = double(:item3) + items1 = [item1, item2] + items2 = [item2, item3] + groups = { items1: items1, items2: items1 } + + subject = OrderGrouper.new rules, columns + + column1.should_receive(:call) + column2.should_receive(:call) + + subject.build_table(items1).should == [["Column1", "Column2"]] + end + + it "should return a row for each key-value pair when given a Hash" do + rule1 = double(:rule1) + rule2 = double(:rule2) + rules = [rule1, rule2] + column1 = double(:col1) + column2 = double(:col2) + columns = [column1, column2] + column1.stub(:call) { "Column1" } + column2.stub(:call) { "Column2" } + + item1 = double(:item1) + item2 = double(:item2) + item3 = double(:item3) + items1 = [item1, item2] + items2 = [item2, item3] + items3 = [item3, item1] + groups = { items1: items1, items2: items2, items3: items3 } + + subject = OrderGrouper.new rules, columns + + #subject.should_receive(:build_table).exactly(2).times + + expected_return = [] + groups.length.times { expected_return << ["Column1", "Column2"] } + subject.build_table(groups).should == expected_return + end + + it "should return an extra row when a :summary_row key appears in a given Hash" do + rule1 = double(:rule1) + rule2 = double(:rule2) + rules = [rule1, rule2] + column1 = double(:col1) + column2 = double(:col2) + columns = [column1, column2] + column1.stub(:call) { "Column1" } + column2.stub(:call) { "Column2" } + + sumcol1 = double(:sumcol1) + sumcol2 = double(:sumcol2) + sumcols = [sumcol1, sumcol2] + sumcol1.stub(:call) { "SumColumn1" } + sumcol2.stub(:call) { "SumColumn2" } + + item1 = double(:item1) + item2 = double(:item2) + item3 = double(:item3) + items1 = [item1, item2] + items2 = [item2, item3] + items3 = [item3, item1] + groups = { items1: items1, items2: items2, items3: items3, summary_row: { items: { items2: items2, items3: items3 }, columns: sumcols } } + + subject = OrderGrouper.new rules, columns + + expected_return = [] + groups.each do |key, group| + if key == :summary_row + expected_return << ["SumColumn1", "SumColumn2"] + else + expected_return << ["Column1", "Column2"] + end + end + subject.build_table(groups).should == expected_return + end + end + end +end \ No newline at end of file From eb7d69fe6bb7ec04dda2b4e96e2f6f5b01788ebb Mon Sep 17 00:00:00 2001 From: Rob H Date: Mon, 22 Oct 2012 11:35:48 +1100 Subject: [PATCH 02/18] commit routes.rb file to prevent overwriting --- config/routes.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/routes.rb b/config/routes.rb index 0befa2892e..7fde8d7b66 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -20,5 +20,7 @@ Spree::Core::Engine.routes.prepend do 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] + match '/admin/reports/bulk_coop' => 'admin/reports#bulk_coop', :as => "bulk_coop_admin_reports", :via => [:get, :post] + match '/admin/reports/payments' => 'admin/reports#payments', :as => "payments_admin_reports", :via => [:get, :post] end From 81b33772fe6aa427dbe461b676a8301a08f59dc5 Mon Sep 17 00:00:00 2001 From: Rob H Date: Wed, 24 Oct 2012 15:21:16 +1100 Subject: [PATCH 03/18] Fixes to syntax and formatting for group-reports --- .../admin/reports_controller_decorator.rb | 211 +++++++++++++----- .../spree/admin/reports/bulk_coop.html.haml | 2 - .../spree/admin/reports/payments.html.haml | 2 - db/schema.rb | 156 ++++++------- lib/open_food_web/order_grouper.rb | 28 +-- spec/lib/open_food_web/order_grouper_spec.rb | 181 ++------------- 6 files changed, 276 insertions(+), 304 deletions(-) diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index ed2d7a0c7c..67fe169317 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -85,55 +85,114 @@ Spree::Admin::ReportsController.class_eval do params[:q][:meta_sort] ||= "created_at.desc" @search = Spree::Order.complete.search(params[:q]) - orders = @search.result.select { |o| o.completed? } # Only select complete orders + orders = @search.result line_items = orders.map { |o| o.line_items }.flatten - # Ignore supplier conditions if "All" selected - #if params[:supplier_id] && params[:supplier_id] != "All" - # line_items = line_items.select { |li| li.variant.product.supplier_id == params[:supplier_id] } - #end - - #[Distributor.new(:id => nil, :name => 'All')]+ @distributors = Spree::Distributor.all @report_type = params[:report_type] case params[:report_type] when "bulk_coop_supplier_report" - rules = [ { group_by: Proc.new { |li| li.variant.product.supplier }, sort_by: Proc.new { |supplier| supplier.name } }, { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name }, summary_columns: [ Proc.new { |lis| lis.first.variant.product.supplier.name }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| "" }, Proc.new { |lis| "" }, Proc.new { |lis| lis.sum { |li| li.quantity * li.variant.weight } }, Proc.new { |lis| lis.sum { |li| (li.max_quantity || 0) * li.variant.weight } } ] }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } } ] - columns = [ Proc.new { |lis| lis.first.variant.product.supplier.name }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - header = ["Supplier","Product","Unit Size","Variant","Weight","Sum Total","Sum Max Total"] + + header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total"] + + columns = [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| "UNIT SIZE" }, + proc { |lis| lis.first.variant.options_text }, + proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.sum { |li| li.quantity } }, + proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + + 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| "UNIT SIZE" }, + proc { |lis| "" }, proc { |lis| "" }, + proc { |lis| lis.sum { |li| li.quantity * li.variant.weight } }, + proc { |lis| lis.sum { |li| (li.max_quantity || 0) * li.variant.weight } } ] }, + { group_by: proc { |li| li.variant }, + sort_by: proc { |variant| variant.options_text } } ] + when "bulk_coop_allocation" - rules = [ { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } }, { group_by: Proc.new { |li| li.order.user }, sort_by: Proc.new { |user| user.to_s } } ] - columns = [ Proc.new { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - header = ["Customer","Product","Unit Size","Variant","Weight","Sum Total","Sum Max Total"] + + header = ["Customer", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max 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| "UNIT SIZE" }, + proc { |lis| lis.first.variant.options_text }, + proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.sum { |li| li.quantity } }, + proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + + 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.options_text } }, + { group_by: proc { |li| li.order.user }, + sort_by: proc { |user| user.to_s } } ] + when "bulk_coop_packing_sheets" - rules = [ { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } }, { group_by: Proc.new { |li| li.order.user }, sort_by: Proc.new { |user| user.to_s } } ] - columns = [ Proc.new { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.sum { |li| li.quantity } } ] - header = ["Customer","Product","Variant","Sum Total"] + + 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.options_text }, + 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.options_text } }, + { group_by: proc { |li| li.order.user }, + sort_by: proc { |user| user.to_s } } ] + when "bulk_coop_customer_payments" - rules = [ { group_by: Proc.new { |li| li.order.user }, sort_by: Proc.new { |user| user.to_s } }, { group_by: Proc.new { |li| li.order }, sort_by: Proc.new { |order| order.created_at } } ] - columns = [ Proc.new { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, Proc.new { |lis| lis.first.order.created_at.to_s }, Proc.new { |lis| lis.map { |li| li.order }.to_set.to_a.sum { |o| o.total } }, Proc.new { |lis| lis.map { |li| li.order }.to_set.to_a.sum { |o| o.outstanding_balance } }, Proc.new { |lis| lis.map { |li| li.order }.to_set.to_a.sum { |o| o.payment_total } } ] - header = ["Customer","Date of Order","Total Cost","Amount Owing","Amount Paid"] + + 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.created_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.user }, + sort_by: proc { |user| user.to_s } }, + { group_by: proc { |li| li.order }, + sort_by: proc { |order| order.created_at } } ] + else # List all line items - rules = [ { group_by: Proc.new { |li| li.variant.product.supplier }, sort_by: Proc.new { |supplier| supplier.name } }, { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } } ] - columns = [ Proc.new { |lis| lis.first.variant.product.supplier.name }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - header = ["Supplier","Product","Unit Size","Variant","Weight","Sum Total","Sum Max Total"] + + header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total"] + + columns = [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| "UNIT SIZE" }, + proc { |lis| lis.first.variant.options_text }, + proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.sum { |li| li.quantity } }, + proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + + 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 } }, + { group_by: proc { |li| li.variant }, + sort_by: proc { |variant| variant.options_text } } ] end order_grouper = OpenFoodWeb::OrderGrouper.new rules, columns @header = header @table = order_grouper.table(line_items) + csv_file_name = "bulk_coop.csv" - unless params[:csv] - render :html => @table - else - csv_string = CSV.generate do |csv| - csv << @header - @table.each { |row| csv << row } - end - send_data csv_string, :filename => "bulk_coop.csv" - end + generate_report(@header, @table, params[:csv], csv_file_name) end def payments @@ -151,54 +210,104 @@ Spree::Admin::ReportsController.class_eval do params[:q][:meta_sort] ||= "created_at.desc" @search = Spree::Order.complete.search(params[:q]) - orders = @search.result.select { |o| o.complete? } # Only select complete orders + orders = @search.result payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments - # Ignore supplier conditions if "All" selected - #if params[:supplier_id] && params[:supplier_id] != "All" - # line_items = line_items.select { |li| li.variant.product.supplier_id == params[:supplier_id] } - #end - - #[Distributor.new(:id => nil, :name => 'All')]+ @distributors = Spree::Distributor.all @report_type = params[:report_type] case params[:report_type] when "payments_by_payment_type" table_items = payments - rules = [ { group_by: Proc.new { |payment| payment.order.payment_state }, sort_by: Proc.new { |payment_state| payment_state } }, { group_by: Proc.new { |payment| payment.order.distributor }, sort_by: Proc.new { |distributor| distributor.name } }, { group_by: Proc.new { |payment| payment.payment_method }, sort_by: Proc.new { |method| method.name } } ] - columns = [ Proc.new { |payments| payments.first.order.payment_state }, Proc.new { |payments| payments.first.order.distributor.name }, Proc.new { |payments| payments.first.payment_method.name }, Proc.new { |payments| payments.sum { |payment| payment.amount } } ] + header = ["Payment State", "Distributor", "Payment Type", "Total ($)"] + + 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 } } ] + when "itemised_payment_totals" table_items = orders - rules = [ { group_by: Proc.new { |order| order.payment_state }, sort_by: Proc.new { |payment_state| payment_state } }, { group_by: Proc.new { |order| order.distributor }, sort_by: Proc.new { |distributor| distributor.name } } ] - columns = [ Proc.new { |orders| orders.first.payment_state }, Proc.new { |orders| orders.first.distributor.name }, Proc.new { |orders| orders.sum { |o| o.item_total } }, Proc.new { |orders| orders.sum { |o| o.ship_total } }, Proc.new { |orders| orders.sum { |o| o.outstanding_balance } }, Proc.new { |orders| orders.sum { |o| o.total } } ] + header = ["Payment State", "Distributor", "Product Total ($)", "Shipping Total ($)", "Outstanding Balance ($)", "Total ($)"] + + 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 - rules = [ { group_by: Proc.new { |order| order.payment_state }, sort_by: Proc.new { |payment_state| payment_state } }, { group_by: Proc.new { |order| order.distributor }, sort_by: Proc.new { |distributor| distributor.name } } ] - columns = [ Proc.new { |orders| orders.first.payment_state }, Proc.new { |orders| orders.first.distributor.name }, Proc.new { |orders| orders.sum { |o| o.item_total } }, Proc.new { |orders| orders.sum { |o| o.ship_total } }, Proc.new { |orders| orders.sum { |o| o.total } }, Proc.new { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "EFT") }.sum { |payment| payment.amount } } }, Proc.new { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "PayPal") }.sum{ |payment| payment.amount } } }, Proc.new { |orders| orders.sum { |o| o.outstanding_balance } } ] + header = ["Payment State", "Distributor", "Product Total ($)", "Shipping Total ($)", "Total ($)", "EFT ($)", "PayPal ($)", "Outstanding Balance ($)"] + + 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 - rules = [ { group_by: Proc.new { |payment| payment.order.payment_state }, sort_by: Proc.new { |payment_state| payment_state } }, { group_by: Proc.new { |payment| payment.order.distributor }, sort_by: Proc.new { |distributor| distributor.name } }, { group_by: Proc.new { |payment| payment.payment_method }, sort_by: Proc.new { |method| method.name } } ] - columns = [ Proc.new { |payments| payments.first.order.payment_state }, Proc.new { |payments| payments.first.order.distributor.name }, Proc.new { |payments| payments.first.payment_method.name }, Proc.new { |payments| payments.sum { |payment| payment.amount } } ] + header = ["Payment State", "Distributor", "Payment Type", "Total ($)"] + + 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 = OpenFoodWeb::OrderGrouper.new rules, columns @header = header @table = order_grouper.table(table_items) + csv_file_name = "payments.csv" + + generate_report(@header, @table, params[:csv], csv_file_name) - unless params[:csv] - render :html => @table + end + + def generate_report (header, table, create_csv, csv_file_name) + unless create_csv + render :html => table else csv_string = CSV.generate do |csv| - csv << @header - @table.each { |row| csv << row } + csv << header + table.each { |row| csv << row } end - send_data csv_string, :filename => "payments.csv" + send_data csv_string, :filename => csv_file_name end end end \ No newline at end of file diff --git a/app/views/spree/admin/reports/bulk_coop.html.haml b/app/views/spree/admin/reports/bulk_coop.html.haml index b1b4824d1a..8c570e8de1 100644 --- a/app/views/spree/admin/reports/bulk_coop.html.haml +++ b/app/views/spree/admin/reports/bulk_coop.html.haml @@ -13,8 +13,6 @@ %br = label_tag nil, "Distributor: " = f.collection_select(:distributor_id_eq, @distributors, :id, :name, :include_blank => 'All') - /= label_tag nil, "Supplier: " - /= collection_select(:supplier, :supplier_id, @suppliers, :id, :name, :prompt => 'All') %br = label_tag nil, "Report Type: " = select_tag(:report_type, options_for_select([['Bulk Co-op - Totals by Supplier',:bulk_coop_supplier_report],['Bulk Co-op - Allocation',:bulk_coop_allocation],['Bulk Co-op - Packing Sheets',:bulk_coop_packing_sheets],['Bulk Co-op - Customer Payments',:bulk_coop_customer_payments]], @report_type)) diff --git a/app/views/spree/admin/reports/payments.html.haml b/app/views/spree/admin/reports/payments.html.haml index 559e456a8f..898bba70ef 100644 --- a/app/views/spree/admin/reports/payments.html.haml +++ b/app/views/spree/admin/reports/payments.html.haml @@ -13,8 +13,6 @@ %br = label_tag nil, "Distributor: " = f.collection_select(:distributor_id_eq, @distributors, :id, :name, :include_blank => 'All') - /= label_tag nil, "Supplier: " - /= collection_select(:supplier, :supplier_id, @suppliers, :id, :name, :prompt => 'All') %br = label_tag nil, "Report Type: " = select_tag(:report_type, options_for_select([['Payments By Type',:payments_by_payment_type],['Itemised Payment Totals',:itemised_payment_totals],['Payment Totals',:payment_totals]], @report_type)) diff --git a/db/schema.rb b/db/schema.rb index e23f9e59a8..09dc89c12e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -140,8 +140,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "abn" t.string "acn" t.string "description" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "pickup_address_id" t.string "next_collection_at" t.text "long_description" @@ -183,8 +183,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "alternative_phone" t.integer "state_id" t.integer "country_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.string "company" end @@ -193,12 +193,12 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_adjustments", :force => true do |t| t.integer "source_id" - t.decimal "amount", :precision => 8, :scale => 2, :default => 0.0 + t.decimal "amount", :precision => 8, :scale => 2 t.string "label" t.string "source_type" t.integer "adjustable_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.boolean "mandatory" t.boolean "locked" t.integer "originator_id" @@ -230,15 +230,15 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "type" t.integer "calculable_id", :null => false t.string "calculable_type", :null => false - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_configurations", :force => true do |t| t.string "name" t.string "type", :limit => 50 - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end add_index "spree_configurations", ["name", "type"], :name => "index_configurations_on_name_and_type" @@ -276,8 +276,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "environment", :default => "development" t.string "server", :default => "test" t.boolean "test_mode", :default => true - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_inventory_units", :force => true do |t| @@ -285,8 +285,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "state" t.integer "variant_id" t.integer "order_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "shipment_id" t.integer "return_authorization_id" end @@ -300,8 +300,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "variant_id" t.integer "quantity", :null => false t.decimal "price", :precision => 8, :scale => 2, :null => false - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "max_quantity" t.integer "shipping_method_id" end @@ -313,22 +313,22 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "source_id" t.string "source_type" t.text "details" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_mail_methods", :force => true do |t| t.string "environment" t.boolean "active", :default => true - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_option_types", :force => true do |t| t.string "name", :limit => 100 t.string "presentation", :limit => 100 - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "position", :default => 0, :null => false end @@ -342,8 +342,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "name" t.string "presentation" t.integer "option_type_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_option_values_variants", :id => false, :force => true do |t| @@ -362,8 +362,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.decimal "adjustment_total", :precision => 8, :scale => 2, :default => 0.0, :null => false t.decimal "credit_total", :precision => 8, :scale => 2, :default => 0.0, :null => false t.integer "user_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.datetime "completed_at" t.integer "bill_address_id" t.integer "ship_address_id" @@ -384,8 +384,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.text "description" t.boolean "active", :default => true t.string "environment", :default => "development" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.datetime "deleted_at" t.string "display_on" end @@ -393,8 +393,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_payments", :force => true do |t| t.decimal "amount", :precision => 8, :scale => 2, :default => 0.0, :null => false t.integer "order_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "source_id" t.string "source_type" t.integer "payment_method_id" @@ -423,8 +423,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "owner_id" t.string "owner_type" t.text "value" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.string "key" t.string "value_type" end @@ -449,16 +449,16 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "position" t.integer "product_id" t.integer "option_type_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_product_properties", :force => true do |t| t.string "value" t.integer "product_id" t.integer "property_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end add_index "spree_product_properties", ["product_id"], :name => "index_product_properties_on_product_id" @@ -482,8 +482,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "meta_keywords" t.integer "tax_category_id" t.integer "shipping_category_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "count_on_hand", :default => 0, :null => false t.integer "supplier_id" t.boolean "group_buy" @@ -528,8 +528,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "user_id" t.integer "product_group_id" t.string "type" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end add_index "spree_promotion_rules", ["product_group_id"], :name => "index_promotion_rules_on_product_group_id" @@ -546,8 +546,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_properties", :force => true do |t| t.string "name" t.string "presentation", :null => false - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_properties_prototypes", :id => false, :force => true do |t| @@ -557,8 +557,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_prototypes", :force => true do |t| t.string "name" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_return_authorizations", :force => true do |t| @@ -567,8 +567,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.decimal "amount", :precision => 8, :scale => 2, :default => 0.0, :null => false t.integer "order_id" t.text "reason" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_roles", :force => true do |t| @@ -591,8 +591,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "order_id" t.integer "shipping_method_id" t.integer "address_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.string "state" end @@ -600,15 +600,15 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_shipping_categories", :force => true do |t| t.string "name" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_shipping_methods", :force => true do |t| t.string "name" t.integer "zone_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.string "display_on" t.integer "shipping_category_id" t.boolean "match_none" @@ -624,8 +624,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "transaction_id" t.integer "customer_id" t.string "payment_type" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_state_changes", :force => true do |t| @@ -633,8 +633,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "previous_state" t.integer "stateful_id" t.integer "user_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.string "stateful_type" t.string "next_state" end @@ -648,8 +648,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_tax_categories", :force => true do |t| t.string "name" t.string "description" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.boolean "is_default", :default => false t.datetime "deleted_at" end @@ -658,15 +658,15 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.decimal "amount", :precision => 8, :scale => 5 t.integer "zone_id" t.integer "tax_category_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.boolean "included_in_price", :default => false end create_table "spree_taxonomies", :force => true do |t| t.string "name", :null => false - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_taxons", :force => true do |t| @@ -675,8 +675,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "name", :null => false t.string "permalink" t.integer "taxonomy_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "lft" t.integer "rgt" t.string "icon_file_name" @@ -694,8 +694,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "permissable_id" t.string "permissable_type" t.string "token" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end add_index "spree_tokenized_permissions", ["permissable_id", "permissable_type"], :name => "index_tokenized_name_and_type" @@ -704,8 +704,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "environment" t.string "analytics_id" t.boolean "active", :default => true - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_users", :force => true do |t| @@ -726,8 +726,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "login" t.integer "ship_address_id" t.integer "bill_address_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.string "authentication_token" t.string "unlock_token" t.datetime "locked_at" @@ -750,7 +750,7 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.boolean "is_master", :default => false t.integer "product_id" t.integer "count_on_hand", :default => 0, :null => false - t.decimal "cost_price", :precision => 8, :scale => 2, :default => 0.0 + t.decimal "cost_price", :precision => 8, :scale => 2 t.integer "position" end @@ -760,15 +760,15 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "zoneable_id" t.string "zoneable_type" t.integer "zone_id" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false end create_table "spree_zones", :force => true do |t| t.string "name" t.string "description" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.boolean "default_tax", :default => false t.integer "zone_members_count", :default => 0 end @@ -779,8 +779,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "email" t.string "twitter" t.string "website" - t.datetime "created_at" - t.datetime "updated_at" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false t.integer "address_id" t.text "long_description" end diff --git a/lib/open_food_web/order_grouper.rb b/lib/open_food_web/order_grouper.rb index 43587ae83b..d222a7cc13 100644 --- a/lib/open_food_web/order_grouper.rb +++ b/lib/open_food_web/order_grouper.rb @@ -1,12 +1,12 @@ module OpenFoodWeb class OrderGrouper - def initialize rules, column_constructors + def initialize(rules, column_constructors) @rules = rules @column_constructors = column_constructors end - def build_tree items, remaining_rules + def build_tree(items, remaining_rules) rules = remaining_rules.clone unless rules.empty? rule = rules.delete_at(0) # Remove current rule for subsequent groupings @@ -16,41 +16,43 @@ module OpenFoodWeb end end - def group_and_sort rule, remaining_rules, items + def group_and_sort(rule, remaining_rules, items) branch = {} groups = items.group_by { |item| rule[:group_by].call(item) } sorted_groups = groups.sort_by { |key, value| rule[:sort_by].call(key) } sorted_groups.each do |property,items_by_property| branch[property] = build_tree(items_by_property, remaining_rules) - branch[property][:summary_row] = { items: items_by_property, columns: rule[:summary_columns] } unless rule[:summary_columns] == nil || branch[property].class == Array + branch[property][:summary_row] = { items: items_by_property, columns: rule[:summary_columns] } unless rule[:summary_columns] == nil || is_leaf_node(branch[property]) end branch end - def build_table groups + def build_table(groups) rows = [] - unless groups.class == Array + unless is_leaf_node(groups) groups.each do |key, group| unless key == :summary_row build_table(group).each { |g| rows << g } else - row = Array.new - group[:columns].each { |cols| row << cols.call(group[:items]) } - rows << row + rows << group[:columns].map { |cols| cols.call(group[:items]) } end end else - row = Array.new - @column_constructors.each { |column_constructor| row << column_constructor.call(groups) } - rows << row + rows << @column_constructors.map { |column_constructor| column_constructor.call(groups) } end rows end - def table items + def table(items) tree = build_tree(items,@rules) table = build_table(tree) table end + + private + + def is_leaf_node(node) + node.is_a? Array + end end end \ No newline at end of file diff --git a/spec/lib/open_food_web/order_grouper_spec.rb b/spec/lib/open_food_web/order_grouper_spec.rb index 010fd319e2..3acd0b49ad 100644 --- a/spec/lib/open_food_web/order_grouper_spec.rb +++ b/spec/lib/open_food_web/order_grouper_spec.rb @@ -1,102 +1,3 @@ -#require 'spec_helper' - -#module OpenFoodWeb -# describe OrderGrouper do -# -# before(:each) do -# @orders = [] -# 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!" -# -# bill_address1 = create(:address) -# order1 = create(:order, :distributor => distributor, :bill_address => bill_address1, :special_instructions => shipping_instructions) -# line_item11 = create(:line_item, :variant => @variant1, :order => order1) -# order1.line_items << line_item11 -# @orders << order1 -# -# bill_address2 = create(:address) -# order2 = create(:order, :distributor => distributor, :bill_address => bill_address2, :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)) - -# bill_address3 = create(:address) -# order3 = create(:order, :distributor => distributor, :bill_address => bill_address3, :special_instructions => shipping_instructions) -# line_item31 = create(:line_item, :variant => @variant3, :order => order3) -# order3.line_items << line_item31 -# @orders << order3 -# end - -# context "when grouping by supplier, then product, then variant" do -# group_rules = [ { group_by: Proc.new { |li| li.variant.product.supplier }, sort_by: Proc.new { |supplier| supplier.name } }, { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } } ] -# column_properties = [ Proc.new { |lis| lis.first.variant.product.supplier.name }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - -# it "should return a Hash with one key for each supplier represented by the orders" do -# subject = OrderGrouper.new group_rules, column_properties - -# line_items = @orders.map { |o| o.line_items }.flatten - -# groups = subject.grouper_sorter(line_items, group_rules) -# groups.class.should == Hash -# groups.length.should == 2 -# end - -# it "should group items over multiple levels according to group by rules" do -# subject = OrderGrouper.new group_rules, column_properties - -# line_items = @orders.map { |o| o.line_items }.flatten - -# groups = subject.grouper_sorter(line_items, group_rules) -# groups[@supplier1].length.should == 2 -# groups[@supplier2].length.should == 1 -# end - -# it "should return a table as an array" do -# subject = OrderGrouper.new group_rules, column_properties -# -# line_items = @orders.map { |o| o.line_items }.flatten - -# subject.table(line_items).class.should == Array -# end -# end - -# context "when grouping by customers" do -# group_rules = [ { group_by: Proc.new { |li| li.variant.product }, sort_by: Proc.new { |product| product.name } }, { group_by: Proc.new { |li| li.variant }, sort_by: Proc.new { |variant| variant.options_text } }, { group_by: Proc.new { |li| li.order.bill_address }, sort_by: Proc.new { |bill_address| bill_address.firstname + " " + bill_address.lastname } } ] -# column_properties = [ Proc.new { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, Proc.new { |lis| lis.first.variant.product.name }, Proc.new { |lis| "UNIT SIZE" }, Proc.new { |lis| lis.first.variant.options_text }, Proc.new { |lis| lis.first.variant.weight }, Proc.new { |lis| lis.sum { |li| li.quantity } }, Proc.new { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - -# it "should return a table as an array" do -# subject = OrderGrouper.new group_rules, column_properties - -# line_items = @orders.map { |o| o.line_items }.flatten - -# subject.table(line_items).class.should == Array -# end -# end -# end -#end - require 'spec_helper' module OpenFoodWeb @@ -137,7 +38,7 @@ module OpenFoodWeb end context "grouping items with rules" do - it "builds branches by removing a rule from \"rules\" and running group_and_sort" do + it "builds branches by removing a rule from 'rules' and running group_and_sort" do rule1 = double(:rule1) rule2 = double(:rule2) rules = [rule1, rule2] @@ -147,9 +48,6 @@ module OpenFoodWeb subject = OrderGrouper.new rules, columns - #rules = [ { group_by: Proc.new { |sentence| sentence.paragraph.chapter }, sort_by: Proc.new { |chapter| chapter.name }, summary_columns: [Proc.new { |is| is.first.paragraph.chapter.name }, Proc.new { |is| "TOTAL" }, Proc.new { |is| "" }, Proc.new { |is| is.sum {|i| i.property1 } } ] }, - #{ group_by: Proc.new { |sentence| sentence.paragraph }, sort_by: Proc.new { |paragraph| paragraph.name } } ] - #columns = [Proc.new { |is| is.first.paragraph.chapter.name }, Proc.new { |is| is.first.paragraph.name }, Proc.new { |is| is.first.name }, Proc.new { |is| is.sum {|i| i.property1 } }] rules.should_receive(:clone).and_return(rules) rules.should_receive(:delete_at).with(0) grouped_tree = double(:grouped_tree) @@ -205,50 +103,38 @@ module OpenFoodWeb end context "building the table Array" do - it "should return columns when given an Array" do + before(:each) do rule1 = double(:rule1) rule2 = double(:rule2) - rules = [rule1, rule2] - column1 = double(:col1) - column2 = double(:col2) - columns = [column1, column2] - column1.stub(:call) { "Column1" } - column2.stub(:call) { "Column2" } + @rules = [rule1, rule2] + @column1 = double(:col1, :call => "Column1") + @column2 = double(:col2, :call => "Column2") + @columns = [@column1, @column2] + + sumcol1 = double(:sumcol1, :call => "SumColumn1") + sumcol2 = double(:sumcol2, :call => "SumColumn2") + @sumcols = [sumcol1, sumcol2] item1 = double(:item1) item2 = double(:item2) item3 = double(:item3) - items1 = [item1, item2] - items2 = [item2, item3] - groups = { items1: items1, items2: items1 } + @items1 = [item1, item2] + @items2 = [item2, item3] + @items3 = [item3, item1] + end + it "should return columns when given an Array" do + subject = OrderGrouper.new @rules, @columns - subject = OrderGrouper.new rules, columns + @column1.should_receive(:call) + @column2.should_receive(:call) - column1.should_receive(:call) - column2.should_receive(:call) - - subject.build_table(items1).should == [["Column1", "Column2"]] + subject.build_table(@items1).should == [["Column1", "Column2"]] end it "should return a row for each key-value pair when given a Hash" do - rule1 = double(:rule1) - rule2 = double(:rule2) - rules = [rule1, rule2] - column1 = double(:col1) - column2 = double(:col2) - columns = [column1, column2] - column1.stub(:call) { "Column1" } - column2.stub(:call) { "Column2" } + groups = { items1: @items1, items2: @items2, items3: @items3 } - item1 = double(:item1) - item2 = double(:item2) - item3 = double(:item3) - items1 = [item1, item2] - items2 = [item2, item3] - items3 = [item3, item1] - groups = { items1: items1, items2: items2, items3: items3 } - - subject = OrderGrouper.new rules, columns + subject = OrderGrouper.new @rules, @columns #subject.should_receive(:build_table).exactly(2).times @@ -258,30 +144,9 @@ module OpenFoodWeb end it "should return an extra row when a :summary_row key appears in a given Hash" do - rule1 = double(:rule1) - rule2 = double(:rule2) - rules = [rule1, rule2] - column1 = double(:col1) - column2 = double(:col2) - columns = [column1, column2] - column1.stub(:call) { "Column1" } - column2.stub(:call) { "Column2" } + groups = { items1: @items1, items2: @items2, items3: @items3, summary_row: { items: { items2: @items2, items3: @items3 }, columns: @sumcols } } - sumcol1 = double(:sumcol1) - sumcol2 = double(:sumcol2) - sumcols = [sumcol1, sumcol2] - sumcol1.stub(:call) { "SumColumn1" } - sumcol2.stub(:call) { "SumColumn2" } - - item1 = double(:item1) - item2 = double(:item2) - item3 = double(:item3) - items1 = [item1, item2] - items2 = [item2, item3] - items3 = [item3, item1] - groups = { items1: items1, items2: items2, items3: items3, summary_row: { items: { items2: items2, items3: items3 }, columns: sumcols } } - - subject = OrderGrouper.new rules, columns + subject = OrderGrouper.new @rules, @columns expected_return = [] groups.each do |key, group| From 41d547ac2d1e8e34c79c7387c1652c63408c0c9b Mon Sep 17 00:00:00 2001 From: Rob H Date: Wed, 24 Oct 2012 16:13:23 +1100 Subject: [PATCH 04/18] Minor formatting changes to Order Group Spec --- spec/lib/open_food_web/order_grouper_spec.rb | 49 ++++++++------------ 1 file changed, 19 insertions(+), 30 deletions(-) diff --git a/spec/lib/open_food_web/order_grouper_spec.rb b/spec/lib/open_food_web/order_grouper_spec.rb index 3acd0b49ad..d734b78c7b 100644 --- a/spec/lib/open_food_web/order_grouper_spec.rb +++ b/spec/lib/open_food_web/order_grouper_spec.rb @@ -38,53 +38,42 @@ module OpenFoodWeb end context "grouping items with rules" do - it "builds branches by removing a rule from 'rules' and running group_and_sort" do - rule1 = double(:rule1) + + before(:each) do + @rule1 = double(:rule1) rule2 = double(:rule2) - rules = [rule1, rule2] + @rules = [@rule1, rule2] + @remaining_rules = [rule2] column1 = double(:col1) column2 = double(:col2) - columns = [column1, column2] + @columns = [column1, column2] + end + + it "builds branches by removing a rule from 'rules' and running group_and_sort" do + subject = OrderGrouper.new @rules, @columns - subject = OrderGrouper.new rules, columns - - rules.should_receive(:clone).and_return(rules) - rules.should_receive(:delete_at).with(0) + @rules.should_receive(:clone).and_return(@rules) + @rules.should_receive(:delete_at).with(0) grouped_tree = double(:grouped_tree) subject.should_receive(:group_and_sort).and_return(grouped_tree) - subject.build_tree(@items, rules).should == grouped_tree + subject.build_tree(@items, @rules).should == grouped_tree end it "separates the first rule from rules before sending to group_and_sort" do - rule1 = double(:rule1) - rule2 = double(:rule2) - rules = [rule1, rule2] - column1 = double(:col1) - column2 = double(:col2) - columns = [column1, column2] - - subject = OrderGrouper.new rules, columns + subject = OrderGrouper.new @rules, @columns grouped_tree = double(:grouped_tree) - subject.should_receive(:group_and_sort).with(rule1, rules[1..-1], @items).and_return(grouped_tree) + subject.should_receive(:group_and_sort).with(@rule1, @rules[1..-1], @items).and_return(grouped_tree) - subject.build_tree(@items, rules).should == grouped_tree + subject.build_tree(@items, @rules).should == grouped_tree end it "should group, then sort, send each group to build_tree, and return a branch" do - rule1 = double(:rule1) - rule2 = double(:rule2) - rules = [rule1, rule2] - remaining_rules = [rule2] - column1 = double(:col1) - column2 = double(:col2) - columns = [column1, column2] - summary_columns_object = double(:summary_columns) - rule1.stub(:[]).with(:summary_columns) { summary_columns_object } + @rule1.stub(:[]).with(:summary_columns) { summary_columns_object } - subject = OrderGrouper.new rules, columns + subject = OrderGrouper.new @rules, @columns number_of_categories = 3 groups = double(:groups) @@ -98,7 +87,7 @@ module OpenFoodWeb group_tree = {} 1.upto(number_of_categories) { |i| group_tree[i] = group } 1.upto(number_of_categories) { |i| group_tree[i][:summary_row] = summary_columns_object } - subject.group_and_sort(rule1, remaining_rules, @items).should == group_tree + subject.group_and_sort(@rule1, @remaining_rules, @items).should == group_tree end end From a362dd51613830ec0132d0af0155733824316fff Mon Sep 17 00:00:00 2001 From: Rob H Date: Wed, 24 Oct 2012 17:01:50 +1100 Subject: [PATCH 05/18] Change reports controller: generate_report to render_report --- app/controllers/spree/admin/reports_controller_decorator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 67fe169317..a8cbd23f08 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -299,7 +299,7 @@ Spree::Admin::ReportsController.class_eval do end - def generate_report (header, table, create_csv, csv_file_name) + def render_report (header, table, create_csv, csv_file_name) unless create_csv render :html => table else From d74591afe61a9b2a874236d86f3056cdd272364a Mon Sep 17 00:00:00 2001 From: Rob H Date: Fri, 26 Oct 2012 13:44:13 +1100 Subject: [PATCH 06/18] Fixes to reports controller and addition of order cycles reports --- .../admin/reports_controller_decorator.rb | 435 +++++++++++++----- .../admin/reports/order_cycles.html.haml | 39 ++ config/routes.rb | 1 + 3 files changed, 348 insertions(+), 127 deletions(-) create mode 100644 app/views/spree/admin/reports/order_cycles.html.haml diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index a8cbd23f08..110a93dfd9 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -9,6 +9,7 @@ Spree::Admin::ReportsController.class_eval do Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:group_buys => {:name => "Group Buys", :description => "Orders by supplier and variant"}}) Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:bulk_coop => {:name => "Bulk Co-Op", :description => "Reports for Bulk Co-Op orders"}}) Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:payments => {:name => "Payment Reports", :description => "Reports for Payments"}}) + Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:order_cycles => {:name => "Order Cycle Reports", :description => "Reports for Order Cycles"}}) def orders_and_distributors params[:q] = {} unless params[:q] @@ -93,96 +94,98 @@ Spree::Admin::ReportsController.class_eval do case params[:report_type] when "bulk_coop_supplier_report" - + header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total"] - - columns = [ proc { |lis| lis.first.variant.product.supplier.name }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| "UNIT SIZE" }, - proc { |lis| lis.first.variant.options_text }, - proc { |lis| lis.first.variant.weight }, - proc { |lis| lis.sum { |li| li.quantity } }, + + columns = [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| "UNIT SIZE" }, + proc { |lis| lis.first.variant.options_text }, + proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.sum { |li| li.quantity } }, proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - - rules = [ { group_by: proc { |li| li.variant.product.supplier }, + + 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| "UNIT SIZE" }, - proc { |lis| "" }, proc { |lis| "" }, - proc { |lis| lis.sum { |li| li.quantity * li.variant.weight } }, + { 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| "UNIT SIZE" }, + proc { |lis| "" }, + proc { |lis| "" }, + proc { |lis| lis.sum { |li| li.quantity * li.variant.weight } }, proc { |lis| lis.sum { |li| (li.max_quantity || 0) * li.variant.weight } } ] }, - { group_by: proc { |li| li.variant }, + { group_by: proc { |li| li.variant }, sort_by: proc { |variant| variant.options_text } } ] - + when "bulk_coop_allocation" - + header = ["Customer", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max 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| "UNIT SIZE" }, - proc { |lis| lis.first.variant.options_text }, - proc { |lis| lis.first.variant.weight }, - proc { |lis| lis.sum { |li| li.quantity } }, - proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - - 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.options_text } }, - { group_by: proc { |li| li.order.user }, - sort_by: proc { |user| user.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.options_text }, - 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.options_text } }, - { group_by: proc { |li| li.order.user }, - sort_by: proc { |user| user.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.created_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.user }, - sort_by: proc { |user| user.to_s } }, - { group_by: proc { |li| li.order }, - sort_by: proc { |order| order.created_at } } ] - - else # List all line items - - header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total"] - - columns = [ proc { |lis| lis.first.variant.product.supplier.name }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| "UNIT SIZE" }, - proc { |lis| lis.first.variant.options_text }, - proc { |lis| lis.first.variant.weight }, - proc { |lis| lis.sum { |li| li.quantity } }, + + columns = [ proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| "UNIT SIZE" }, + proc { |lis| lis.first.variant.options_text }, + proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.sum { |li| li.quantity } }, proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - - 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 } }, - { group_by: proc { |li| li.variant }, + + 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.options_text } }, + { group_by: proc { |li| li.order.user }, + sort_by: proc { |user| user.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.options_text }, + 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.options_text } }, + { group_by: proc { |li| li.order.user }, + sort_by: proc { |user| user.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.created_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.user }, + sort_by: proc { |user| user.to_s } }, + { group_by: proc { |li| li.order }, + sort_by: proc { |order| order.created_at } } ] + + else # List all line items + + header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total"] + + columns = [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| "UNIT SIZE" }, + proc { |lis| lis.first.variant.options_text }, + proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.sum { |li| li.quantity } }, + proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + + 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 } }, + { group_by: proc { |li| li.variant }, sort_by: proc { |variant| variant.options_text } } ] end @@ -192,7 +195,7 @@ Spree::Admin::ReportsController.class_eval do @table = order_grouper.table(line_items) csv_file_name = "bulk_coop.csv" - generate_report(@header, @table, params[:csv], csv_file_name) + render_report(@header, @table, params[:csv], csv_file_name) end def payments @@ -219,72 +222,72 @@ Spree::Admin::ReportsController.class_eval do case params[:report_type] when "payments_by_payment_type" table_items = payments - + header = ["Payment State", "Distributor", "Payment Type", "Total ($)"] - columns = [ proc { |payments| payments.first.order.payment_state }, - proc { |payments| payments.first.order.distributor.name }, - proc { |payments| payments.first.payment_method.name }, + 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 }, + 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 } } ] - + when "itemised_payment_totals" table_items = orders - + header = ["Payment State", "Distributor", "Product Total ($)", "Shipping Total ($)", "Outstanding Balance ($)", "Total ($)"] - - 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 } }, + + 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 }, + + 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 ($)", "Shipping Total ($)", "Total ($)", "EFT ($)", "PayPal ($)", "Outstanding Balance ($)"] - 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 } } }, + 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 }, + 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 ($)"] - columns = [ proc { |payments| payments.first.order.payment_state }, - proc { |payments| payments.first.order.distributor.name }, - proc { |payments| payments.first.payment_method.name }, + 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 }, + 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 @@ -294,11 +297,189 @@ Spree::Admin::ReportsController.class_eval do @header = header @table = order_grouper.table(table_items) csv_file_name = "payments.csv" - - generate_report(@header, @table, params[:csv], csv_file_name) + + render_report(@header, @table, params[:csv], csv_file_name) end - + + def order_cycles + 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 + line_items = orders.map { |o| o.line_items }.flatten + #payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments + + @distributors = Spree::Distributor.all + @report_type = params[:report_type] + + case params[:report_type] + when "order_cycle_supplier_totals" + table_items = line_items + @include_blank = 'All' + + header = ["Supplier", "Product", "Variant", "Amount", "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.options_text }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.first.variant.price }, + proc { |line_items| line_items.sum { |li| li.quantity * li.variant.price } }, + proc { |line_items| "status" }, + 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.options_text } } ] + + when "order_cycle_supplier_totals_by_distributor" + table_items = line_items + @include_blank = 'All' + + header = ["Supplier", "Product", "Variant", "To Distributor", "Amount", "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.options_text }, + proc { |line_items| line_items.first.order.distributor.name }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.first.variant.price }, + proc { |line_items| line_items.sum { |li| li.quantity * li.variant.price } }, + 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.options_text }, + summary_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.options_text }, + proc { |line_items| "TOTAL" }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.first.variant.price }, + proc { |line_items| line_items.sum { |li| li.quantity * li.variant.price } }, + 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 = ["Distributor", "Supplier", "Product", "Variant", "Amount", "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.options_text }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.first.variant.price }, + proc { |line_items| line_items.sum { |li| li.quantity * li.variant.price } }, + 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| line_items.first.order.distributor.name }, + proc { |line_items| "TOTAL" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| line_items.sum { |li| li.quantity * li.variant.price } }, + proc { |line_items| "total shipping cost" }, + 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.options_text } } ] + + when "order_cycle_customer_totals" + table_items = line_items + @include_blank = false + + header = ["Customer", "Email", "Phone", "Product", "Variant", "Amount", "Total Cost", "Paid?", "Packed?", "Shipped?"] + + columns = [ 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.name }, + proc { |line_items| line_items.first.variant.options_text }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.sum { |li| li.quantity * li.variant.price } }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| "" } ] + + rules = [ { group_by: proc { |line_item| line_item.order.user }, + sort_by: proc { |user| user.to_s }, + summary_columns: [ 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| "TOTAL" }, + proc { |line_items| "" }, + proc { |line_items| "" }, + proc { |line_items| line_items.sum { |li| li.quantity * li.variant.price } }, + proc { |line_items| "work out whether paid or not" }, + 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.options_text } } ] + + else + table_items = line_items + + header = ["Supplier", "Product", "Variant", "Amount", "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.options_text }, + proc { |line_items| line_items.sum { |li| li.quantity } }, + proc { |line_items| line_items.first.variant.price }, + proc { |line_items| line_items.sum { |li| li.quantity * li.variant.price } }, + proc { |line_items| "status" }, + 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.options_text } } ] + + end + + order_grouper = OpenFoodWeb::OrderGrouper.new rules, columns + + @header = header + @table = order_grouper.table(table_items) + csv_file_name = "order_cycles.csv" + + render_report(@header, @table, params[:csv], csv_file_name) + + end + def render_report (header, table, create_csv, csv_file_name) unless create_csv render :html => table diff --git a/app/views/spree/admin/reports/order_cycles.html.haml b/app/views/spree/admin/reports/order_cycles.html.haml new file mode 100644 index 0000000000..33bd97cb06 --- /dev/null +++ b/app/views/spree/admin/reports/order_cycles.html.haml @@ -0,0 +1,39 @@ += form_for @search, :url => spree.order_cycles_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, :include_blank => @include_blank) + %br + = label_tag nil, "Report Type: " + = select_tag(:report_type, options_for_select([['Order Cycle Supplier Totals',:order_cycle_supplier_totals], ['Order Cycle Supplier Totals by Distributor',:order_cycle_supplier_totals_by_distributor], ['Order Cycle Distributor Totals by Supplier',:order_cycle_distributor_totals_by_supplier], ['Order Cycle Customer Totals',:order_cycle_customer_totals]], @report_type)) + %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"} + - @header.each do |heading| + %th=heading + %tbody + - @table.each do |row| + %tr + - row.each do |column| + %td= column + - if @table.empty? + %tr + %td{:colspan => "2"}= t(:none) \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 7fde8d7b66..354e2d0dbd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -22,5 +22,6 @@ Spree::Core::Engine.routes.prepend do match '/admin/reports/group_buys' => 'admin/reports#group_buys', :as => "group_buys_admin_reports", :via => [:get, :post] match '/admin/reports/bulk_coop' => 'admin/reports#bulk_coop', :as => "bulk_coop_admin_reports", :via => [:get, :post] match '/admin/reports/payments' => 'admin/reports#payments', :as => "payments_admin_reports", :via => [:get, :post] + match '/admin/reports/order_cycles' => 'admin/reports#order_cycles', :as => "order_cycles_admin_reports", :via => [:get, :post] end From 4dd5e129680e2115c12fe20bc4c8b04b9c2ae72f Mon Sep 17 00:00:00 2001 From: Rob H Date: Fri, 26 Oct 2012 13:49:39 +1100 Subject: [PATCH 07/18] Fix reports controller, previous changes to fix change generate_report were incomplete --- .../admin/reports_controller_decorator.rb | 254 +++++++++--------- 1 file changed, 127 insertions(+), 127 deletions(-) diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index a8cbd23f08..d5bb667845 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -93,96 +93,96 @@ Spree::Admin::ReportsController.class_eval do case params[:report_type] when "bulk_coop_supplier_report" - + header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total"] - - columns = [ proc { |lis| lis.first.variant.product.supplier.name }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| "UNIT SIZE" }, - proc { |lis| lis.first.variant.options_text }, - proc { |lis| lis.first.variant.weight }, - proc { |lis| lis.sum { |li| li.quantity } }, + + columns = [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| "UNIT SIZE" }, + proc { |lis| lis.first.variant.options_text }, + proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.sum { |li| li.quantity } }, proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - - rules = [ { group_by: proc { |li| li.variant.product.supplier }, + + 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| "UNIT SIZE" }, - proc { |lis| "" }, proc { |lis| "" }, - proc { |lis| lis.sum { |li| li.quantity * li.variant.weight } }, + { 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| "UNIT SIZE" }, + proc { |lis| "" }, proc { |lis| "" }, + proc { |lis| lis.sum { |li| li.quantity * li.variant.weight } }, proc { |lis| lis.sum { |li| (li.max_quantity || 0) * li.variant.weight } } ] }, - { group_by: proc { |li| li.variant }, + { group_by: proc { |li| li.variant }, sort_by: proc { |variant| variant.options_text } } ] - + when "bulk_coop_allocation" - + header = ["Customer", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max 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| "UNIT SIZE" }, - proc { |lis| lis.first.variant.options_text }, - proc { |lis| lis.first.variant.weight }, - proc { |lis| lis.sum { |li| li.quantity } }, - proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - - 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.options_text } }, - { group_by: proc { |li| li.order.user }, - sort_by: proc { |user| user.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.options_text }, - 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.options_text } }, - { group_by: proc { |li| li.order.user }, - sort_by: proc { |user| user.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.created_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.user }, - sort_by: proc { |user| user.to_s } }, - { group_by: proc { |li| li.order }, - sort_by: proc { |order| order.created_at } } ] - - else # List all line items - - header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total"] - - columns = [ proc { |lis| lis.first.variant.product.supplier.name }, - proc { |lis| lis.first.variant.product.name }, - proc { |lis| "UNIT SIZE" }, - proc { |lis| lis.first.variant.options_text }, - proc { |lis| lis.first.variant.weight }, - proc { |lis| lis.sum { |li| li.quantity } }, + + columns = [ proc { |lis| lis.first.order.bill_address.firstname + " " + lis.first.order.bill_address.lastname }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| "UNIT SIZE" }, + proc { |lis| lis.first.variant.options_text }, + proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.sum { |li| li.quantity } }, proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] - - 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 } }, - { group_by: proc { |li| li.variant }, + + 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.options_text } }, + { group_by: proc { |li| li.order.user }, + sort_by: proc { |user| user.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.options_text }, + 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.options_text } }, + { group_by: proc { |li| li.order.user }, + sort_by: proc { |user| user.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.created_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.user }, + sort_by: proc { |user| user.to_s } }, + { group_by: proc { |li| li.order }, + sort_by: proc { |order| order.created_at } } ] + + else # List all line items + + header = ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Sum Total", "Sum Max Total"] + + columns = [ proc { |lis| lis.first.variant.product.supplier.name }, + proc { |lis| lis.first.variant.product.name }, + proc { |lis| "UNIT SIZE" }, + proc { |lis| lis.first.variant.options_text }, + proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.sum { |li| li.quantity } }, + proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] + + 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 } }, + { group_by: proc { |li| li.variant }, sort_by: proc { |variant| variant.options_text } } ] end @@ -192,7 +192,7 @@ Spree::Admin::ReportsController.class_eval do @table = order_grouper.table(line_items) csv_file_name = "bulk_coop.csv" - generate_report(@header, @table, params[:csv], csv_file_name) + render_report(@header, @table, params[:csv], csv_file_name) end def payments @@ -219,72 +219,72 @@ Spree::Admin::ReportsController.class_eval do case params[:report_type] when "payments_by_payment_type" table_items = payments - + header = ["Payment State", "Distributor", "Payment Type", "Total ($)"] - columns = [ proc { |payments| payments.first.order.payment_state }, - proc { |payments| payments.first.order.distributor.name }, - proc { |payments| payments.first.payment_method.name }, + 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 }, + 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 } } ] - + when "itemised_payment_totals" table_items = orders - + header = ["Payment State", "Distributor", "Product Total ($)", "Shipping Total ($)", "Outstanding Balance ($)", "Total ($)"] - - 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 } }, + + 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 }, + + 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 ($)", "Shipping Total ($)", "Total ($)", "EFT ($)", "PayPal ($)", "Outstanding Balance ($)"] - 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 } } }, + 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 }, + 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 ($)"] - columns = [ proc { |payments| payments.first.order.payment_state }, - proc { |payments| payments.first.order.distributor.name }, - proc { |payments| payments.first.payment_method.name }, + 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 }, + 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 @@ -294,11 +294,11 @@ Spree::Admin::ReportsController.class_eval do @header = header @table = order_grouper.table(table_items) csv_file_name = "payments.csv" - - generate_report(@header, @table, params[:csv], csv_file_name) + + render_report(@header, @table, params[:csv], csv_file_name) end - + def render_report (header, table, create_csv, csv_file_name) unless create_csv render :html => table From f960cc44ba6c2cc5b20aa54b354d79f7508ccb9b Mon Sep 17 00:00:00 2001 From: Rob H Date: Fri, 26 Oct 2012 17:27:08 +1100 Subject: [PATCH 09/18] Fixed calculations when variant weight is nil --- .../spree/admin/reports_controller_decorator.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 60ed1a4e03..58343bf4eb 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -100,7 +100,7 @@ Spree::Admin::ReportsController.class_eval do proc { |lis| lis.first.variant.product.name }, proc { |lis| "UNIT SIZE" }, proc { |lis| lis.first.variant.options_text }, - proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.first.variant.weight || 0 }, proc { |lis| lis.sum { |li| li.quantity } }, proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] @@ -111,8 +111,8 @@ Spree::Admin::ReportsController.class_eval do summary_columns: [ proc { |lis| lis.first.variant.product.supplier.name }, proc { |lis| lis.first.variant.product.name }, proc { |lis| "UNIT SIZE" }, proc { |lis| "" }, proc { |lis| "" }, - proc { |lis| lis.sum { |li| li.quantity * li.variant.weight } }, - proc { |lis| lis.sum { |li| (li.max_quantity || 0) * li.variant.weight } } ] }, + proc { |lis| lis.sum { |li| li.quantity * li.variant.weight || 0 } }, + proc { |lis| lis.sum { |li| (li.max_quantity || 0) * li.variant.weight || 0 } } ] }, { group_by: proc { |li| li.variant }, sort_by: proc { |variant| variant.options_text } } ] @@ -124,7 +124,7 @@ Spree::Admin::ReportsController.class_eval do proc { |lis| lis.first.variant.product.name }, proc { |lis| "UNIT SIZE" }, proc { |lis| lis.first.variant.options_text }, - proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.first.variant.weight || 0 }, proc { |lis| lis.sum { |li| li.quantity } }, proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] @@ -174,7 +174,7 @@ Spree::Admin::ReportsController.class_eval do proc { |lis| lis.first.variant.product.name }, proc { |lis| "UNIT SIZE" }, proc { |lis| lis.first.variant.options_text }, - proc { |lis| lis.first.variant.weight }, + proc { |lis| lis.first.variant.weight || 0 }, proc { |lis| lis.sum { |li| li.quantity } }, proc { |lis| lis.sum { |li| li.max_quantity || 0 } } ] From 13317347bb8db1f9e5ef715cab087098d253e6a3 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Sat, 27 Oct 2012 12:19:44 +1100 Subject: [PATCH 10/18] Display an explanation message on product page when no distributor is selected --- .../stylesheets/store/openfoodweb.css.scss | 10 ++++++++++ .../add_distributor_details_to_product.rb | 4 ++++ app/views/distributors/_details.html.haml | 2 ++ spec/requests/consumer/product_spec.rb | 19 +++++++++++++++++++ 4 files changed, 35 insertions(+) create mode 100644 app/overrides/add_distributor_details_to_product.rb create mode 100644 app/views/distributors/_details.html.haml diff --git a/app/assets/stylesheets/store/openfoodweb.css.scss b/app/assets/stylesheets/store/openfoodweb.css.scss index a3cb0a29f1..06979bf3ea 100644 --- a/app/assets/stylesheets/store/openfoodweb.css.scss +++ b/app/assets/stylesheets/store/openfoodweb.css.scss @@ -144,6 +144,16 @@ ul.product-listing { } +/* Distributor details on product details page */ +#product-distributor-details { + float: right; +} + +#product-variants { + float: none; +} + + /* Add to cart form on product details page */ #cart-form { .error-distributor { diff --git a/app/overrides/add_distributor_details_to_product.rb b/app/overrides/add_distributor_details_to_product.rb new file mode 100644 index 0000000000..b107869e19 --- /dev/null +++ b/app/overrides/add_distributor_details_to_product.rb @@ -0,0 +1,4 @@ +Deface::Override.new(:virtual_path => "spree/products/show", + :insert_before => "[data-hook='cart_form']", + :partial => "distributors/details", + :name => "product_distributor_details") diff --git a/app/views/distributors/_details.html.haml b/app/views/distributors/_details.html.haml new file mode 100644 index 0000000000..6646588ef4 --- /dev/null +++ b/app/views/distributors/_details.html.haml @@ -0,0 +1,2 @@ +#product-distributor-details.columns.five.omega + When you select a distributor for your order, their address and pickup times will be displayed here. diff --git a/spec/requests/consumer/product_spec.rb b/spec/requests/consumer/product_spec.rb index 97712d1e13..368452ab54 100644 --- a/spec/requests/consumer/product_spec.rb +++ b/spec/requests/consumer/product_spec.rb @@ -22,4 +22,23 @@ feature %q{ page.should have_selector 'td', :text => d.name end + describe "viewing distributor details" do + context "without Javascript" do + it "displays a holding message when no distributor is selected" do + p = create(:product) + + visit spree.product_path p + + page.should have_selector '#product-distributor-details', :text => 'When you select a distributor for your order, their address and pickup times will be displayed here.' + end + + it "displays distributor details when one is selected" + end + + context "with Javascript" do + it "changes distributor details when the distributor is changed" + end + end + + end From 773adca838931c945c3db35c1130bdbd1aa1e94e Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Sat, 27 Oct 2012 12:49:57 +1100 Subject: [PATCH 11/18] Display distributor details on product page when distributor is selected --- .../stylesheets/store/openfoodweb.css.scss | 5 +++- .../add_distributor_details_to_product.rb | 2 +- app/views/distributors/_details.html.haml | 25 +++++++++++++++-- .../spree/checkout/_distributor.html.haml | 25 +---------------- .../products/_distributor_details.html.haml | 7 +++++ spec/requests/consumer/product_spec.rb | 28 ++++++++++++++++++- 6 files changed, 63 insertions(+), 29 deletions(-) create mode 100644 app/views/spree/products/_distributor_details.html.haml diff --git a/app/assets/stylesheets/store/openfoodweb.css.scss b/app/assets/stylesheets/store/openfoodweb.css.scss index 06979bf3ea..fa4d16689f 100644 --- a/app/assets/stylesheets/store/openfoodweb.css.scss +++ b/app/assets/stylesheets/store/openfoodweb.css.scss @@ -145,8 +145,11 @@ ul.product-listing { /* Distributor details on product details page */ -#product-distributor-details { +fieldset#product-distributor-details { float: right; + margin-top: 0; + width: 250px; + @extend #shipping; } #product-variants { diff --git a/app/overrides/add_distributor_details_to_product.rb b/app/overrides/add_distributor_details_to_product.rb index b107869e19..6671ed40b5 100644 --- a/app/overrides/add_distributor_details_to_product.rb +++ b/app/overrides/add_distributor_details_to_product.rb @@ -1,4 +1,4 @@ Deface::Override.new(:virtual_path => "spree/products/show", :insert_before => "[data-hook='cart_form']", - :partial => "distributors/details", + :partial => "spree/products/distributor_details", :name => "product_distributor_details") diff --git a/app/views/distributors/_details.html.haml b/app/views/distributors/_details.html.haml index 6646588ef4..2a354be1db 100644 --- a/app/views/distributors/_details.html.haml +++ b/app/views/distributors/_details.html.haml @@ -1,2 +1,23 @@ -#product-distributor-details.columns.five.omega - When you select a distributor for your order, their address and pickup times will be displayed here. +%h2= distributor.name +%p + %strong Address: + %br/ + = render 'spree/shared/address', :address => distributor.pickup_address +%p + %strong Next collection time: + %br/ + = distributor.next_collection_at +%p + %strong Regular collection times: + %br/ + = distributor.pickup_times +%p + %strong Contact: + %br/ + = distributor.contact + %br/ + = "Phone: #{distributor.phone}" + %br/ + = "Email: #{distributor.email}" +%p= distributor.description +%p= link_to distributor.url, distributor.url if distributor.url diff --git a/app/views/spree/checkout/_distributor.html.haml b/app/views/spree/checkout/_distributor.html.haml index 9460e3a94b..b2eac11c71 100644 --- a/app/views/spree/checkout/_distributor.html.haml +++ b/app/views/spree/checkout/_distributor.html.haml @@ -1,27 +1,4 @@ .columns.omega.six %fieldset#shipping %legend Distributor - %h2= @order.distributor.name - %p - %strong Address: - %br/ - = render 'spree/shared/address', :address => @order.distributor.pickup_address - %p - %strong Next collection time: - %br/ - = @order.distributor.next_collection_at - %p - %strong Regular collection times: - %br/ - = @order.distributor.pickup_times - %p - %strong Contact: - %br/ - = @order.distributor.contact - %br/ - = "Phone: #{@order.distributor.phone}" - %br/ - = "Email: #{@order.distributor.email}" - %p= @order.distributor.description - %p= link_to @order.distributor.url, @order.distributor.url if @order.distributor.url - + = render 'distributors/details', :distributor => @order.distributor diff --git a/app/views/spree/products/_distributor_details.html.haml b/app/views/spree/products/_distributor_details.html.haml new file mode 100644 index 0000000000..808468f806 --- /dev/null +++ b/app/views/spree/products/_distributor_details.html.haml @@ -0,0 +1,7 @@ +%fieldset#product-distributor-details.columns.five.omega + %legend Distributor + - order = current_order(false) + - if order.andand.distributor.present? + = render 'distributors/details', :distributor => order.distributor + - else + When you select a distributor for your order, their address and pickup times will be displayed here. diff --git a/spec/requests/consumer/product_spec.rb b/spec/requests/consumer/product_spec.rb index 368452ab54..76a647d074 100644 --- a/spec/requests/consumer/product_spec.rb +++ b/spec/requests/consumer/product_spec.rb @@ -32,7 +32,33 @@ feature %q{ page.should have_selector '#product-distributor-details', :text => 'When you select a distributor for your order, their address and pickup times will be displayed here.' end - it "displays distributor details when one is selected" + it "displays distributor details when one is selected" do + d = create(:distributor) + p = create(:product, :distributors => [d]) + + visit spree.root_path + click_link d.name + visit spree.product_path p + + within '#product-distributor-details' do + [d.name, + d.pickup_address.address1, + d.pickup_address.city, + d.pickup_address.zipcode, + d.pickup_address.state_text, + d.pickup_address.country.name, + d.pickup_times, + d.next_collection_at, + d.contact, + d.phone, + d.email, + d.description, + d.url].each do |value| + + page.should have_content value + end + end + end end context "with Javascript" do From c5941d6cb5068cefeafd23b41045f1ce1dd25408 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Sat, 27 Oct 2012 18:50:09 +1100 Subject: [PATCH 12/18] Update distributor details when distributor is changed --- app/assets/javascripts/store/products.js | 9 ++++++++ app/controllers/distributors_controller.rb | 10 +++++++++ .../add_distributor_details_to_product.rb | 5 +++++ app/views/distributors/index.js.erb | 1 + .../products/_distributor_details.html.haml | 11 +++++----- spec/requests/consumer/product_spec.rb | 21 +++++++++++++++---- 6 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 app/views/distributors/index.js.erb diff --git a/app/assets/javascripts/store/products.js b/app/assets/javascripts/store/products.js index 3e972161a6..0dabff5f4d 100644 --- a/app/assets/javascripts/store/products.js +++ b/app/assets/javascripts/store/products.js @@ -10,6 +10,15 @@ $(document).ready(function() { // Product page with master price only $(".add-to-cart input.title:not(#quantity):not(.max_quantity)").change(products_update_price_without_variant).change(); + + // Product page other + $("#distributor_id").change(function() { + var distributor_html = distributors[$(this).val()]; + if(!distributor_html) { + distributor_html = 'When you select a distributor for your order, their address and pickup times will be displayed here.'; + } + $("#product-distributor-details .distributor-details").html(distributor_html); + }); }); diff --git a/app/controllers/distributors_controller.rb b/app/controllers/distributors_controller.rb index 97c6d81691..2dc50f4af6 100644 --- a/app/controllers/distributors_controller.rb +++ b/app/controllers/distributors_controller.rb @@ -1,4 +1,14 @@ class DistributorsController < BaseController + def index + @distributors = Distributor.all + + respond_to do |format| + format.js do + @distributor_details = Hash[@distributors.map { |d| [d.id, render_to_string(:partial => 'distributors/details', :locals => {:distributor => d})] }] + end + end + end + def show options = {:distributor_id => params[:id]} options.merge(params.reject { |k,v| k == :id }) diff --git a/app/overrides/add_distributor_details_to_product.rb b/app/overrides/add_distributor_details_to_product.rb index 6671ed40b5..4d1b1d344f 100644 --- a/app/overrides/add_distributor_details_to_product.rb +++ b/app/overrides/add_distributor_details_to_product.rb @@ -2,3 +2,8 @@ Deface::Override.new(:virtual_path => "spree/products/show", :insert_before => "[data-hook='cart_form']", :partial => "spree/products/distributor_details", :name => "product_distributor_details") + +Deface::Override.new(:virtual_path => "spree/products/show", + :insert_after => "[data-hook='product_show']", + :text => "<%= javascript_include_tag main_app.distributors_path(:format => :js) %>", + :name => "product_distributor_details_js") diff --git a/app/views/distributors/index.js.erb b/app/views/distributors/index.js.erb new file mode 100644 index 0000000000..aed01164da --- /dev/null +++ b/app/views/distributors/index.js.erb @@ -0,0 +1 @@ +distributors = <%= @distributor_details.to_json.html_safe %>; \ No newline at end of file diff --git a/app/views/spree/products/_distributor_details.html.haml b/app/views/spree/products/_distributor_details.html.haml index 808468f806..e68b6c49ca 100644 --- a/app/views/spree/products/_distributor_details.html.haml +++ b/app/views/spree/products/_distributor_details.html.haml @@ -1,7 +1,8 @@ %fieldset#product-distributor-details.columns.five.omega %legend Distributor - - order = current_order(false) - - if order.andand.distributor.present? - = render 'distributors/details', :distributor => order.distributor - - else - When you select a distributor for your order, their address and pickup times will be displayed here. + .distributor-details + - order = current_order(false) + - if order.andand.distributor.present? + = render 'distributors/details', :distributor => order.distributor + - else + When you select a distributor for your order, their address and pickup times will be displayed here. diff --git a/spec/requests/consumer/product_spec.rb b/spec/requests/consumer/product_spec.rb index 76a647d074..40b65cace8 100644 --- a/spec/requests/consumer/product_spec.rb +++ b/spec/requests/consumer/product_spec.rb @@ -61,10 +61,23 @@ feature %q{ end end - context "with Javascript" do - it "changes distributor details when the distributor is changed" + context "with Javascript", js: true do + it "changes distributor details when the distributor is changed" do + d1 = create(:distributor) + d2 = create(:distributor) + d3 = create(:distributor) + p = create(:product, :distributors => [d1, d2, d3]) + + visit spree.product_path p + + [d1, d2, d3].each do |d| + select d.name, :from => 'distributor_id' + + within '#product-distributor-details' do + page.should have_selector 'h2', :text => d.name + end + end + end end end - - end From 03610c93de31febc1fd35b9f7501738286d2b459 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Sun, 28 Oct 2012 12:28:55 +1100 Subject: [PATCH 13/18] Upgrade capybara and selenium-webdriver for compatibility with Firefox 16 --- Gemfile.lock | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a79ae3a26e..83954e36f3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -129,7 +129,7 @@ GEM i18n (~> 0.6) multi_json (~> 1.0) acts_as_list (0.1.4) - addressable (2.2.8) + addressable (2.3.2) andand (1.3.3) ansi (1.4.2) arel (3.0.2) @@ -152,8 +152,8 @@ GEM rack-test (>= 0.5.4) selenium-webdriver (~> 2.0) xpath (~> 0.1.4) - childprocess (0.3.2) - ffi (~> 1.0.6) + childprocess (0.3.6) + ffi (~> 1.0, >= 1.0.6) cocaine (0.4.2) coderay (1.0.7) coffee-rails (3.2.2) @@ -196,7 +196,7 @@ GEM faker (1.0.1) i18n (~> 0.4) ffaker (1.12.1) - ffi (1.0.11) + ffi (1.1.5) haml (3.1.6) highline (1.6.11) hike (1.2.1) @@ -215,7 +215,7 @@ GEM railties (>= 3.0.0) kgio (2.7.4) libv8 (3.3.10.4) - libwebsocket (0.1.3) + libwebsocket (0.1.5) addressable mail (2.4.4) i18n (>= 0.4.0) @@ -295,15 +295,14 @@ GEM activesupport (>= 3.0) railties (>= 3.0) rspec (~> 2.10.0) - rubyzip (0.9.8) + rubyzip (0.9.9) sass (3.1.19) sass-rails (3.2.5) railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) - selenium-webdriver (2.22.2) + selenium-webdriver (2.25.0) childprocess (>= 0.2.5) - ffi (~> 1.0) libwebsocket (~> 0.1.3) multi_json (~> 1.0) rubyzip From 9b32579bd69d7023befc84b6d71d90d9499981ad Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 31 Oct 2012 10:37:40 +1100 Subject: [PATCH 14/18] Group buy report handles nil variant weight gracefully --- lib/open_food_web/group_buy_report.rb | 4 ++-- spec/lib/open_food_web/group_buy_report_spec.rb | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/open_food_web/group_buy_report.rb b/lib/open_food_web/group_buy_report.rb index f8582f88a1..3234d1078c 100644 --- a/lib/open_food_web/group_buy_report.rb +++ b/lib/open_food_web/group_buy_report.rb @@ -38,8 +38,8 @@ module OpenFoodWeb 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) } + sum_quantities = line_items_by_product.sum { |li| (li.variant.weight || 0) * li.quantity } + sum_max_quantities = line_items_by_product.sum { |li| (li.variant.weight || 0) * (li.max_quantity || 0) } variants_and_quantities << GroupBuyProductRow.new(product, sum_quantities, sum_max_quantities) end end diff --git a/spec/lib/open_food_web/group_buy_report_spec.rb b/spec/lib/open_food_web/group_buy_report_spec.rb index c3ed851d55..0513c235c7 100644 --- a/spec/lib/open_food_web/group_buy_report_spec.rb +++ b/spec/lib/open_food_web/group_buy_report_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module OpenFoodWeb describe GroupBuyReport do - before(:each) do + before(:all) do @orders = [] bill_address = create(:address) distributor_address = create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234") @@ -36,7 +36,7 @@ module OpenFoodWeb @orders << order2 @supplier2 = create(:supplier) - @variant3 = create(:variant) + @variant3 = create(:variant, :weight => nil) @variant3.product.supplier = @supplier2 @variant3.product.save! product_distribution = create(:product_distribution, :product => @variant3.product, :distributor => distributor, :shipping_method => create(:shipping_method)) @@ -82,16 +82,16 @@ module OpenFoodWeb 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 } + 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 } + 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 \ No newline at end of file +end From 926440a978e0cb99402b17c6a8fec3a923fd8a8c Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 31 Oct 2012 11:13:55 +1100 Subject: [PATCH 15/18] Fix namespacing of Distributor in reports controller --- app/controllers/spree/admin/reports_controller_decorator.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/spree/admin/reports_controller_decorator.rb b/app/controllers/spree/admin/reports_controller_decorator.rb index 081be1be5a..04bba767ae 100644 --- a/app/controllers/spree/admin/reports_controller_decorator.rb +++ b/app/controllers/spree/admin/reports_controller_decorator.rb @@ -89,7 +89,7 @@ Spree::Admin::ReportsController.class_eval do orders = @search.result line_items = orders.map { |o| o.line_items }.flatten - @distributors = Spree::Distributor.all + @distributors = Distributor.all @report_type = params[:report_type] case params[:report_type] @@ -216,7 +216,7 @@ Spree::Admin::ReportsController.class_eval do orders = @search.result payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments - @distributors = Spree::Distributor.all + @distributors = Distributor.all @report_type = params[:report_type] case params[:report_type] @@ -321,7 +321,7 @@ Spree::Admin::ReportsController.class_eval do line_items = orders.map { |o| o.line_items }.flatten #payments = orders.map { |o| o.payments.select { |payment| payment.completed? } }.flatten # Only select completed payments - @distributors = Spree::Distributor.all + @distributors = Distributor.all @report_type = params[:report_type] case params[:report_type] From 5dcba7403b006228a68f41477e2d06fa6050b970 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 31 Oct 2012 13:54:14 +1100 Subject: [PATCH 16/18] Avoid contaminating test data --- spec/lib/open_food_web/group_buy_report_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/lib/open_food_web/group_buy_report_spec.rb b/spec/lib/open_food_web/group_buy_report_spec.rb index 0513c235c7..ed21aba6d2 100644 --- a/spec/lib/open_food_web/group_buy_report_spec.rb +++ b/spec/lib/open_food_web/group_buy_report_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' module OpenFoodWeb describe GroupBuyReport do - before(:all) do + before(:each) do @orders = [] bill_address = create(:address) distributor_address = create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234") From f03d9b66f05716dad0569aee3295b68c8ec88ce2 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Wed, 31 Oct 2012 15:17:05 +1100 Subject: [PATCH 17/18] Update spree_paypal_express to fail gracefully when setting address --- Gemfile.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 83954e36f3..21adee8e4d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,7 +23,7 @@ GIT GIT remote: git://github.com/eaterprises/spree_paypal_express.git - revision: ec7fd298f117fe6c598070dc0e7a38887b9bcbc4 + revision: 7dd46e6e549d82c4d603f685a7cb7fbb4af0d973 branch: 1-1-stable specs: spree_paypal_express (1.1.0) @@ -320,13 +320,13 @@ GEM libv8 (~> 3.3.10) thor (0.16.0) tilt (1.3.3) - treetop (1.4.11) + treetop (1.4.12) polyglot polyglot (>= 0.3.1) truncate_html (0.5.5) turn (0.8.3) ansi - tzinfo (0.3.33) + tzinfo (0.3.34) uglifier (1.2.4) execjs (>= 0.3.0) multi_json (>= 1.0.2) From f8c2c8bbedeb8c567a7a3c31896c0d7838e06551 Mon Sep 17 00:00:00 2001 From: Rohan Mitchell Date: Thu, 1 Nov 2012 08:02:11 +1100 Subject: [PATCH 18/18] Convert group buy unit size field from string to float --- ...roup_buy_unit_size_from_string_to_float.rb | 21 +++ db/schema.rb | 160 +++++++++--------- spec/requests/admin/product_spec.rb | 4 +- 3 files changed, 103 insertions(+), 82 deletions(-) create mode 100644 db/migrate/20121031203807_change_group_buy_unit_size_from_string_to_float.rb diff --git a/db/migrate/20121031203807_change_group_buy_unit_size_from_string_to_float.rb b/db/migrate/20121031203807_change_group_buy_unit_size_from_string_to_float.rb new file mode 100644 index 0000000000..44caf3beaa --- /dev/null +++ b/db/migrate/20121031203807_change_group_buy_unit_size_from_string_to_float.rb @@ -0,0 +1,21 @@ +class ChangeGroupBuyUnitSizeFromStringToFloat < ActiveRecord::Migration + class Spree::Product < ActiveRecord::Base; end + + def up + add_column :spree_products, :group_buy_unit_size_f, :float + Spree::Product.reset_column_information + + Spree::Product.all.each do |product| + product.group_buy_unit_size_f = product.group_buy_unit_size.to_f + product.save! + end + + remove_column :spree_products, :group_buy_unit_size + rename_column :spree_products, :group_buy_unit_size_f, :group_buy_unit_size + end + + def down + change_column :spree_products, :group_buy_unit_size, :string + end + +end diff --git a/db/schema.rb b/db/schema.rb index 09dc89c12e..4a0fe39ee3 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20121018002907) do +ActiveRecord::Schema.define(:version => 20121031203807) do create_table "cms_blocks", :force => true do |t| t.integer "page_id", :null => false @@ -140,8 +140,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "abn" t.string "acn" t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "pickup_address_id" t.string "next_collection_at" t.text "long_description" @@ -183,8 +183,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "alternative_phone" t.integer "state_id" t.integer "country_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "company" end @@ -193,12 +193,12 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_adjustments", :force => true do |t| t.integer "source_id" - t.decimal "amount", :precision => 8, :scale => 2 + t.decimal "amount", :precision => 8, :scale => 2, :default => 0.0 t.string "label" t.string "source_type" t.integer "adjustable_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "mandatory" t.boolean "locked" t.integer "originator_id" @@ -230,15 +230,15 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "type" t.integer "calculable_id", :null => false t.string "calculable_type", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_configurations", :force => true do |t| t.string "name" t.string "type", :limit => 50 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "spree_configurations", ["name", "type"], :name => "index_configurations_on_name_and_type" @@ -276,8 +276,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "environment", :default => "development" t.string "server", :default => "test" t.boolean "test_mode", :default => true - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_inventory_units", :force => true do |t| @@ -285,8 +285,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "state" t.integer "variant_id" t.integer "order_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "shipment_id" t.integer "return_authorization_id" end @@ -300,8 +300,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "variant_id" t.integer "quantity", :null => false t.decimal "price", :precision => 8, :scale => 2, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "max_quantity" t.integer "shipping_method_id" end @@ -313,22 +313,22 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "source_id" t.string "source_type" t.text "details" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_mail_methods", :force => true do |t| t.string "environment" t.boolean "active", :default => true - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_option_types", :force => true do |t| t.string "name", :limit => 100 t.string "presentation", :limit => 100 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "position", :default => 0, :null => false end @@ -342,8 +342,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "name" t.string "presentation" t.integer "option_type_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_option_values_variants", :id => false, :force => true do |t| @@ -362,8 +362,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.decimal "adjustment_total", :precision => 8, :scale => 2, :default => 0.0, :null => false t.decimal "credit_total", :precision => 8, :scale => 2, :default => 0.0, :null => false t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.datetime "completed_at" t.integer "bill_address_id" t.integer "ship_address_id" @@ -384,8 +384,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.text "description" t.boolean "active", :default => true t.string "environment", :default => "development" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.datetime "deleted_at" t.string "display_on" end @@ -393,8 +393,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_payments", :force => true do |t| t.decimal "amount", :precision => 8, :scale => 2, :default => 0.0, :null => false t.integer "order_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "source_id" t.string "source_type" t.integer "payment_method_id" @@ -423,8 +423,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "owner_id" t.string "owner_type" t.text "value" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "key" t.string "value_type" end @@ -449,16 +449,16 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "position" t.integer "product_id" t.integer "option_type_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_product_properties", :force => true do |t| t.string "value" t.integer "product_id" t.integer "property_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "spree_product_properties", ["product_id"], :name => "index_product_properties_on_product_id" @@ -482,12 +482,12 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "meta_keywords" t.integer "tax_category_id" t.integer "shipping_category_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "count_on_hand", :default => 0, :null => false t.integer "supplier_id" t.boolean "group_buy" - t.string "group_buy_unit_size" + t.float "group_buy_unit_size" end add_index "spree_products", ["available_on"], :name => "index_products_on_available_on" @@ -528,8 +528,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "user_id" t.integer "product_group_id" t.string "type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "spree_promotion_rules", ["product_group_id"], :name => "index_promotion_rules_on_product_group_id" @@ -546,8 +546,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_properties", :force => true do |t| t.string "name" t.string "presentation", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_properties_prototypes", :id => false, :force => true do |t| @@ -557,8 +557,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_prototypes", :force => true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_return_authorizations", :force => true do |t| @@ -567,8 +567,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.decimal "amount", :precision => 8, :scale => 2, :default => 0.0, :null => false t.integer "order_id" t.text "reason" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_roles", :force => true do |t| @@ -591,8 +591,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "order_id" t.integer "shipping_method_id" t.integer "address_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "state" end @@ -600,15 +600,15 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_shipping_categories", :force => true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_shipping_methods", :force => true do |t| t.string "name" t.integer "zone_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "display_on" t.integer "shipping_category_id" t.boolean "match_none" @@ -624,8 +624,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "transaction_id" t.integer "customer_id" t.string "payment_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_state_changes", :force => true do |t| @@ -633,8 +633,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "previous_state" t.integer "stateful_id" t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "stateful_type" t.string "next_state" end @@ -648,8 +648,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do create_table "spree_tax_categories", :force => true do |t| t.string "name" t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "is_default", :default => false t.datetime "deleted_at" end @@ -658,15 +658,15 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.decimal "amount", :precision => 8, :scale => 5 t.integer "zone_id" t.integer "tax_category_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "included_in_price", :default => false end create_table "spree_taxonomies", :force => true do |t| t.string "name", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_taxons", :force => true do |t| @@ -675,8 +675,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "name", :null => false t.string "permalink" t.integer "taxonomy_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "lft" t.integer "rgt" t.string "icon_file_name" @@ -694,8 +694,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "permissable_id" t.string "permissable_type" t.string "token" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end add_index "spree_tokenized_permissions", ["permissable_id", "permissable_type"], :name => "index_tokenized_name_and_type" @@ -704,8 +704,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "environment" t.string "analytics_id" t.boolean "active", :default => true - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_users", :force => true do |t| @@ -726,8 +726,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "login" t.integer "ship_address_id" t.integer "bill_address_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "authentication_token" t.string "unlock_token" t.datetime "locked_at" @@ -750,7 +750,7 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.boolean "is_master", :default => false t.integer "product_id" t.integer "count_on_hand", :default => 0, :null => false - t.decimal "cost_price", :precision => 8, :scale => 2 + t.decimal "cost_price", :precision => 8, :scale => 2, :default => 0.0 t.integer "position" end @@ -760,15 +760,15 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.integer "zoneable_id" t.string "zoneable_type" t.integer "zone_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end create_table "spree_zones", :force => true do |t| t.string "name" t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "default_tax", :default => false t.integer "zone_members_count", :default => 0 end @@ -779,8 +779,8 @@ ActiveRecord::Schema.define(:version => 20121018002907) do t.string "email" t.string "twitter" t.string "website" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "address_id" t.text "long_description" end diff --git a/spec/requests/admin/product_spec.rb b/spec/requests/admin/product_spec.rb index 37d9935dd2..bb707ef681 100644 --- a/spec/requests/admin/product_spec.rb +++ b/spec/requests/admin/product_spec.rb @@ -49,14 +49,14 @@ feature %q{ fill_in 'product_price', :with => '19.99' select 'New supplier', :from => 'product_supplier_id' choose 'product_group_buy_1' - fill_in 'Group buy unit size', :with => '10 kg' + fill_in 'Group buy unit size', :with => '10' click_button 'Create' flash_message.should == 'Product "A new product !!!" has been successfully created!' product = Spree::Product.find_by_name('A new product !!!') product.group_buy.should be_true - product.group_buy_unit_size.should == '10 kg' + product.group_buy_unit_size.should == 10.0 end end