spree_advanced_reporting 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +5 -0
- data/README.md +23 -0
- data/Rakefile +20 -0
- data/TODO.txt +3 -0
- data/app/assets/images/admin/advanced_reporting/asc.gif +0 -0
- data/app/assets/images/admin/advanced_reporting/barchart.png +0 -0
- data/app/assets/images/admin/advanced_reporting/bg.gif +0 -0
- data/app/assets/images/admin/advanced_reporting/close.png +0 -0
- data/app/assets/images/admin/advanced_reporting/desc.gif +0 -0
- data/app/assets/images/admin/advanced_reporting/menu-current-opposite.png +0 -0
- data/app/assets/images/admin/advanced_reporting/open.png +0 -0
- data/app/assets/images/admin/advanced_reporting/save.png +0 -0
- data/app/assets/images/admin/advanced_reporting/search.png +0 -0
- data/app/assets/images/admin/advanced_reporting/usa.png +0 -0
- data/app/assets/images/admin/advanced_reporting/world.png +0 -0
- data/app/assets/javascripts/admin/advanced_reporting/advanced_reporting.js +46 -0
- data/app/assets/javascripts/admin/advanced_reporting/jquery.tablesorter.min.js +4 -0
- data/app/assets/stylesheets/admin/advanced_reporting/advanced_reporting.css.erb +18 -0
- data/app/assets/stylesheets/pdf.css +15 -0
- data/app/controllers/spree/admin/advanced_report_overview_controller.rb +21 -0
- data/app/controllers/spree/admin/reports_controller_decorator.rb +127 -0
- data/app/helpers/advanced_report_helper.rb +13 -0
- data/app/models/ruport/formatter/html_decorator.rb +29 -0
- data/app/models/ruport/formatter/wicked_pdf_decorator.rb +12 -0
- data/app/views/spree/admin/advanced_report_overview/index.html.erb +117 -0
- data/app/views/spree/admin/reports/_advanced_report_criteria.html.erb +64 -0
- data/app/views/spree/admin/reports/geo_base.html.erb +61 -0
- data/app/views/spree/admin/reports/increment_base.html.erb +63 -0
- data/app/views/spree/admin/reports/outstanding.html.erb +16 -0
- data/app/views/spree/admin/reports/top_base.html.erb +17 -0
- data/config/locales/en.yml +96 -0
- data/config/locales/pt-BR.yml +92 -0
- data/config/routes.rb +37 -0
- data/lib/spree/advanced_report.rb +225 -0
- data/lib/spree/advanced_report/geo_report.rb +2 -0
- data/lib/spree/advanced_report/geo_report/geo_profit.rb +44 -0
- data/lib/spree/advanced_report/geo_report/geo_revenue.rb +44 -0
- data/lib/spree/advanced_report/geo_report/geo_units.rb +42 -0
- data/lib/spree/advanced_report/increment_report.rb +78 -0
- data/lib/spree/advanced_report/increment_report/count.rb +33 -0
- data/lib/spree/advanced_report/increment_report/profit.rb +41 -0
- data/lib/spree/advanced_report/increment_report/revenue.rb +40 -0
- data/lib/spree/advanced_report/increment_report/units.rb +33 -0
- data/lib/spree/advanced_report/top_report.rb +2 -0
- data/lib/spree/advanced_report/top_report/top_customers.rb +32 -0
- data/lib/spree/advanced_report/top_report/top_products.rb +35 -0
- data/lib/spree/advanced_report/transaction_report.rb +79 -0
- data/lib/spree_advanced_reporting.rb +25 -0
- data/spree_advanced_reporting.gemspec +22 -0
- metadata +133 -0
@@ -0,0 +1,225 @@
|
|
1
|
+
module Spree
|
2
|
+
class AdvancedReport
|
3
|
+
include Ruport
|
4
|
+
attr_accessor :orders, :product_text, :date_text, :taxon_text, :ruportdata, :search,
|
5
|
+
:data, :params, :taxon, :product, :product_in_taxon, :unfiltered_params
|
6
|
+
|
7
|
+
def name
|
8
|
+
I18n.t("adv_report.base.name")
|
9
|
+
end
|
10
|
+
|
11
|
+
def description
|
12
|
+
I18n.t("adv_report.base.description")
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize(params)
|
16
|
+
# this enables subclasses to provide different defaults to the search
|
17
|
+
# by setting the defaults before calling super
|
18
|
+
self.params ||= params
|
19
|
+
|
20
|
+
self.data = {}
|
21
|
+
self.ruportdata = {}
|
22
|
+
self.unfiltered_params = params[:search].blank? ? {} : params[:search].clone
|
23
|
+
|
24
|
+
params[:search] ||= {}
|
25
|
+
params[:advanced_reporting] ||= {}
|
26
|
+
|
27
|
+
if Order.count > 0
|
28
|
+
begin
|
29
|
+
params[:search][:created_at_gt] = Time.zone.parse(params[:search][:created_at_gt]).beginning_of_day
|
30
|
+
rescue
|
31
|
+
params[:search][:created_at_gt] = Date.today.beginning_of_day
|
32
|
+
end
|
33
|
+
|
34
|
+
# TODO if lt is defined, and gt is not, gt then should use better default than end of today
|
35
|
+
# maybe 24 hours before the defined lt end of day
|
36
|
+
|
37
|
+
begin
|
38
|
+
params[:search][:created_at_lt] = Time.zone.parse(params[:search][:created_at_lt]).end_of_day
|
39
|
+
rescue
|
40
|
+
params[:search][:created_at_lt] = Date.today.end_of_day
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# offer shipped vs completed order filtering
|
45
|
+
# in some cases, revenue reports should be based on the time when the revenue
|
46
|
+
# is earned (i.e. shipped) not when the order was made or the credit card was processed
|
47
|
+
|
48
|
+
# it is also important to exclude canceled orders and orders that were not completed
|
49
|
+
# before spree 1.1.3 there was a bug that caused Spree::Shipment.shipped_at not be filled
|
50
|
+
# easy fix is to copy the completed_at from the order associated with the shipment
|
51
|
+
# https://gist.github.com/3187793#file_shipments_shipped_at_fix.rb
|
52
|
+
|
53
|
+
filter_address = 'billing'
|
54
|
+
|
55
|
+
if params[:advanced_reporting][:state_based_on_taxable_address] == '1'
|
56
|
+
filter_address = Spree::Config[:tax_using_ship_address] ? 'shipping' : 'billing'
|
57
|
+
end
|
58
|
+
|
59
|
+
if params[:advanced_reporting][:order_type] == 'shipped'
|
60
|
+
shipped_search_params = {
|
61
|
+
:shipped_at_gt => params[:search][:created_at_gt],
|
62
|
+
:shipped_at_lt => params[:search][:created_at_lt],
|
63
|
+
:order_state_not_eq => 'canceled',
|
64
|
+
:order_completed_at_not_null => true
|
65
|
+
}
|
66
|
+
|
67
|
+
if params[:advanced_reporting][:state_id].present?
|
68
|
+
shipped_search_params[
|
69
|
+
filter_address == 'shipping' ? :order_ship_address_state_id_eq : :order_bill_address_state_id_eq
|
70
|
+
] = params[:advanced_reporting][:state_id]
|
71
|
+
end
|
72
|
+
|
73
|
+
# including the ransack predicate will not speed up the SQL query but will not include only fully shipped orders
|
74
|
+
only_fully_shipped = params[:advanced_reporting][:shipment] == 'fully_shipped'
|
75
|
+
shipped_search_params[:order_inventory_units_shipment_id_not_null] = true if only_fully_shipped
|
76
|
+
|
77
|
+
# the tricky part here is that orders can have multiple shipments
|
78
|
+
# we need to prevent orders from being included twice in the report
|
79
|
+
# by choosing to include the order in the earliest report possible
|
80
|
+
# (i.e. the first order that shipped) and exclude it from any reports after that
|
81
|
+
|
82
|
+
@search = Shipment.includes(:order).search shipped_search_params
|
83
|
+
|
84
|
+
self.orders = @search.result(:distinct => true).select do |shipment|
|
85
|
+
# these manual exclusions could not be done via SQL queries as far as I could tell
|
86
|
+
# they are ordered by least to greatest SQL complexity
|
87
|
+
|
88
|
+
next true if shipment.order.shipments.size == 1
|
89
|
+
|
90
|
+
# if the shipment retrieved is the last shipment shipped for the order, then include the order
|
91
|
+
next false if shipment.order.shipments.sort { |a, b| b.shipped_at <=> a.shipped_at }.first == shipment
|
92
|
+
|
93
|
+
# conditionally exclude orders which are not fully shipped
|
94
|
+
next false if only_fully_shipped && shipment.order.inventory_units.detect { |i| i.shipment.blank? }.blank?
|
95
|
+
|
96
|
+
true
|
97
|
+
end.map(&:order)
|
98
|
+
else
|
99
|
+
params[:search][:completed_at_not_null] = true
|
100
|
+
params[:search][:state_not_eq] = 'canceled'
|
101
|
+
|
102
|
+
if params[:advanced_reporting][:state_id].present?
|
103
|
+
params[:search][
|
104
|
+
filter_address == 'shipping' ? :ship_address_state_id_eq : :bill_address_state_id_eq
|
105
|
+
] = params[:advanced_reporting][:state_id]
|
106
|
+
end
|
107
|
+
|
108
|
+
only_fully_shipped = params[:advanced_reporting][:shipment] == 'fully_shipped'
|
109
|
+
params[:inventory_units_shipment_id_not_null] = true if only_fully_shipped
|
110
|
+
|
111
|
+
@search = Order.search(params[:search])
|
112
|
+
|
113
|
+
self.orders = @search.result(:distinct => true).select do |order|
|
114
|
+
next false if only_fully_shipped && order.inventory_units.detect { |i| i.shipment.blank? }.blank?
|
115
|
+
|
116
|
+
true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
self.product_in_taxon = true
|
121
|
+
if params[:advanced_reporting]
|
122
|
+
if params[:advanced_reporting][:taxon_id] && params[:advanced_reporting][:taxon_id] != ''
|
123
|
+
self.taxon = Taxon.find(params[:advanced_reporting][:taxon_id])
|
124
|
+
end
|
125
|
+
if params[:advanced_reporting][:product_id] && params[:advanced_reporting][:product_id] != ''
|
126
|
+
self.product = Product.find(params[:advanced_reporting][:product_id])
|
127
|
+
end
|
128
|
+
end
|
129
|
+
if self.taxon && self.product && !self.product.taxons.include?(self.taxon)
|
130
|
+
self.product_in_taxon = false
|
131
|
+
end
|
132
|
+
|
133
|
+
if self.product
|
134
|
+
self.product_text = "Product: #{self.product.name}<br />"
|
135
|
+
end
|
136
|
+
if self.taxon
|
137
|
+
self.taxon_text = "Taxon: #{self.taxon.name}<br />"
|
138
|
+
end
|
139
|
+
|
140
|
+
# Above searchlogic date settings
|
141
|
+
self.date_text = "#{I18n.t("adv_report.base.range")}:"
|
142
|
+
if self.unfiltered_params
|
143
|
+
if self.unfiltered_params[:created_at_gt] != '' && self.unfiltered_params[:created_at_lt] != ''
|
144
|
+
self.date_text += " From #{self.unfiltered_params[:created_at_gt]} to #{self.unfiltered_params[:created_at_lt]}"
|
145
|
+
elsif self.unfiltered_params[:created_at_gt] != ''
|
146
|
+
self.date_text += " After #{self.unfiltered_params[:created_at_gt]}"
|
147
|
+
elsif self.unfiltered_params[:created_at_lt] != ''
|
148
|
+
self.date_text += " Before #{self.unfiltered_params[:created_at_lt]}"
|
149
|
+
|
150
|
+
# TODO this was pulled in from another branch and has some nice internationalization improvements
|
151
|
+
# if self.unfiltered_params[:created_at_greater_than] != '' && self.unfiltered_params[:created_at_less_than] != ''
|
152
|
+
# self.date_text += " #{I18n.t("adv_report.base.from")} #{self.unfiltered_params[:created_at_greater_than]} to #{self.unfiltered_params[:created_at_less_than]}"
|
153
|
+
# elsif self.unfiltered_params[:created_at_greater_than] != ''
|
154
|
+
# self.date_text += " #{I18n.t("adv_report.base.after")} #{self.unfiltered_params[:created_at_greater_than]}"
|
155
|
+
# elsif self.unfiltered_params[:created_at_less_than] != ''
|
156
|
+
# self.date_text += " #{I18n.t("adv_report.base.before")} #{self.unfiltered_params[:created_at_less_than]}"
|
157
|
+
else
|
158
|
+
self.date_text += " #{I18n.t("adv_report.base.all")}"
|
159
|
+
end
|
160
|
+
else
|
161
|
+
self.date_text += " #{I18n.t("adv_report.base.all")}"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def download_url(base, format, report_type = nil)
|
166
|
+
elements = []
|
167
|
+
params[:advanced_reporting] ||= {}
|
168
|
+
params[:advanced_reporting]["report_type"] = report_type if report_type
|
169
|
+
if params
|
170
|
+
[:search, :advanced_reporting].each do |type|
|
171
|
+
if params[type]
|
172
|
+
params[type].each { |k, v| elements << "#{type}[#{k}]=#{v}" }
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
base.gsub!(/^\/\//,'/')
|
177
|
+
base + '.' + format + '?' + elements.join('&')
|
178
|
+
end
|
179
|
+
|
180
|
+
def revenue(order)
|
181
|
+
rev = order.item_total
|
182
|
+
if !self.product.nil? && product_in_taxon
|
183
|
+
rev = order.line_items.select { |li| li.product == self.product }.inject(0) { |a, b| a += b.quantity * b.price }
|
184
|
+
elsif !self.taxon.nil?
|
185
|
+
rev = order.line_items.select { |li| li.product && li.product.taxons.include?(self.taxon) }.inject(0) { |a, b| a += b.quantity * b.price }
|
186
|
+
end
|
187
|
+
adjustment_revenue = order.adjustments.sum(:amount)
|
188
|
+
rev += adjustment_revenue if rev > 0
|
189
|
+
self.product_in_taxon ? rev : 0
|
190
|
+
end
|
191
|
+
|
192
|
+
def profit(order)
|
193
|
+
profit = order.line_items.inject(0) { |profit, li| profit + (li.variant.price - li.variant.cost_price.to_f)*li.quantity }
|
194
|
+
if !self.product.nil? && product_in_taxon
|
195
|
+
profit = order.line_items.select { |li| li.product == self.product }.inject(0) { |profit, li| profit + (li.variant.price - li.variant.cost_price.to_f)*li.quantity }
|
196
|
+
elsif !self.taxon.nil?
|
197
|
+
profit = order.line_items.select { |li| li.product && li.product.taxons.include?(self.taxon) }.inject(0) { |profit, li| profit + (li.variant.price - li.variant.cost_price.to_f)*li.quantity }
|
198
|
+
end
|
199
|
+
profit += order.adjustments.sum(:amount)
|
200
|
+
self.product_in_taxon ? profit : 0
|
201
|
+
end
|
202
|
+
|
203
|
+
def units(order)
|
204
|
+
units = order.line_items.sum(:quantity)
|
205
|
+
if !self.product.nil? && product_in_taxon
|
206
|
+
units = order.line_items.select { |li| li.product == self.product }.inject(0) { |a, b| a += b.quantity }
|
207
|
+
elsif !self.taxon.nil?
|
208
|
+
units = order.line_items.select { |li| li.product && li.product.taxons.include?(self.taxon) }.inject(0) { |a, b| a += b.quantity }
|
209
|
+
end
|
210
|
+
self.product_in_taxon ? units : 0
|
211
|
+
end
|
212
|
+
|
213
|
+
def order_count(order)
|
214
|
+
self.product_in_taxon ? 1 : 0
|
215
|
+
end
|
216
|
+
|
217
|
+
def date_range
|
218
|
+
if self.params[:search][:created_at_gt].to_date == self.params[:search][:created_at_lt].to_date
|
219
|
+
self.params[:search][:created_at_gt].to_date.to_s
|
220
|
+
else
|
221
|
+
"#{self.params[:search][:created_at_gt].to_date} – #{self.params[:search][:created_at_lt].to_date}"
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Spree::AdvancedReport::GeoReport::GeoProfit < Spree::AdvancedReport::GeoReport
|
2
|
+
def name
|
3
|
+
I18n.t("adv_report.geo_report.profit.name")
|
4
|
+
end
|
5
|
+
|
6
|
+
def column
|
7
|
+
I18n.t("adv_report.geo_report.profit.column")
|
8
|
+
end
|
9
|
+
|
10
|
+
def description
|
11
|
+
I18n.t("adv_report.geo_report.profit.description")
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(params)
|
15
|
+
super(params)
|
16
|
+
|
17
|
+
data = { :state => {}, :country => {} }
|
18
|
+
orders.each do |order|
|
19
|
+
profit = profit(order)
|
20
|
+
if order.bill_address.state
|
21
|
+
data[:state][order.bill_address.state_id] ||= {
|
22
|
+
:name => order.bill_address.state.name,
|
23
|
+
:profit => 0
|
24
|
+
}
|
25
|
+
data[:state][order.bill_address.state_id][:profit] += profit
|
26
|
+
end
|
27
|
+
if order.bill_address.country
|
28
|
+
data[:country][order.bill_address.country_id] ||= {
|
29
|
+
:name => order.bill_address.country.name,
|
30
|
+
:profit => 0
|
31
|
+
}
|
32
|
+
data[:country][order.bill_address.country_id][:profit] += profit
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
[:state, :country].each do |type|
|
37
|
+
ruportdata[type] = Table(I18n.t("adv_report.geo_report.profit.table"))
|
38
|
+
data[type].each { |k, v| ruportdata[type] << { "location" => v[:name], I18n.t("adv_report.profit") => v[:profit] } }
|
39
|
+
ruportdata[type].sort_rows_by!([I18n.t("adv_report.profit")], :order => :descending)
|
40
|
+
ruportdata[type].rename_column("location", type.to_s.capitalize)
|
41
|
+
ruportdata[type].replace_column(I18n.t("adv_report.profit")) { |r| "$%0.2f" % r.send(I18n.t("adv_report.profit")) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Spree::AdvancedReport::GeoReport::GeoRevenue < Spree::AdvancedReport::GeoReport
|
2
|
+
def name
|
3
|
+
I18n.t("adv_report.geo_report.revenue.name")
|
4
|
+
end
|
5
|
+
|
6
|
+
def column
|
7
|
+
I18n.t("adv_report.geo_report.revenue.column")
|
8
|
+
end
|
9
|
+
|
10
|
+
def description
|
11
|
+
I18n.t("adv_report.geo_report.revenue.description")
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(params)
|
15
|
+
super(params)
|
16
|
+
|
17
|
+
data = { :state => {}, :country => {} }
|
18
|
+
orders.each do |order|
|
19
|
+
revenue = revenue(order)
|
20
|
+
if order.bill_address.state
|
21
|
+
data[:state][order.bill_address.state_id] ||= {
|
22
|
+
:name => order.bill_address.state.name,
|
23
|
+
:revenue => 0
|
24
|
+
}
|
25
|
+
data[:state][order.bill_address.state_id][:revenue] += revenue
|
26
|
+
end
|
27
|
+
if order.bill_address.country
|
28
|
+
data[:country][order.bill_address.country_id] ||= {
|
29
|
+
:name => order.bill_address.country.name,
|
30
|
+
:revenue => 0
|
31
|
+
}
|
32
|
+
data[:country][order.bill_address.country_id][:revenue] += revenue
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
[:state, :country].each do |type|
|
37
|
+
ruportdata[type] = Table(I18n.t("adv_report.geo_report.revenue.table"))
|
38
|
+
data[type].each { |k, v| ruportdata[type] << { "location" => v[:name], I18n.t("adv_report.revenue") => v[:revenue] } }
|
39
|
+
ruportdata[type].sort_rows_by!([I18n.t("adv_report.revenue")], :order => :descending)
|
40
|
+
ruportdata[type].rename_column("location", type.to_s.capitalize)
|
41
|
+
ruportdata[type].replace_column(I18n.t("adv_report.revenue")) { |r| "$%0.2f" % r.send(I18n.t("adv_report.revenue")) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Spree::AdvancedReport::GeoReport::GeoUnits < Spree::AdvancedReport::GeoReport
|
2
|
+
def name
|
3
|
+
I18n.t("adv_report.geo_report.units.name")
|
4
|
+
end
|
5
|
+
|
6
|
+
def column
|
7
|
+
I18n.t("adv_report.geo_report.units.column")
|
8
|
+
end
|
9
|
+
|
10
|
+
def description
|
11
|
+
I18n.t("adv_report.geo_report.units.description")
|
12
|
+
end
|
13
|
+
def initialize(params)
|
14
|
+
super(params)
|
15
|
+
|
16
|
+
data = { :state => {}, :country => {} }
|
17
|
+
orders.each do |order|
|
18
|
+
units = units(order)
|
19
|
+
if order.bill_address.state
|
20
|
+
data[:state][order.bill_address.state_id] ||= {
|
21
|
+
:name => order.bill_address.state.name,
|
22
|
+
:units => 0
|
23
|
+
}
|
24
|
+
data[:state][order.bill_address.state_id][:units] += units
|
25
|
+
end
|
26
|
+
if order.bill_address.country
|
27
|
+
data[:country][order.bill_address.country_id] ||= {
|
28
|
+
:name => order.bill_address.country.name,
|
29
|
+
:units => 0
|
30
|
+
}
|
31
|
+
data[:country][order.bill_address.country_id][:units] += units
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
[:state, :country].each do |type|
|
36
|
+
ruportdata[type] = Table(I18n.t("adv_report.geo_report.units.table"))
|
37
|
+
data[type].each { |k, v| ruportdata[type] << { "location" => v[:name], I18n.t("adv_report.units") => v[:units] } }
|
38
|
+
ruportdata[type].sort_rows_by!([I18n.t("adv_report.units")], :order => :descending)
|
39
|
+
ruportdata[type].rename_column("location", type.to_s.capitalize)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class Spree::AdvancedReport::IncrementReport < Spree::AdvancedReport
|
2
|
+
INCREMENTS = I18n.t("adv_report.increments").map(&:to_sym)
|
3
|
+
attr_accessor :increments, :dates, :total, :all_data
|
4
|
+
|
5
|
+
def initialize(params)
|
6
|
+
super(params)
|
7
|
+
|
8
|
+
self.increments = INCREMENTS
|
9
|
+
self.ruportdata = INCREMENTS.inject({}) { |h, inc| h[inc] = Table(%w[key display value]); h }
|
10
|
+
self.data = INCREMENTS.inject({}) { |h, inc| h[inc] = {}; h }
|
11
|
+
|
12
|
+
self.dates = {
|
13
|
+
I18n.t("adv_report.daily").downcase.to_sym => {
|
14
|
+
:date_bucket => "%F",
|
15
|
+
:date_display => "%m-%d-%Y",
|
16
|
+
:header_display => I18n.t("adv_report.daily"),
|
17
|
+
},
|
18
|
+
I18n.t("adv_report.weekly").downcase.to_sym => {
|
19
|
+
:header_display => I18n.t("adv_report.weekly")
|
20
|
+
},
|
21
|
+
I18n.t("adv_report.monthly").downcase.to_sym => {
|
22
|
+
:date_bucket => "%Y-%m",
|
23
|
+
:date_display => "%B %Y",
|
24
|
+
:header_display => I18n.t("adv_report.monthly"),
|
25
|
+
},
|
26
|
+
I18n.t("adv_report.quarterly").downcase.to_sym => {
|
27
|
+
:header_display => I18n.t("adv_report.quarterly")
|
28
|
+
},
|
29
|
+
I18n.t("adv_report.yearly").downcase.to_sym => {
|
30
|
+
:date_bucket => "%Y",
|
31
|
+
:date_display => "%Y",
|
32
|
+
:header_display => I18n.t("adv_report.yearly"),
|
33
|
+
}
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def generate_ruport_data
|
38
|
+
self.all_data = Table(%w[increment key display value])
|
39
|
+
INCREMENTS.each do |inc|
|
40
|
+
data[inc].each { |k,v| ruportdata[inc] << { "key" => k, "display" => v[:display], "value" => v[:value] } }
|
41
|
+
ruportdata[inc].data.each do |p|
|
42
|
+
self.all_data << { "increment" => inc.to_s.capitalize, "key" => p.data["key"], "display" => p.data["display"], "value" => p.data["value"] }
|
43
|
+
end
|
44
|
+
Rails.logger.info "THE DATES #{self.dates} : #{inc}"
|
45
|
+
ruportdata[inc].sort_rows_by!(["key"])
|
46
|
+
ruportdata[inc].remove_column("key")
|
47
|
+
ruportdata[inc].rename_column("display", dates[inc][:header_display])
|
48
|
+
ruportdata[inc].rename_column("value", self.name)
|
49
|
+
end
|
50
|
+
self.all_data.sort_rows_by!(["key"])
|
51
|
+
self.all_data.remove_column("key")
|
52
|
+
self.all_data = Grouping(self.all_data, :by => "increment")
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_bucket(type, completed_at)
|
56
|
+
if type == I18n.t("adv_report.weekly").downcase.to_sym
|
57
|
+
return completed_at.beginning_of_week.strftime("%Y-%m-%d")
|
58
|
+
elsif type == I18n.t("adv_report.quarterly").downcase.to_sym
|
59
|
+
return completed_at.beginning_of_quarter.strftime("%Y-%m")
|
60
|
+
end
|
61
|
+
completed_at.strftime(dates[type][:date_bucket])
|
62
|
+
end
|
63
|
+
|
64
|
+
def get_display(type, completed_at)
|
65
|
+
if type == I18n.t("adv_report.weekly").downcase.to_sym
|
66
|
+
#funny business
|
67
|
+
#next_week = completed_at + 7
|
68
|
+
return completed_at.beginning_of_week.strftime("%m-%d-%Y") # + ' - ' + next_week.beginning_of_week.strftime("%m-%d-%Y")
|
69
|
+
elsif type == I18n.t("adv_report.quarterly").downcase.to_sym
|
70
|
+
return completed_at.strftime("%Y") + ' Q' + (completed_at.beginning_of_quarter.strftime("%m").to_i/3 + 1).to_s
|
71
|
+
end
|
72
|
+
completed_at.strftime(dates[type][:date_display])
|
73
|
+
end
|
74
|
+
|
75
|
+
def format_total
|
76
|
+
self.total
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
class Spree::AdvancedReport::IncrementReport::Count < Spree::AdvancedReport::IncrementReport
|
2
|
+
def name
|
3
|
+
I18n.t("adv_report.increment_report.count.name")
|
4
|
+
end
|
5
|
+
|
6
|
+
def column
|
7
|
+
I18n.t("adv_report.increment_report.count.column")
|
8
|
+
end
|
9
|
+
|
10
|
+
def description
|
11
|
+
I18n.t("adv_report.increment_report.count.description")
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(params)
|
15
|
+
super(params)
|
16
|
+
self.total = 0
|
17
|
+
self.orders.each do |order|
|
18
|
+
date = {}
|
19
|
+
INCREMENTS.each do |type|
|
20
|
+
date[type] = get_bucket(type, order.completed_at)
|
21
|
+
data[type][date[type]] ||= {
|
22
|
+
:value => 0,
|
23
|
+
:display => get_display(type, order.completed_at),
|
24
|
+
}
|
25
|
+
end
|
26
|
+
order_count = order_count(order)
|
27
|
+
INCREMENTS.each { |type| data[type][date[type]][:value] += order_count }
|
28
|
+
self.total += order_count
|
29
|
+
end
|
30
|
+
|
31
|
+
generate_ruport_data
|
32
|
+
end
|
33
|
+
end
|