spree_reports 0.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +37 -0
- data/app/assets/stylesheets/spree_reports/spree_reports.css.scss +61 -0
- data/app/controllers/spree/admin/reports_controller_decorator.rb +23 -0
- data/app/controllers/spree/api/spree_reports_controller.rb +19 -0
- data/app/views/spree/admin/reports/orders_by_period.html.erb +138 -0
- data/config/locales/en.yml +8 -0
- data/config/routes.rb +23 -0
- data/lib/spree_reports.rb +52 -0
- data/lib/spree_reports/engine.rb +27 -0
- data/lib/spree_reports/helper.rb +20 -0
- data/lib/spree_reports/reports/orders_by_period.rb +151 -0
- data/lib/spree_reports/version.rb +3 -0
- data/lib/tasks/spree_reports_tasks.rake +4 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +85 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +56 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/spree_reports_test.rb +7 -0
- data/test/test_helper.rb +19 -0
- metadata +189 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 115b2468f528c98184477a62985580afb9690021
|
4
|
+
data.tar.gz: 3c8ae48b20a1cbb8366782d453a63873122cf306
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a66840a9351e4b2b19ab7aa7bc84a129dea27e97f88919647780eaacb793ee7f351301e55f5829a4581ed43611cef662f1d981be759ebf4eac8e8c00caf8028a
|
7
|
+
data.tar.gz: be812cdede4ffae1f9ad2ace302df8ed07f959f3fe6548020675967d4c306b9ace52ff17a8f47442d22072bdfbe6cee3174533631bb6e7f7f4a152eea4f99441
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2015 Mike Lieser
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'SpreeReports'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
load 'rails/tasks/statistics.rake'
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
Bundler::GemHelper.install_tasks
|
26
|
+
|
27
|
+
require 'rake/testtask'
|
28
|
+
|
29
|
+
Rake::TestTask.new(:test) do |t|
|
30
|
+
t.libs << 'lib'
|
31
|
+
t.libs << 'test'
|
32
|
+
t.pattern = 'test/**/*_test.rb'
|
33
|
+
t.verbose = false
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
task default: :test
|
@@ -0,0 +1,61 @@
|
|
1
|
+
.spree_reports.report {
|
2
|
+
|
3
|
+
text-align: center;
|
4
|
+
padding-bottom: 30px;
|
5
|
+
|
6
|
+
h1 {
|
7
|
+
margin-bottom: 20px;
|
8
|
+
margin-top: 20px;
|
9
|
+
font-size: 28px;
|
10
|
+
}
|
11
|
+
|
12
|
+
h2 {
|
13
|
+
margin-top: 50px;
|
14
|
+
}
|
15
|
+
|
16
|
+
form.options {
|
17
|
+
margin-bottom: 25px;
|
18
|
+
|
19
|
+
.option {
|
20
|
+
margin-right: 12px;
|
21
|
+
}
|
22
|
+
|
23
|
+
select {
|
24
|
+
max-width: 150px;
|
25
|
+
}
|
26
|
+
|
27
|
+
input[type=submit] {
|
28
|
+
padding: 1px 6px 1px 6px;
|
29
|
+
font-size: 12px;
|
30
|
+
border-radius: 5px;
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
table.data {
|
35
|
+
margin-top:30px;
|
36
|
+
|
37
|
+
th.help {
|
38
|
+
cursor:help;
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
div.permalink {
|
43
|
+
h2 {
|
44
|
+
font-weight:bold;
|
45
|
+
margin-bottom:15px;
|
46
|
+
}
|
47
|
+
|
48
|
+
#spree_reports_permalink {
|
49
|
+
font-size:13px;
|
50
|
+
font-weight:bold;
|
51
|
+
width:700px;
|
52
|
+
text-align:center;
|
53
|
+
}
|
54
|
+
|
55
|
+
a {
|
56
|
+
display: block;
|
57
|
+
margin-top: 12px;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Spree::Admin::ReportsController.class_eval do
|
2
|
+
before_filter :spree_reports_setup, only: [:index]
|
3
|
+
|
4
|
+
def orders_by_period
|
5
|
+
@report = SpreeReports::Reports::OrdersByPeriod.new(params)
|
6
|
+
respond_to do |format|
|
7
|
+
format.html
|
8
|
+
format.csv {
|
9
|
+
return head :unauthorized unless SpreeReports.csv_export
|
10
|
+
send_data @report.to_csv, filename: @report.csv_filename, type: "text/csv"
|
11
|
+
}
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def spree_reports_setup
|
18
|
+
SpreeReports.reports.each do |report|
|
19
|
+
Spree::Admin::ReportsController.add_available_report! report
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Spree
|
2
|
+
module Api
|
3
|
+
class SpreeReportsController < Spree::Api::BaseController
|
4
|
+
before_filter :requires_admin
|
5
|
+
|
6
|
+
def orders_by_period
|
7
|
+
@report = SpreeReports::Reports::OrdersByPeriod.new(params)
|
8
|
+
render json: @report.data
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def requires_admin
|
13
|
+
return if @current_user_roles.include?(SpreeReports.api_user_role)
|
14
|
+
unauthorized and return
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
<%= stylesheet_link_tag 'spree_reports/spree_reports', media: 'all' %>
|
2
|
+
<%= javascript_include_tag "//www.google.com/jsapi", "chartkick" %>
|
3
|
+
|
4
|
+
<div class="spree_reports report">
|
5
|
+
|
6
|
+
<h1>Orders Per Period</h1>
|
7
|
+
|
8
|
+
<div class="options">
|
9
|
+
|
10
|
+
<%= form_tag "", method: :get, class: "options" do %>
|
11
|
+
|
12
|
+
<span class="option">
|
13
|
+
group by:
|
14
|
+
<%= select_tag "group_by", options_for_select(@report.group_by_list, selected: @report.group_by) %>
|
15
|
+
</span>
|
16
|
+
|
17
|
+
<span class="option">
|
18
|
+
<span title="<%= @report.date_start ? "date_start: #{l(@report.date_start.to_date)}" : "" %>">months:</span>
|
19
|
+
<%= select_tag "months", options_for_select(SpreeReports.report_months, selected: @report.months) %>
|
20
|
+
</span>
|
21
|
+
|
22
|
+
<span class="option">
|
23
|
+
state:
|
24
|
+
<%= select_tag "state", options_for_select(@report.states, selected: @report.state) %>
|
25
|
+
</span>
|
26
|
+
|
27
|
+
<% if @report.currencies.size > 1 %>
|
28
|
+
<span class="option">
|
29
|
+
currency:
|
30
|
+
<%= select_tag "currency", options_for_select(@report.currencies, selected: @report.currency) %>
|
31
|
+
</span>
|
32
|
+
<% end %>
|
33
|
+
|
34
|
+
<% if @report.stores.size > 2 %>
|
35
|
+
<span class="option">
|
36
|
+
store:
|
37
|
+
<%= select_tag "store", options_for_select(@report.stores, selected: @report.store) %>
|
38
|
+
</span>
|
39
|
+
<% end %>
|
40
|
+
|
41
|
+
<%= submit_tag 'reload' %>
|
42
|
+
|
43
|
+
<% end %>
|
44
|
+
|
45
|
+
</div>
|
46
|
+
|
47
|
+
<div class="table">
|
48
|
+
|
49
|
+
<table class="data" border="1">
|
50
|
+
<tr>
|
51
|
+
<th><%= @report.group_by.capitalize %></th>
|
52
|
+
<th>Orders</th>
|
53
|
+
<th class="help" title="Item Count Total">ICT</th>
|
54
|
+
<th class="help" title="Items per Order">IPO</th>
|
55
|
+
<th class="help" title="Average Total">Avg. T.</th>
|
56
|
+
<th class="help" title="Total">Total</th>
|
57
|
+
<th class="help" title="Item Total">Item T.</th>
|
58
|
+
<th class="help" title="Adjustment Total">Adjustment T.</th>
|
59
|
+
<th class="help" title="Shipment Total">Shipment T.</th>
|
60
|
+
<th class="help" title="Promo Total">Promo T.</th>
|
61
|
+
<th class="help" title="Included Tax Total">Included Tax T.</th>
|
62
|
+
</tr>
|
63
|
+
|
64
|
+
<% @report.data.each do |item| %>
|
65
|
+
<tr>
|
66
|
+
<td><%= item[:date_formatted] %></td>
|
67
|
+
<td><%= number_with_delimiter(item[:count]) %></td>
|
68
|
+
<td><%= number_with_delimiter(item[:item_count_total]) %></td>
|
69
|
+
<td><%= number_with_precision(item[:items_per_order], precision: 2) %></td>
|
70
|
+
<td><%= Spree::Money.new(item[:avg_total], :currency => @report.currency).to_s %></td>
|
71
|
+
<td><%= Spree::Money.new(item[:total], :currency => @report.currency).to_s %></td>
|
72
|
+
<td><%= Spree::Money.new(item[:item_total], :currency => @report.currency).to_s %></td>
|
73
|
+
<td><%= Spree::Money.new(item[:adjustment_total], :currency => @report.currency).to_s %></td>
|
74
|
+
<td><%= Spree::Money.new(item[:shipment_total], :currency => @report.currency).to_s %></td>
|
75
|
+
<td><%= Spree::Money.new(item[:promo_total], :currency => @report.currency).to_s %></td>
|
76
|
+
<td><%= Spree::Money.new(item[:included_tax_total], :currency => @report.currency).to_s %></td>
|
77
|
+
</tr>
|
78
|
+
<% end %>
|
79
|
+
|
80
|
+
</table>
|
81
|
+
|
82
|
+
</div>
|
83
|
+
|
84
|
+
<div class="charts">
|
85
|
+
|
86
|
+
<h2>Order Count</h2>
|
87
|
+
<div class="chart">
|
88
|
+
<%= column_chart Hash[@report.data.collect { |i| [i[:date_formatted], i[:count]] }] %>
|
89
|
+
</div>
|
90
|
+
|
91
|
+
<h2>Item Count Total</h2>
|
92
|
+
<div class="chart">
|
93
|
+
<%= column_chart Hash[@report.data.collect { |i| [i[:date_formatted], i[:item_count_total]] }] %>
|
94
|
+
</div>
|
95
|
+
|
96
|
+
<h2>Items per Order</h2>
|
97
|
+
<div class="chart">
|
98
|
+
<%= column_chart Hash[@report.data.collect { |i| [i[:date_formatted], i[:items_per_order]] }] %>
|
99
|
+
</div>
|
100
|
+
|
101
|
+
<h2>Average Total</h2>
|
102
|
+
<div class="chart">
|
103
|
+
<%= column_chart Hash[@report.data.collect { |i| [i[:date_formatted], i[:avg_total]] }] %>
|
104
|
+
</div>
|
105
|
+
|
106
|
+
<h2>Total & Item Total</h2>
|
107
|
+
<div class="chart">
|
108
|
+
<%=
|
109
|
+
column_chart [
|
110
|
+
{ name: "Total", data: Hash[@report.data.collect { |i| [i[:date_formatted], i[:total]] }] },
|
111
|
+
{ name: "Item Total", data: Hash[@report.data.collect { |i| [i[:date_formatted], i[:item_total]] }] }
|
112
|
+
]
|
113
|
+
%>
|
114
|
+
</div>
|
115
|
+
|
116
|
+
<h2>Misc Totals</h2>
|
117
|
+
<div class="chart">
|
118
|
+
<%=
|
119
|
+
column_chart [
|
120
|
+
{ name: "Shipment Total", data: Hash[@report.data.collect { |i| [i[:date_formatted], i[:shipment_total]] }] },
|
121
|
+
{ name: "Included Tax Total", data: Hash[@report.data.collect { |i| [i[:date_formatted], i[:included_tax_total]] }] },
|
122
|
+
{ name: "Adjustment Total", data: Hash[@report.data.collect { |i| [i[:date_formatted], i[:adjustment_total]] }] },
|
123
|
+
{ name: "Promo Total", data: Hash[@report.data.collect { |i| [i[:date_formatted], i[:promo_total]] }] }
|
124
|
+
]
|
125
|
+
%>
|
126
|
+
</div>
|
127
|
+
|
128
|
+
</div>
|
129
|
+
|
130
|
+
<div class="permalink">
|
131
|
+
<h2>Permalink</h2>
|
132
|
+
<input id="spree_reports_permalink" type="text" value="<%= request.url.split('?').first + "?" + params.except(:utf8, :commit, :action, :controller).to_query %>" onclick="$(this).select();return;">
|
133
|
+
<% if SpreeReports.csv_export %>
|
134
|
+
<%= link_to 'Download as CSV', params.except(:utf8, :commit).merge(format: "csv") %>
|
135
|
+
<% end %>
|
136
|
+
</div>
|
137
|
+
|
138
|
+
</div>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Spree::Core::Engine.routes.draw do
|
2
|
+
|
3
|
+
namespace :admin do
|
4
|
+
resources :reports, :only => [] do
|
5
|
+
collection do
|
6
|
+
SpreeReports.reports.each do |report|
|
7
|
+
get report
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :api do
|
14
|
+
resources :spree_reports, :only => [] do
|
15
|
+
collection do
|
16
|
+
SpreeReports.reports.each do |report|
|
17
|
+
get report
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'spree_core'
|
2
|
+
require "spree_reports/engine"
|
3
|
+
|
4
|
+
module SpreeReports
|
5
|
+
|
6
|
+
# list of visible reports
|
7
|
+
mattr_accessor :reports
|
8
|
+
|
9
|
+
# time zone
|
10
|
+
mattr_accessor :time_zone
|
11
|
+
|
12
|
+
# start of week
|
13
|
+
mattr_accessor :week_start
|
14
|
+
|
15
|
+
# export
|
16
|
+
mattr_accessor :csv_export
|
17
|
+
|
18
|
+
# available months to select in reports
|
19
|
+
mattr_accessor :report_months
|
20
|
+
|
21
|
+
# default months selection in reports
|
22
|
+
mattr_accessor :default_months
|
23
|
+
|
24
|
+
# check if the api user has this role
|
25
|
+
mattr_accessor :api_user_role
|
26
|
+
|
27
|
+
# date formats for different group_by settings
|
28
|
+
mattr_accessor :date_formats
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
# default configuration, overrideable in config/initializer spree_reports.rb
|
33
|
+
|
34
|
+
SpreeReports.reports = [
|
35
|
+
:orders_by_period
|
36
|
+
]
|
37
|
+
|
38
|
+
# :orders_by_payment_type
|
39
|
+
# :orders_by_value_range
|
40
|
+
|
41
|
+
SpreeReports.time_zone = "Pacific Time (US & Canada)"
|
42
|
+
SpreeReports.week_start = :mon
|
43
|
+
SpreeReports.csv_export = true
|
44
|
+
SpreeReports.report_months = %w{1 3 6 12 24 36 48 all}
|
45
|
+
SpreeReports.default_months = 6
|
46
|
+
SpreeReports.api_user_role = "admin"
|
47
|
+
SpreeReports.date_formats = {
|
48
|
+
year: "%Y",
|
49
|
+
month: "%m.%Y",
|
50
|
+
week: "%W/%Y",
|
51
|
+
day: "%m.%d.%y"
|
52
|
+
}
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spree/core'
|
2
|
+
|
3
|
+
module SpreeReports
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
isolate_namespace Spree
|
6
|
+
engine_name "spree_reports"
|
7
|
+
|
8
|
+
config.autoload_paths += %W(#{config.root}/lib)
|
9
|
+
|
10
|
+
# use rspec for tests
|
11
|
+
config.generators do |g|
|
12
|
+
g.test_framework :rspec
|
13
|
+
end
|
14
|
+
|
15
|
+
# apply decorators
|
16
|
+
def self.activate
|
17
|
+
Dir.glob(File.join(File.dirname(__FILE__), '../../app/**/*.rb')) do |c|
|
18
|
+
Rails.configuration.cache_classes ? require(c) : load(c)
|
19
|
+
end
|
20
|
+
|
21
|
+
Rails.application.config.assets.precompile += %w( spree_reports/spree_reports.css )
|
22
|
+
end
|
23
|
+
|
24
|
+
config.to_prepare &method(:activate).to_proc
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module SpreeReports
|
2
|
+
class Helper
|
3
|
+
|
4
|
+
def self.divide(a, b)
|
5
|
+
return nil if b == 0
|
6
|
+
a / b
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.round(a)
|
10
|
+
return a.round(2) if a
|
11
|
+
a
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.date_formatted(date, group_by)
|
15
|
+
date_format = SpreeReports.date_formats[group_by]
|
16
|
+
date.strftime(date_format)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|