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