workarea-core 3.5.0.beta.1 → 3.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/workarea/current_tracking.rb +4 -0
- data/app/models/workarea/checkout/collect_payment.rb +5 -5
- data/app/models/workarea/data_file/operation.rb +4 -0
- data/app/models/workarea/fulfillment/policies/base.rb +0 -4
- data/app/models/workarea/fulfillment/policies/{ignore.rb → shipping.rb} +2 -2
- data/app/models/workarea/fulfillment/sku.rb +0 -2
- data/app/models/workarea/insights/trending_searches.rb +8 -1
- data/app/models/workarea/metrics/search_by_day.rb +2 -0
- data/app/models/workarea/order.rb +12 -2
- data/app/models/workarea/order/item.rb +28 -2
- data/app/models/workarea/pricing/calculators/tax_calculator.rb +2 -2
- data/app/models/workarea/pricing/discount.rb +3 -2
- data/app/models/workarea/releasable.rb +3 -5
- data/app/models/workarea/reports/custom_event.rb +22 -0
- data/app/models/workarea/search/admin/releasable.rb +18 -6
- data/app/models/workarea/segment/life_cycle.rb +5 -5
- data/app/models/workarea/segment/rules/last_order.rb +9 -2
- data/app/models/workarea/segment/rules/traffic_referrer.rb +16 -5
- data/app/models/workarea/segmentable.rb +13 -0
- data/app/models/workarea/traffic_referrer.rb +3 -0
- data/app/queries/workarea/alerts.rb +21 -0
- data/app/queries/workarea/order_item_details.rb +16 -16
- data/app/queries/workarea/search/admin_index_search.rb +2 -1
- data/app/queries/workarea/search/product_display_rules.rb +0 -2
- data/app/services/workarea/direct_upload.rb +5 -0
- data/app/services/workarea/packaging.rb +1 -1
- data/app/workers/workarea/deactivate_stale_discounts.rb +1 -1
- data/app/workers/workarea/synchronize_user_metrics.rb +9 -0
- data/config/locales/en.yml +22 -0
- data/lib/tasks/migrate.rake +9 -12
- data/lib/workarea/configuration.rb +6 -6
- data/lib/workarea/configuration/redis.rb +21 -3
- data/lib/workarea/core.rb +3 -0
- data/lib/workarea/ext/freedom_patches/referer_parser.rb +7 -0
- data/lib/workarea/ext/mongoid/embedded_children.rb +20 -0
- data/lib/workarea/latest_version.rb +24 -0
- data/lib/workarea/ping_home_base.rb +0 -1
- data/lib/workarea/version.rb +1 -1
- data/lib/workarea/visit.rb +5 -2
- data/lib/workarea/warnings.rb +6 -6
- data/test/lib/workarea/ext/mongoid/embedded_children_test.rb +32 -0
- data/test/lib/workarea/latest_version_test.rb +11 -0
- data/test/models/workarea/checkout/collect_payment_test.rb +6 -6
- data/test/models/workarea/data_file/csv_test.rb +15 -0
- data/test/models/workarea/fulfillment/sku_test.rb +5 -5
- data/test/models/workarea/insights/cold_searches_test.rb +13 -11
- data/test/models/workarea/insights/hot_searches_test.rb +13 -11
- data/test/models/workarea/insights/searches_to_improve_test.rb +9 -6
- data/test/models/workarea/insights/star_searches_test.rb +5 -4
- data/test/models/workarea/insights/trending_searches_test.rb +12 -9
- data/test/models/workarea/pricing/calculators/tax_calculator_test.rb +1 -1
- data/test/models/workarea/search/admin/releasable_test.rb +5 -7
- data/test/models/workarea/segment/life_cycle_test.rb +5 -0
- data/test/models/workarea/segment/rules/last_order_test.rb +15 -3
- data/test/models/workarea/segment/rules/traffic_referrer_test.rb +10 -8
- data/test/models/workarea/segmentable_test.rb +18 -0
- data/test/queries/workarea/alerts_test.rb +11 -0
- data/test/queries/workarea/order_item_details_test.rb +4 -12
- data/test/services/workarea/direct_upload_test.rb +3 -0
- data/test/vcr_cassettes/get_latest_version.yml +90 -0
- data/test/workers/workarea/deactivate_stale_discounts_test.rb +2 -2
- data/workarea-core.gemspec +2 -3
- metadata +16 -25
- data/app/controllers/workarea/current_referrer.rb +0 -14
- data/app/models/workarea/fulfillment/policies/ship.rb +0 -15
@@ -45,24 +45,24 @@ module Workarea
|
|
45
45
|
@fulfillment ||= Fulfillment::Sku.find_or_initialize_by(id: sku)
|
46
46
|
end
|
47
47
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
48
|
+
def to_h
|
49
|
+
Rails.cache.fetch(cache_key, expires_in: cache_expiration) do
|
50
|
+
{
|
51
|
+
product_id: product.id,
|
52
|
+
product_attributes: product.as_document,
|
53
|
+
category_ids: category_ids,
|
54
|
+
discountable: pricing.discountable?,
|
55
|
+
fulfillment: fulfillment.policy
|
56
|
+
}
|
57
|
+
end
|
56
58
|
end
|
57
59
|
|
58
|
-
def
|
59
|
-
{
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
requires_shipping: requires_shipping?
|
65
|
-
}
|
60
|
+
def cache_key
|
61
|
+
"order_item_details/#{product.cache_key}/#{sku}"
|
62
|
+
end
|
63
|
+
|
64
|
+
def cache_expiration
|
65
|
+
Workarea.config.cache_expirations.order_item_details
|
66
66
|
end
|
67
67
|
end
|
68
68
|
end
|
@@ -119,7 +119,8 @@ module Workarea
|
|
119
119
|
TermsFacet.new(self, 'type'),
|
120
120
|
TermsFacet.new(self, 'status'),
|
121
121
|
TermsFacet.new(self, 'tags'),
|
122
|
-
TermsFacet.new(self, 'upcoming_changes')
|
122
|
+
TermsFacet.new(self, 'upcoming_changes'),
|
123
|
+
TermsFacet.new(self, 'active_by_segment')
|
123
124
|
]
|
124
125
|
end
|
125
126
|
end
|
@@ -7,6 +7,9 @@ module Workarea
|
|
7
7
|
url = "#{uri.scheme}://#{uri.host}"
|
8
8
|
url += ":#{uri.port}" unless uri.port.in? [80, 443]
|
9
9
|
|
10
|
+
redis_key = "cors_#{url.optionize}"
|
11
|
+
return if Workarea.redis.get(redis_key) == 'true'
|
12
|
+
|
10
13
|
Workarea.s3.put_bucket_cors(
|
11
14
|
Configuration::S3.bucket,
|
12
15
|
'CORSConfiguration' => [
|
@@ -18,6 +21,8 @@ module Workarea
|
|
18
21
|
}
|
19
22
|
]
|
20
23
|
)
|
24
|
+
|
25
|
+
Workarea.redis.set(redis_key, 'true')
|
21
26
|
end
|
22
27
|
|
23
28
|
attr_reader :type, :filename
|
@@ -29,7 +29,7 @@ module Workarea
|
|
29
29
|
|
30
30
|
def all_active_discount_ids
|
31
31
|
Pricing::Discount
|
32
|
-
.where(:
|
32
|
+
.where(:updated_at.lt => Workarea.config.discount_staleness_ttl.ago)
|
33
33
|
.select(&:active?)
|
34
34
|
.map(&:id)
|
35
35
|
.map(&:to_s)
|
@@ -8,6 +8,15 @@ module Workarea
|
|
8
8
|
queue: 'low'
|
9
9
|
)
|
10
10
|
|
11
|
+
# It's essential for the {Metrics::User#admin} field always be in sync, so
|
12
|
+
# we always want this worker enabled.
|
13
|
+
#
|
14
|
+
# @return [Boolean]
|
15
|
+
#
|
16
|
+
def self.enabled?
|
17
|
+
true
|
18
|
+
end
|
19
|
+
|
11
20
|
def perform(id)
|
12
21
|
user = User.find(id)
|
13
22
|
metrics = Metrics::User.find_or_create_by(id: user.email)
|
data/config/locales/en.yml
CHANGED
@@ -50,6 +50,28 @@ en:
|
|
50
50
|
unit: instance
|
51
51
|
csv:
|
52
52
|
unit: row
|
53
|
+
duration:
|
54
|
+
years:
|
55
|
+
one: '%{count} year'
|
56
|
+
other: '%{count} years'
|
57
|
+
months:
|
58
|
+
one: '%{count} month'
|
59
|
+
other: '%{count} months'
|
60
|
+
weeks:
|
61
|
+
one: '%{count} week'
|
62
|
+
other: '%{count} weeks'
|
63
|
+
days:
|
64
|
+
one: '%{count} day'
|
65
|
+
other: '%{count} days'
|
66
|
+
hours:
|
67
|
+
one: '%{count} hour'
|
68
|
+
other: '%{count} hours'
|
69
|
+
minutes:
|
70
|
+
one: '%{count} minute'
|
71
|
+
other: '%{count} minutes'
|
72
|
+
seconds:
|
73
|
+
one: '%{count} second'
|
74
|
+
other: '%{count} seconds'
|
53
75
|
errors:
|
54
76
|
messages:
|
55
77
|
contains_type: cannot contain 'type'
|
data/lib/tasks/migrate.rake
CHANGED
@@ -35,18 +35,6 @@ namespace :workarea do
|
|
35
35
|
|
36
36
|
puts "✅ #{count} tax categories updated."
|
37
37
|
|
38
|
-
Workarea::Catalog::Product.each_by(500) do |product|
|
39
|
-
next unless product.digital?
|
40
|
-
|
41
|
-
product.skus.each do |sku|
|
42
|
-
fulfillment = Workarea::Fulfillment::Sku.find_or_initialize_by(id: sku)
|
43
|
-
fulfillment.policy = 'ignore'
|
44
|
-
fulfillment.save!
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
puts "✅ #{count} fulfillment skus for digital product have been created."
|
49
|
-
|
50
38
|
count = 0
|
51
39
|
failed_ids = []
|
52
40
|
backup = Mongo::Collection.new(Mongoid::Clients.default.database, 'workarea_legacy_segments')
|
@@ -100,6 +88,15 @@ namespace :workarea do
|
|
100
88
|
puts "The segments that failed are #{failed_ids.to_sentence}."
|
101
89
|
end
|
102
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
|
+
|
103
100
|
puts "\nMigration complete!"
|
104
101
|
end
|
105
102
|
end
|
@@ -821,8 +821,7 @@ module Workarea
|
|
821
821
|
# recommended as the default policy.
|
822
822
|
config.fulfillment_policies = SwappableList.new(
|
823
823
|
%w(
|
824
|
-
Workarea::Fulfillment::Policies::
|
825
|
-
Workarea::Fulfillment::Policies::Ignore
|
824
|
+
Workarea::Fulfillment::Policies::Shipping
|
826
825
|
Workarea::Fulfillment::Policies::Download
|
827
826
|
)
|
828
827
|
)
|
@@ -877,6 +876,7 @@ module Workarea
|
|
877
876
|
config.cache_expirations.sitemap_fragment_cache = 1.day
|
878
877
|
config.cache_expirations.free_gift_attributes = 1.hour
|
879
878
|
config.cache_expirations.reports = 1.hour
|
879
|
+
config.cache_expirations.order_item_details = 15.minutes
|
880
880
|
|
881
881
|
# Send transactional emails. Allows default transaction emails to be
|
882
882
|
# disabled when using third-party email services.
|
@@ -1257,14 +1257,14 @@ module Workarea
|
|
1257
1257
|
# setting to configure the `:encoding` options for `CSV.foreach`
|
1258
1258
|
# if your CSV files are failing to import with a UTF-8 encoding
|
1259
1259
|
# error.
|
1260
|
-
config.csv_import_options = {}
|
1260
|
+
config.csv_import_options = { encoding: 'bom|utf-8' }
|
1261
1261
|
|
1262
1262
|
# Determines what payment action happens when "place order" is submitted.
|
1263
1263
|
# These correspond to methods on the {Checkout}'s instance of {Payment}
|
1264
1264
|
config.checkout_payment_action = {
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1265
|
+
shipping: 'authorize!',
|
1266
|
+
partial_shipping: 'purchase!',
|
1267
|
+
no_shipping: 'purchase!'
|
1268
1268
|
}
|
1269
1269
|
|
1270
1270
|
# Class used to determine if an order is fraudlent
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Workarea
|
2
2
|
module Configuration
|
3
3
|
class Redis
|
4
|
-
DEFAULT = { host: 'localhost', port: 6379, db: 0 }.freeze
|
4
|
+
DEFAULT = { host: 'localhost', port: 6379, db: 0, scheme: 'redis' }.freeze
|
5
5
|
|
6
6
|
class << self
|
7
7
|
# Used for Sidekiq and Predictor
|
@@ -39,11 +39,15 @@ module Workarea
|
|
39
39
|
return from_config if from_config.present?
|
40
40
|
|
41
41
|
env_slug = name.to_s.underscore.upcase
|
42
|
+
scheme = ENV["WORKAREA_#{env_slug}_SCHEME"].presence || DEFAULT[:scheme]
|
42
43
|
|
43
44
|
{
|
45
|
+
scheme: scheme,
|
44
46
|
host: ENV["WORKAREA_#{env_slug}_HOST"].presence || DEFAULT[:host],
|
45
47
|
port: ENV["WORKAREA_#{env_slug}_PORT"].presence || DEFAULT[:port],
|
46
|
-
db: ENV["WORKAREA_#{env_slug}_DB"].presence || DEFAULT[:db]
|
48
|
+
db: ENV["WORKAREA_#{env_slug}_DB"].presence || DEFAULT[:db],
|
49
|
+
password: ENV["WORKAREA_#{env_slug}_PASSWORD"].presence,
|
50
|
+
ssl: scheme == 'rediss' ? true : false
|
47
51
|
}
|
48
52
|
end
|
49
53
|
end
|
@@ -55,10 +59,22 @@ module Workarea
|
|
55
59
|
@config = config.to_h.deep_symbolize_keys
|
56
60
|
end
|
57
61
|
|
62
|
+
def scheme
|
63
|
+
@config[:scheme]
|
64
|
+
end
|
65
|
+
|
66
|
+
def ssl
|
67
|
+
@config[:ssl]
|
68
|
+
end
|
69
|
+
|
58
70
|
def host
|
59
71
|
@config[:host]
|
60
72
|
end
|
61
73
|
|
74
|
+
def password
|
75
|
+
@config[:password]
|
76
|
+
end
|
77
|
+
|
62
78
|
def port
|
63
79
|
@config[:port]
|
64
80
|
end
|
@@ -68,7 +84,9 @@ module Workarea
|
|
68
84
|
end
|
69
85
|
|
70
86
|
def to_url
|
71
|
-
base = "
|
87
|
+
base = "#{scheme}://"
|
88
|
+
base << "admin:#{password}@" if password.present?
|
89
|
+
base << "#{host}"
|
72
90
|
base << ":#{port}" if port.present?
|
73
91
|
base << "/#{db}" if db.present?
|
74
92
|
base
|
data/lib/workarea/core.rb
CHANGED
@@ -131,6 +131,7 @@ require 'workarea/ext/freedom_patches/dragonfly_job_fetch_url'
|
|
131
131
|
require 'workarea/ext/freedom_patches/dragonfly_callable_url_host'
|
132
132
|
require 'workarea/ext/freedom_patches/active_support_duration'
|
133
133
|
require 'workarea/ext/freedom_patches/premailer'
|
134
|
+
require 'workarea/ext/freedom_patches/referer_parser'
|
134
135
|
require 'workarea/ext/mongoid/list_field'
|
135
136
|
require 'workarea/ext/mongoid/each_by'
|
136
137
|
require 'workarea/ext/mongoid/except'
|
@@ -141,6 +142,7 @@ require 'workarea/ext/mongoid/lookup_hash'
|
|
141
142
|
require 'workarea/ext/active_shipping/workarea'
|
142
143
|
require 'workarea/ext/mongoid/audit_log_entry.decorator'
|
143
144
|
require 'workarea/ext/mongoid/find_ordered'
|
145
|
+
require 'workarea/ext/mongoid/embedded_children'
|
144
146
|
require 'workarea/ext/sprockets/ruby_processor'
|
145
147
|
require 'workarea/ext/jbuilder/jbuilder_append_partials'
|
146
148
|
|
@@ -218,6 +220,7 @@ require 'workarea/string_id'
|
|
218
220
|
require 'workarea/mail_interceptor'
|
219
221
|
require 'workarea/visit'
|
220
222
|
require 'workarea/warnings'
|
223
|
+
require 'workarea/latest_version'
|
221
224
|
|
222
225
|
#
|
223
226
|
# Core
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Document
|
3
|
+
# Returns all the embedded children in this document by recursion.
|
4
|
+
#
|
5
|
+
# @return [Array<Mongoid::Document>]
|
6
|
+
#
|
7
|
+
def embedded_children
|
8
|
+
result = []
|
9
|
+
|
10
|
+
embedded_relations.each do |name, metadata|
|
11
|
+
Array.wrap(send(name)).each do |child|
|
12
|
+
result << child
|
13
|
+
result += child.embedded_children
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
result
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Workarea
|
2
|
+
module LatestVersion
|
3
|
+
def self.get
|
4
|
+
Rails.cache.fetch('workarea/version/latest', expires_in: 3.days) do
|
5
|
+
request = Net::HTTP::Get.new('/api/v1/gems/workarea.json')
|
6
|
+
request.content_type = 'application/json'
|
7
|
+
|
8
|
+
uri = URI('https://rubygems.org')
|
9
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
10
|
+
http.use_ssl = true
|
11
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
12
|
+
response = http.start { |h| h.request(request) }
|
13
|
+
|
14
|
+
JSON.parse(response.body)['version']
|
15
|
+
end
|
16
|
+
rescue Exception => e
|
17
|
+
Rails.logger.error '-------------------------------------'
|
18
|
+
Rails.logger.error "There was an error contacting rubygems.org!"
|
19
|
+
Rails.logger.error e.class
|
20
|
+
Rails.logger.error e.message
|
21
|
+
Rails.logger.error '-------------------------------------'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/workarea/version.rb
CHANGED
data/lib/workarea/visit.rb
CHANGED
@@ -64,8 +64,11 @@ module Workarea
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def referrer
|
67
|
-
|
68
|
-
|
67
|
+
@referrer ||= begin
|
68
|
+
value = cookies['workarea_referrer'].presence || request.referrer
|
69
|
+
attributes = Workarea.referrer_parser.parse(value) rescue {}
|
70
|
+
TrafficReferrer.new(attributes)
|
71
|
+
end
|
69
72
|
end
|
70
73
|
|
71
74
|
def browser
|
data/lib/workarea/warnings.rb
CHANGED
@@ -75,16 +75,16 @@ of items in the order.
|
|
75
75
|
You should set Workarea.config.checkout_payment_action instead. You can set it
|
76
76
|
for each type of order, here are the defaults:
|
77
77
|
{
|
78
|
-
|
79
|
-
|
80
|
-
|
78
|
+
shipping: 'authorize!',
|
79
|
+
partial_shipping: 'authorize!',
|
80
|
+
no_shipping: 'purchase!'
|
81
81
|
}
|
82
82
|
|
83
83
|
To achieve the same functionality as Workarea.config.auto_capture, you'd set:
|
84
84
|
{
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
shipping: 'purchase!',
|
86
|
+
partial_shipping: 'purchase!',
|
87
|
+
no_shipping: 'purchase!'
|
88
88
|
}
|
89
89
|
|
90
90
|
**************************************************
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
class EmbeddedChildrenTest < Workarea::TestCase
|
5
|
+
class Parent
|
6
|
+
include Mongoid::Document
|
7
|
+
embeds_one :child, class_name: 'Mongoid::EmbeddedChildrenTest::Child'
|
8
|
+
embeds_many :children, class_name: 'Mongoid::EmbeddedChildrenTest::Child'
|
9
|
+
end
|
10
|
+
|
11
|
+
class Child
|
12
|
+
include Mongoid::Document
|
13
|
+
field :name, type: String
|
14
|
+
embeds_one :grandchild, class_name: 'Mongoid::EmbeddedChildrenTest::Grandchild'
|
15
|
+
embeds_many :grandchildren, class_name: 'Mongoid::EmbeddedChildrenTest::Grandchild'
|
16
|
+
end
|
17
|
+
|
18
|
+
class Grandchild
|
19
|
+
include Mongoid::Document
|
20
|
+
field :name, type: String
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_embedded_children
|
24
|
+
model = Parent.create!(
|
25
|
+
child: { name: '1', grandchild: { name: '2' } },
|
26
|
+
children: [{ name: '3' }, { name: '4', grandchildren: [{ name: '5' }] }]
|
27
|
+
)
|
28
|
+
|
29
|
+
assert_equal(%w(1 2 3 4 5), model.embedded_children.map(&:name))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|