spree_reports 0.1.3 → 0.2.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.
- checksums.yaml +4 -4
- data/app/controllers/spree/admin/reports_controller_decorator.rb +11 -0
- data/app/controllers/spree/api/spree_reports_controller.rb +5 -0
- data/app/views/spree/admin/reports/sold_products.html.erb +84 -0
- data/config/locales/en.yml +2 -0
- data/lib/spree_reports/reports/base.rb +6 -0
- data/lib/spree_reports/reports/orders_by_period.rb +2 -7
- data/lib/spree_reports/reports/sold_products.rb +86 -0
- data/lib/spree_reports/version.rb +1 -1
- data/lib/spree_reports.rb +2 -4
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6500106e38d28eb5485eb9b6c178925ce9dc38ef
|
4
|
+
data.tar.gz: e67b9c9a9f0a956c69d282a214463a7d6abfb2c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9db51ba8cf0813443f00119188dc75b3fc0f9aa7ccc7f9c4d9efa01ebba795f869c2acc0f8b55baadba496c2bd349fece14c1f134d6719b21deaca5e2f179763
|
7
|
+
data.tar.gz: cd4285331e0964650058ffbe8e92fba5156ff8bf55c7e0ff4bc7e1ac5196142b3e8e2769757e1cd586e3380af59927271f784368518b46938e698e3cb5ca946f
|
@@ -11,6 +11,17 @@ Spree::Admin::ReportsController.class_eval do
|
|
11
11
|
}
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
def sold_products
|
16
|
+
@report = SpreeReports::Reports::SoldProducts.new(params)
|
17
|
+
respond_to do |format|
|
18
|
+
format.html
|
19
|
+
format.csv {
|
20
|
+
return head :unauthorized unless SpreeReports.csv_export
|
21
|
+
send_data @report.to_csv, filename: @report.csv_filename, type: "text/csv"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
14
25
|
|
15
26
|
protected
|
16
27
|
|
@@ -8,6 +8,11 @@ module Spree
|
|
8
8
|
render json: @report.data
|
9
9
|
end
|
10
10
|
|
11
|
+
def sold_products
|
12
|
+
@report = SpreeReports::Reports::SoldProducts.new(params)
|
13
|
+
render json: @report.data
|
14
|
+
end
|
15
|
+
|
11
16
|
private
|
12
17
|
def requires_admin
|
13
18
|
return if @current_user_roles.include?(SpreeReports.api_user_role)
|
@@ -0,0 +1,84 @@
|
|
1
|
+
<%= stylesheet_link_tag 'spree_reports/spree_reports', media: 'all' %>
|
2
|
+
<%= javascript_include_tag "//www.google.com/jsapi", "chartkick" %>
|
3
|
+
<%= %>
|
4
|
+
|
5
|
+
<div class="spree_reports report">
|
6
|
+
|
7
|
+
<h1>Sold Products</h1>
|
8
|
+
|
9
|
+
<div class="options">
|
10
|
+
|
11
|
+
<%= form_tag "", method: :get, class: "options" do %>
|
12
|
+
|
13
|
+
<span class="option">
|
14
|
+
<span title="<%= @report.date_start ? "date_start: #{l(@report.date_start.to_date)}" : "" %>">months:</span>
|
15
|
+
<%= select_tag "months", options_for_select(SpreeReports.report_months, selected: @report.months) %>
|
16
|
+
</span>
|
17
|
+
|
18
|
+
<% if @report.currencies.size > 1 %>
|
19
|
+
<span class="option">
|
20
|
+
currency:
|
21
|
+
<%= select_tag "currency", options_for_select(@report.currencies, selected: @report.currency) %>
|
22
|
+
</span>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<% if @report.stores.size > 2 %>
|
26
|
+
<span class="option">
|
27
|
+
store:
|
28
|
+
<%= select_tag "store", options_for_select(@report.stores, selected: @report.store) %>
|
29
|
+
</span>
|
30
|
+
<% end %>
|
31
|
+
|
32
|
+
<%= submit_tag 'reload' %>
|
33
|
+
|
34
|
+
<% end %>
|
35
|
+
|
36
|
+
</div>
|
37
|
+
|
38
|
+
<div class="table">
|
39
|
+
|
40
|
+
<table class="data" border="1">
|
41
|
+
<tr>
|
42
|
+
<th>Variant ID</th>
|
43
|
+
<th>Product Variant Name</th>
|
44
|
+
<th>Quantity</th>
|
45
|
+
</tr>
|
46
|
+
|
47
|
+
<% @report.data.each do |item| %>
|
48
|
+
<tr>
|
49
|
+
<td><%= item[:variant_id] %></td>
|
50
|
+
<td>
|
51
|
+
<%= link_to item[:variant_name], product_path(item[:variant_slug]) %>
|
52
|
+
<%= link_to "edit", admin_product_path(item[:variant_slug]) %>
|
53
|
+
</td>
|
54
|
+
<td><%= number_with_delimiter(item[:quantity]) %></td>
|
55
|
+
</tr>
|
56
|
+
<% end %>
|
57
|
+
|
58
|
+
</table>
|
59
|
+
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div class="charts">
|
63
|
+
|
64
|
+
<h2>Top 20 Products</h2>
|
65
|
+
<div class="chart">
|
66
|
+
<%= column_chart Hash[@report.data.first(20).collect { |i| [i[:variant_name], i[:quantity]] }] %>
|
67
|
+
</div>
|
68
|
+
|
69
|
+
<h2>Flop 20 Products</h2>
|
70
|
+
<div class="chart">
|
71
|
+
<%= column_chart Hash[@report.data.reverse.first(20).collect { |i| [i[:variant_name], i[:quantity]] }] %>
|
72
|
+
</div>
|
73
|
+
|
74
|
+
</div>
|
75
|
+
|
76
|
+
<div class="permalink">
|
77
|
+
<h2>Permalink</h2>
|
78
|
+
<input id="spree_reports_permalink" type="text" value="<%= request.url.split('?').first + "?" + params.except(:utf8, :commit, :action, :controller).to_query %>" onclick="$(this).select();return;">
|
79
|
+
<% if SpreeReports.csv_export %>
|
80
|
+
<%= link_to 'Download as CSV', params.except(:utf8, :commit).merge(format: "csv") %>
|
81
|
+
<% end %>
|
82
|
+
</div>
|
83
|
+
|
84
|
+
</div>
|
data/config/locales/en.yml
CHANGED
@@ -2,6 +2,8 @@ en:
|
|
2
2
|
spree:
|
3
3
|
orders_by_period: "Orders per period"
|
4
4
|
orders_by_period_description: "Orders for a specific time range per period"
|
5
|
+
sold_products: "Sold products"
|
6
|
+
sold_products_description: "Quantity of sold products for a specific time range"
|
5
7
|
|
6
8
|
spree_reports:
|
7
9
|
test: "TEST"
|
@@ -16,6 +16,12 @@ module SpreeReports
|
|
16
16
|
users.uniq
|
17
17
|
end
|
18
18
|
|
19
|
+
def without_excluded_orders(orders)
|
20
|
+
return orders if excluded_user_ids.none?
|
21
|
+
excluded_order_ids = Spree::Order.where(user_id: excluded_user_ids).pluck(:id)
|
22
|
+
orders.where.not(id: excluded_order_ids) if excluded_order_ids.any?
|
23
|
+
end
|
24
|
+
|
19
25
|
end
|
20
26
|
end
|
21
27
|
end
|
@@ -70,12 +70,8 @@ module SpreeReports
|
|
70
70
|
|
71
71
|
@sales = @sales.where("#{date_column.to_s} >= ?", @date_start) if @date_start
|
72
72
|
@sales = @sales.where(currency: @currency) if @currencies.size > 1
|
73
|
-
@sales = @sales.where(store_id: @store) if @stores.size > 2 && @store != "all"
|
74
|
-
|
75
|
-
if excluded_user_ids.any?
|
76
|
-
excluded_sales = Spree::Order.where(user_id: excluded_user_ids).pluck(:id)
|
77
|
-
@sales = @sales.where.not(id: excluded_sales) if excluded_sales.any?
|
78
|
-
end
|
73
|
+
@sales = @sales.where(store_id: @store) if @stores.size > 2 && @store != "all"
|
74
|
+
@sales = without_excluded_orders(@sales)
|
79
75
|
|
80
76
|
# group by
|
81
77
|
|
@@ -118,7 +114,6 @@ module SpreeReports
|
|
118
114
|
items_per_order: SpreeReports::Helper.round(SpreeReports::Helper.divide(@sales_item_count_total[k].to_f, v.to_f))
|
119
115
|
}
|
120
116
|
end
|
121
|
-
|
122
117
|
end
|
123
118
|
|
124
119
|
def to_csv
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module SpreeReports
|
2
|
+
module Reports
|
3
|
+
class SoldProducts < SpreeReports::Reports::Base
|
4
|
+
|
5
|
+
attr_accessor :params, :data, :orders
|
6
|
+
attr_accessor :currencies, :currency, :stores, :store, :months, :date_start
|
7
|
+
|
8
|
+
def initialize(params)
|
9
|
+
@params = params
|
10
|
+
setup_params
|
11
|
+
get_data
|
12
|
+
build_response
|
13
|
+
end
|
14
|
+
|
15
|
+
def setup_params
|
16
|
+
@currencies = Spree::Order.select('currency').distinct.map { |c| c.currency }
|
17
|
+
@currency = @currencies.include?(params[:currency]) ? params[:currency] : @currencies.first
|
18
|
+
|
19
|
+
@stores = Spree::Store.all.map { |store| [store.name, store.id] }
|
20
|
+
@stores << ["all", "all"]
|
21
|
+
@store = @stores.map{ |s| s[1].to_s }.include?(params[:store]) ? params[:store] : @stores.first[1]
|
22
|
+
|
23
|
+
@months = SpreeReports.report_months.include?(params[:months]) ? params[:months] : SpreeReports.default_months.to_s
|
24
|
+
@date_start = (@months != "all") ? (Time.now - (@months.to_i).months) : nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def get_data
|
28
|
+
@orders = Spree::Order.complete.where(payment_state: 'paid')
|
29
|
+
@orders = @orders.where("completed_at >= ?", @date_start) if @date_start
|
30
|
+
@orders = @orders.where(currency: @currency) if @currencies.size > 1
|
31
|
+
@orders = @orders.where(store_id: @store) if @stores.size > 2 && @store != "all"
|
32
|
+
@orders = without_excluded_orders(@orders)
|
33
|
+
|
34
|
+
order_ids = @orders.pluck(:id)
|
35
|
+
line_items = Spree::LineItem.where(order_id: order_ids)
|
36
|
+
variant_ids_and_quantity = line_items.group(:variant_id).sum(:quantity).sort_by { |k,v| v }.reverse
|
37
|
+
|
38
|
+
variants = Spree::Variant.all
|
39
|
+
variant_names = variants.all.map { |v| [v.id, [variant_name_with_option_values(v), v.slug] ] }.to_h
|
40
|
+
|
41
|
+
@data_tmp = variant_ids_and_quantity.map { |id, quantity| [id, quantity, variant_names[id][0], variant_names[id][1]] }
|
42
|
+
end
|
43
|
+
|
44
|
+
def build_response
|
45
|
+
@data = @data_tmp.map do |item|
|
46
|
+
{
|
47
|
+
variant_id: item[0],
|
48
|
+
variant_name: item[2],
|
49
|
+
variant_slug: item[3],
|
50
|
+
quantity: item[1]
|
51
|
+
}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def variant_name_with_option_values(v)
|
56
|
+
s = v.name
|
57
|
+
option_values = v.option_values.map { |o| o.presentation }
|
58
|
+
s += " (#{option_values.join(", ")})" if option_values.any?
|
59
|
+
s
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_csv
|
63
|
+
|
64
|
+
CSV.generate(headers: true, col_sep: ";") do |csv|
|
65
|
+
csv << %w{ variant_id variant_name variant_slug quantity }
|
66
|
+
|
67
|
+
@data.each do |item|
|
68
|
+
csv << [
|
69
|
+
item[:variant_id],
|
70
|
+
item[:variant_name],
|
71
|
+
item[:variant_slug],
|
72
|
+
item[:quantity]
|
73
|
+
]
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
def csv_filename
|
81
|
+
"sold_products_#{@months}-months.csv"
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/spree_reports.rb
CHANGED
@@ -40,12 +40,10 @@ end
|
|
40
40
|
# default configuration, overrideable in config/initializer spree_reports.rb
|
41
41
|
|
42
42
|
SpreeReports.reports = [
|
43
|
-
:orders_by_period
|
43
|
+
:orders_by_period,
|
44
|
+
:sold_products
|
44
45
|
]
|
45
46
|
|
46
|
-
# :orders_by_payment_type
|
47
|
-
# :orders_by_value_range
|
48
|
-
|
49
47
|
SpreeReports.time_zone = "Pacific Time (US & Canada)"
|
50
48
|
SpreeReports.week_start = :mon
|
51
49
|
SpreeReports.csv_export = true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_reports
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Lieser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: spree_core
|
@@ -66,6 +66,7 @@ files:
|
|
66
66
|
- app/controllers/spree/admin/reports_controller_decorator.rb
|
67
67
|
- app/controllers/spree/api/spree_reports_controller.rb
|
68
68
|
- app/views/spree/admin/reports/orders_by_period.html.erb
|
69
|
+
- app/views/spree/admin/reports/sold_products.html.erb
|
69
70
|
- config/locales/en.yml
|
70
71
|
- config/routes.rb
|
71
72
|
- lib/spree_reports.rb
|
@@ -73,6 +74,7 @@ files:
|
|
73
74
|
- lib/spree_reports/helper.rb
|
74
75
|
- lib/spree_reports/reports/base.rb
|
75
76
|
- lib/spree_reports/reports/orders_by_period.rb
|
77
|
+
- lib/spree_reports/reports/sold_products.rb
|
76
78
|
- lib/spree_reports/version.rb
|
77
79
|
- lib/tasks/spree_reports_tasks.rake
|
78
80
|
- test/dummy/README.rdoc
|