workarea-core 3.5.18 → 3.5.23

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/workarea/current_tracking.rb +6 -2
  3. data/app/controllers/workarea/impersonation.rb +2 -1
  4. data/app/models/workarea/metrics/user.rb +18 -8
  5. data/app/models/workarea/order/item.rb +4 -4
  6. data/app/models/workarea/release.rb +8 -0
  7. data/app/models/workarea/release/changeset.rb +4 -1
  8. data/app/models/workarea/search/admin.rb +1 -1
  9. data/app/models/workarea/search/admin/inventory_sku.rb +5 -1
  10. data/app/models/workarea/search/storefront.rb +1 -5
  11. data/app/models/workarea/search/storefront/product.rb +1 -14
  12. data/app/models/workarea/shipping/service.rb +12 -5
  13. data/app/models/workarea/tax/rate.rb +3 -1
  14. data/app/queries/workarea/product_releases.rb +1 -11
  15. data/app/queries/workarea/search/product_entries.rb +12 -6
  16. data/app/workers/workarea/update_email.rb +33 -0
  17. data/config/initializers/00_configuration.rb +20 -6
  18. data/config/initializers/05_scheduled_jobs.rb +1 -1
  19. data/config/initializers/22_session_store.rb +1 -1
  20. data/config/locales/en.yml +1 -0
  21. data/lib/workarea.rb +10 -0
  22. data/lib/workarea/changelog.rake +1 -1
  23. data/lib/workarea/configuration.rb +4 -1
  24. data/lib/workarea/configuration/administrable_options.rb +2 -1
  25. data/lib/workarea/scheduled_jobs.rb +1 -1
  26. data/lib/workarea/version.rb +1 -1
  27. data/lib/workarea/visit.rb +8 -1
  28. data/lib/workarea/warnings.rb +1 -1
  29. data/test/integration/workarea/authentication_test.rb +2 -1
  30. data/test/lib/workarea/scheduled_jobs_test.rb +1 -5
  31. data/test/models/workarea/data_file/csv_test.rb +2 -1
  32. data/test/models/workarea/metrics/user_test.rb +55 -52
  33. data/test/models/workarea/order/item_test.rb +9 -0
  34. data/test/models/workarea/shipping/service_test.rb +26 -0
  35. data/test/workers/workarea/status_reporter_test.rb +3 -1
  36. data/test/workers/workarea/update_email_test.rb +39 -0
  37. data/workarea-core.gemspec +1 -1
  38. metadata +6 -6
  39. data/app/workers/workarea/update_payment_profile_email.rb +0 -22
  40. data/test/workers/workarea/update_payment_profile_email_test.rb +0 -27
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84d99f1dbf010e7d67b9dbc7785720bbed5cd17c22528dfe57e194dfbb660892
4
- data.tar.gz: c5453a27cf96335ae9d35fe857ccc770a0412117579b37dc1cb84e9221cd6efe
3
+ metadata.gz: edc99891d1b58bf06d070ed152b77852db6ebb0bd9e3b023faafaf93079c1626
4
+ data.tar.gz: b7095d6fecc6996d72eb680c6a4a7baa8d10769aad48204c0afe7080cd425c14
5
5
  SHA512:
6
- metadata.gz: 4605fd9a72741e6cac8ab7a32d2408ba1b8f2bfb79ac875875461ab59fe660ffd5254e3b0eb69d5534222217de0ec2fc3d60351bee5e7575d93d2393fb8d9221
7
- data.tar.gz: e2946da1f9618bc92f65ceca4281c426747f4c75d162b33e68a6fe629008507c43e07dcde39e12f871b2f0011225f40bfd5d9ecdc8d7f563586b90900f43c447
6
+ metadata.gz: 4d6fc54dbd4f849840c8cfeff3c97061539e99e124898df794e2ea7ac8ef36bc532c92209e99acbfb669dcfff70932dd3bf49b8cbdf70cce88eebda9f8ca45a1
7
+ data.tar.gz: 1bb8092da0dfb2fb9c8f774b90a9be3a352d55e4261550471dffb0dd761d2d75e713544bfd96cd8836b448cbee382bfc7234e5a724bd5dc8ae9cbdb2adfb5702
@@ -1,7 +1,6 @@
1
1
  module Workarea
2
2
  module CurrentTracking
3
3
  extend ActiveSupport::Concern
4
- include HttpCaching
5
4
 
6
5
  included do
7
6
  before_action :ensure_current_metrics
@@ -27,7 +26,12 @@ module Workarea
27
26
  if email.blank?
28
27
  cookies.delete(:email)
29
28
  elsif email != cookies.signed[:email]
30
- Metrics::User.find_or_initialize_by(id: email).merge!(current_visit&.metrics)
29
+ unless impersonating?
30
+ Metrics::User
31
+ .find_or_initialize_by(id: email)
32
+ .merge_views!(current_visit&.metrics)
33
+ end
34
+
31
35
  cookies.permanent.signed[:email] = email
32
36
  end
33
37
 
@@ -15,10 +15,11 @@ module Workarea
15
15
  session[:user_id] = user.id.to_s
16
16
 
17
17
  user.mark_impersonated_by!(current_user)
18
- @current_user = user
18
+ update_tracking!(email: user.email)
19
19
  end
20
20
 
21
21
  def stop_impersonation
22
+ update_tracking!(email: current_admin.email)
22
23
  session[:user_id] = current_admin.id.to_s
23
24
  session.delete(:admin_id)
24
25
  end
@@ -110,6 +110,8 @@ module Workarea
110
110
  end
111
111
 
112
112
  def merge!(other)
113
+ return if other.blank?
114
+
113
115
  # To recalculate average_order_value
114
116
  self.orders += other.orders
115
117
  self.revenue += other.revenue
@@ -132,14 +134,8 @@ module Workarea
132
134
  update['$max'] = { last_order_at: other.last_order_at.utc } if other.last_order_at.present?
133
135
 
134
136
  self.class.collection.update_one({ _id: id }, update, upsert: true)
137
+ other.delete
135
138
 
136
- self.class.save_affinity(
137
- id: id,
138
- action: 'viewed',
139
- product_ids: other.viewed.product_ids,
140
- category_ids: other.viewed.category_ids,
141
- search_ids: other.viewed.search_ids
142
- )
143
139
  self.class.save_affinity(
144
140
  id: id,
145
141
  action: 'purchased',
@@ -148,7 +144,21 @@ module Workarea
148
144
  search_ids: other.purchased.search_ids
149
145
  )
150
146
 
151
- reload
147
+ merge_views!(other)
148
+ end
149
+
150
+ def merge_views!(other)
151
+ return if other.blank?
152
+
153
+ self.class.save_affinity(
154
+ id: id,
155
+ action: 'viewed',
156
+ product_ids: other.viewed.product_ids,
157
+ category_ids: other.viewed.category_ids,
158
+ search_ids: other.viewed.search_ids
159
+ )
160
+
161
+ reload rescue self # save_affinity might not have actually persisted anything
152
162
  end
153
163
  end
154
164
  end
@@ -33,17 +33,17 @@ module Workarea
33
33
  # To allow for custom policies defining their own methods here
34
34
  Workarea.config.fulfillment_policies.each do |class_name|
35
35
  define_method "#{class_name.demodulize.underscore}?" do
36
- fulfillment == class_name.demodulize.underscore
36
+ fulfilled_by?(class_name.demodulize.underscore)
37
37
  end
38
38
  end
39
39
 
40
40
  # These methods exist for findability
41
41
  def shipping?
42
- fulfillment == 'shipping'
42
+ fulfilled_by?('shipping')
43
43
  end
44
44
 
45
45
  def download?
46
- fulfillment == 'download'
46
+ fulfilled_by?('download')
47
47
  end
48
48
 
49
49
  # Whether this order has any items that need to be fulfilled by a particular
@@ -53,7 +53,7 @@ module Workarea
53
53
  # @return [Boolean]
54
54
  #
55
55
  def fulfilled_by?(*types)
56
- types.any? { |t| send("#{t}?") }
56
+ types.map(&:to_s).include?(fulfillment)
57
57
  end
58
58
 
59
59
  # Whether this item is a digital (not-shipped) type of item.
@@ -129,6 +129,14 @@ module Workarea
129
129
  scoped.sort_by { |r| [r.publish_at, r.created_at] }
130
130
  end
131
131
 
132
+ def self.schedule_affected_by_changesets(changesets)
133
+ changesets
134
+ .uniq(&:release)
135
+ .reject { |cs| cs.release.blank? }
136
+ .flat_map { |cs| [cs.release] + cs.release.scheduled_after }
137
+ .uniq
138
+ end
139
+
132
140
  def as_current
133
141
  self.class.with_current(self) { yield }
134
142
  end
@@ -15,7 +15,10 @@ module Workarea
15
15
  belongs_to :release, class_name: 'Workarea::Release', index: true
16
16
  belongs_to :releasable, polymorphic: true, index: true, optional: true
17
17
 
18
- index({ 'document_path.type' => 1, 'document_path.document_id' => 1 })
18
+ index(
19
+ { 'document_path.type' => 1, 'document_path.document_id' => 1 },
20
+ { name: 'document_path' }
21
+ )
19
22
  index('changeset.product_ids' => 1)
20
23
  index('original.product_ids' => 1)
21
24
  index('releasable_type' => 1, 'releasable_id' => 1)
@@ -38,7 +38,7 @@ module Workarea
38
38
  aggregation = search(query)['aggregations']['grouped_by_type']['type']
39
39
  aggregation['buckets']
40
40
  .reduce([]) { |m, b| m + b['top']['hits']['hits'] }
41
- .sort_by { |r| [r['_source']['jump_to_position'], r['_score']] }
41
+ .sort_by { |r| [r['_source']['jump_to_position'] || 999, r['_score'] || 0] }
42
42
  .map do |result|
43
43
  {
44
44
  label: result['_source']['jump_to_text'],
@@ -11,7 +11,11 @@ module Workarea
11
11
  end
12
12
 
13
13
  def jump_to_text
14
- "#{model.id} (#{model.available} available)"
14
+ I18n.t(
15
+ 'workarea.inventory_sku.jump_to_text',
16
+ id: model.id,
17
+ count: model.available_to_sell
18
+ )
15
19
  end
16
20
 
17
21
  def jump_to_position
@@ -83,11 +83,7 @@ module Workarea
83
83
  end
84
84
 
85
85
  def releases
86
- changesets
87
- .uniq(&:release)
88
- .reject { |cs| cs.release.blank? }
89
- .flat_map { |cs| [cs.release] + cs.release.scheduled_after }
90
- .uniq
86
+ Release.schedule_affected_by_changesets(changesets)
91
87
  end
92
88
 
93
89
  def as_document
@@ -122,21 +122,8 @@ module Workarea
122
122
  ProductPrimaryImageUrl.new(model).path
123
123
  end
124
124
 
125
- # All {Releasable}s that could affect the product's Elasticsearch document
126
- # should add their changesets to this method.
127
- #
128
- # @example Add to the changesets affecting a product in a decorator
129
- # def changesets
130
- # super.merge(SomeReleasable.for_product(product.id).changesets_with_children)
131
- # end
132
- #
133
- # @return [Mongoid::Criteria]
134
- #
135
125
  def changesets
136
- criteria = model.changesets_with_children
137
- pricing.each { |ps| criteria.merge!(ps.changesets_with_children) }
138
- criteria.merge!(FeaturedProducts.changesets(model.id))
139
- criteria.includes(:release)
126
+ ProductReleases.new(model).changesets
140
127
  end
141
128
 
142
129
  private
@@ -37,15 +37,22 @@ module Workarea
37
37
  end
38
38
 
39
39
  def self.by_price(price)
40
- cache.select do |method|
41
- (method.subtotal_min.nil? || method.subtotal_min <= price) &&
42
- (method.subtotal_max.nil? || method.subtotal_max >= price)
40
+ cache.select do |service|
41
+ (service.subtotal_min.nil? || service.subtotal_min <= price) &&
42
+ (service.subtotal_max.nil? || service.subtotal_max >= price)
43
43
  end
44
44
  end
45
45
 
46
46
  def self.find_tax_code(carrier, name)
47
- method = find_by(carrier: carrier, name: name) rescue nil
48
- method.try(:tax_code)
47
+ service = find_by(carrier: carrier, name: name) rescue nil
48
+ service.present? ? service.tax_code : default_tax_code(carrier, name)
49
+ end
50
+
51
+ def self.default_tax_code(carrier, name)
52
+ default = Workarea.config.default_shipping_service_tax_code
53
+ return default unless default.respond_to?(:call)
54
+
55
+ default.call(carrier, name)
49
56
  end
50
57
 
51
58
  def find_rate(price = 0.to_m)
@@ -57,7 +57,9 @@ module Workarea
57
57
  percentage_field = super
58
58
  return percentage_field unless percentage_field.zero?
59
59
 
60
- country_percentage + region_percentage + postal_code_percentage
60
+ [country_percentage, region_percentage, postal_code_percentage]
61
+ .compact
62
+ .sum
61
63
  end
62
64
  end
63
65
  end
@@ -1,10 +1,4 @@
1
1
  module Workarea
2
- #
3
- # TODO remove in v3.6
4
- #
5
- # This is no longer used, this logic was moved into the search models to allow
6
- # it to be used for any model (not just products).
7
- #
8
2
  class ProductReleases
9
3
  attr_reader :product
10
4
 
@@ -13,11 +7,7 @@ module Workarea
13
7
  end
14
8
 
15
9
  def releases
16
- changesets
17
- .uniq(&:release)
18
- .reject { |cs| cs.release.blank? }
19
- .flat_map { |cs| [cs.release] + cs.release.scheduled_after }
20
- .uniq
10
+ Release.schedule_affected_by_changesets(changesets)
21
11
  end
22
12
 
23
13
  # All {Releasable}s that could affect the product's Elasticsearch document
@@ -18,17 +18,23 @@ module Workarea
18
18
 
19
19
  def live_entries
20
20
  @live_entries ||= @products.reduce([]) do |memo, product|
21
- memo + Array.wrap(index_entries_for(product.without_release))
21
+ memo + live_entries_for(product)
22
22
  end
23
23
  end
24
24
 
25
25
  def release_entries
26
- @release_entries ||= @products.reduce([]) do |results, product|
27
- releases = ProductReleases.new(product).releases
26
+ @release_entries ||= @products.reduce([]) do |memo, product|
27
+ memo + release_entries_for(product)
28
+ end
29
+ end
30
+
31
+ def live_entries_for(product)
32
+ Array.wrap(index_entries_for(product.without_release))
33
+ end
28
34
 
29
- results + releases.reduce([]) do |memo, release|
30
- memo + Array.wrap(index_entries_for(product.in_release(release)))
31
- end
35
+ def release_entries_for(product)
36
+ ProductReleases.new(product).releases.reduce([]) do |memo, release|
37
+ memo + Array.wrap(index_entries_for(product.in_release(release)))
32
38
  end
33
39
  end
34
40
 
@@ -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
@@ -76,6 +76,17 @@ Workarea::Configuration.define_fields do
76
76
  zip: '19106'
77
77
  },
78
78
  description: 'Origin location for calculating shipping costs'
79
+
80
+ # This can be overwritten within the app to use a proc for more complex
81
+ # scenarios.
82
+ field 'Default Shipping Service Tax Code',
83
+ type: String,
84
+ allow_blank: true,
85
+ description: %(
86
+ Tax code assigned to shipping options when an existing service does
87
+ not exist. This is useful for third-party gateways to assign tax codes
88
+ to dynamically generated options.
89
+ ).squish
79
90
  end
80
91
 
81
92
  fieldset 'Payment', namespaced: false do
@@ -116,11 +127,6 @@ Workarea::Configuration.define_fields do
116
127
  end
117
128
 
118
129
  fieldset 'Search', namespaced: false do
119
- field 'Default Search Facet Result Sizes',
120
- type: :integer,
121
- default: 10,
122
- description: 'The number of filter results returned for each filter type.'
123
-
124
130
  field 'Search Facet Result Sizes',
125
131
  type: :hash,
126
132
  values_type: :integer,
@@ -128,7 +134,15 @@ Workarea::Configuration.define_fields do
128
134
  description: %(
129
135
  The number of filter results returned for any specified filter type. If no
130
136
  size is defined for a filter type, the default will be what is specified
131
- in the default config above.
137
+ in the default config below.
138
+ ).squish
139
+
140
+ field 'Default Search Facet Result Sizes',
141
+ type: :integer,
142
+ default: 10,
143
+ description: %(
144
+ The number of filter results returned for each filter type when not
145
+ specified above.
132
146
  ).squish
133
147
 
134
148
  field 'Search Size Facet Sort',
@@ -1,4 +1,4 @@
1
- unless Workarea.config.skip_service_connections
1
+ unless Workarea.skip_services?
2
2
  Sidekiq::Cron::Job.create(
3
3
  name: 'Workarea::CleanInventoryTransactions',
4
4
  klass: 'Workarea::CleanInventoryTransactions',
@@ -7,5 +7,5 @@ env_expire_after = ENV['WORKAREA_SESSION_STORE_EXPIRE_AFTER']
7
7
  Rails.application.config.session_store(
8
8
  :cookie_store,
9
9
  key: "_#{Rails.application.class.name.deconstantize.underscore}_session",
10
- expire_after: env_expire_after.present? ? env_expire_after.to_i : 2.weeks
10
+ expire_after: env_expire_after.present? ? env_expire_after.to_i : 30.minutes
11
11
  )
@@ -102,6 +102,7 @@ en:
102
102
  name: "Fulfillment SKU %{id}"
103
103
  inventory_sku:
104
104
  name: "Inventory %{id}"
105
+ jump_to_text: "%{id} (%{count} sellable)"
105
106
  inquiry:
106
107
  subjects: {}
107
108
  order:
@@ -182,6 +182,16 @@ module Workarea
182
182
  def self.deprecation
183
183
  @deprecation ||= ActiveSupport::Deprecation.new('3.6', 'Workarea')
184
184
  end
185
+
186
+ # Whether the app should skip connecting to external services on boot,
187
+ # such as Mongo, Elasticsearch, or Redis. Note that this will break
188
+ # functionality relying on these services.
189
+ #
190
+ # @return [Boolean]
191
+ #
192
+ def self.skip_services?
193
+ !!(ENV['WORKAREA_SKIP_SERVICES'] =~ /true/)
194
+ end
185
195
  end
186
196
 
187
197
  require 'workarea/core'
@@ -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
@@ -940,7 +940,10 @@ module Workarea
940
940
 
941
941
  # Whether the app should skip connecting to external services on boot,
942
942
  # such as Mongo, Elasticsearch, or Redis.
943
- config.skip_service_connections = ENV['WORKAREA_SKIP_SERVICES'].to_s =~ /true/
943
+ #
944
+ # @deprecated Use `Workarea.skip_services?` instead
945
+ #
946
+ config.skip_service_connections = Workarea.skip_services?
944
947
 
945
948
  # This is a feature flag, which enables localized active fields. If you're
946
949
  # upgrading, you can set this to false to avoid having to do a MongoDB
@@ -12,7 +12,8 @@ module Workarea
12
12
  private
13
13
 
14
14
  def check_fieldsets?(name)
15
- ::Mongoid.clients.any? &&
15
+ !Workarea.skip_services? &&
16
+ ::Mongoid.clients.any? &&
16
17
  Configuration::Admin.fields.keys.include?(name.to_s)
17
18
  end
18
19
  end
@@ -5,7 +5,7 @@ module Workarea
5
5
  # removing a previously scheduled job from initializers doesn't
6
6
  # actually stop the job from being enqueued.
7
7
  def self.clean
8
- return if Workarea.config.skip_service_connections
8
+ return if Workarea.skip_services?
9
9
 
10
10
  Sidekiq::Cron::Job.all.each do |job|
11
11
  job.destroy unless const_defined?(job.klass)
@@ -2,7 +2,7 @@ module Workarea
2
2
  module VERSION
3
3
  MAJOR = 3
4
4
  MINOR = 5
5
- PATCH = 18
5
+ PATCH = 23
6
6
  PRE = nil
7
7
  STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
8
8
 
@@ -6,7 +6,6 @@ module Workarea
6
6
  attr_writer :override_segments
7
7
 
8
8
  delegate :postal_code, :city, :subdivision, :region, :country, to: :geolocation
9
- delegate :admin?, to: :metrics
10
9
 
11
10
  def initialize(env)
12
11
  @env = env
@@ -25,6 +24,14 @@ module Workarea
25
24
  session[:user_id].present?
26
25
  end
27
26
 
27
+ def impersonating?
28
+ session[:admin_id].present?
29
+ end
30
+
31
+ def admin?
32
+ (logged_in? && impersonating?) || metrics.admin?
33
+ end
34
+
28
35
  def request
29
36
  @request ||= ActionDispatch::Request.new(env)
30
37
  end
@@ -26,7 +26,7 @@ find their preference.
26
26
 
27
27
  def check_mongo_notable_scan
28
28
  if (Rails.env.development? &&
29
- !Workarea.config.skip_service_connections &&
29
+ !Workarea.skip_services? &&
30
30
  Configuration::Mongoid.indexes_enforced?)
31
31
  warn <<~eos
32
32
  **************************************************
@@ -3,8 +3,9 @@ require 'test_helper'
3
3
  module Workarea
4
4
  class AuthenticationTest < IntegrationTest
5
5
  class AuthenticationController < Workarea::ApplicationController
6
- include Authentication
7
6
  include HttpCaching
7
+ include Authentication
8
+ include Impersonation
8
9
  include Storefront::CurrentCheckout
9
10
 
10
11
  before_action :cache_page, only: :cached
@@ -15,12 +15,8 @@ module Workarea
15
15
  end
16
16
 
17
17
  def test_redis_not_available
18
- @_skip_services = Workarea.config.skip_service_connections
19
- Workarea.config.skip_service_connections = true
20
-
18
+ Workarea.stubs(skip_services?: true)
21
19
  assert_nil(ScheduledJobs.clean)
22
- ensure
23
- Workarea.config.skip_service_connections = @_skip_services
24
20
  end
25
21
  end
26
22
  end
@@ -309,7 +309,8 @@ module Workarea
309
309
  end
310
310
 
311
311
  def test_blank_rows_are_ignored
312
- model = Foo.new(id: nil)
312
+ model = Foo.new
313
+ Foo.fields.keys.each { |f| model.send("#{f}=", nil) }
313
314
 
314
315
  import = create_import(
315
316
  model_type: Foo.name,
@@ -134,7 +134,7 @@ module Workarea
134
134
  def test_merging_metrics
135
135
  freeze_time
136
136
 
137
- metrics = User.create!(
137
+ first = User.create!(
138
138
  first_order_at: 2.weeks.ago,
139
139
  last_order_at: 1.day.ago,
140
140
  orders: 2,
@@ -147,41 +147,43 @@ module Workarea
147
147
  purchased: { product_ids: ['qoo'], category_ids: ['quo'], search_ids: ['qux'] }
148
148
  )
149
149
 
150
- metrics.merge!(User.new)
151
- metrics.reload
152
- assert_equal(2.weeks.ago, metrics.first_order_at)
153
- assert_equal(1.day.ago, metrics.last_order_at)
154
- assert_equal(2, metrics.orders)
155
- assert_equal(100, metrics.revenue)
156
- assert_equal(-10, metrics.discounts)
157
- assert_equal(50, metrics.average_order_value)
158
- assert_equal(1, metrics.cancellations)
159
- assert_equal(-20, metrics.refund)
160
- assert_equal(['foo'], metrics.viewed.product_ids)
161
- assert_equal(['bar'], metrics.viewed.category_ids)
162
- assert_equal(['baz'], metrics.viewed.search_ids)
163
- assert_equal(['qoo'], metrics.purchased.product_ids)
164
- assert_equal(['quo'], metrics.purchased.category_ids)
165
- assert_equal(['qux'], metrics.purchased.search_ids)
166
-
167
- blank = User.create!(id: 'foo').tap { |u| u.merge!(metrics) }
168
- blank.reload
169
- assert_equal(2.weeks.ago, blank.first_order_at)
170
- assert_equal(1.day.ago, blank.last_order_at)
171
- assert_equal(2, blank.orders)
172
- assert_equal(100, blank.revenue)
173
- assert_equal(-10, blank.discounts)
174
- assert_equal(50, blank.average_order_value)
175
- assert_equal(1, blank.cancellations)
176
- assert_equal(-20, blank.refund)
177
- assert_equal(['foo'], blank.viewed.product_ids)
178
- assert_equal(['bar'], blank.viewed.category_ids)
179
- assert_equal(['baz'], blank.viewed.search_ids)
180
- assert_equal(['qoo'], blank.purchased.product_ids)
181
- assert_equal(['quo'], blank.purchased.category_ids)
182
- assert_equal(['qux'], blank.purchased.search_ids)
183
-
184
- existing = User.create!(
150
+ first.merge!(User.new)
151
+ first.reload
152
+ assert_equal(1, Metrics::User.count)
153
+ assert_equal(2.weeks.ago, first.first_order_at)
154
+ assert_equal(1.day.ago, first.last_order_at)
155
+ assert_equal(2, first.orders)
156
+ assert_equal(100, first.revenue)
157
+ assert_equal(-10, first.discounts)
158
+ assert_equal(50, first.average_order_value)
159
+ assert_equal(1, first.cancellations)
160
+ assert_equal(-20, first.refund)
161
+ assert_equal(['foo'], first.viewed.product_ids)
162
+ assert_equal(['bar'], first.viewed.category_ids)
163
+ assert_equal(['baz'], first.viewed.search_ids)
164
+ assert_equal(['qoo'], first.purchased.product_ids)
165
+ assert_equal(['quo'], first.purchased.category_ids)
166
+ assert_equal(['qux'], first.purchased.search_ids)
167
+
168
+ second = User.create!(id: 'foo').tap { |u| u.merge!(first) }
169
+ second.reload
170
+ assert_equal(1, Metrics::User.count)
171
+ assert_equal(2.weeks.ago, second.first_order_at)
172
+ assert_equal(1.day.ago, second.last_order_at)
173
+ assert_equal(2, second.orders)
174
+ assert_equal(100, second.revenue)
175
+ assert_equal(-10, second.discounts)
176
+ assert_equal(50, second.average_order_value)
177
+ assert_equal(1, second.cancellations)
178
+ assert_equal(-20, second.refund)
179
+ assert_equal(['foo'], second.viewed.product_ids)
180
+ assert_equal(['bar'], second.viewed.category_ids)
181
+ assert_equal(['baz'], second.viewed.search_ids)
182
+ assert_equal(['qoo'], second.purchased.product_ids)
183
+ assert_equal(['quo'], second.purchased.category_ids)
184
+ assert_equal(['qux'], second.purchased.search_ids)
185
+
186
+ third = User.create!(
185
187
  first_order_at: 3.weeks.ago,
186
188
  last_order_at: 3.weeks.ago,
187
189
  orders: 2,
@@ -191,22 +193,23 @@ module Workarea
191
193
  purchased: { product_ids: ['four'], category_ids: ['five'], search_ids: ['six'] }
192
194
  )
193
195
 
194
- existing.merge!(metrics)
195
- existing.reload
196
- assert_equal(3.weeks.ago, existing.first_order_at)
197
- assert_equal(1.day.ago, existing.last_order_at)
198
- assert_equal(4, existing.orders)
199
- assert_equal(220, existing.revenue)
200
- assert_equal(-10, existing.discounts)
201
- assert_equal(55, existing.average_order_value)
202
- assert_equal(1, existing.cancellations)
203
- assert_equal(-20, existing.refund)
204
- assert_equal(%w(one foo), existing.viewed.product_ids)
205
- assert_equal(%w(two bar), existing.viewed.category_ids)
206
- assert_equal(%w(three baz), existing.viewed.search_ids)
207
- assert_equal(%w(four qoo), existing.purchased.product_ids)
208
- assert_equal(%w(five quo), existing.purchased.category_ids)
209
- assert_equal(%w(six qux), existing.purchased.search_ids)
196
+ third.merge!(second)
197
+ third.reload
198
+ assert_equal(1, Metrics::User.count)
199
+ assert_equal(3.weeks.ago, third.first_order_at)
200
+ assert_equal(1.day.ago, third.last_order_at)
201
+ assert_equal(4, third.orders)
202
+ assert_equal(220, third.revenue)
203
+ assert_equal(-10, third.discounts)
204
+ assert_equal(55, third.average_order_value)
205
+ assert_equal(1, third.cancellations)
206
+ assert_equal(-20, third.refund)
207
+ assert_equal(%w(one foo), third.viewed.product_ids)
208
+ assert_equal(%w(two bar), third.viewed.category_ids)
209
+ assert_equal(%w(three baz), third.viewed.search_ids)
210
+ assert_equal(%w(four qoo), third.purchased.product_ids)
211
+ assert_equal(%w(five quo), third.purchased.category_ids)
212
+ assert_equal(%w(six qux), third.purchased.search_ids)
210
213
  end
211
214
  end
212
215
  end
@@ -55,6 +55,15 @@ module Workarea
55
55
  )
56
56
  assert(item.on_sale?)
57
57
  end
58
+
59
+ def test_fulfilled_by?
60
+ item.fulfillment = 'shipping'
61
+ assert(item.fulfilled_by?(:shipping))
62
+ assert(item.fulfilled_by?(:shipping, :download))
63
+ refute(item.fulfilled_by?(:download))
64
+ assert(item.shipping?)
65
+ refute(item.download?)
66
+ end
58
67
  end
59
68
  end
60
69
  end
@@ -35,6 +35,32 @@ module Workarea
35
35
  assert_equal(3.to_m, shipping_service.find_rate(7.to_m).price)
36
36
  assert_equal(2.to_m, shipping_service.find_rate(10.to_m).price)
37
37
  end
38
+
39
+ def test_find_tax_code
40
+ create_shipping_service(name: 'Ground', carrier: 'UPS', tax_code: '001')
41
+ create_shipping_service(name: 'Express', carrier: 'UPS', tax_code: nil)
42
+ Workarea.config.default_shipping_service_tax_code = nil
43
+
44
+ assert_equal('001', Service.find_tax_code('UPS', 'Ground'))
45
+ assert_nil(Service.find_tax_code('UPS', 'Express'))
46
+ assert_nil(Service.find_tax_code('FedEx', 'Express'))
47
+
48
+ Workarea.config.default_shipping_service_tax_code = '101'
49
+
50
+ assert_equal('001', Service.find_tax_code('UPS', 'Ground'))
51
+ assert_nil(Service.find_tax_code('UPS', 'Express'))
52
+ assert_equal('101', Service.find_tax_code('FedEx', 'Express'))
53
+ assert_equal('101', Service.find_tax_code('FedEx', 'Express'))
54
+
55
+ Workarea.config.default_shipping_service_tax_code = -> (carrier, name) do
56
+ carrier == 'FedEx' ? '101' : '001'
57
+ end
58
+
59
+ assert_equal('001', Service.find_tax_code('UPS', 'Ground'))
60
+ assert_nil(Service.find_tax_code('UPS', 'Express'))
61
+ assert_equal('101', Service.find_tax_code('FedEx', 'Express'))
62
+ assert_equal('001', Service.find_tax_code('DHL', 'Overnight'))
63
+ end
38
64
  end
39
65
  end
40
66
  end
@@ -12,8 +12,10 @@ module Workarea
12
12
 
13
13
  StatusReporter.new.perform
14
14
 
15
- assert(2, ActionMailer::Base.deliveries.count)
15
+ assert_equal(2, ActionMailer::Base.deliveries.count)
16
+
16
17
  delivery_emails = ActionMailer::Base.deliveries.map(&:to).flatten
18
+
17
19
  assert(delivery_emails.include?('foo@workarea.com'))
18
20
  assert(delivery_emails.include?('bar@workarea.com'))
19
21
  end
@@ -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
@@ -59,7 +59,7 @@ Gem::Specification.new do |s|
59
59
  s.add_dependency 'i18n-js', '~> 3.2.1'
60
60
  s.add_dependency 'local_time', '~> 1.0.3'
61
61
  s.add_dependency 'lodash-rails', '~> 4.17.4'
62
- s.add_dependency 'jquery-rails', '~> 4.3.1'
62
+ s.add_dependency 'jquery-rails', '~> 4.4.0'
63
63
  s.add_dependency 'jquery-ui-rails', '~> 6.0.1'
64
64
  s.add_dependency 'tooltipster-rails', '~> 4.1.2'
65
65
  s.add_dependency 'chart-js-rails', '~> 0.0.9' # TODO remove v4
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.5.18
4
+ version: 3.5.23
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-09-01 00:00:00.000000000 Z
11
+ date: 2020-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -646,14 +646,14 @@ dependencies:
646
646
  requirements:
647
647
  - - "~>"
648
648
  - !ruby/object:Gem::Version
649
- version: 4.3.1
649
+ version: 4.4.0
650
650
  type: :runtime
651
651
  prerelease: false
652
652
  version_requirements: !ruby/object:Gem::Requirement
653
653
  requirements:
654
654
  - - "~>"
655
655
  - !ruby/object:Gem::Version
656
- version: 4.3.1
656
+ version: 4.4.0
657
657
  - !ruby/object:Gem::Dependency
658
658
  name: jquery-ui-rails
659
659
  requirement: !ruby/object:Gem::Requirement
@@ -1795,7 +1795,7 @@ files:
1795
1795
  - app/workers/workarea/status_reporter.rb
1796
1796
  - app/workers/workarea/synchronize_user_metrics.rb
1797
1797
  - app/workers/workarea/update_elasticsearch_settings.rb
1798
- - app/workers/workarea/update_payment_profile_email.rb
1798
+ - app/workers/workarea/update_email.rb
1799
1799
  - app/workers/workarea/verify_scheduled_releases.rb
1800
1800
  - bin/rails
1801
1801
  - config/i18n-js.yml
@@ -2499,7 +2499,7 @@ files:
2499
2499
  - test/workers/workarea/send_refund_email_test.rb
2500
2500
  - test/workers/workarea/status_reporter_test.rb
2501
2501
  - test/workers/workarea/synchronize_user_metrics_test.rb
2502
- - test/workers/workarea/update_payment_profile_email_test.rb
2502
+ - test/workers/workarea/update_email_test.rb
2503
2503
  - test/workers/workarea/verify_scheduled_releases_test.rb
2504
2504
  - vendor/active_shipping/.gitignore
2505
2505
  - 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