workarea-core 3.4.38 → 3.4.43

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9ffbb2028cd43e91abbc3601126483073b55997738eba74759b902e353590b67
4
- data.tar.gz: 70acccdddb99146faaf878e862bc8a1e2161f5c2a62a10cd0f3f1f5f97bc4b19
3
+ metadata.gz: 30d5b2273f510412bf81387ac4d229e05ef322219dba42166dffd16c2a30d458
4
+ data.tar.gz: 0163e5cd44474ad11c119debb3dd116a0637be8f514b8d920cab4e093f3f4578
5
5
  SHA512:
6
- metadata.gz: fb66b15c9317d085e8dbd97262ddf4ae85ef31eb5cbb77b1bf6375f69b284a6ce439579c534b6ec05c337644b022e4b186e4f55c51cabf555a29c490f131bc8e
7
- data.tar.gz: db47bf0b35f4f7f12a27b05759d242301e7b0b6779670d41fab803129fd391c9246ecc08f494314e3865c5f8190a636d6f1df521b3b31d545dec53c624c5a6dd
6
+ metadata.gz: 00d52ab3b83bb7057218e4b70d668a98e85b1c953f2607b15826599d75d6970fdd681eea595b1270533889f90e75be3db8a539f4a16016578acd6c285fffb4aa
7
+ data.tar.gz: d73e489b510f361b0a75cbd705c1731ae6bea3693fd25ed3ee76d502ff4802724ba744442bade25b99171d444c0ec0f805591650a852fe74f8f7a5bfef83d5df
@@ -9,6 +9,7 @@ module Workarea
9
9
  @current_referrer ||= TrafficReferrer.new(
10
10
  RefererParser::Parser.new.parse(referrer).slice(:source, :medium, :uri)
11
11
  )
12
+ rescue RefererParser::InvalidUriError
12
13
  end
13
14
  end
14
15
  end
@@ -50,7 +50,8 @@ module Workarea
50
50
  end
51
51
 
52
52
  def current_impersonation
53
- @current_impersonation ||= User.find(cookies.signed[:user_id])
53
+ return @current_impersonation if defined?(@current_impersonation)
54
+ @current_impersonation = User.find(cookies.signed[:user_id]) rescue nil
54
55
  end
55
56
 
56
57
  def touch_impersonation
@@ -123,6 +123,31 @@ module Workarea
123
123
  return nil if orders.zero?
124
124
  revenue / orders.to_f
125
125
  end
126
+
127
+ def merge!(other)
128
+ # To recalculate average_order_value
129
+ self.orders += other.orders
130
+ self.revenue += other.revenue
131
+
132
+ update = {
133
+ '$set' => {
134
+ average_order_value: average_order_value,
135
+ updated_at: Time.current.utc
136
+ },
137
+ '$inc' => {
138
+ orders: other.orders,
139
+ revenue: other.revenue,
140
+ discounts: other.discounts
141
+ }
142
+ }
143
+
144
+ update['$min'] = { first_order_at: other.first_order_at.utc } if other.first_order_at.present?
145
+ update['$max'] = { last_order_at: other.last_order_at.utc } if other.last_order_at.present?
146
+
147
+ self.class.collection.update_one({ _id: id }, update, upsert: true)
148
+ other.delete
149
+ reload
150
+ end
126
151
  end
127
152
  end
128
153
  end
@@ -11,6 +11,10 @@ module Workarea
11
11
  def self.available_sorts
12
12
  AdminSorting.available_sorts
13
13
  end
14
+
15
+ def default_admin_sort
16
+ [{ _score: :desc }, { updated_at: :desc }]
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -16,7 +16,7 @@ module Workarea
16
16
  end
17
17
 
18
18
  def default_admin_sort
19
- [{ _score: :desc }, { updated_at: :desc }]
19
+ [{ updated_at: :desc }, { _score: :desc }]
20
20
  end
21
21
 
22
22
  def user_selected_sort
@@ -0,0 +1,33 @@
1
+ module Workarea
2
+ class UpdateEmail
3
+ include Sidekiq::Worker
4
+ include Sidekiq::CallbacksWorker
5
+
6
+ sidekiq_options(
7
+ enqueue_on: { User => :update, with: -> { [id, changes] } }
8
+ )
9
+
10
+ def perform(id, changes)
11
+ return unless changes['email'].present? && changes['email'].first.present?
12
+
13
+ old_email, new_email = changes['email']
14
+ update_payment_profile(id, old_email, new_email)
15
+ update_metrics(old_email, new_email)
16
+ end
17
+
18
+ def update_payment_profile(id, old_email, new_email)
19
+ user = User.find(id)
20
+ user.email = old_email # set old email so we lookup by old email value
21
+
22
+ Payment::Profile.update_email(PaymentReference.new(user), new_email)
23
+ end
24
+
25
+ def update_metrics(old_email, new_email)
26
+ old_metrics = Metrics::User.find(old_email) rescue nil
27
+ return if old_metrics.blank?
28
+
29
+ new_metrics = Metrics::User.find_or_initialize_by(id: new_email)
30
+ new_metrics.merge!(old_metrics)
31
+ end
32
+ end
33
+ end
@@ -38,7 +38,7 @@ namespace :workarea do
38
38
  author: author
39
39
  }
40
40
 
41
- if subject.start_with?('Revert')
41
+ if subject.start_with?('Revert "')
42
42
  reverts << body.match(/[a-f0-9]{40}/)
43
43
  reverts << sha
44
44
  end
@@ -140,6 +140,7 @@ require 'workarea/ext/mongoid/find_ordered'
140
140
  require 'workarea/ext/sprockets/ruby_processor'
141
141
  require 'workarea/ext/jbuilder/jbuilder_append_partials'
142
142
  require 'workarea/ext/jbuilder/jbuilder_cache'
143
+ require 'workarea/ext/referer_parser/parser.decorator'
143
144
 
144
145
  if Rails.env.development?
145
146
  require 'workarea/ext/freedom_patches/routes_reloader'
@@ -0,0 +1,43 @@
1
+ module RefererParser
2
+ # This code is actually in `master` branch of
3
+ # https://github.com/snowplow-referer-parser/ruby-referer-parser but
4
+ # has not yet been released. It's used to allow through android-app://
5
+ # URLs.
6
+ decorate Parser do
7
+ # Given a string or URI, return a hash of data
8
+ def parse(obj)
9
+ url = obj.is_a?(URI) ? obj : URI.parse(obj.to_s)
10
+
11
+ unless ['android-app', 'http', 'https'].include?(url.scheme)
12
+ raise InvalidUriError, "Only Android-App, HTTP, and HTTPS schemes are supported -- #{url.scheme}"
13
+ end
14
+
15
+ data = { known: false, uri: url.to_s }
16
+
17
+ domain, name_key = domain_and_name_key_for(url)
18
+ if domain && name_key
19
+ referer_data = @name_hash[name_key]
20
+ data[:known] = true
21
+ data[:source] = referer_data[:source]
22
+ data[:medium] = referer_data[:medium]
23
+ data[:domain] = domain
24
+
25
+ # Parse parameters if the referer uses them
26
+ if url.query && referer_data[:parameters]
27
+ query_params = CGI.parse(url.query)
28
+ referer_data[:parameters].each do |param|
29
+ # If there is a matching parameter, get the first non-blank value
30
+ unless (values = query_params[param]).empty?
31
+ data[:term] = values.reject { |v| v.strip == '' }.first
32
+ break if data[:term]
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ data
39
+ rescue URI::InvalidURIError
40
+ raise InvalidUriError.new("Unable to parse URI, not a URI? -- #{obj.inspect}", $ERROR_INFO)
41
+ end
42
+ end
43
+ end
@@ -2,7 +2,7 @@ module Workarea
2
2
  module VERSION
3
3
  MAJOR = 3
4
4
  MINOR = 4
5
- PATCH = 38
5
+ PATCH = 43
6
6
  PRE = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
@@ -0,0 +1,20 @@
1
+ require 'test_helper'
2
+
3
+ module RefererParser
4
+ class ParserTest < Workarea::TestCase
5
+ def test_parse_android_app_referrers
6
+ referrers = [
7
+ 'android-app://com.linkedin.android',
8
+ 'android-app://org.telegram.plus',
9
+ 'android-app://com.twitter.android'
10
+ ]
11
+
12
+ referrers.each do |uri|
13
+ referrer = Parser.new.parse(uri)
14
+
15
+ refute(referrer[:known])
16
+ assert_equal(uri, referrer[:uri])
17
+ end
18
+ end
19
+ end
20
+ end
@@ -74,6 +74,57 @@ module Workarea
74
74
  assert_equal(50, two.revenue_percentile)
75
75
  assert_equal(50, two.average_order_value_percentile)
76
76
  end
77
+
78
+ def test_merging_metrics
79
+ freeze_time
80
+
81
+ first = User.create!(
82
+ first_order_at: 2.weeks.ago,
83
+ last_order_at: 1.day.ago,
84
+ orders: 2,
85
+ revenue: 100,
86
+ discounts: -10,
87
+ average_order_value: 50,
88
+ )
89
+
90
+ first.merge!(User.new)
91
+ first.reload
92
+ assert_equal(1, Metrics::User.count)
93
+ assert_equal(2.weeks.ago, first.first_order_at)
94
+ assert_equal(1.day.ago, first.last_order_at)
95
+ assert_equal(2, first.orders)
96
+ assert_equal(100, first.revenue)
97
+ assert_equal(-10, first.discounts)
98
+ assert_equal(50, first.average_order_value)
99
+
100
+ second = User.create!(id: 'foo').tap { |u| u.merge!(first) }
101
+ second.reload
102
+ assert_equal(1, Metrics::User.count)
103
+ assert_equal(2.weeks.ago, second.first_order_at)
104
+ assert_equal(1.day.ago, second.last_order_at)
105
+ assert_equal(2, second.orders)
106
+ assert_equal(100, second.revenue)
107
+ assert_equal(-10, second.discounts)
108
+ assert_equal(50, second.average_order_value)
109
+
110
+ third = User.create!(
111
+ first_order_at: 3.weeks.ago,
112
+ last_order_at: 3.weeks.ago,
113
+ orders: 2,
114
+ revenue: 120,
115
+ average_order_value: 60,
116
+ )
117
+
118
+ third.merge!(second)
119
+ third.reload
120
+ assert_equal(1, Metrics::User.count)
121
+ assert_equal(3.weeks.ago, third.first_order_at)
122
+ assert_equal(1.day.ago, third.last_order_at)
123
+ assert_equal(4, third.orders)
124
+ assert_equal(220, third.revenue)
125
+ assert_equal(-10, third.discounts)
126
+ assert_equal(55, third.average_order_value)
127
+ end
77
128
  end
78
129
  end
79
130
  end
@@ -81,6 +81,16 @@ module Workarea
81
81
  assert_equal(results.reverse, search.results)
82
82
  end
83
83
 
84
+ def test_default_sort_by_score
85
+ # Unlike other admin searches (primarily indexes), we want searching to
86
+ # default sort by score. Testing scores directly is unreliable so just
87
+ # do a simple check here.
88
+ assert_equal(
89
+ [{ _score: :desc }, { updated_at: :desc }],
90
+ AdminSearch.new.default_admin_sort
91
+ )
92
+ end
93
+
84
94
  def test_selected_sorting
85
95
  results = [
86
96
  create_product(name: 'A', variants: []),
@@ -0,0 +1,39 @@
1
+ require 'test_helper'
2
+
3
+ module Workarea
4
+ class UpdateEmailTest < TestCase
5
+ def test_updating_payment_profile
6
+ user = create_user(email: 'user@workarea.com')
7
+ profile = Payment::Profile.lookup(PaymentReference.new(user))
8
+
9
+ UpdateEmail.new.perform(user.id.to_s, 'email' => [nil, 'user@workarea.com'])
10
+ assert_equal(profile.reload.email, 'user@workarea.com')
11
+
12
+ UpdateEmail.new.perform(
13
+ user.id.to_s,
14
+ 'email' => ['user@workarea.com', 'test@workarea.com']
15
+ )
16
+ assert_equal(profile.reload.email, 'test@workarea.com')
17
+ end
18
+
19
+ def test_updating_metrics
20
+ user = create_user(email: 'user@workarea.com')
21
+ old_metrics = Metrics::User.find_or_initialize_by(id: 'user@workarea.com')
22
+ old_metrics.update!(orders: 3)
23
+
24
+ UpdateEmail.new.perform(user.id.to_s, 'email' => [nil, 'user@workarea.com'])
25
+ assert_equal(1, Metrics::User.count)
26
+ assert_equal(3, old_metrics.reload.orders)
27
+
28
+ new_metrics = Metrics::User.create!(id: 'test@workarea.com', orders: 1)
29
+
30
+ UpdateEmail.new.perform(
31
+ user.id.to_s,
32
+ 'email' => ['user@workarea.com', 'test@workarea.com']
33
+ )
34
+ assert_equal(1, Metrics::User.count)
35
+ assert_raises(Mongoid::Errors::DocumentNotFound) { old_metrics.reload }
36
+ assert_equal(4, new_metrics.reload.orders)
37
+ end
38
+ end
39
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: workarea-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.4.38
4
+ version: 3.4.43
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ben Crouse
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-19 00:00:00.000000000 Z
11
+ date: 2020-11-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -1711,7 +1711,7 @@ files:
1711
1711
  - app/workers/workarea/status_reporter.rb
1712
1712
  - app/workers/workarea/undo_release.rb
1713
1713
  - app/workers/workarea/update_elasticsearch_settings.rb
1714
- - app/workers/workarea/update_payment_profile_email.rb
1714
+ - app/workers/workarea/update_email.rb
1715
1715
  - app/workers/workarea/verify_scheduled_releases.rb
1716
1716
  - bin/rails
1717
1717
  - config/i18n-js.yml
@@ -1873,6 +1873,7 @@ files:
1873
1873
  - lib/workarea/ext/mongoid/list_field.rb
1874
1874
  - lib/workarea/ext/mongoid/moped_bson.rb
1875
1875
  - lib/workarea/ext/mongoid/timestamps_timeless.rb
1876
+ - lib/workarea/ext/referer_parser/parser.decorator
1876
1877
  - lib/workarea/ext/sprockets/ruby_processor.rb
1877
1878
  - lib/workarea/ext/sprockets/task.rb
1878
1879
  - lib/workarea/geolocation.rb
@@ -2017,6 +2018,7 @@ files:
2017
2018
  - test/lib/workarea/ext/mongoid/except_test.rb
2018
2019
  - test/lib/workarea/ext/mongoid/find_ordered_test.rb
2019
2020
  - test/lib/workarea/ext/mongoid/list_field_test.rb
2021
+ - test/lib/workarea/ext/referer_parser/parser_test.rb
2020
2022
  - test/lib/workarea/geolocation_test.rb
2021
2023
  - test/lib/workarea/lint/inconsistent_details_test.rb
2022
2024
  - test/lib/workarea/lint/products_missing_images_test.rb
@@ -2366,7 +2368,7 @@ files:
2366
2368
  - test/workers/workarea/send_refund_email_test.rb
2367
2369
  - test/workers/workarea/status_reporter_test.rb
2368
2370
  - test/workers/workarea/undo_release_test.rb
2369
- - test/workers/workarea/update_payment_profile_email_test.rb
2371
+ - test/workers/workarea/update_email_test.rb
2370
2372
  - test/workers/workarea/verify_scheduled_releases_test.rb
2371
2373
  - vendor/active_shipping/.gitignore
2372
2374
  - vendor/active_shipping/.travis.yml
@@ -1,22 +0,0 @@
1
- module Workarea
2
- class UpdatePaymentProfileEmail
3
- include Sidekiq::Worker
4
- include Sidekiq::CallbacksWorker
5
-
6
- sidekiq_options(
7
- enqueue_on: { User => :update, with: -> { [id, changes] } }
8
- )
9
-
10
- def perform(id, changes)
11
- if changes['email'].present? && changes['email'].first.present?
12
- old_email = changes['email'].first
13
- new_email = changes['email'].last
14
-
15
- user = User.find(id)
16
- user.email = old_email # set old email so we lookup by old email value
17
-
18
- Payment::Profile.update_email(PaymentReference.new(user), new_email)
19
- end
20
- end
21
- end
22
- end
@@ -1,27 +0,0 @@
1
- require 'test_helper'
2
-
3
- module Workarea
4
- class UpdatePaymentProfileEmailTest < Workarea::TestCase
5
- setup do
6
- @user = create_user(email: 'user@workarea.com')
7
- @profile = Payment::Profile.lookup(PaymentReference.new(@user))
8
- @worker = UpdatePaymentProfileEmail.new
9
- end
10
-
11
- def test_updating_payment_profile_email_address
12
- @worker.perform(
13
- @user.id.to_s,
14
- 'email' => ['user@workarea.com', 'test@workarea.com']
15
- )
16
-
17
- @profile.reload
18
- assert_equal(@profile.email, 'test@workarea.com')
19
- end
20
-
21
- def test_skipping_update_if_email_change_is_nil
22
- @worker.perform(@user.id.to_s, 'email' => [nil, 'user@workarea.com'])
23
- @profile.reload
24
- assert_equal(@profile.email, 'user@workarea.com')
25
- end
26
- end
27
- end