atlas_engine 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/models/atlas_engine/address_validation/candidate.rb +3 -2
- data/app/models/atlas_engine/address_validation/es/candidate_selector.rb +12 -12
- data/app/models/atlas_engine/address_validation/es/validators/full_address.rb +9 -10
- data/app/models/atlas_engine/address_validation/es/validators/full_address_street.rb +1 -1
- data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +20 -20
- data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result_base.rb +4 -6
- data/app/models/atlas_engine/address_validation/validators/full_address/concern_builder.rb +8 -3
- data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb +6 -2
- data/app/models/atlas_engine/address_validation/validators/full_address/{invalid_zip_for_country_concern.rb → invalid_zip_for_country_concern_builder.rb} +14 -13
- data/app/models/atlas_engine/address_validation/validators/full_address/{invalid_zip_for_province_concern.rb → invalid_zip_for_province_concern_builder.rb} +15 -15
- data/app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb +2 -4
- data/app/models/atlas_engine/address_validation/validators/full_address/relevant_components.rb +9 -13
- data/app/models/atlas_engine/address_validation/validators/full_address/{unknown_address_concern.rb → unknown_address_concern_builder.rb} +11 -4
- data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern_builder.rb +38 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/{unknown_zip_for_address_concern.rb → unknown_zip_for_address_concern_builder.rb} +12 -10
- data/app/models/atlas_engine/address_validation/validators/full_address/{unmatched_field_concern.rb → unmatched_field_concern_builder.rb} +17 -9
- data/app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb +1 -1
- data/lib/atlas_engine/version.rb +1 -1
- metadata +8 -11
- data/app/models/atlas_engine/address_validation/candidate_tuple.rb +0 -15
- data/app/models/atlas_engine/address_validation/session.rb +0 -47
- data/app/models/atlas_engine/address_validation/validators/full_address/result_updater.rb +0 -42
- data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern.rb +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56b5b41a624c3481954aadfa0101c9883dfe3479a3cdec373f8ecccab8bae879
|
4
|
+
data.tar.gz: 73ee021ecf5d8357ae8f000df7e963e7504153fdc3b7bb98f188445aa8cd7989
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b93dee8561c73619222ca4a4e803fb2f911b3149955c5b1af7803990318a7ebd36e781c41643cf3076197f579833e9c2d361e8e4550a9d2d3de628d8e7819ef7
|
7
|
+
data.tar.gz: f2f593c6e2a7849dae6dce6a52d9402ce7d907a90511664d1218133b5d4a501b5ae98a26e54a06412c3fb37e3dc74c75ae17c575ae24fa4805c02ad888467d21
|
@@ -6,9 +6,10 @@ module AtlasEngine
|
|
6
6
|
class Candidate
|
7
7
|
extend T::Sig
|
8
8
|
attr_reader :id, :index
|
9
|
+
attr_accessor :position
|
9
10
|
|
10
|
-
sig { params(id: String, source: Hash, index: T.nilable(String)).void }
|
11
|
-
def initialize(id:, source:, index: nil)
|
11
|
+
sig { params(id: String, source: Hash, position: Integer, index: T.nilable(String)).void }
|
12
|
+
def initialize(id:, source:, position: 0, index: nil)
|
12
13
|
components_hash = Hash.new { |hash, key| hash[key] = Component.new(key, nil) }
|
13
14
|
|
14
15
|
@components = source.each_with_object(components_hash) do |(key, value), hash|
|
@@ -21,7 +21,7 @@ module AtlasEngine
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
sig { returns(T.nilable(
|
24
|
+
sig { returns(T.nilable(AddressValidation::Validators::FullAddress::AddressComparison)) }
|
25
25
|
def best_candidate
|
26
26
|
street_sequences_future = datastore.fetch_street_sequences_async
|
27
27
|
city_sequences_future = datastore.fetch_city_sequence_async
|
@@ -36,28 +36,28 @@ module AtlasEngine
|
|
36
36
|
|
37
37
|
attr_reader :datastore, :address
|
38
38
|
|
39
|
-
sig { returns(T::Array[
|
39
|
+
sig { returns(T::Array[AddressValidation::Validators::FullAddress::AddressComparison]) }
|
40
40
|
def sorted_candidates
|
41
|
-
|
41
|
+
sorted_address_comparisons = datastore.fetch_full_address_candidates
|
42
42
|
.filter_map.with_index(1) do |candidate, position|
|
43
|
-
|
43
|
+
candidate.position = position
|
44
|
+
address_comparison = AddressValidation::Validators::FullAddress::AddressComparison.new(
|
44
45
|
address: address,
|
45
46
|
candidate: candidate,
|
46
47
|
datastore: datastore,
|
47
48
|
)
|
48
|
-
|
49
|
-
tuple if tuple.address_comparison.potential_match?
|
49
|
+
address_comparison if address_comparison.potential_match?
|
50
50
|
end.sort
|
51
51
|
|
52
|
-
emit_sorted_candidates(
|
53
|
-
|
52
|
+
emit_sorted_candidates(sorted_address_comparisons.map(&:candidate))
|
53
|
+
sorted_address_comparisons
|
54
54
|
end
|
55
55
|
|
56
|
-
sig { params(
|
57
|
-
def emit_sorted_candidates(
|
58
|
-
log_info("Sorted candidates:\n #{
|
56
|
+
sig { params(sorted_candidates: T::Array[Candidate]).void }
|
57
|
+
def emit_sorted_candidates(sorted_candidates)
|
58
|
+
log_info("Sorted candidates:\n #{sorted_candidates.map(&:serialize)}")
|
59
59
|
|
60
|
-
initial_position_top_candidate =
|
60
|
+
initial_position_top_candidate = sorted_candidates.first&.position || 0
|
61
61
|
StatsD.distribution(
|
62
62
|
"AddressValidation.query.initial_position_top_candidate",
|
63
63
|
initial_position_top_candidate,
|
@@ -9,12 +9,11 @@ module AtlasEngine
|
|
9
9
|
include LogHelper
|
10
10
|
|
11
11
|
attr_reader :address, :result
|
12
|
-
attr_accessor :session
|
13
12
|
|
14
13
|
sig { params(address: TAddress, result: Result).void }
|
15
14
|
def initialize(address:, result: Result.new)
|
16
15
|
super
|
17
|
-
@
|
16
|
+
@matching_strategy = MatchingStrategies::Es
|
18
17
|
end
|
19
18
|
|
20
19
|
sig { override.returns(Result) }
|
@@ -30,23 +29,23 @@ module AtlasEngine
|
|
30
29
|
sig { returns(AddressValidation::Validators::FullAddress::CandidateResultBase) }
|
31
30
|
def build_candidate_result
|
32
31
|
unless supported_address?(address)
|
33
|
-
return AddressValidation::Validators::FullAddress::UnsupportedScriptResult.new(
|
32
|
+
return AddressValidation::Validators::FullAddress::UnsupportedScriptResult.new(address:, result:)
|
34
33
|
end
|
35
34
|
|
36
35
|
if best_candidate.nil?
|
37
|
-
AddressValidation::Validators::FullAddress::NoCandidateResult.new(
|
36
|
+
AddressValidation::Validators::FullAddress::NoCandidateResult.new(address:, result:)
|
38
37
|
else
|
39
38
|
AddressValidation::Validators::FullAddress::CandidateResult.new(
|
40
|
-
|
39
|
+
address_comparison: T.must(best_candidate),
|
40
|
+
matching_strategy: @matching_strategy,
|
41
41
|
result: result,
|
42
|
-
session: session,
|
43
42
|
)
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
47
46
|
private
|
48
47
|
|
49
|
-
sig { returns(T.nilable(
|
48
|
+
sig { returns(T.nilable(AddressValidation::Validators::FullAddress::AddressComparison)) }
|
50
49
|
def best_candidate
|
51
50
|
@best_candidate ||= T.let(
|
52
51
|
begin
|
@@ -63,15 +62,15 @@ module AtlasEngine
|
|
63
62
|
# We want our futures to complete even when we do not consume their value.
|
64
63
|
candidate_futures&.map(&:wait!)
|
65
64
|
end,
|
66
|
-
T.nilable(
|
65
|
+
T.nilable(AddressValidation::Validators::FullAddress::AddressComparison),
|
67
66
|
)
|
68
67
|
end
|
69
68
|
|
70
69
|
sig { params(locale: T.nilable(String)).returns(Concurrent::Promises::Future) }
|
71
70
|
def best_candidate_future(locale = nil)
|
72
71
|
AddressValidation::Es::CandidateSelector.new(
|
73
|
-
datastore:
|
74
|
-
address:
|
72
|
+
datastore: Es::Datastore.new(address: address, locale: locale),
|
73
|
+
address: address,
|
75
74
|
).best_candidate_async
|
76
75
|
end
|
77
76
|
|
@@ -9,7 +9,7 @@ module AtlasEngine
|
|
9
9
|
sig { params(address: TAddress, result: Result).void }
|
10
10
|
def initialize(address:, result: Result.new)
|
11
11
|
super
|
12
|
-
@
|
12
|
+
@matching_strategy = MatchingStrategies::EsStreet
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|
@@ -11,16 +11,16 @@ module AtlasEngine
|
|
11
11
|
|
12
12
|
sig do
|
13
13
|
params(
|
14
|
-
|
15
|
-
|
14
|
+
address_comparison: AddressComparison,
|
15
|
+
matching_strategy: AddressValidation::MatchingStrategies,
|
16
16
|
result: Result,
|
17
|
-
)
|
18
|
-
.void
|
17
|
+
).void
|
19
18
|
end
|
20
|
-
def initialize(
|
21
|
-
super(
|
22
|
-
@
|
23
|
-
@
|
19
|
+
def initialize(address_comparison:, matching_strategy:, result:)
|
20
|
+
super(address: address_comparison.address, result: result)
|
21
|
+
@address_comparison = address_comparison
|
22
|
+
@candidate = address_comparison.candidate
|
23
|
+
@matching_strategy = matching_strategy
|
24
24
|
end
|
25
25
|
|
26
26
|
sig { override.void }
|
@@ -34,7 +34,7 @@ module AtlasEngine
|
|
34
34
|
|
35
35
|
sig { returns(T::Boolean) }
|
36
36
|
def suggestable?
|
37
|
-
ConcernBuilder.should_suggest?(
|
37
|
+
ConcernBuilder.should_suggest?(address, unmatched_components.keys)
|
38
38
|
end
|
39
39
|
|
40
40
|
private
|
@@ -56,11 +56,11 @@ module AtlasEngine
|
|
56
56
|
|
57
57
|
sig { void }
|
58
58
|
def add_concerns_without_suggestions
|
59
|
-
concern = InvalidZipConcernBuilder.for(
|
59
|
+
concern = InvalidZipConcernBuilder.for(address, [])
|
60
60
|
result.concerns << concern if concern
|
61
61
|
|
62
|
-
if ConcernBuilder.too_many_unmatched_components?(
|
63
|
-
result.concerns <<
|
62
|
+
if ConcernBuilder.too_many_unmatched_components?(address, unmatched_components.keys)
|
63
|
+
result.concerns << UnknownAddressConcernBuilder.new(address).build
|
64
64
|
end
|
65
65
|
end
|
66
66
|
|
@@ -77,7 +77,7 @@ module AtlasEngine
|
|
77
77
|
unmatched_component: unmatched_component,
|
78
78
|
unmatched_field: field_name,
|
79
79
|
matched_components: matched_components_to_validate.keys,
|
80
|
-
address:
|
80
|
+
address: address,
|
81
81
|
suggestion_ids: [suggestion.id].compact,
|
82
82
|
).build
|
83
83
|
result.concerns << concern
|
@@ -90,7 +90,7 @@ module AtlasEngine
|
|
90
90
|
unmatched_fields = { street: unmatched_field_name(:street) }.compact
|
91
91
|
|
92
92
|
@suggestion ||= SuggestionBuilder.from_comparisons(
|
93
|
-
|
93
|
+
address.to_h,
|
94
94
|
unmatched_components_to_validate,
|
95
95
|
candidate,
|
96
96
|
unmatched_fields,
|
@@ -126,7 +126,7 @@ module AtlasEngine
|
|
126
126
|
components = {}
|
127
127
|
@matched_and_unmatched_components ||= begin
|
128
128
|
components_to_compare.each do |component|
|
129
|
-
components[component] =
|
129
|
+
components[component] = address_comparison.for(component).sequence_comparison
|
130
130
|
end
|
131
131
|
components
|
132
132
|
end
|
@@ -144,7 +144,7 @@ module AtlasEngine
|
|
144
144
|
|
145
145
|
sig { returns(RelevantComponents) }
|
146
146
|
def relevant_components
|
147
|
-
@relevant_components ||= RelevantComponents.new(
|
147
|
+
@relevant_components ||= RelevantComponents.new(address_comparison, @matching_strategy)
|
148
148
|
end
|
149
149
|
|
150
150
|
sig do
|
@@ -167,17 +167,17 @@ module AtlasEngine
|
|
167
167
|
|
168
168
|
original_street = T.must(unmatched_components_to_validate[:street]).left_sequence.raw_value
|
169
169
|
|
170
|
-
if
|
170
|
+
if address.address1.to_s.include?(original_street)
|
171
171
|
:address1
|
172
|
-
elsif
|
172
|
+
elsif address.address2.to_s.include?(original_street)
|
173
173
|
:address2
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
177
177
|
sig { void }
|
178
178
|
def log_unknown_field_name
|
179
|
-
potential_streets = { potential_streets:
|
180
|
-
input_address =
|
179
|
+
potential_streets = { potential_streets: address_comparison.parsings.potential_streets }
|
180
|
+
input_address = address.to_h.compact_blank.except(:phone)
|
181
181
|
log_details = input_address.merge(potential_streets)
|
182
182
|
log_info("[AddressValidation] Unable to identify unmatched field name", log_details)
|
183
183
|
end
|
data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result_base.rb
CHANGED
@@ -11,9 +11,9 @@ module AtlasEngine
|
|
11
11
|
|
12
12
|
abstract!
|
13
13
|
|
14
|
-
sig { params(
|
15
|
-
def initialize(
|
16
|
-
@
|
14
|
+
sig { params(address: AbstractAddress, result: Result).void }
|
15
|
+
def initialize(address:, result:)
|
16
|
+
@address = address
|
17
17
|
@result = result
|
18
18
|
end
|
19
19
|
|
@@ -22,9 +22,7 @@ module AtlasEngine
|
|
22
22
|
|
23
23
|
private
|
24
24
|
|
25
|
-
attr_reader :
|
26
|
-
|
27
|
-
delegate :address, to: :session
|
25
|
+
attr_reader :result, :address
|
28
26
|
|
29
27
|
sig { void }
|
30
28
|
def update_result_scope
|
@@ -110,7 +110,7 @@ module AtlasEngine
|
|
110
110
|
return concern if concern
|
111
111
|
|
112
112
|
if :province_code.in?(matched_components) && :city.in?(matched_components)
|
113
|
-
return
|
113
|
+
return UnknownZipForAddressConcernBuilder.new(address).build(suggestion_ids)
|
114
114
|
end
|
115
115
|
|
116
116
|
build_default_concern
|
@@ -119,7 +119,7 @@ module AtlasEngine
|
|
119
119
|
sig { returns(AddressValidation::Concern) }
|
120
120
|
def build_province_concern
|
121
121
|
if ([:zip, :city] - matched_components).empty?
|
122
|
-
|
122
|
+
UnknownProvinceConcernBuilder.new(address).build(suggestion_ids)
|
123
123
|
else
|
124
124
|
build_default_concern
|
125
125
|
end
|
@@ -127,7 +127,12 @@ module AtlasEngine
|
|
127
127
|
|
128
128
|
sig { returns(AddressValidation::Concern) }
|
129
129
|
def build_default_concern
|
130
|
-
|
130
|
+
UnmatchedFieldConcernBuilder.new(
|
131
|
+
unmatched_component,
|
132
|
+
matched_components,
|
133
|
+
address,
|
134
|
+
unmatched_field,
|
135
|
+
).build(suggestion_ids)
|
131
136
|
end
|
132
137
|
end
|
133
138
|
end
|
@@ -22,9 +22,13 @@ module AtlasEngine
|
|
22
22
|
return unless country.has_zip?
|
23
23
|
|
24
24
|
if country_expects_zone_in_address?(country) && province.province?
|
25
|
-
|
25
|
+
return if province.valid_zip?(address.zip)
|
26
|
+
|
27
|
+
InvalidZipForProvinceConcernBuilder.new(address).build
|
26
28
|
else
|
27
|
-
|
29
|
+
return if country.valid_zip?(address.zip)
|
30
|
+
|
31
|
+
InvalidZipForCountryConcernBuilder.new(address).build(suggestion_ids)
|
28
32
|
end
|
29
33
|
end
|
30
34
|
|
@@ -5,31 +5,32 @@ module AtlasEngine
|
|
5
5
|
module AddressValidation
|
6
6
|
module Validators
|
7
7
|
module FullAddress
|
8
|
-
class
|
8
|
+
class InvalidZipForCountryConcernBuilder
|
9
|
+
extend T::Sig
|
9
10
|
include ConcernFormatter
|
10
11
|
attr_reader :address
|
11
12
|
|
12
|
-
sig { params(address: AbstractAddress
|
13
|
-
def initialize(address
|
13
|
+
sig { params(address: AbstractAddress).void }
|
14
|
+
def initialize(address)
|
14
15
|
@address = address
|
16
|
+
end
|
17
|
+
|
18
|
+
sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
|
19
|
+
def build(suggestion_ids = [])
|
20
|
+
message = country.field(key: :zip).error(
|
21
|
+
code: :invalid_for_country,
|
22
|
+
options: { country: country.full_name },
|
23
|
+
).to_s
|
15
24
|
|
16
|
-
|
25
|
+
Concern.new(
|
17
26
|
code: :zip_invalid_for_country,
|
18
27
|
field_names: [:zip],
|
19
28
|
message: message,
|
20
29
|
type: T.must(Concern::TYPES[:error]),
|
21
30
|
type_level: 1,
|
22
|
-
suggestion_ids: suggestion_ids
|
31
|
+
suggestion_ids: suggestion_ids,
|
23
32
|
)
|
24
33
|
end
|
25
|
-
|
26
|
-
sig { returns(String) }
|
27
|
-
def message
|
28
|
-
country.field(key: :zip).error(
|
29
|
-
code: :invalid_for_country,
|
30
|
-
options: { country: country.full_name },
|
31
|
-
).to_s
|
32
|
-
end
|
33
34
|
end
|
34
35
|
end
|
35
36
|
end
|
@@ -5,30 +5,30 @@ module AtlasEngine
|
|
5
5
|
module AddressValidation
|
6
6
|
module Validators
|
7
7
|
module FullAddress
|
8
|
-
class
|
8
|
+
class InvalidZipForProvinceConcernBuilder
|
9
|
+
extend T::Sig
|
9
10
|
include ConcernFormatter
|
10
11
|
attr_reader :address
|
11
12
|
|
12
|
-
|
13
|
-
def initialize(address, suggestion_ids)
|
13
|
+
def initialize(address)
|
14
14
|
@address = address
|
15
|
-
|
16
|
-
super(
|
17
|
-
code: :zip_invalid_for_province,
|
18
|
-
field_names: [:zip],
|
19
|
-
message: message,
|
20
|
-
type: T.must(Concern::TYPES[:error]),
|
21
|
-
type_level: 1,
|
22
|
-
suggestion_ids: suggestion_ids
|
23
|
-
)
|
24
15
|
end
|
25
16
|
|
26
|
-
sig {
|
27
|
-
def
|
28
|
-
country.field(key: :zip).error(
|
17
|
+
sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
|
18
|
+
def build(suggestion_ids = [])
|
19
|
+
message = country.field(key: :zip).error(
|
29
20
|
code: :invalid_for_province,
|
30
21
|
options: { province: province_name },
|
31
22
|
).to_s
|
23
|
+
|
24
|
+
Concern.new(
|
25
|
+
field_names: [:zip],
|
26
|
+
code: :zip_invalid_for_province,
|
27
|
+
type: T.must(Concern::TYPES[:error]),
|
28
|
+
type_level: 1,
|
29
|
+
suggestion_ids: suggestion_ids,
|
30
|
+
message: message,
|
31
|
+
)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
data/app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb
CHANGED
@@ -10,11 +10,9 @@ module AtlasEngine
|
|
10
10
|
|
11
11
|
sig { void }
|
12
12
|
def update_result
|
13
|
-
result.concerns <<
|
14
|
-
address,
|
15
|
-
)
|
13
|
+
result.concerns << UnknownAddressConcernBuilder.new(address).build
|
16
14
|
|
17
|
-
concern = InvalidZipConcernBuilder.for(
|
15
|
+
concern = InvalidZipConcernBuilder.for(address, [])
|
18
16
|
result.concerns << concern if concern
|
19
17
|
|
20
18
|
update_result_scope
|
data/app/models/atlas_engine/address_validation/validators/full_address/relevant_components.rb
CHANGED
@@ -8,9 +8,6 @@ module AtlasEngine
|
|
8
8
|
class RelevantComponents
|
9
9
|
extend T::Sig
|
10
10
|
|
11
|
-
sig { returns(Session) }
|
12
|
-
attr_reader :session
|
13
|
-
|
14
11
|
sig { returns(Candidate) }
|
15
12
|
attr_reader :candidate
|
16
13
|
|
@@ -19,15 +16,15 @@ module AtlasEngine
|
|
19
16
|
|
20
17
|
sig do
|
21
18
|
params(
|
22
|
-
session: Session,
|
23
|
-
candidate: Candidate,
|
24
19
|
address_comparison: AddressComparison,
|
20
|
+
matching_strategy: AtlasEngine::AddressValidation::MatchingStrategies,
|
25
21
|
).void
|
26
22
|
end
|
27
|
-
def initialize(
|
28
|
-
@session = session
|
29
|
-
@candidate = candidate
|
23
|
+
def initialize(address_comparison, matching_strategy)
|
30
24
|
@address_comparison = address_comparison
|
25
|
+
@matching_strategy = matching_strategy
|
26
|
+
@address = address_comparison.address
|
27
|
+
@candidate = address_comparison.candidate
|
31
28
|
@all_supported_components = address_comparison.relevant_components.dup
|
32
29
|
end
|
33
30
|
|
@@ -62,8 +59,7 @@ module AtlasEngine
|
|
62
59
|
def exclude_street_validation?
|
63
60
|
return @exclude_street_validation if defined?(@exclude_street_validation)
|
64
61
|
|
65
|
-
@exclude_street_validation = if
|
66
|
-
AddressValidation::MatchingStrategies::EsStreet
|
62
|
+
@exclude_street_validation = if @matching_strategy != AddressValidation::MatchingStrategies::EsStreet
|
67
63
|
true
|
68
64
|
elsif address_comparison.street_comparison.sequence_comparison.blank?
|
69
65
|
emit_excluded_validation(:street, "not_found")
|
@@ -80,7 +76,7 @@ module AtlasEngine
|
|
80
76
|
|
81
77
|
sig { returns(CountryProfile) }
|
82
78
|
def country_profile
|
83
|
-
@country_profile ||= CountryProfile.for(
|
79
|
+
@country_profile ||= CountryProfile.for(@address.country_code)
|
84
80
|
end
|
85
81
|
|
86
82
|
sig { params(component: Symbol, reason: String).void }
|
@@ -88,7 +84,7 @@ module AtlasEngine
|
|
88
84
|
tags = [
|
89
85
|
"reason:#{reason}",
|
90
86
|
"component:#{component}",
|
91
|
-
"country:#{
|
87
|
+
"country:#{@address.country_code}",
|
92
88
|
]
|
93
89
|
StatsD.increment("AddressValidation.skip", sample_rate: 1.0, tags: tags)
|
94
90
|
end
|
@@ -97,7 +93,7 @@ module AtlasEngine
|
|
97
93
|
def unsupported_components_for_country
|
98
94
|
@unsupported_components_for_country ||= begin
|
99
95
|
unsupported_components = []
|
100
|
-
country = Worldwide.region(code:
|
96
|
+
country = Worldwide.region(code: @address.country_code)
|
101
97
|
unsupported_components << :province_code if country.province_optional?
|
102
98
|
unsupported_components << :province_code if country.hide_provinces_from_addresses
|
103
99
|
unsupported_components << :city unless country.city_required?
|
@@ -5,7 +5,8 @@ module AtlasEngine
|
|
5
5
|
module AddressValidation
|
6
6
|
module Validators
|
7
7
|
module FullAddress
|
8
|
-
class
|
8
|
+
class UnknownAddressConcernBuilder
|
9
|
+
extend T::Sig
|
9
10
|
include ConcernFormatter
|
10
11
|
|
11
12
|
sig { returns(TAddress) }
|
@@ -14,12 +15,18 @@ module AtlasEngine
|
|
14
15
|
sig { params(address: TAddress).void }
|
15
16
|
def initialize(address)
|
16
17
|
@address = address
|
17
|
-
|
18
|
+
end
|
19
|
+
|
20
|
+
sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
|
21
|
+
def build(suggestion_ids = [])
|
22
|
+
message = country.field(key: :address).error(code: :may_not_exist)
|
23
|
+
|
24
|
+
Concern.new(
|
18
25
|
code: :address_unknown,
|
19
|
-
message:
|
26
|
+
message: message,
|
20
27
|
type: T.must(Concern::TYPES[:warning]),
|
21
28
|
type_level: 1,
|
22
|
-
suggestion_ids:
|
29
|
+
suggestion_ids: suggestion_ids,
|
23
30
|
field_names: [:address1],
|
24
31
|
)
|
25
32
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
module Validators
|
7
|
+
module FullAddress
|
8
|
+
class UnknownProvinceConcernBuilder
|
9
|
+
extend T::Sig
|
10
|
+
include ConcernFormatter
|
11
|
+
attr_reader :address
|
12
|
+
|
13
|
+
sig { params(address: AbstractAddress).void }
|
14
|
+
def initialize(address)
|
15
|
+
@address = address
|
16
|
+
end
|
17
|
+
|
18
|
+
sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
|
19
|
+
def build(suggestion_ids = [])
|
20
|
+
message = country.field(key: :province).error(
|
21
|
+
code: :unknown_for_city_and_zip,
|
22
|
+
options: { city: address.city, zip: address.zip },
|
23
|
+
).to_s
|
24
|
+
|
25
|
+
Concern.new(
|
26
|
+
code: :province_inconsistent,
|
27
|
+
field_names: [:province],
|
28
|
+
message: message,
|
29
|
+
type: T.must(Concern::TYPES[:error]),
|
30
|
+
type_level: 1,
|
31
|
+
suggestion_ids: suggestion_ids,
|
32
|
+
)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -5,26 +5,28 @@ module AtlasEngine
|
|
5
5
|
module AddressValidation
|
6
6
|
module Validators
|
7
7
|
module FullAddress
|
8
|
-
class
|
8
|
+
class UnknownZipForAddressConcernBuilder
|
9
|
+
extend T::Sig
|
9
10
|
attr_reader :address
|
10
11
|
|
11
|
-
sig { params(address: AbstractAddress
|
12
|
-
def initialize(address
|
12
|
+
sig { params(address: AbstractAddress).void }
|
13
|
+
def initialize(address)
|
13
14
|
@address = address
|
14
|
-
|
15
|
+
end
|
16
|
+
|
17
|
+
sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
|
18
|
+
def build(suggestion_ids = [])
|
19
|
+
message = "Enter a valid ZIP for #{address.address1}, #{address.city}"
|
20
|
+
|
21
|
+
Concern.new(
|
15
22
|
code: :zip_inconsistent,
|
16
23
|
field_names: [:zip],
|
17
24
|
message: message,
|
18
25
|
type: T.must(Concern::TYPES[:warning]),
|
19
26
|
type_level: 3,
|
20
|
-
suggestion_ids: suggestion_ids
|
27
|
+
suggestion_ids: suggestion_ids,
|
21
28
|
)
|
22
29
|
end
|
23
|
-
|
24
|
-
sig { returns(String) }
|
25
|
-
def message
|
26
|
-
"Enter a valid ZIP for #{address.address1}, #{address.city}"
|
27
|
-
end
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|
@@ -5,9 +5,10 @@ module AtlasEngine
|
|
5
5
|
module AddressValidation
|
6
6
|
module Validators
|
7
7
|
module FullAddress
|
8
|
-
class
|
8
|
+
class UnmatchedFieldConcernBuilder
|
9
|
+
extend T::Sig
|
9
10
|
include ConcernFormatter
|
10
|
-
attr_reader :
|
11
|
+
attr_reader :address, :component, :matched_components, :unmatched_field
|
11
12
|
|
12
13
|
COMPONENTS_TO_LABELS = {
|
13
14
|
zip: "ZIP",
|
@@ -25,26 +26,34 @@ module AtlasEngine
|
|
25
26
|
unmatched_component: Symbol,
|
26
27
|
matched_components: T::Array[Symbol],
|
27
28
|
address: AbstractAddress,
|
28
|
-
suggestion_ids: T::Array[String],
|
29
29
|
unmatched_field: T.nilable(Symbol),
|
30
30
|
).void
|
31
31
|
end
|
32
|
-
def initialize(unmatched_component, matched_components, address,
|
32
|
+
def initialize(unmatched_component, matched_components, address, unmatched_field = nil)
|
33
|
+
@address = address
|
33
34
|
@component = unmatched_component
|
34
35
|
@matched_components = matched_components
|
35
|
-
@address = address
|
36
36
|
@unmatched_field = unmatched_field
|
37
|
+
end
|
37
38
|
|
38
|
-
|
39
|
+
sig do
|
40
|
+
params(
|
41
|
+
suggestion_ids: T::Array[String],
|
42
|
+
).returns(Concern)
|
43
|
+
end
|
44
|
+
def build(suggestion_ids = [])
|
45
|
+
Concern.new(
|
39
46
|
code: code,
|
40
47
|
field_names: field_names,
|
41
48
|
message: message,
|
42
49
|
type: T.must(Concern::TYPES[:warning]),
|
43
50
|
type_level: 3,
|
44
|
-
suggestion_ids: suggestion_ids
|
51
|
+
suggestion_ids: suggestion_ids,
|
45
52
|
)
|
46
53
|
end
|
47
54
|
|
55
|
+
private
|
56
|
+
|
48
57
|
sig { returns(String) }
|
49
58
|
def message
|
50
59
|
"Enter a valid #{COMPONENTS_TO_LABELS[component]} for #{valid_address_component_values.join(", ")}"
|
@@ -60,8 +69,6 @@ module AtlasEngine
|
|
60
69
|
[field_name]
|
61
70
|
end
|
62
71
|
|
63
|
-
private
|
64
|
-
|
65
72
|
sig { returns(T::Array[String]) }
|
66
73
|
def valid_address_component_values
|
67
74
|
matched_components.last(2).map do |component|
|
@@ -74,6 +81,7 @@ module AtlasEngine
|
|
74
81
|
SHORTENED_COMPONENT_NAMES[component] || component
|
75
82
|
end
|
76
83
|
|
84
|
+
sig { returns(Symbol) }
|
77
85
|
def field_name
|
78
86
|
unmatched_field || shortened_component_name
|
79
87
|
end
|
data/lib/atlas_engine/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atlas_engine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: annex_29
|
@@ -437,7 +437,6 @@ files:
|
|
437
437
|
- app/models/atlas_engine/address_validation/abstract_address.rb
|
438
438
|
- app/models/atlas_engine/address_validation/address.rb
|
439
439
|
- app/models/atlas_engine/address_validation/candidate.rb
|
440
|
-
- app/models/atlas_engine/address_validation/candidate_tuple.rb
|
441
440
|
- app/models/atlas_engine/address_validation/concern.rb
|
442
441
|
- app/models/atlas_engine/address_validation/concern_producer.rb
|
443
442
|
- app/models/atlas_engine/address_validation/concern_queue.rb
|
@@ -463,7 +462,6 @@ files:
|
|
463
462
|
- app/models/atlas_engine/address_validation/request.rb
|
464
463
|
- app/models/atlas_engine/address_validation/result.rb
|
465
464
|
- app/models/atlas_engine/address_validation/runs_validation.rb
|
466
|
-
- app/models/atlas_engine/address_validation/session.rb
|
467
465
|
- app/models/atlas_engine/address_validation/statsd_emitter.rb
|
468
466
|
- app/models/atlas_engine/address_validation/strategies.rb
|
469
467
|
- app/models/atlas_engine/address_validation/suggestion.rb
|
@@ -485,20 +483,19 @@ files:
|
|
485
483
|
- app/models/atlas_engine/address_validation/validators/full_address/exclusions/exclusion_base.rb
|
486
484
|
- app/models/atlas_engine/address_validation/validators/full_address/field_comparison_base.rb
|
487
485
|
- app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb
|
488
|
-
- app/models/atlas_engine/address_validation/validators/full_address/
|
489
|
-
- app/models/atlas_engine/address_validation/validators/full_address/
|
486
|
+
- app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_country_concern_builder.rb
|
487
|
+
- app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_province_concern_builder.rb
|
490
488
|
- app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb
|
491
489
|
- app/models/atlas_engine/address_validation/validators/full_address/number_comparison.rb
|
492
490
|
- app/models/atlas_engine/address_validation/validators/full_address/postal_code_matcher.rb
|
493
491
|
- app/models/atlas_engine/address_validation/validators/full_address/province_code_comparison.rb
|
494
492
|
- app/models/atlas_engine/address_validation/validators/full_address/relevant_components.rb
|
495
|
-
- app/models/atlas_engine/address_validation/validators/full_address/result_updater.rb
|
496
493
|
- app/models/atlas_engine/address_validation/validators/full_address/street_comparison.rb
|
497
494
|
- app/models/atlas_engine/address_validation/validators/full_address/suggestion_builder.rb
|
498
|
-
- app/models/atlas_engine/address_validation/validators/full_address/
|
499
|
-
- app/models/atlas_engine/address_validation/validators/full_address/
|
500
|
-
- app/models/atlas_engine/address_validation/validators/full_address/
|
501
|
-
- app/models/atlas_engine/address_validation/validators/full_address/
|
495
|
+
- app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern_builder.rb
|
496
|
+
- app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern_builder.rb
|
497
|
+
- app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern_builder.rb
|
498
|
+
- app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern_builder.rb
|
502
499
|
- app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb
|
503
500
|
- app/models/atlas_engine/address_validation/validators/full_address/zip_comparison.rb
|
504
501
|
- app/models/atlas_engine/address_validation/validators/predicates/cache.rb
|
@@ -1,15 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module AtlasEngine
|
5
|
-
module AddressValidation
|
6
|
-
CandidateTuple = Struct.new(:address_comparison, :position, :candidate) do
|
7
|
-
extend T::Sig
|
8
|
-
|
9
|
-
sig { params(other: CandidateTuple).returns(Integer) }
|
10
|
-
def <=>(other)
|
11
|
-
to_a[0..1] <=> other.to_a[0..1] # only consider address_comparison and position
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,47 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require "forwardable"
|
5
|
-
|
6
|
-
module AtlasEngine
|
7
|
-
module AddressValidation
|
8
|
-
class Session
|
9
|
-
extend Forwardable
|
10
|
-
extend T::Sig
|
11
|
-
|
12
|
-
sig { returns(AbstractAddress) }
|
13
|
-
attr_reader :address
|
14
|
-
|
15
|
-
sig { returns(MatchingStrategies) }
|
16
|
-
attr_accessor :matching_strategy
|
17
|
-
|
18
|
-
sig { returns(T::Hash[String, AtlasEngine::AddressValidation::DatastoreBase]) }
|
19
|
-
attr_reader :datastore_hash
|
20
|
-
|
21
|
-
def_delegators :@address, :address1, :address2, :city, :province_code, :country_code, :zip, :phone
|
22
|
-
|
23
|
-
sig do
|
24
|
-
params(
|
25
|
-
address: AbstractAddress,
|
26
|
-
matching_strategy: MatchingStrategies,
|
27
|
-
).void
|
28
|
-
end
|
29
|
-
def initialize(address:, matching_strategy: MatchingStrategies::Es)
|
30
|
-
@address = address
|
31
|
-
@matching_strategy = matching_strategy
|
32
|
-
@datastore_hash = T.let({}, T::Hash[String, AtlasEngine::AddressValidation::DatastoreBase])
|
33
|
-
end
|
34
|
-
|
35
|
-
sig { params(locale: T.nilable(String)).returns(ValidationTranscriber::AddressParsings) }
|
36
|
-
def parsings(locale: nil)
|
37
|
-
datastore(locale: locale).parsings
|
38
|
-
end
|
39
|
-
|
40
|
-
sig { params(locale: T.nilable(String)).returns(AtlasEngine::AddressValidation::DatastoreBase) }
|
41
|
-
def datastore(locale: nil)
|
42
|
-
key = locale || "default"
|
43
|
-
@datastore_hash[key] ||= AtlasEngine::AddressValidation::Es::Datastore.new(address: address, locale: locale)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,42 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module AtlasEngine
|
5
|
-
module AddressValidation
|
6
|
-
module Validators
|
7
|
-
module FullAddress
|
8
|
-
class ResultUpdater
|
9
|
-
extend T::Sig
|
10
|
-
extend T::Helpers
|
11
|
-
abstract!
|
12
|
-
|
13
|
-
sig { params(session: Session, result: Result).void }
|
14
|
-
def initialize(session:, result:)
|
15
|
-
@session = session
|
16
|
-
@result = result
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
attr_reader :session, :result
|
22
|
-
|
23
|
-
delegate :address, to: :session
|
24
|
-
|
25
|
-
sig { void }
|
26
|
-
def update_result_scope
|
27
|
-
concern_fields = result.concerns.flat_map(&:field_names).uniq
|
28
|
-
scopes_to_remove = concern_fields.flat_map { |field| contained_scopes_for(field) }
|
29
|
-
result.validation_scope.reject! { |scope| scope.in?(scopes_to_remove) }
|
30
|
-
end
|
31
|
-
|
32
|
-
sig { params(scope: Symbol).returns(T.nilable(T::Array[Symbol])) }
|
33
|
-
def contained_scopes_for(scope)
|
34
|
-
return [] unless (scope_index = Result::SORTED_VALIDATION_SCOPES.index(scope))
|
35
|
-
|
36
|
-
Result::SORTED_VALIDATION_SCOPES.slice(scope_index..)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
# typed: true
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module AtlasEngine
|
5
|
-
module AddressValidation
|
6
|
-
module Validators
|
7
|
-
module FullAddress
|
8
|
-
class UnknownProvinceConcern < AddressValidation::Concern
|
9
|
-
include ConcernFormatter
|
10
|
-
attr_reader :address
|
11
|
-
|
12
|
-
sig { params(address: AbstractAddress, suggestion_ids: T::Array[String]).void }
|
13
|
-
def initialize(address, suggestion_ids)
|
14
|
-
@address = address
|
15
|
-
super(
|
16
|
-
code: :province_inconsistent,
|
17
|
-
field_names: [:province],
|
18
|
-
message: message,
|
19
|
-
type: T.must(Concern::TYPES[:error]),
|
20
|
-
type_level: 1,
|
21
|
-
suggestion_ids: suggestion_ids
|
22
|
-
)
|
23
|
-
end
|
24
|
-
|
25
|
-
sig { returns(String) }
|
26
|
-
def message
|
27
|
-
country
|
28
|
-
.field(key: :province)
|
29
|
-
.error(
|
30
|
-
code: :unknown_for_city_and_zip,
|
31
|
-
options: { city: address.city, zip: address.zip },
|
32
|
-
).to_s
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|