spree_reports 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +37 -0
  4. data/app/assets/stylesheets/spree_reports/spree_reports.css.scss +61 -0
  5. data/app/controllers/spree/admin/reports_controller_decorator.rb +23 -0
  6. data/app/controllers/spree/api/spree_reports_controller.rb +19 -0
  7. data/app/views/spree/admin/reports/orders_by_period.html.erb +138 -0
  8. data/config/locales/en.yml +8 -0
  9. data/config/routes.rb +23 -0
  10. data/lib/spree_reports.rb +52 -0
  11. data/lib/spree_reports/engine.rb +27 -0
  12. data/lib/spree_reports/helper.rb +20 -0
  13. data/lib/spree_reports/reports/orders_by_period.rb +151 -0
  14. data/lib/spree_reports/version.rb +3 -0
  15. data/lib/tasks/spree_reports_tasks.rake +4 -0
  16. data/test/dummy/README.rdoc +28 -0
  17. data/test/dummy/Rakefile +6 -0
  18. data/test/dummy/app/assets/javascripts/application.js +13 -0
  19. data/test/dummy/app/assets/stylesheets/application.css +15 -0
  20. data/test/dummy/app/controllers/application_controller.rb +5 -0
  21. data/test/dummy/app/helpers/application_helper.rb +2 -0
  22. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  23. data/test/dummy/bin/bundle +3 -0
  24. data/test/dummy/bin/rails +4 -0
  25. data/test/dummy/bin/rake +4 -0
  26. data/test/dummy/bin/setup +29 -0
  27. data/test/dummy/config.ru +4 -0
  28. data/test/dummy/config/application.rb +26 -0
  29. data/test/dummy/config/boot.rb +5 -0
  30. data/test/dummy/config/database.yml +85 -0
  31. data/test/dummy/config/environment.rb +5 -0
  32. data/test/dummy/config/environments/development.rb +41 -0
  33. data/test/dummy/config/environments/production.rb +79 -0
  34. data/test/dummy/config/environments/test.rb +42 -0
  35. data/test/dummy/config/initializers/assets.rb +11 -0
  36. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  37. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  38. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  39. data/test/dummy/config/initializers/inflections.rb +16 -0
  40. data/test/dummy/config/initializers/mime_types.rb +4 -0
  41. data/test/dummy/config/initializers/session_store.rb +3 -0
  42. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  43. data/test/dummy/config/locales/en.yml +23 -0
  44. data/test/dummy/config/routes.rb +56 -0
  45. data/test/dummy/config/secrets.yml +22 -0
  46. data/test/dummy/public/404.html +67 -0
  47. data/test/dummy/public/422.html +67 -0
  48. data/test/dummy/public/500.html +66 -0
  49. data/test/dummy/public/favicon.ico +0 -0
  50. data/test/integration/navigation_test.rb +10 -0
  51. data/test/spree_reports_test.rb +7 -0
  52. data/test/test_helper.rb +19 -0
  53. metadata +189 -0
@@ -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
@@ -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.
@@ -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>
@@ -0,0 +1,8 @@
1
+ en:
2
+ spree:
3
+ orders_by_period: "Orders per period"
4
+ orders_by_period_description: "Orders for a specific time range per period"
5
+
6
+ spree_reports:
7
+ test: "TEST"
8
+
@@ -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