solidus_events_tracker 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +73 -0
  3. data/Gemfile +5 -0
  4. data/LICENSE +26 -0
  5. data/README.md +52 -0
  6. data/Rakefile +21 -0
  7. data/app/assets/javascripts/spree/backend/solidus_events_tracker.js +2 -0
  8. data/app/assets/javascripts/spree/frontend/solidus_events_tracker.js +2 -0
  9. data/app/assets/stylesheets/spree/backend/solidus_events_tracker.css +4 -0
  10. data/app/assets/stylesheets/spree/frontend/solidus_events_tracker.css +4 -0
  11. data/app/controllers/concerns/spree/checkout_event_tracker.rb +28 -0
  12. data/app/controllers/concerns/spree/page_tracker.rb +55 -0
  13. data/app/controllers/spree/checkout_controller_decorator.rb +22 -0
  14. data/app/controllers/spree/home_controller_decorator.rb +4 -0
  15. data/app/controllers/spree/orders_controller_decorator.rb +32 -0
  16. data/app/controllers/spree/products_controller_decorator.rb +4 -0
  17. data/app/controllers/spree/taxons_controller_decorator.rb +4 -0
  18. data/app/models/concerns/spree/order_contents_decorator.rb +38 -0
  19. data/app/models/spree/cart_event.rb +20 -0
  20. data/app/models/spree/checkout_event.rb +11 -0
  21. data/app/models/spree/page_event.rb +14 -0
  22. data/app/trackers/spree/cart/event/tracker.rb +44 -0
  23. data/app/trackers/spree/checkout/event/tracker.rb +18 -0
  24. data/app/trackers/spree/event/tracker.rb +17 -0
  25. data/app/trackers/spree/page/event/tracker.rb +17 -0
  26. data/bin/rails +7 -0
  27. data/config/locales/en.yml +4 -0
  28. data/config/routes.rb +3 -0
  29. data/db/migrate/20160313145434_create_spree_cart_events.rb +15 -0
  30. data/db/migrate/20160314080710_create_spree_page_events.rb +14 -0
  31. data/db/migrate/20160314080822_create_spree_checkout_events.rb +14 -0
  32. data/lib/generators/solidus_events_tracker/install/install_generator.rb +31 -0
  33. data/lib/solidus_events_tracker.rb +2 -0
  34. data/lib/solidus_events_tracker/engine.rb +20 -0
  35. data/lib/solidus_events_tracker/factories.rb +6 -0
  36. data/solidus_events_tracker.gemspec +37 -0
  37. data/spec/controllers/spree/checkout_controller_decorator_spec.rb +132 -0
  38. data/spec/controllers/spree/orders_controller_decorator_spec.rb +136 -0
  39. data/spec/models/spree/cart_event_spec.rb +18 -0
  40. data/spec/models/spree/checkout_event_spec.rb +16 -0
  41. data/spec/models/spree/page_event_spec.rb +15 -0
  42. data/spec/spec_helper.rb +97 -0
  43. data/spec/trackers/spree/cart/event/tracker_spec.rb +67 -0
  44. data/spec/trackers/spree/checkout/event/tracker_spec.rb +33 -0
  45. data/spec/trackers/spree/event/tracker_spec.rb +29 -0
  46. data/spec/trackers/spree/page/event/tracker_spec.rb +32 -0
  47. metadata +47 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5207d6b6f9bdac0e62f5dd4d215fda33e732ca77
4
- data.tar.gz: bb4db818202615ad96a2f28c16bd4ab315f5676f
3
+ metadata.gz: fc9d932b29081cbbb4a1b13d092b2016a85a7211
4
+ data.tar.gz: 6b6aede72f41dbcc4fb0a399e362e42582fbed1c
5
5
  SHA512:
6
- metadata.gz: fbcd05b501b6f197f50e6b7aa631345101e0e9c41b6cc7530e99af5fa80099ff26e9c2ea2071b424900da9e6e12d0f00bbd46b2d892ce2941dd2034a7a5b78db
7
- data.tar.gz: 38ece47268bddae954490d74d3e86a0fd634a7dc6f87d43c55c377482cb39211d45705aa5ec933865d0d5584acdb53a74dd9b0db5d170248ac806e3e481b071a
6
+ metadata.gz: 62f76b683cbd06af0b23504b33b7373864907d33c2cc664d5784464d865fc0feed7855885ad72aaedad5817b3fb6cab2687819b4a510f61696207f019a43b0cb
7
+ data.tar.gz: 5ddefadfa935923d548ab35b044c62f518711de9a82098625ae9cc811c239c1b1e8ff39fa4d41e9cf4871cb87f17cb315dbf7b284a90d185b5dd4d0eaa0fcc8a
@@ -0,0 +1,73 @@
1
+ \#*
2
+ *~
3
+ .#*
4
+ *.sassc
5
+ *.DS_Store
6
+ .sass-cache
7
+ coverage
8
+ Gemfile.lock
9
+ .idea
10
+ .project
11
+ nbproject
12
+ .ruby-gemset
13
+ pkg
14
+ *.swp
15
+ spec/dummy
16
+
17
+ *.rbc
18
+ capybara-*.html
19
+ .rspec
20
+ /log
21
+ /tmp
22
+ /db/*.sqlite3
23
+ /db/*.sqlite3-journal
24
+ /public/system
25
+ /coverage/
26
+ /spec/tmp
27
+ **.orig
28
+ rerun.txt
29
+ pickle-email-*.html
30
+
31
+ # TODO Comment out these rules if you are OK with secrets being uploaded to the repo
32
+ config/initializers/secret_token.rb
33
+ config/secrets.yml
34
+
35
+ ## Environment normalization:
36
+ /.bundle/
37
+ /vendor/bundle
38
+ /lib/bundler/man/
39
+
40
+ # these should all be checked in to normalize the environment:
41
+ # Gemfile.lock, .ruby-version, .ruby-gemset
42
+
43
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
44
+ .rvmrc
45
+ .ruby-version
46
+ /test
47
+ /config/*.yml
48
+ *.log
49
+ /public/test_files
50
+ /public/system/*
51
+ /public/*.json
52
+ .byebug_history
53
+
54
+ # if using bower-rails ignore default bower_components path bower.json files
55
+ /vendor/assets/bower_components
56
+ *.bowerrc
57
+ bower.json
58
+
59
+ # Ignore pow environment settings
60
+ .powenv
61
+
62
+ *.gem
63
+ /.config
64
+ /InstalledFiles
65
+ /spec/examples.txt
66
+ /test/tmp/
67
+ /test/version_tmp/
68
+ /tmp/*
69
+
70
+ ## Specific to RubyMotion:
71
+ .dat*
72
+ .repl_history
73
+ build/
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'solidus', '~> 2.1'
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,26 @@
1
+ Copyright (c) 2017 [Vinsol & community]
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright notice,
10
+ this list of conditions and the following disclaimer in the documentation
11
+ and/or other materials provided with the distribution.
12
+ * Neither the name Spree nor the names of its contributors may be used to
13
+ endorse or promote products derived from this software without specific
14
+ prior written permission.
15
+
16
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
20
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,52 @@
1
+ Solidus Events Tracker
2
+ ==================
3
+
4
+ Solidus Port for Spree Events Tracker.
5
+
6
+ Tracks user activity and events on the server side. Use Solidus Admin Insights to build reports of user activity.
7
+
8
+
9
+ ## Installation
10
+
11
+ 1. Add this extension to your Gemfile with this line:
12
+ ```ruby
13
+ gem 'solidus_events_tracker'
14
+ ```
15
+
16
+ 2. Install the gem using Bundler:
17
+ ```ruby
18
+ bundle install
19
+ ```
20
+
21
+ 3. Copy & run migrations
22
+ ```ruby
23
+ bundle exec rails g solidus_events_tracker:install
24
+ ```
25
+
26
+ 4. Restart your server
27
+
28
+ If your server was running, restart it so that it can find the assets properly.
29
+
30
+ ## Testing
31
+
32
+ First bundle your dependencies, then run `rake`. `rake` will default to building the dummy app if it does not exist, then it will run specs. The dummy app can be regenerated by using `rake test_app`.
33
+
34
+ ```shell
35
+ bundle
36
+ bundle exec rake
37
+ ```
38
+
39
+ When testing your applications integration with this extension you may use it's factories.
40
+ Simply add this require statement to your spec_helper:
41
+
42
+ ```ruby
43
+ require 'solidus_events_tracker/factories'
44
+ ```
45
+
46
+
47
+ Credits
48
+ -------
49
+
50
+ [![vinsol.com: Ruby on Rails, iOS and Android developers](http://vinsol.com/vin_logo.png "Ruby on Rails, iOS and Android developers")](http://vinsol.com)
51
+
52
+ Copyright (c) 2017 [vinsol.com](http://vinsol.com "Ruby on Rails, iOS and Android developers"), released under the New MIT License
@@ -0,0 +1,21 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ require 'spree/testing_support/extension_rake'
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ task :default do
10
+ if Dir["spec/dummy"].empty?
11
+ Rake::Task[:test_app].invoke
12
+ Dir.chdir("../../")
13
+ end
14
+ Rake::Task[:spec].invoke
15
+ end
16
+
17
+ desc 'Generates a dummy app for testing'
18
+ task :test_app do
19
+ ENV['LIB_NAME'] = 'solidus_events_tracker'
20
+ Rake::Task['extension:test_app'].invoke
21
+ end
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/backend/all.js'
@@ -0,0 +1,2 @@
1
+ // Placeholder manifest file.
2
+ // the installer will append this file to the app vendored assets here: vendor/assets/javascripts/spree/frontend/all.js'
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/backend/all.css'
4
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Placeholder manifest file.
3
+ the installer will append this file to the app vendored assets here: 'vendor/assets/stylesheets/spree/frontend/all.css'
4
+ */
@@ -0,0 +1,28 @@
1
+ module Spree
2
+ module CheckoutEventTracker
3
+ extend ActiveSupport::Concern
4
+
5
+ def track_activity(attributes)
6
+ default_attributes = {
7
+ referrer: request.referrer,
8
+ actor: spree_current_user,
9
+ target: @order,
10
+ session_id: session.id
11
+ }
12
+ Spree::Checkout::Event::Tracker.new(default_attributes.merge(attributes)).track
13
+ end
14
+
15
+ def next_state
16
+ @next_state ||= checkout_state(request.url)
17
+ end
18
+
19
+ def previous_state
20
+ referrer = request.referrer
21
+ @previous_state ||= (referrer ? checkout_state(referrer) : nil)
22
+ end
23
+
24
+ def checkout_state(request_path)
25
+ request_path.split('/').last.split('?').first
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,55 @@
1
+ module Spree
2
+ module PageTracker
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def track_actions(actions = [])
7
+ after_action :track_event, only: actions
8
+ end
9
+ end
10
+
11
+ def track_event
12
+ if event_trackable?
13
+ Spree::Page::Event::Tracker.new(
14
+ session_id: session.id,
15
+ referrer: request.referrer,
16
+ actor: current_spree_user,
17
+ target: instance_variable_get("@#{ controller_name.singularize }"),
18
+ activity: get_activity,
19
+ search_keywords: get_keywords,
20
+ query_string: request.query_string
21
+ ).track
22
+ end
23
+ end
24
+
25
+ def get_activity
26
+ if index_action?
27
+ if @searcher && (@searcher.keywords || @searcher.search)
28
+ Spree::Page::Event::Tracker::EVENTS[:search]
29
+ else
30
+ Spree::Page::Event::Tracker::EVENTS[:index]
31
+ end
32
+ elsif show_action?
33
+ if @searcher && @searcher.search
34
+ Spree::Page::Event::Tracker::EVENTS[:filter]
35
+ else
36
+ Spree::Page::Event::Tracker::EVENTS[:show]
37
+ end
38
+ end
39
+ end
40
+
41
+ def get_keywords
42
+ @searcher && (@searcher.search.to_s + @searcher.keywords.to_s)
43
+ end
44
+
45
+ def event_trackable?
46
+ show_action? || index_action?
47
+ end
48
+
49
+ %w(index show).each do |_action_|
50
+ define_method("#{ _action_ }_action?") do
51
+ action_name == _action_
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,22 @@
1
+ Spree::CheckoutController.class_eval do
2
+
3
+ include Spree::CheckoutEventTracker
4
+
5
+ after_action :track_order_state_change, only: :edit
6
+ after_action :track_order_completion, only: :update, if: :confirm?
7
+
8
+ private
9
+ def confirm?
10
+ previous_state == 'confirm'
11
+ end
12
+
13
+ def track_order_completion
14
+ track_activity(activity: :complete_order, previous_state: previous_state, next_state: 'complete')
15
+ end
16
+
17
+ def track_order_state_change
18
+ unless previous_state == next_state
19
+ track_activity(activity: :change_order_state, previous_state: previous_state, next_state: next_state)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,4 @@
1
+ Spree::HomeController.class_eval do
2
+ include Spree::PageTracker
3
+ track_actions [:index]
4
+ end
@@ -0,0 +1,32 @@
1
+ Spree::OrdersController.class_eval do
2
+
3
+ include Spree::CheckoutEventTracker
4
+
5
+ after_action :track_return_to_cart, only: :edit, if: :current_order
6
+ after_action :track_empty_cart_activity, only: :empty
7
+
8
+ private
9
+ def track_empty_cart_activity
10
+ track_activity(activity: :empty_cart, previous_state: previous_state, next_state: nil)
11
+ end
12
+
13
+ def track_return_to_cart
14
+ preceeding_state = referred_from_any_checkout_step? ? previous_state : nil
15
+ unless preceeding_state == next_state
16
+ track_activity(activity: activity, previous_state: preceeding_state, next_state: next_state)
17
+ end
18
+ end
19
+
20
+ def activity
21
+ !(referred_from_any_checkout_step?) ? :initialize_order : :return_to_cart
22
+ end
23
+
24
+ def current_order_includes_previous_state?
25
+ current_order.checkout_steps.include?(previous_state)
26
+ end
27
+
28
+ def referred_from_any_checkout_step?
29
+ current_order_includes_previous_state? || previous_state.eql?('cart')
30
+ end
31
+
32
+ end
@@ -0,0 +1,4 @@
1
+ Spree::ProductsController.class_eval do
2
+ include Spree::PageTracker
3
+ track_actions [:show, :index]
4
+ end
@@ -0,0 +1,4 @@
1
+ Spree::TaxonsController.class_eval do
2
+ include Spree::PageTracker
3
+ track_actions [:show]
4
+ end
@@ -0,0 +1,38 @@
1
+ module Spree
2
+ module OrderContentsWithTracker
3
+
4
+ # Override: since order's line_items were overridden
5
+ def update_cart(params)
6
+ if order.update_attributes(params)
7
+ order.line_items.select(&:quantity_previously_changed?).each do |line_item|
8
+ Spree::Cart::Event::Tracker.new(
9
+ actor: order, target: line_item, total: order.total, variant_id: line_item.variant_id
10
+ ).track
11
+ end
12
+ # line_items which have 0 quantity will be lost and couldn't be tracked
13
+ # so tracking is done before the execution of next statement
14
+ order.line_items = order.line_items.select { |li| li.quantity > 0 }
15
+ reload_totals
16
+ PromotionHandler::Cart.new(order).activate
17
+ order.ensure_updated_shipments
18
+ reload_totals
19
+ true
20
+ else
21
+ false
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ # Override: Add tracking entry after a line_item is added or removed
28
+ def after_add_or_remove(line_item, options = {})
29
+ line_item = super
30
+ Spree::Cart::Event::Tracker.new(
31
+ actor: order, target: line_item, total: order.total, variant_id: line_item.variant_id
32
+ ).track
33
+ line_item
34
+ end
35
+ end
36
+ end
37
+
38
+ Spree::OrderContents.send(:prepend, Spree::OrderContentsWithTracker)
@@ -0,0 +1,20 @@
1
+ module Spree
2
+ class CartEvent < Spree::Base
3
+
4
+ belongs_to :actor, polymorphic: true
5
+ belongs_to :target, polymorphic: true
6
+ belongs_to :variant
7
+ has_one :product, through: :variant
8
+
9
+ validates :activity,
10
+ :actor,
11
+ :quantity,
12
+ :target,
13
+ :total,
14
+ :variant, presence: true
15
+
16
+ scope :added, -> { where(activity: 'add') }
17
+ scope :removed, -> { where(activity: 'remove') }
18
+ scope :updated, -> { where(activity: 'update') }
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ module Spree
2
+ class CheckoutEvent < Spree::Base
3
+
4
+ belongs_to :actor, polymorphic: true
5
+ belongs_to :target, polymorphic: true
6
+
7
+ validates :activity,
8
+ :session_id,
9
+ :target, presence: true
10
+ end
11
+ end