atlas_engine 0.6.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 (18) 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/es/datastore.rb +23 -0
  6. data/app/models/atlas_engine/address_validation/validators/full_address/concern_builder.rb +0 -4
  7. data/app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern_builder.rb +1 -1
  8. data/app/models/atlas_engine/address_validation/validators/predicates/country/valid_for_zip.rb +1 -1
  9. data/app/models/atlas_engine/address_validation/validators/predicates/province/valid_for_country.rb +1 -1
  10. data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1.rb +1 -1
  11. data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1_or_address2.rb +1 -1
  12. data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_country.rb +1 -1
  13. data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_province.rb +1 -1
  14. data/app/models/atlas_engine/elasticsearch/error.rb +19 -0
  15. data/app/models/atlas_engine/elasticsearch/repository.rb +8 -8
  16. data/lib/atlas_engine/version.rb +1 -1
  17. metadata +5 -3
  18. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern_builder.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56b5b41a624c3481954aadfa0101c9883dfe3479a3cdec373f8ecccab8bae879
4
- data.tar.gz: 73ee021ecf5d8357ae8f000df7e963e7504153fdc3b7bb98f188445aa8cd7989
3
+ metadata.gz: 9948b64010b57506c90e07bf0fc324c7ad158112169375aa1ac1f7053850a9be
4
+ data.tar.gz: 872cd26b540c96af7a777b044a4af20cce6d1b7df5569f0b3cd7aaf999fb1847
5
5
  SHA512:
6
- metadata.gz: b93dee8561c73619222ca4a4e803fb2f911b3149955c5b1af7803990318a7ebd36e781c41643cf3076197f579833e9c2d361e8e4550a9d2d3de628d8e7819ef7
7
- data.tar.gz: f2f593c6e2a7849dae6dce6a52d9402ce7d907a90511664d1218133b5d4a501b5ae98a26e54a06412c3fb37e3dc74c75ae17c575ae24fa4805c02ad888467d21
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
@@ -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
@@ -109,10 +109,6 @@ 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 UnknownZipForAddressConcernBuilder.new(address).build(suggestion_ids)
114
- end
115
-
116
112
  build_default_concern
117
113
  end
118
114
 
@@ -56,7 +56,7 @@ module AtlasEngine
56
56
 
57
57
  sig { returns(String) }
58
58
  def message
59
- "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
60
60
  end
61
61
 
62
62
  sig { returns(Symbol) }
@@ -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.6.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.6.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-26 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
@@ -494,7 +496,6 @@ files:
494
496
  - app/models/atlas_engine/address_validation/validators/full_address/suggestion_builder.rb
495
497
  - app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern_builder.rb
496
498
  - app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern_builder.rb
497
- - app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern_builder.rb
498
499
  - app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern_builder.rb
499
500
  - app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb
500
501
  - app/models/atlas_engine/address_validation/validators/full_address/zip_comparison.rb
@@ -530,6 +531,7 @@ files:
530
531
  - app/models/atlas_engine/country_repository.rb
531
532
  - app/models/atlas_engine/elasticsearch/client.rb
532
533
  - app/models/atlas_engine/elasticsearch/client_interface.rb
534
+ - app/models/atlas_engine/elasticsearch/error.rb
533
535
  - app/models/atlas_engine/elasticsearch/repository.rb
534
536
  - app/models/atlas_engine/elasticsearch/repository_interface.rb
535
537
  - app/models/atlas_engine/elasticsearch/response.rb
@@ -1,34 +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 UnknownZipForAddressConcernBuilder
9
- extend T::Sig
10
- attr_reader :address
11
-
12
- sig { params(address: AbstractAddress).void }
13
- def initialize(address)
14
- @address = address
15
- end
16
-
17
- sig { params(suggestion_ids: T::Array[String]).returns(Concern) }
18
- def build(suggestion_ids = [])
19
- message = "Enter a valid ZIP for #{address.address1}, #{address.city}"
20
-
21
- Concern.new(
22
- code: :zip_inconsistent,
23
- field_names: [:zip],
24
- message: message,
25
- type: T.must(Concern::TYPES[:warning]),
26
- type_level: 3,
27
- suggestion_ids: suggestion_ids,
28
- )
29
- end
30
- end
31
- end
32
- end
33
- end
34
- end