atlas_engine 0.5.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/app/countries/atlas_engine/gg/address_validation/validators/full_address/exclusions/city.rb +32 -0
  3. data/app/countries/atlas_engine/gg/country_profile.yml +4 -0
  4. data/app/countries/atlas_engine/gg/validation_transcriber/address_parser.rb +43 -0
  5. data/app/models/atlas_engine/address_validation/candidate.rb +3 -2
  6. data/app/models/atlas_engine/address_validation/es/candidate_selector.rb +12 -12
  7. data/app/models/atlas_engine/address_validation/es/datastore.rb +23 -0
  8. data/app/models/atlas_engine/address_validation/es/validators/full_address.rb +9 -10
  9. data/app/models/atlas_engine/address_validation/es/validators/full_address_street.rb +1 -1
  10. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +20 -20
  11. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result_base.rb +4 -6
  12. data/app/models/atlas_engine/address_validation/validators/full_address/concern_builder.rb +7 -6
  13. data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb +6 -2
  14. 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
  15. 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
  16. data/app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb +2 -4
  17. data/app/models/atlas_engine/address_validation/validators/full_address/relevant_components.rb +9 -13
  18. data/app/models/atlas_engine/address_validation/validators/full_address/{unknown_address_concern.rb → unknown_address_concern_builder.rb} +11 -4
  19. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern_builder.rb +38 -0
  20. data/app/models/atlas_engine/address_validation/validators/full_address/{unmatched_field_concern.rb → unmatched_field_concern_builder.rb} +18 -10
  21. data/app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb +1 -1
  22. data/app/models/atlas_engine/address_validation/validators/predicates/country/valid_for_zip.rb +1 -1
  23. data/app/models/atlas_engine/address_validation/validators/predicates/province/valid_for_country.rb +1 -1
  24. data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1.rb +1 -1
  25. data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1_or_address2.rb +1 -1
  26. data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_country.rb +1 -1
  27. data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_province.rb +1 -1
  28. data/app/models/atlas_engine/elasticsearch/error.rb +19 -0
  29. data/app/models/atlas_engine/elasticsearch/repository.rb +8 -8
  30. data/lib/atlas_engine/version.rb +1 -1
  31. metadata +10 -11
  32. data/app/models/atlas_engine/address_validation/candidate_tuple.rb +0 -15
  33. data/app/models/atlas_engine/address_validation/session.rb +0 -47
  34. data/app/models/atlas_engine/address_validation/validators/full_address/result_updater.rb +0 -42
  35. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern.rb +0 -38
  36. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern.rb +0 -32
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3285871f59bee7bdf0084bfb5f985a6e582a173a78baa496c07ba9e8bd526eda
4
- data.tar.gz: b25b6b4d8637c34d43a78e60f457342ccd9f7117f02d039f961476a7a4ef310e
3
+ metadata.gz: 9948b64010b57506c90e07bf0fc324c7ad158112169375aa1ac1f7053850a9be
4
+ data.tar.gz: 872cd26b540c96af7a777b044a4af20cce6d1b7df5569f0b3cd7aaf999fb1847
5
5
  SHA512:
6
- metadata.gz: ea581fe90f17c1924f2d370fef820dc8bf18ed094e570666cdc60f13b0ec37b7e8876749176bbb14cd9f408931c525f6f7b29afdf4da47270bf24f147f8f0bce
7
- data.tar.gz: 6ef3dca52ae9bfc224d694c6cb326f743701280cb8d6be14f30421ea247c53822d8017acdeaad5641cfe34ac080ca33a1b010308575057fec2e040a1d7a3222e
6
+ metadata.gz: d8ea33678c4c924fb202cecf027e4796892430c35394233c0a971474166b71a10881a6ddc2cc6056d7f66df6b225a63cfdafe18b5590327035d19f3f4e70cf99
7
+ data.tar.gz: 30d5b8b914d14f4fd6871228435383ff90499e25617af0c7dc5a6a5580fbf4005854f2189034712f4030001878be8c6ee42223e5b94a1890b2a14f8be80e0dc3
@@ -0,0 +1,32 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module Gg
6
+ module AddressValidation
7
+ module Validators
8
+ module FullAddress
9
+ module Exclusions
10
+ class City <
11
+ AtlasEngine::AddressValidation::Validators::FullAddress::Exclusions::ExclusionBase
12
+ extend T::Sig
13
+ class << self
14
+ sig do
15
+ override.params(
16
+ candidate: AtlasEngine::AddressValidation::Candidate,
17
+ address_comparison: AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison,
18
+ )
19
+ .returns(T::Boolean)
20
+ end
21
+ def apply?(candidate, address_comparison)
22
+ # If the candidate city is already present in the parsings
23
+ address_comparison.parsings.parsings.pluck(:city)&.include?(candidate.component(:city)&.value&.first)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -3,5 +3,9 @@ validation:
3
3
  enabled: true
4
4
  default_matching_strategy: es
5
5
  has_provinces: false
6
+ address_parser: AtlasEngine::Gg::ValidationTranscriber::AddressParser
6
7
  restrictions:
7
8
  - class: AtlasEngine::Gg::AddressValidation::Validators::FullAddress::Restrictions::UnsupportedCity
9
+ exclusions:
10
+ city:
11
+ - AtlasEngine::Gg::AddressValidation::Validators::FullAddress::Exclusions::City
@@ -0,0 +1,43 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module Gg
6
+ module ValidationTranscriber
7
+ class AddressParser < AtlasEngine::ValidationTranscriber::AddressParserBase
8
+ private
9
+
10
+ CITY = %r{
11
+ (?<city>
12
+ st\.?\s?saviour[']?[s]?|
13
+ st\.?\s?sampson[']?[s]?|
14
+ st\.?\s?andrew[']?[s]?|
15
+ st\.?\s?martin[']?[s]?|
16
+ st\.?\s?peter[']?[s]?\s?port|
17
+ st\.?\s?peter[']?[s]?|
18
+ st\.?\s?pierre\s?du\s?bois|
19
+ vale|
20
+ torteval|
21
+ castel|
22
+ forest
23
+ )
24
+ }ix
25
+
26
+ sig { returns(T::Array[Regexp]) }
27
+ def country_regex_formats
28
+ @country_regex_formats ||= [
29
+ /^#{BUILDING_NAME},\s+#{CITY}$/,
30
+ /^#{BUILDING_NAME},\s+#{STREET_NO_COMMAS},\s+#{CITY}$/,
31
+ /^#{BUILDING_NAME},\s+#{STREET_NO_COMMAS}$/,
32
+ /^#{NUMERIC_ONLY_BUILDING_NUM}?\s+#{STREET_NO_COMMAS},\s+#{CITY}$/,
33
+ /^#{UNIT_TYPE}\s+#{UNIT_NUM_NO_HYPHEN},\s+#{BUILDING_NAME},\s+#{CITY}$/,
34
+ /^#{CITY}$/,
35
+ /^#{NUMERIC_ONLY_BUILDING_NUM}?\s+#{STREET_NO_COMMAS}$/,
36
+ /^#{BUILDING_NAME}$/,
37
+ /^#{STREET_NO_COMMAS}$/,
38
+ ]
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -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(CandidateTuple)) }
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[CandidateTuple]) }
39
+ sig { returns(T::Array[AddressValidation::Validators::FullAddress::AddressComparison]) }
40
40
  def sorted_candidates
41
- sorted_candidate_tuples = datastore.fetch_full_address_candidates
41
+ sorted_address_comparisons = datastore.fetch_full_address_candidates
42
42
  .filter_map.with_index(1) do |candidate, position|
43
- address_comparison = AtlasEngine::AddressValidation::Validators::FullAddress::AddressComparison.new(
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
- tuple = CandidateTuple.new(address_comparison, position, candidate)
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(sorted_candidate_tuples)
53
- sorted_candidate_tuples
52
+ emit_sorted_candidates(sorted_address_comparisons.map(&:candidate))
53
+ sorted_address_comparisons
54
54
  end
55
55
 
56
- sig { params(sorted_candidate_tuples: T::Array[CandidateTuple]).void }
57
- def emit_sorted_candidates(sorted_candidate_tuples)
58
- log_info("Sorted candidates:\n #{sorted_candidate_tuples.map { |tuple| tuple.candidate.serialize }}")
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 = sorted_candidate_tuples.first&.position || 0
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,
@@ -128,6 +128,9 @@ module AtlasEngine
128
128
  end
129
129
  Token::Sequence.new(tokens: tokens, raw_value: city_value)
130
130
  end
131
+ rescue Elasticsearch::Error => e
132
+ log_elasticsearch_error(error: e, method: "city_sequence")
133
+ Token::Sequence.new(tokens: [], raw_value: city_value)
131
134
  end
132
135
 
133
136
  sig { returns(T::Array[T::Hash[String, T.untyped]]) }
@@ -135,6 +138,9 @@ module AtlasEngine
135
138
  measure_es_validation_request_time(method: "full_address_candidates") do
136
139
  repository.search(query_builder.full_address_query)
137
140
  end
141
+ rescue Elasticsearch::Error => e
142
+ log_elasticsearch_error(error: e, method: "full_address_candidates")
143
+ []
138
144
  end
139
145
 
140
146
  sig { returns(T::Array[Token::Sequence]) }
@@ -154,6 +160,9 @@ module AtlasEngine
154
160
  end
155
161
  end
156
162
  end
163
+ rescue Elasticsearch::Error => e
164
+ log_elasticsearch_error(error: e, method: "street_sequence")
165
+ [Token::Sequence.new(tokens: [], raw_value: "")]
157
166
  end
158
167
 
159
168
  sig { params(candidates: T::Array[Candidate]).void }
@@ -165,6 +174,8 @@ module AtlasEngine
165
174
  end
166
175
 
167
176
  TermVectors.new(term_vectors_hashes: candidate_term_vectors, candidates: candidates).set_candidate_sequences
177
+ rescue Elasticsearch::Error => e
178
+ log_elasticsearch_error(error: e, method: "term_vectors")
168
179
  end
169
180
 
170
181
  sig { params(candidates: T::Array[Candidate]).returns(T::Hash[String, T.untyped]) }
@@ -190,6 +201,18 @@ module AtlasEngine
190
201
  )
191
202
  end
192
203
 
204
+ sig { params(error: Elasticsearch::Error, method: String).void }
205
+ def log_elasticsearch_error(error:, method:)
206
+ log_error("Elasticsearch error: #{error.message}")
207
+ StatsD.increment(
208
+ "AddressValidation.elasticsearch_error",
209
+ tags: {
210
+ country: country_code,
211
+ method:,
212
+ },
213
+ )
214
+ end
215
+
193
216
  sig { params(future: T.nilable(Concurrent::Promises::Future), method: String).void }
194
217
  def log_future_state_on_join(future:, method:)
195
218
  state = future&.state || :unsubmitted
@@ -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
- @session = T.let(Session.new(address: address, matching_strategy: MatchingStrategies::Es), Session)
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(session:, result:)
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(session:, result:)
36
+ AddressValidation::Validators::FullAddress::NoCandidateResult.new(address:, result:)
38
37
  else
39
38
  AddressValidation::Validators::FullAddress::CandidateResult.new(
40
- candidate: T.must(best_candidate),
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(CandidateTuple)) }
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(CandidateTuple),
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: session.datastore(locale: locale),
74
- address: session.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
- @session = T.let(Session.new(address: address, matching_strategy: MatchingStrategies::EsStreet), Session)
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
- candidate: AddressValidation::CandidateTuple,
15
- session: Session,
14
+ address_comparison: AddressComparison,
15
+ matching_strategy: AddressValidation::MatchingStrategies,
16
16
  result: Result,
17
- )
18
- .void
17
+ ).void
19
18
  end
20
- def initialize(candidate:, session:, result:)
21
- super(session: session, result: result)
22
- @candidate = candidate.candidate
23
- @address_comparison = candidate.address_comparison
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?(session.address, unmatched_components.keys)
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(session.address, [])
59
+ concern = InvalidZipConcernBuilder.for(address, [])
60
60
  result.concerns << concern if concern
61
61
 
62
- if ConcernBuilder.too_many_unmatched_components?(session.address, unmatched_components.keys)
63
- result.concerns << UnknownAddressConcern.new(session.address)
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: session.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
- session.address.to_h,
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] = @address_comparison.for(component).sequence_comparison
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(session, candidate, address_comparison)
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 session.address.address1.to_s.include?(original_street)
170
+ if address.address1.to_s.include?(original_street)
171
171
  :address1
172
- elsif session.address.address2.to_s.include?(original_street)
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: session.parsings.potential_streets }
180
- input_address = session.address.to_h.compact_blank.except(:phone)
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
@@ -11,9 +11,9 @@ module AtlasEngine
11
11
 
12
12
  abstract!
13
13
 
14
- sig { params(session: Session, result: Result).void }
15
- def initialize(session:, result:)
16
- @session = session
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 :session, :result
26
-
27
- delegate :address, to: :session
25
+ attr_reader :result, :address
28
26
 
29
27
  sig { void }
30
28
  def update_result_scope
@@ -109,17 +109,13 @@ module AtlasEngine
109
109
  concern = InvalidZipConcernBuilder.for(address, suggestion_ids)
110
110
  return concern if concern
111
111
 
112
- if :province_code.in?(matched_components) && :city.in?(matched_components)
113
- return UnknownZipForAddressConcern.new(address, suggestion_ids)
114
- end
115
-
116
112
  build_default_concern
117
113
  end
118
114
 
119
115
  sig { returns(AddressValidation::Concern) }
120
116
  def build_province_concern
121
117
  if ([:zip, :city] - matched_components).empty?
122
- UnknownProvinceConcern.new(address, suggestion_ids)
118
+ UnknownProvinceConcernBuilder.new(address).build(suggestion_ids)
123
119
  else
124
120
  build_default_concern
125
121
  end
@@ -127,7 +123,12 @@ module AtlasEngine
127
123
 
128
124
  sig { returns(AddressValidation::Concern) }
129
125
  def build_default_concern
130
- UnmatchedFieldConcern.new(unmatched_component, matched_components, address, suggestion_ids, unmatched_field)
126
+ UnmatchedFieldConcernBuilder.new(
127
+ unmatched_component,
128
+ matched_components,
129
+ address,
130
+ unmatched_field,
131
+ ).build(suggestion_ids)
131
132
  end
132
133
  end
133
134
  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
- InvalidZipForProvinceConcern.new(address, suggestion_ids) unless province.valid_zip?(address.zip)
25
+ return if province.valid_zip?(address.zip)
26
+
27
+ InvalidZipForProvinceConcernBuilder.new(address).build
26
28
  else
27
- InvalidZipForCountryConcern.new(address, suggestion_ids) unless country.valid_zip?(address.zip)
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 InvalidZipForCountryConcern < AddressValidation::Concern
8
+ class InvalidZipForCountryConcernBuilder
9
+ extend T::Sig
9
10
  include ConcernFormatter
10
11
  attr_reader :address
11
12
 
12
- sig { params(address: AbstractAddress, suggestion_ids: T::Array[String]).void }
13
- def initialize(address, suggestion_ids)
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
- super(
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 InvalidZipForProvinceConcern < AddressValidation::Concern
8
+ class InvalidZipForProvinceConcernBuilder
9
+ extend T::Sig
9
10
  include ConcernFormatter
10
11
  attr_reader :address
11
12
 
12
- sig { params(address: AbstractAddress, suggestion_ids: T::Array[String]).void }
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 { returns(String) }
27
- def message
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
@@ -10,11 +10,9 @@ module AtlasEngine
10
10
 
11
11
  sig { void }
12
12
  def update_result
13
- result.concerns << UnknownAddressConcern.new(
14
- address,
15
- )
13
+ result.concerns << UnknownAddressConcernBuilder.new(address).build
16
14
 
17
- concern = InvalidZipConcernBuilder.for(session.address, [])
15
+ concern = InvalidZipConcernBuilder.for(address, [])
18
16
  result.concerns << concern if concern
19
17
 
20
18
  update_result_scope
@@ -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(session, candidate, address_comparison)
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 session.matching_strategy !=
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(session.country_code)
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:#{session.country_code}",
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: session.address.country_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 UnknownAddressConcern < AddressValidation::Concern
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
- super(
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: Worldwide.region(code: address.country_code).field(key: :address).error(code: :may_not_exist),
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,9 +5,10 @@ module AtlasEngine
5
5
  module AddressValidation
6
6
  module Validators
7
7
  module FullAddress
8
- class UnmatchedFieldConcern < AddressValidation::Concern
8
+ class UnmatchedFieldConcernBuilder
9
+ extend T::Sig
9
10
  include ConcernFormatter
10
- attr_reader :component, :matched_components, :address, :unmatched_field
11
+ attr_reader :address, :component, :matched_components, :unmatched_field
11
12
 
12
13
  COMPONENTS_TO_LABELS = {
13
14
  zip: "ZIP",
@@ -25,29 +26,37 @@ 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, suggestion_ids, unmatched_field = nil)
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
- super(
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
- "Enter a valid #{COMPONENTS_TO_LABELS[component]} for #{valid_address_component_values.join(", ")}"
59
+ country.field(key: field_name).error(code: :unknown_for_address).to_s
51
60
  end
52
61
 
53
62
  sig { returns(Symbol) }
@@ -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
@@ -10,7 +10,7 @@ module AtlasEngine
10
10
 
11
11
  sig { void }
12
12
  def update_result
13
- concern = InvalidZipConcernBuilder.for(session.address, [])
13
+ concern = InvalidZipConcernBuilder.for(address, [])
14
14
  result.concerns << concern if concern
15
15
 
16
16
  update_result_scope
@@ -28,7 +28,7 @@ module AtlasEngine
28
28
  sig { params(suggestion: Suggestion).returns(Concern) }
29
29
  def build_concern(suggestion)
30
30
  Concern.new(
31
- field_names: [:country, :zip],
31
+ field_names: [:country],
32
32
  code: :country_invalid_for_zip,
33
33
  type: T.must(Concern::TYPES[:error]),
34
34
  type_level: 1,
@@ -24,7 +24,7 @@ module AtlasEngine
24
24
  sig { returns(Concern) }
25
25
  def build_concern
26
26
  Concern.new(
27
- field_names: [:province, :country],
27
+ field_names: [:province],
28
28
  code: :province_invalid,
29
29
  type: T.must(Concern::TYPES[:error]),
30
30
  type_level: 3,
@@ -24,7 +24,7 @@ module AtlasEngine
24
24
  sig { returns(Concern) }
25
25
  def build_concern
26
26
  Concern.new(
27
- field_names: [:address1, :country],
27
+ field_names: [:address1],
28
28
  code: :missing_building_number,
29
29
  type: T.must(Concern::TYPES[:warning]),
30
30
  type_level: 1,
@@ -22,7 +22,7 @@ module AtlasEngine
22
22
  sig { returns(Concern) }
23
23
  def build_concern
24
24
  Concern.new(
25
- field_names: [:address1, :address2, :country],
25
+ field_names: [:address1, :address2],
26
26
  code: :missing_building_number,
27
27
  type: T.must(Concern::TYPES[:warning]),
28
28
  type_level: 3,
@@ -26,7 +26,7 @@ module AtlasEngine
26
26
  sig { returns(Concern) }
27
27
  def build_concern
28
28
  Concern.new(
29
- field_names: [:zip, :country],
29
+ field_names: [:zip],
30
30
  code: :zip_invalid_for_country,
31
31
  type: T.must(Concern::TYPES[:error]),
32
32
  type_level: 3,
@@ -29,7 +29,7 @@ module AtlasEngine
29
29
  sig { returns(Concern) }
30
30
  def build_concern
31
31
  Concern.new(
32
- field_names: [:zip, :country, :province],
32
+ field_names: [:zip],
33
33
  code: :zip_invalid_for_province,
34
34
  type: T.must(Concern::TYPES[:error]),
35
35
  type_level: 3,
@@ -0,0 +1,19 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module Elasticsearch
6
+ class Error < StandardError
7
+ extend T::Sig
8
+
9
+ sig { params(message: String, cause: T.nilable(Exception)).void }
10
+ def initialize(message, cause = nil)
11
+ super(message)
12
+ @cause = cause
13
+ end
14
+
15
+ sig { returns(T.nilable(Exception)) }
16
+ attr_reader :cause
17
+ end
18
+ end
19
+ end
@@ -133,8 +133,8 @@ module AtlasEngine
133
133
  response = client.post(path, query, {})
134
134
 
135
135
  response.body
136
- rescue ::Elastic::Transport::Transport::Error
137
- { "hits" => { "hits" => [] } }
136
+ rescue ::Elastic::Transport::Transport::Error => e
137
+ raise Elasticsearch::Error.new(e.message, e)
138
138
  end
139
139
 
140
140
  sig { override.params(query: T::Hash[String, T.untyped]).returns(T::Hash[String, T.untyped]) }
@@ -143,8 +143,8 @@ module AtlasEngine
143
143
  response = client.post(path, query, {})
144
144
 
145
145
  response.body
146
- rescue ::Elastic::Transport::Transport::Error
147
- { "tokens" => [] }
146
+ rescue ::Elastic::Transport::Transport::Error => e
147
+ raise Elasticsearch::Error.new(e.message, e)
148
148
  end
149
149
 
150
150
  sig { override.params(query: T::Hash[String, T.untyped]).returns(T::Hash[String, T.untyped]) }
@@ -153,8 +153,8 @@ module AtlasEngine
153
153
  response = client.post(path, query, {})
154
154
 
155
155
  response.body
156
- rescue ::Elastic::Transport::Transport::Error
157
- { "docs" => [] }
156
+ rescue ::Elastic::Transport::Transport::Error => e
157
+ raise Elasticsearch::Error.new(e.message, e)
158
158
  end
159
159
 
160
160
  sig { override.params(id: T.any(String, Integer)).returns(T::Hash[String, T.untyped]) }
@@ -163,8 +163,8 @@ module AtlasEngine
163
163
  response = client.get(path, nil, {})
164
164
 
165
165
  response.body["_source"]
166
- rescue ::Elastic::Transport::Transport::Error
167
- {}
166
+ rescue ::Elastic::Transport::Transport::Error => e
167
+ raise Elasticsearch::Error.new(e.message, e)
168
168
  end
169
169
 
170
170
  sig { override.params(post_address: PostAddressData).returns(T::Hash[Symbol, T.untyped]) }
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module AtlasEngine
5
- VERSION = "0.5.0"
5
+ VERSION = "0.7.0"
6
6
  end
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.5.0
4
+ version: 0.7.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-20 00:00:00.000000000 Z
11
+ date: 2024-03-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: annex_29
@@ -305,8 +305,10 @@ files:
305
305
  - app/countries/atlas_engine/gb/country_profile.yml
306
306
  - app/countries/atlas_engine/gb/validation_transcriber/full_address_parser.rb
307
307
  - app/countries/atlas_engine/gb/validation_transcriber/parsed_address.rb
308
+ - app/countries/atlas_engine/gg/address_validation/validators/full_address/exclusions/city.rb
308
309
  - app/countries/atlas_engine/gg/address_validation/validators/full_address/restrictions/unsupported_city.rb
309
310
  - app/countries/atlas_engine/gg/country_profile.yml
311
+ - app/countries/atlas_engine/gg/validation_transcriber/address_parser.rb
310
312
  - app/countries/atlas_engine/ie/country_profile.yml
311
313
  - app/countries/atlas_engine/it/address_importer/corrections/open_address/city_corrector.rb
312
314
  - app/countries/atlas_engine/it/address_importer/corrections/open_address/province_corrector.rb
@@ -437,7 +439,6 @@ files:
437
439
  - app/models/atlas_engine/address_validation/abstract_address.rb
438
440
  - app/models/atlas_engine/address_validation/address.rb
439
441
  - app/models/atlas_engine/address_validation/candidate.rb
440
- - app/models/atlas_engine/address_validation/candidate_tuple.rb
441
442
  - app/models/atlas_engine/address_validation/concern.rb
442
443
  - app/models/atlas_engine/address_validation/concern_producer.rb
443
444
  - app/models/atlas_engine/address_validation/concern_queue.rb
@@ -463,7 +464,6 @@ files:
463
464
  - app/models/atlas_engine/address_validation/request.rb
464
465
  - app/models/atlas_engine/address_validation/result.rb
465
466
  - app/models/atlas_engine/address_validation/runs_validation.rb
466
- - app/models/atlas_engine/address_validation/session.rb
467
467
  - app/models/atlas_engine/address_validation/statsd_emitter.rb
468
468
  - app/models/atlas_engine/address_validation/strategies.rb
469
469
  - app/models/atlas_engine/address_validation/suggestion.rb
@@ -485,20 +485,18 @@ files:
485
485
  - app/models/atlas_engine/address_validation/validators/full_address/exclusions/exclusion_base.rb
486
486
  - app/models/atlas_engine/address_validation/validators/full_address/field_comparison_base.rb
487
487
  - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb
488
- - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_country_concern.rb
489
- - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_province_concern.rb
488
+ - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_country_concern_builder.rb
489
+ - app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_province_concern_builder.rb
490
490
  - app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb
491
491
  - app/models/atlas_engine/address_validation/validators/full_address/number_comparison.rb
492
492
  - app/models/atlas_engine/address_validation/validators/full_address/postal_code_matcher.rb
493
493
  - app/models/atlas_engine/address_validation/validators/full_address/province_code_comparison.rb
494
494
  - 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
495
  - app/models/atlas_engine/address_validation/validators/full_address/street_comparison.rb
497
496
  - app/models/atlas_engine/address_validation/validators/full_address/suggestion_builder.rb
498
- - app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern.rb
499
- - app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern.rb
500
- - app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern.rb
501
- - app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern.rb
497
+ - app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern_builder.rb
498
+ - app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern_builder.rb
499
+ - app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern_builder.rb
502
500
  - app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb
503
501
  - app/models/atlas_engine/address_validation/validators/full_address/zip_comparison.rb
504
502
  - app/models/atlas_engine/address_validation/validators/predicates/cache.rb
@@ -533,6 +531,7 @@ files:
533
531
  - app/models/atlas_engine/country_repository.rb
534
532
  - app/models/atlas_engine/elasticsearch/client.rb
535
533
  - app/models/atlas_engine/elasticsearch/client_interface.rb
534
+ - app/models/atlas_engine/elasticsearch/error.rb
536
535
  - app/models/atlas_engine/elasticsearch/repository.rb
537
536
  - app/models/atlas_engine/elasticsearch/repository_interface.rb
538
537
  - app/models/atlas_engine/elasticsearch/response.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
@@ -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
@@ -1,32 +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 UnknownZipForAddressConcern < AddressValidation::Concern
9
- attr_reader :address
10
-
11
- sig { params(address: AbstractAddress, suggestion_ids: T::Array[String]).void }
12
- def initialize(address, suggestion_ids)
13
- @address = address
14
- super(
15
- code: :zip_inconsistent,
16
- field_names: [:zip],
17
- message: message,
18
- type: T.must(Concern::TYPES[:warning]),
19
- type_level: 3,
20
- suggestion_ids: suggestion_ids
21
- )
22
- end
23
-
24
- sig { returns(String) }
25
- def message
26
- "Enter a valid ZIP for #{address.address1}, #{address.city}"
27
- end
28
- end
29
- end
30
- end
31
- end
32
- end