workarea-core 3.5.13 → 3.5.18

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/workarea/impersonation.rb +2 -1
  3. data/app/mailers/workarea/application_mailer.rb +4 -1
  4. data/app/middleware/workarea/application_middleware.rb +5 -2
  5. data/app/models/workarea/checkout.rb +7 -7
  6. data/app/models/workarea/data_file/csv.rb +9 -1
  7. data/app/models/workarea/inquiry.rb +2 -1
  8. data/app/models/workarea/inventory/sku.rb +2 -2
  9. data/app/models/workarea/metrics/user.rb +24 -8
  10. data/app/models/workarea/order.rb +10 -0
  11. data/app/models/workarea/payment.rb +1 -6
  12. data/app/models/workarea/search/storefront/category_query.rb +1 -1
  13. data/app/queries/workarea/search/admin_search.rb +4 -0
  14. data/app/queries/workarea/search/admin_sorting.rb +1 -1
  15. data/app/services/workarea/index_release_schedule_previews.rb +37 -0
  16. data/app/workers/workarea/index_release_schedule_change.rb +32 -0
  17. data/app/workers/workarea/publish_release.rb +1 -0
  18. data/config/initializers/00_configuration.rb +3 -2
  19. data/config/locales/en.yml +2 -0
  20. data/lib/generators/workarea/install/install_generator.rb +13 -0
  21. data/lib/generators/workarea/install/templates/initializer.rb.erb +1 -13
  22. data/lib/tasks/cache.rake +3 -33
  23. data/lib/tasks/help.rake +4 -43
  24. data/lib/tasks/insights.rake +3 -35
  25. data/lib/tasks/migrate.rake +3 -96
  26. data/lib/tasks/search.rake +6 -68
  27. data/lib/tasks/services.rake +4 -54
  28. data/lib/workarea/configuration.rb +11 -2
  29. data/lib/workarea/configuration/administrable_options.rb +1 -5
  30. data/lib/workarea/core.rb +1 -0
  31. data/lib/workarea/core/engine.rb +4 -0
  32. data/lib/workarea/ext/jbuilder/jbuilder_cache.rb +29 -0
  33. data/lib/workarea/tasks/cache.rb +43 -0
  34. data/lib/workarea/tasks/help.rb +55 -0
  35. data/lib/workarea/tasks/insights.rb +47 -0
  36. data/lib/workarea/tasks/migrate.rb +106 -0
  37. data/lib/workarea/tasks/search.rb +105 -0
  38. data/lib/workarea/tasks/services.rb +71 -0
  39. data/lib/workarea/version.rb +1 -1
  40. data/test/generators/workarea/install_generator_test.rb +6 -2
  41. data/test/mailers/workarea/application_mailer_test.rb +10 -0
  42. data/test/models/workarea/checkout_test.rb +57 -0
  43. data/test/models/workarea/data_file/import_test.rb +40 -0
  44. data/test/models/workarea/search/storefront/category_query_test.rb +11 -0
  45. data/test/queries/workarea/search/admin_search_test.rb +10 -0
  46. data/test/services/workarea/index_release_schedule_previews_test.rb +28 -0
  47. data/test/workers/workarea/{reindex_release_test.rb → index_release_schedule_change_test.rb} +30 -4
  48. data/test/workers/workarea/publish_release_test.rb +24 -0
  49. data/workarea-core.gemspec +2 -2
  50. metadata +17 -8
  51. data/app/workers/workarea/reindex_release.rb +0 -42
@@ -1,49 +1,17 @@
1
- require 'active_support/testing/time_helpers'
1
+ require 'workarea/tasks/insights'
2
2
 
3
3
  namespace :workarea do
4
4
  namespace :insights do
5
5
  desc 'Creates metrics and insights based on orders'
6
6
  task generate: :environment do
7
- include ActiveSupport::Testing::TimeHelpers
8
- batch_size = ENV['WORKAREA_INSIGHTS_BATCH_SIZE'].presence || 1000
9
-
10
- Workarea::Order
11
- .placed
12
- .each_by(batch_size.to_i) { |o| Workarea::SaveOrderMetrics.perform(o) }
13
-
14
- 8.times do |i|
15
- travel_to (i.weeks.ago.beginning_of_week + 1.hour)
16
- Workarea::GenerateInsights.generate_all!
17
- end
18
-
7
+ Workarea::Tasks::Insights.generate
19
8
  puts "Success! Generated #{Workarea::Insights::Base.count} insights."
20
9
  end
21
10
 
22
11
  # Clear the metrics/insights environment - deletes lots of data, this task
23
12
  # is very dangerous! Useful for testing/debugging.
24
13
  task reset: :environment do
25
- Workarea::Order
26
- .where(:metrics_saved_at.gt => 0)
27
- .update_all(metrics_saved_at: nil)
28
-
29
-
30
- Workarea::Metrics::CategoryByDay.delete_all
31
- Workarea::Metrics::CountryByDay.delete_all
32
- Workarea::Metrics::DiscountByDay.delete_all
33
- Workarea::Metrics::MenuByDay.delete_all
34
- Workarea::Metrics::ProductByDay.delete_all
35
- Workarea::Metrics::ProductByWeek.delete_all
36
- Workarea::Metrics::ProductForLastWeek.delete_all
37
- Workarea::Metrics::SalesByDay.delete_all
38
- Workarea::Metrics::SearchByDay.delete_all
39
- Workarea::Metrics::SearchByWeek.delete_all
40
- Workarea::Metrics::SearchForLastWeek.delete_all
41
- Workarea::Metrics::SkuByDay.delete_all
42
- Workarea::Metrics::TenderByDay.delete_all
43
- Workarea::Metrics::TrafficReferrerByDay.delete_all
44
- Workarea::Metrics::User.delete_all
45
- Workarea::Insights::Base.delete_all
46
-
14
+ Workarea::Tasks::Insights.reset!
47
15
  puts "Success! Insights and metrics have been cleared."
48
16
  end
49
17
  end
@@ -1,103 +1,10 @@
1
+ require 'workarea/tasks/migrate'
2
+
1
3
  namespace :workarea do
2
4
  namespace :migrate do
3
5
  desc 'Migrate the database from v3.4 to v3.5'
4
6
  task v3_5: :environment do
5
- count = 0
6
-
7
- Workarea::Release.where(:undo_at.gte => Time.current).each do |release|
8
- undo = release.build_undo(publish_at: release.undo_at).tap(&:save!)
9
-
10
- release.changesets.each do |changeset|
11
- changeset.build_undo(release: undo).save!
12
- end
13
-
14
- Workarea::Scheduler.delete(release.undo_job_id)
15
-
16
- release.update_attributes!(undo_at: nil, undo_job_id: nil)
17
- count += 1
18
- end
19
-
20
- Workarea::Release.all.each { |r| Workarea::IndexAdminSearch.perform(r) }
21
-
22
- puts "✅ #{count} undo releases have been created."
23
-
24
- count = 0
25
-
26
- Workarea::Tax::Category.all.each_by(100) do |category|
27
- category.rates.each_by(500) do |rate|
28
- rate.postal_code_percentage = rate.percentage
29
- rate.percentage = nil
30
- end
31
-
32
- category.save!
33
- count += 1
34
- end
35
-
36
- puts "✅ #{count} tax categories updated."
37
-
38
- count = 0
39
- failed_ids = []
40
- backup = Mongo::Collection.new(Mongoid::Clients.default.database, 'workarea_legacy_segments')
41
-
42
- legacy_segments = Workarea::Segment.collection.find.to_a
43
- legacy_segments.each do |doc|
44
- backup.insert_one(doc)
45
- Workarea::Segment.collection.delete_one(doc.slice('_id'))
46
-
47
- segment = Workarea::Segment.new(
48
- id: doc['_id'],
49
- name: doc['name'],
50
- subscribed_user_ids: doc['subscribed_user_ids'],
51
- created_at: doc['created_at'],
52
- updated_at: doc['updated_at']
53
- )
54
-
55
- doc['conditions'].each do |condition|
56
- if condition['_type'] =~ /UserTag/
57
- segment.rules << Workarea::Segment::Rules::Tags.new(tags: condition['tags'])
58
- elsif condition['_type'] =~ /TotalSpent/
59
- rule = Workarea::Segment::Rules::Revenue.new
60
-
61
- if condition['operator'] == 'equals'
62
- rule.minimum = rule.maximum = Money.demongoize(condition['amount'])
63
- elsif condition['operator'] == 'less_than_or_equals'
64
- rule.maximum = Money.demongoize(condition['amount'])
65
- elsif condition['operator'] == 'less_than'
66
- rule.maximum = (Money.demongoize(condition['amount']) - 0.01.to_m)
67
- elsif condition['operator'] == 'greater_than_or_equals'
68
- rule.minimum = Money.demongoize(condition['amount'])
69
- elsif condition['operator'] == 'greater_than'
70
- rule.minimum = (Money.demongoize(condition['amount']) + 0.01.to_m)
71
- end
72
-
73
- segment.rules << rule
74
- end
75
- end
76
-
77
- if doc['conditions'].size == segment.rules.size && segment.save
78
- count += 1
79
- else
80
- failed_ids << doc['_id']
81
- end
82
- end
83
-
84
- puts "✅ #{count} segments have been migrated." if count > 0
85
- if failed_ids.any?
86
- puts "⛔️ #{failed_ids.count} segments failed to migrate."
87
- puts "You can find copies of the original segments in the workarea_legacy_segments collection."
88
- puts "The segments that failed are #{failed_ids.to_sentence}."
89
- end
90
-
91
- Workarea::Segment::LifeCycle.create!
92
- puts "✅ Life cycle segments have been created."
93
-
94
- admin_ids = Workarea::User.admins.pluck(:id)
95
- admin_ids.each do |id|
96
- Workarea::SynchronizeUserMetrics.new.perform(id)
97
- end
98
- puts "✅ #{admin_ids.count} admins have had their metrics synchronized." if admin_ids.count > 0
99
-
100
- puts "\nMigration complete!"
7
+ Workarea::Tasks::Migrate.v3_5
101
8
  end
102
9
  end
103
10
  end
@@ -1,8 +1,9 @@
1
+ require 'workarea/tasks/search'
2
+
1
3
  namespace :workarea do
2
4
  namespace :search_index do
3
5
  def setup
4
- require 'sidekiq/testing/inline' unless ENV['INLINE'] == 'false'
5
- Workarea.config.bulk_index_batch_size = ENV['BATCH_SIZE'].to_i if ENV['BATCH_SIZE'].present?
6
+ Workarea::Tasks::Search.setup
6
7
  end
7
8
 
8
9
  desc 'Reindex all data'
@@ -16,84 +17,21 @@ namespace :workarea do
16
17
  task admin: :environment do
17
18
  setup
18
19
  puts 'Indexing admin...'
19
- Workarea::QueuesPauser.with_paused_queues do
20
- Workarea::Search::Admin.reset_indexes!
21
- end
22
-
23
- Mongoid.models.each do |klass|
24
- next unless Workarea::Search::Admin.for(klass.first).present?
25
-
26
- klass.all.each_slice_of(Workarea.config.bulk_index_batch_size) do |models|
27
- Workarea::BulkIndexAdmin.perform_by_models(models)
28
- end
29
- end
30
-
31
- Workarea.config.jump_to_navigation.to_a.each do |tuple|
32
- Workarea::Search::Admin::Navigation.new(tuple).save
33
- end
20
+ Workarea::Tasks::Search.index_admin
34
21
  end
35
22
 
36
23
  desc 'Reindex storefront'
37
24
  task storefront: :environment do
38
25
  setup
39
26
  puts 'Indexing storefront...'
40
-
41
- Workarea::QueuesPauser.with_paused_queues do
42
- Workarea::Search::Storefront.reset_indexes!
43
- Workarea::Search::Storefront.ensure_dynamic_mappings
44
- end
45
-
46
- # This code finds all unique filters for products so we can index a sample
47
- # product for each to ensure the dynamic mappings get created.
48
- #
49
- # This is necessary to fix mapping errors from Elasticsearch when trying
50
- # to index category percolations against fields which have no mapping.
51
- #
52
- map = %{
53
- function() {
54
- for (var key in this.filters.#{I18n.locale}) {
55
- emit(key, null);
56
- }
57
- }
58
- }
59
- reduce = 'function(key) { return null; }'
60
- results = Workarea::Catalog::Product.map_reduce(map, reduce).out(inline: 1)
61
- unique_filters = results.map { |r| r['_id'] }
62
-
63
- sample_products = unique_filters.reduce([]) do |memo, filter|
64
- filter = "filters.#{I18n.locale}.#{filter}"
65
- memo << Workarea::Catalog::Product.exists(filter => true).sample
66
- end
67
-
68
- sample_products.each do |product|
69
- Workarea::Search::Storefront::Product.new(product).save
70
- end
71
-
72
- Workarea::Catalog::Category.all.each_by(Workarea.config.bulk_index_batch_size) do |category|
73
- Workarea::Search::Storefront::CategoryQuery.new(category).create
74
- Workarea::Search::Storefront::Category.new(category).save
75
- end
76
-
77
- Workarea::Content::Page.all.each_by(Workarea.config.bulk_index_batch_size) do |page|
78
- Workarea::Search::Storefront::Page.new(page).save
79
- end
80
-
81
- Workarea::BulkIndexProducts.perform
82
- Workarea::BulkIndexSearches.perform
27
+ Workarea::Tasks::Search.index_storefront
83
28
  end
84
29
 
85
30
  desc 'Reindex help'
86
31
  task help: :environment do
87
32
  setup
88
33
  puts 'Indexing help...'
89
-
90
- Workarea::QueuesPauser.with_paused_queues do
91
- Workarea::Search::Help.reset_indexes!
92
- end
93
-
94
- Workarea::Help::Article.all.each_by(Workarea.config.bulk_index_batch_size) do |help_article|
95
- Workarea::Search::Help.new(help_article).save
96
- end
34
+ Workarea::Tasks::Search.index_help
97
35
  end
98
36
  end
99
37
  end
@@ -1,73 +1,23 @@
1
- require 'workarea/version'
1
+ require 'workarea/tasks/services'
2
2
 
3
3
  namespace :workarea do
4
4
  namespace :services do
5
- def assert_docker_compose_installed!
6
- unless system('docker-compose -v > /dev/null 2>&1')
7
- STDERR.puts <<~eos
8
- **************************************************
9
- ⛔️ ERROR: workarea:services tasks depend on Docker Compose being installed. \
10
- See https://docs.docker.com/compose/install/ for how to install.
11
- **************************************************
12
- eos
13
- exit
14
- end
15
- end
16
-
17
- def compose_file_path
18
- File.join(Gem::Specification.find_by_name('workarea').gem_dir, 'docker-compose.yml')
19
- end
20
-
21
- def compose_env
22
- {
23
- 'COMPOSE_FILE' => compose_file_path,
24
- 'COMPOSE_PROJECT_NAME' => File.basename(Dir.pwd),
25
-
26
- 'MONGODB_VERSION' => Workarea::VERSION::MONGODB::STRING,
27
- 'MONGODB_PORT' => ENV['WORKAREA_MONGODB_PORT'] || '27017',
28
-
29
- 'REDIS_VERSION' => Workarea::VERSION::REDIS::STRING,
30
- 'REDIS_PORT' => ENV['WORKAREA_REDIS_PORT'] || '6379',
31
-
32
- 'ELASTICSEARCH_VERSION' => Workarea::VERSION::ELASTICSEARCH::STRING,
33
- 'ELASTICSEARCH_PORT' => ENV['WORKAREA_ELASTICSEARCH_PORT'] || '9200'
34
- }
35
- end
36
-
37
5
  desc 'Start Workarea background services for this app'
38
6
  task :up do
39
7
  puts 'Starting Workarea services...'
40
- assert_docker_compose_installed!
41
-
42
- if system(compose_env, "docker-compose up -d #{ENV['COMPOSE_ARGUMENTS']} #{ENV['WORKAREA_SERVICES']}")
43
- puts '✅ Success! Workarea services are running in the background. Run workarea:services:down to stop them.'
44
- else
45
- STDERR.puts '⛔️ Error! There was an error starting Workarea services.'
46
- end
8
+ Workarea::Tasks::Services.up
47
9
  end
48
10
 
49
11
  desc 'Stop Workarea external services for this app'
50
12
  task :down do
51
13
  puts 'Stopping Workarea services...'
52
- assert_docker_compose_installed!
53
-
54
- if system(compose_env, "docker-compose down #{ENV['COMPOSE_ARGUMENTS']}")
55
- puts '✅ Success! Workarea services are stopped. Run workarea:services:up to start them.'
56
- else
57
- STDERR.puts '⛔️ Error! There was an error stopping Workarea services.'
58
- end
14
+ Workarea::Tasks::Services.down
59
15
  end
60
16
 
61
17
  desc 'Remove data volumes associated with Workarea external services. Stops containers.'
62
18
  task :clean do
63
19
  puts 'Removing Workarea service data...'
64
- assert_docker_compose_installed!
65
-
66
- if system(compose_env, "docker-compose down -v #{ENV['COMPOSE_ARGUMENTS']}")
67
- puts '✅ Success! Workarea service volumes have been removed. Run workarea:services:up to start services and recreate volumes.'
68
- else
69
- STDERR.puts '⛔️ Error! There was an error removing Workarea service volumes.'
70
- end
20
+ Workarea::Tasks::Services.clean
71
21
  end
72
22
  end
73
23
  end
@@ -26,8 +26,6 @@ module Workarea
26
26
 
27
27
  config.site_name = 'Workarea'
28
28
  config.host = 'www.example.com'
29
- config.email_to = 'customerservice@example.com'
30
- config.email_from = 'noreply@example.com'
31
29
 
32
30
  # Config sent to the ImageMagick through Dragonfly for optimizing jpgs
33
31
  # All metadata profiles are removed, comments cleared by comment -set ""
@@ -1297,6 +1295,17 @@ module Workarea
1297
1295
 
1298
1296
  # The number of results that will show per-type in the admin jump to
1299
1297
  config.jump_to_results_per_type = 5
1298
+
1299
+ # Attributes that will be sliced out of params and persisted on
1300
+ # the credit card tender during checkout.
1301
+ config.credit_card_attributes = %i[
1302
+ month
1303
+ year
1304
+ saved_card_id
1305
+ number
1306
+ cvv
1307
+ amount
1308
+ ]
1300
1309
  end
1301
1310
  end
1302
1311
  end
@@ -1,7 +1,7 @@
1
1
  module Workarea
2
2
  module Configuration
3
3
  class AdministrableOptions < ActiveSupport::InheritableOptions
4
- def method_missing(name, *args)
4
+ def [](name)
5
5
  static_config = super
6
6
  return static_config if static_config.present? || static_config.to_s == 'false'
7
7
  return static_config unless check_fieldsets?(name)
@@ -9,10 +9,6 @@ module Workarea
9
9
  Configuration::Admin.instance.send(name)
10
10
  end
11
11
 
12
- def respond_to_missing?(name, include_private)
13
- true
14
- end
15
-
16
12
  private
17
13
 
18
14
  def check_fieldsets?(name)
@@ -146,6 +146,7 @@ require 'workarea/ext/mongoid/find_ordered'
146
146
  require 'workarea/ext/mongoid/embedded_children'
147
147
  require 'workarea/ext/sprockets/ruby_processor'
148
148
  require 'workarea/ext/jbuilder/jbuilder_append_partials'
149
+ require 'workarea/ext/jbuilder/jbuilder_cache'
149
150
 
150
151
  if Rails.env.development?
151
152
  require 'workarea/ext/freedom_patches/routes_reloader'
@@ -78,6 +78,10 @@ module Workarea
78
78
  # get autoloaded. Without this, admin actions like updating product
79
79
  # attributes raises a {NameError} "uninitialized constant BulkIndexProducts".
80
80
  require_dependency 'workarea/bulk_index_products'
81
+
82
+ # Fixes a constant error raised in middleware (when doing segmentation)
83
+ # No idea what the cause is. TODO revisit after Zeitwerk.
84
+ require_dependency 'workarea/metrics/user'
81
85
  end
82
86
  end
83
87
  end
@@ -0,0 +1,29 @@
1
+ decorate JbuilderTemplate, with: :workarea do
2
+ def _cache_fragment_for(*)
3
+ return yield if workarea_admin?
4
+
5
+ super
6
+ end
7
+
8
+ def _cache_key(*)
9
+ super.tap do |result|
10
+ result << workarea_cache_varies if workarea_cache_varies.present?
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def workarea_admin?
17
+ @context&.controller&.current_user&.admin?
18
+ rescue ::RuntimeError
19
+ false
20
+ end
21
+
22
+ def workarea_cache_varies
23
+ workarea_request_env['workarea.cache_varies']
24
+ end
25
+
26
+ def workarea_request_env
27
+ @context.controller.request.env || {}
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ module Workarea
2
+ module Tasks
3
+ module Cache
4
+ extend self
5
+
6
+ def prime_images
7
+ include Rails.application.routes.url_helpers
8
+ include Workarea::Storefront::ProductsHelper
9
+ include Workarea::Core::Engine.routes.url_helpers
10
+
11
+ built_in_jobs = [:thumb, :gif, :jpg, :png, :strip, :convert, :optimized]
12
+
13
+ jobs = Dragonfly.app(:workarea).processor_methods.reject do |job|
14
+ built_in_jobs.include?(job)
15
+ end
16
+
17
+ Workarea::Catalog::Product.all.each_by(50) do |product|
18
+ product.images.each do |image|
19
+ jobs.each do |job|
20
+ url = URI.join(
21
+ "https://#{Workarea.config.host}",
22
+ dynamic_product_image_url(
23
+ image.product.slug,
24
+ image.option,
25
+ image.id,
26
+ job,
27
+ only_path: true
28
+ )
29
+ ).to_s
30
+
31
+ begin
32
+ `curl #{url}`
33
+ puts "Downloaded image #{url}"
34
+ rescue StandardError => e
35
+ puts e.inspect
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end