spree_advanced_reporting 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|