atlas_engine 0.5.0 → 0.6.0
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.
- 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
|