atlas_engine 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -17
- data/app/graphql/atlas_engine/schema.graphql +10 -1
- data/app/graphql/atlas_engine/types/address_validation/concern_type.rb +8 -1
- data/app/graphql/atlas_engine/types/address_validation/suggestion_type.rb +4 -0
- data/app/graphql/atlas_engine/types/message_format_type.rb +11 -0
- data/app/graphql/atlas_engine/types/query_type.rb +3 -1
- data/app/lib/atlas_engine/validation_transcriber/address_parsings.rb +14 -9
- data/app/models/atlas_engine/address_validation/es/validators/full_address.rb +18 -5
- data/app/models/atlas_engine/address_validation/es/validators/full_address_street.rb +2 -2
- data/app/models/atlas_engine/address_validation/full_address_validator_base.rb +6 -2
- data/app/models/atlas_engine/address_validation/message_format.rb +13 -0
- data/app/models/atlas_engine/address_validation/predicate_pipeline_builder.rb +90 -0
- data/app/models/atlas_engine/address_validation/request.rb +1 -0
- data/app/models/atlas_engine/address_validation/suggestion.rb +26 -1
- data/app/models/atlas_engine/address_validation/validator.rb +31 -14
- data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +9 -5
- data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result_base.rb +4 -3
- data/app/models/atlas_engine/address_validation/validators/full_address/concern_builder.rb +19 -4
- data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb +4 -3
- data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_country_concern_builder.rb +6 -4
- data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_province_concern_builder.rb +4 -2
- data/app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb +1 -1
- data/app/models/atlas_engine/address_validation/validators/full_address/suggestion_builder.rb +5 -2
- data/app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern_builder.rb +16 -4
- data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern_builder.rb +8 -3
- data/app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern_builder.rb +13 -3
- data/app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb +1 -1
- data/app/models/atlas_engine/address_validation/validators/predicates/city/present.rb +1 -1
- data/app/models/atlas_engine/address_validation/validators/predicates/country/exists.rb +5 -1
- data/app/models/atlas_engine/address_validation/validators/predicates/country/valid_for_zip.rb +1 -1
- data/app/models/atlas_engine/address_validation/validators/predicates/neighborhood/present.rb +35 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/not_exceed_max_length.rb +18 -3
- data/app/models/atlas_engine/address_validation/validators/predicates/phone/valid.rb +3 -1
- data/app/models/atlas_engine/address_validation/validators/predicates/predicate.rb +6 -2
- data/app/models/atlas_engine/address_validation/validators/predicates/province/exists.rb +3 -1
- data/app/models/atlas_engine/address_validation/validators/predicates/province/valid_for_country.rb +3 -1
- data/app/models/atlas_engine/address_validation/validators/predicates/street/present.rb +3 -1
- data/app/models/atlas_engine/address_validation/validators/predicates/street_name/present.rb +35 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/street_number/present.rb +35 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/zip/present.rb +2 -2
- data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_country.rb +1 -1
- data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_province.rb +1 -1
- data/app/models/atlas_engine/services/validation.rb +4 -0
- data/db/data/validation_pipelines/es.yml +46 -0
- data/db/data/validation_pipelines/es_street.yml +46 -0
- data/db/data/validation_pipelines/local.yml +46 -0
- data/lib/atlas_engine/version.rb +1 -1
- metadata +39 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ac0ad464ab86fe1db96b5ca3f5a69254d6ad52571d8c83350645c9e031ea58b
|
4
|
+
data.tar.gz: f683950cfa6d89c1cdf4935d8a49d76e416c57220ac29e5aa62adcdaf2a628d5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79ae2f83d4b4ee2d65a7d6e566bee41ac3b0c5e44f879090b4659151ca9f7987e128badf6f31569530c142ea683b8df6dce10275423469924c44f1477f6480d6
|
7
|
+
data.tar.gz: e1a0e889113742443408d479dba7f1bb294230d4bcfd0af8f128e6c200a19d6c595c1bdf420798ebd2a9cb9caa8fa2cd69ef21ab4361ae066aa6a48861e9f91d
|
data/README.md
CHANGED
@@ -25,7 +25,6 @@ query validation {
|
|
25
25
|
zip: "K2P 2L8"
|
26
26
|
}
|
27
27
|
locale: "en"
|
28
|
-
matchingStrategy: LOCAL
|
29
28
|
) {
|
30
29
|
validationScope
|
31
30
|
concerns {
|
@@ -70,21 +69,6 @@ presence or absence differs per country.
|
|
70
69
|
|
71
70
|
**Locale:** The language in which to render any messages in the validation API response.
|
72
71
|
|
73
|
-
**MatchingStrategy:** The strategy used to evaluate the validity of the address input. Out of the box, Atlas Engine
|
74
|
-
supports three different matching strategies: `local`, `es`, and `es_street`.
|
75
|
-
- `local` matching uses the [worldwide](https://github.com/Shopify/worldwide) gem to provide the most basic level of
|
76
|
-
address validation. This may include simple errors (required fields not populated) or more advanced errors (province
|
77
|
-
not belonging to the country, zip code not belonging to the province). This level of matching does not require
|
78
|
-
[ingestion](#ingestion) of country data to work, but the level of support and suggestions it can provide in its
|
79
|
-
responses is minimal.
|
80
|
-
- `es` matching uses data indexed in elasticsearch via our [ingestion](#ingestion) process to validate the city,
|
81
|
-
province, country, and zip code fields of the input address, in addition to all of the basic functionality provided
|
82
|
-
in the `local` strategy. A more detailed explanation for how this strategy works can be found [here](#elasticsearch-matching-strategy).
|
83
|
-
- `es_street` is our most advanced matching strategy and requires the highest quality data indexed in elasticsearch
|
84
|
-
via our [ingestion](#ingestion) process. This matching strategy provides everything that `es` and `local` does along
|
85
|
-
with validation of the address1 and address2 components of the address input. A more detailed explanation of how
|
86
|
-
this strategy works can be found [here](#elasticsearch-matching-strategy).
|
87
|
-
|
88
72
|
**Validation Scope:** This response object is populated with the field names from the input that have been successfully
|
89
73
|
validated.
|
90
74
|
|
@@ -109,7 +93,6 @@ query validation {
|
|
109
93
|
zip: "90210"
|
110
94
|
}
|
111
95
|
locale: "en"
|
112
|
-
matchingStrategy: LOCAL
|
113
96
|
) {
|
114
97
|
validationScope
|
115
98
|
concerns {
|
@@ -410,6 +393,20 @@ and the US data is in mysql the rest of the process for creating the elasticsear
|
|
410
393
|
|
411
394
|
## Elasticsearch Matching Strategy
|
412
395
|
|
396
|
+
An optional GraphQL parameter, and the strategy used to evaluate the validity of the address input. Out of the box, Atlas Engine
|
397
|
+
supports three different matching strategies: `local`, `es`, and `es_street`.
|
398
|
+
- `local` matching uses the [worldwide](https://github.com/Shopify/worldwide) gem to provide the most basic level of
|
399
|
+
address validation. This may include simple errors (required fields not populated) or more advanced errors (province
|
400
|
+
not belonging to the country, zip code not belonging to the province). This level of matching does not require
|
401
|
+
[ingestion](#ingestion) of country data to work, but the level of support and suggestions it can provide in its
|
402
|
+
responses is minimal.
|
403
|
+
- `es` matching uses data indexed in elasticsearch via our [ingestion](#ingestion) process to validate the city,
|
404
|
+
province, country, and zip code fields of the input address, in addition to all of the basic functionality provided
|
405
|
+
in the `local` strategy.
|
406
|
+
- `es_street` is our most advanced matching strategy and requires the highest quality data indexed in elasticsearch
|
407
|
+
via our [ingestion](#ingestion) process. This matching strategy provides everything that `es` and `local` does along
|
408
|
+
with validation of the address1 and address2 components of the address input.
|
409
|
+
|
413
410
|
Once we have successfully created and activated an elasticsearch index using open address data, we may now use
|
414
411
|
the more advanced elasticsearch matching strategies `es` and `es_street`.
|
415
412
|
|
@@ -47,8 +47,13 @@ enum MatchingStrategy {
|
|
47
47
|
LOCAL
|
48
48
|
}
|
49
49
|
|
50
|
+
enum MessageFormat {
|
51
|
+
INFORMATIVE
|
52
|
+
INSTRUCTIONAL
|
53
|
+
}
|
54
|
+
|
50
55
|
type Query {
|
51
|
-
validation(address: AddressInput!, locale: String!, matchingStrategy: MatchingStrategy): Validation!
|
56
|
+
validation(address: AddressInput!, locale: String!, matchingStrategy: MatchingStrategy, messageFormat: MessageFormat): Validation!
|
52
57
|
}
|
53
58
|
|
54
59
|
"""
|
@@ -60,8 +65,12 @@ type Suggestion {
|
|
60
65
|
city: String
|
61
66
|
countryCode: ValidationSupportedCountry
|
62
67
|
id: String!
|
68
|
+
line2: String
|
69
|
+
neighborhood: String
|
63
70
|
province: String
|
64
71
|
provinceCode: String
|
72
|
+
streetName: String
|
73
|
+
streetNumber: String
|
65
74
|
zip: String
|
66
75
|
}
|
67
76
|
|
@@ -1,10 +1,12 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: true
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module AtlasEngine
|
5
5
|
module Types
|
6
6
|
module AddressValidation
|
7
7
|
class ConcernType < BaseObject
|
8
|
+
extend T::Sig
|
9
|
+
|
8
10
|
description "A piece of relevant information regarding the address validation result." \
|
9
11
|
"They can be categorized as either a Warning or Error."
|
10
12
|
|
@@ -14,6 +16,11 @@ module AtlasEngine
|
|
14
16
|
field :type, Enums::ConcernEnum, null: false
|
15
17
|
field :type_level, Int, null: false
|
16
18
|
field :suggestion_ids, [String], null: false
|
19
|
+
|
20
|
+
sig { returns(T::Array[String]) }
|
21
|
+
def field_names
|
22
|
+
object.field_names.map { |field_name| field_name.to_s.camelize(:lower) }
|
23
|
+
end
|
17
24
|
end
|
18
25
|
end
|
19
26
|
end
|
@@ -9,7 +9,11 @@ module AtlasEngine
|
|
9
9
|
|
10
10
|
field :id, String, null: false
|
11
11
|
field :address1, String, null: true
|
12
|
+
field :street_name, String, null: true
|
13
|
+
field :street_number, String, null: true
|
12
14
|
field :address2, String, null: true
|
15
|
+
field :line2, String, null: true
|
16
|
+
field :neighborhood, String, null: true
|
13
17
|
field :city, String, null: true
|
14
18
|
field :zip, String, null: true
|
15
19
|
field :province_code, String, null: true
|
@@ -10,9 +10,10 @@ module AtlasEngine
|
|
10
10
|
argument :address, AddressValidation::AddressInput, required: true
|
11
11
|
argument :locale, String, required: true
|
12
12
|
argument :matching_strategy, MatchingStrategyType, required: false
|
13
|
+
argument :message_format, MessageFormatType, required: false
|
13
14
|
end
|
14
15
|
|
15
|
-
def validation(address:, locale: "en", matching_strategy: nil)
|
16
|
+
def validation(address:, locale: "en", matching_strategy: nil, message_format: nil)
|
16
17
|
raise build_graphql_error(AtlasEngine::AddressValidation::Errors::MISSING_PARAMETER) if address.blank?
|
17
18
|
|
18
19
|
locale = LocaleFormatHelper.format_locale(locale)
|
@@ -26,6 +27,7 @@ module AtlasEngine
|
|
26
27
|
address: address,
|
27
28
|
locale: locale,
|
28
29
|
matching_strategy: matching_strategy,
|
30
|
+
message_format: message_format,
|
29
31
|
),
|
30
32
|
)
|
31
33
|
end
|
@@ -9,22 +9,27 @@ module AtlasEngine
|
|
9
9
|
|
10
10
|
ParsedComponents = T.type_alias { T::Hash[Symbol, String] }
|
11
11
|
|
12
|
-
sig { returns(T::Array[ParsedComponents]) }
|
13
|
-
attr_reader :parsings
|
14
|
-
|
15
12
|
sig { params(address_input: AddressValidation::AbstractAddress, locale: T.nilable(String)).void }
|
16
13
|
def initialize(address_input:, locale: nil)
|
17
|
-
@
|
14
|
+
@address_input = address_input
|
15
|
+
@locale = locale
|
16
|
+
end
|
17
|
+
|
18
|
+
sig { returns(T::Array[ParsedComponents]) }
|
19
|
+
def parsings
|
20
|
+
@parsings ||= T.let(
|
18
21
|
begin
|
19
|
-
if address_input.country_code.blank?
|
22
|
+
if @address_input.country_code.blank?
|
20
23
|
[]
|
21
|
-
|
22
|
-
parsing_result = AddressParserFactory.create(address: address_input, locale: locale).parse
|
23
|
-
log_unparsable_address(address_input) if parsing_result.empty?
|
24
|
+
elsif @address_input.street_name.nil? && @address_input.street_number.nil?
|
25
|
+
parsing_result = AddressParserFactory.create(address: @address_input, locale: @locale).parse
|
26
|
+
log_unparsable_address(@address_input) if parsing_result.empty?
|
24
27
|
parsing_result
|
28
|
+
else
|
29
|
+
[{ street: @address_input.street_name, building_num: @address_input.street_number }]
|
25
30
|
end
|
26
31
|
end,
|
27
|
-
T::Array[ParsedComponents],
|
32
|
+
T.nilable(T::Array[ParsedComponents]),
|
28
33
|
)
|
29
34
|
end
|
30
35
|
|
@@ -8,12 +8,13 @@ module AtlasEngine
|
|
8
8
|
class FullAddress < FullAddressValidatorBase
|
9
9
|
include LogHelper
|
10
10
|
|
11
|
-
attr_reader :address, :result
|
11
|
+
attr_reader :address, :result, :message_format
|
12
12
|
|
13
|
-
sig { params(address: TAddress, result: Result).void }
|
14
|
-
def initialize(address:, result: Result.new)
|
13
|
+
sig { params(address: TAddress, result: Result, message_format: MessageFormat).void }
|
14
|
+
def initialize(address:, result: Result.new, message_format: MessageFormat::Instructional)
|
15
15
|
super
|
16
16
|
@matching_strategy = MatchingStrategies::Es
|
17
|
+
@message_format = message_format
|
17
18
|
end
|
18
19
|
|
19
20
|
sig { override.returns(Result) }
|
@@ -29,16 +30,23 @@ module AtlasEngine
|
|
29
30
|
sig { returns(AddressValidation::Validators::FullAddress::CandidateResultBase) }
|
30
31
|
def build_candidate_result
|
31
32
|
unless supported_address?(address)
|
32
|
-
return AddressValidation::Validators::FullAddress::UnsupportedScriptResult.new(
|
33
|
+
return AddressValidation::Validators::FullAddress::UnsupportedScriptResult.new(
|
34
|
+
address:,
|
35
|
+
result:,
|
36
|
+
message_format:,
|
37
|
+
)
|
33
38
|
end
|
34
39
|
|
35
40
|
if best_candidate.nil?
|
36
|
-
AddressValidation::Validators::FullAddress::NoCandidateResult.new(
|
41
|
+
AddressValidation::Validators::FullAddress::NoCandidateResult.new(
|
42
|
+
address:, result:, message_format:,
|
43
|
+
)
|
37
44
|
else
|
38
45
|
AddressValidation::Validators::FullAddress::CandidateResult.new(
|
39
46
|
address_comparison: T.must(best_candidate),
|
40
47
|
matching_strategy: @matching_strategy,
|
41
48
|
result: result,
|
49
|
+
message_format:,
|
42
50
|
)
|
43
51
|
end
|
44
52
|
end
|
@@ -100,6 +108,10 @@ module AtlasEngine
|
|
100
108
|
:zip,
|
101
109
|
:address1,
|
102
110
|
:address2,
|
111
|
+
:street_name,
|
112
|
+
:street_number,
|
113
|
+
:neighborhood,
|
114
|
+
:line2,
|
103
115
|
])
|
104
116
|
end
|
105
117
|
|
@@ -108,6 +120,7 @@ module AtlasEngine
|
|
108
120
|
result.concerns.flat_map(&:code).intersect?([
|
109
121
|
:address1_contains_too_many_words,
|
110
122
|
:address2_contains_too_many_words,
|
123
|
+
:street_name_contains_too_many_words,
|
111
124
|
])
|
112
125
|
end
|
113
126
|
|
@@ -6,8 +6,8 @@ module AtlasEngine
|
|
6
6
|
module Es
|
7
7
|
module Validators
|
8
8
|
class FullAddressStreet < FullAddress
|
9
|
-
sig { params(address: TAddress, result: Result).void }
|
10
|
-
def initialize(address:, result: Result.new)
|
9
|
+
sig { params(address: TAddress, message_format: MessageFormat, result: Result).void }
|
10
|
+
def initialize(address:, message_format:, result: Result.new)
|
11
11
|
super
|
12
12
|
@matching_strategy = MatchingStrategies::EsStreet
|
13
13
|
end
|
@@ -14,10 +14,14 @@ module AtlasEngine
|
|
14
14
|
sig { returns(AbstractAddress) }
|
15
15
|
attr_reader :address
|
16
16
|
|
17
|
-
sig {
|
18
|
-
|
17
|
+
sig { returns(MessageFormat) }
|
18
|
+
attr_reader :message_format
|
19
|
+
|
20
|
+
sig { params(address: AbstractAddress, result: Result, message_format: MessageFormat).void }
|
21
|
+
def initialize(address:, result:, message_format: MessageFormat::Instructional)
|
19
22
|
@address = address
|
20
23
|
@result = result
|
24
|
+
@message_format = message_format
|
21
25
|
end
|
22
26
|
|
23
27
|
sig { abstract.returns(Result) }
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class PredicatePipelineBuilder
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig { returns(PredicatePipeline) }
|
10
|
+
attr_reader :predicate_pipeline
|
11
|
+
|
12
|
+
sig { returns(AbstractAddress) }
|
13
|
+
attr_reader :address
|
14
|
+
|
15
|
+
sig { returns(Result) }
|
16
|
+
attr_reader :result
|
17
|
+
|
18
|
+
sig { returns(MessageFormat) }
|
19
|
+
attr_reader :message_format
|
20
|
+
|
21
|
+
sig do
|
22
|
+
params(
|
23
|
+
matching_strategy_name: String,
|
24
|
+
address: AbstractAddress,
|
25
|
+
result: Result,
|
26
|
+
message_format: MessageFormat,
|
27
|
+
).void
|
28
|
+
end
|
29
|
+
def initialize(matching_strategy_name:, address:, result:, message_format:)
|
30
|
+
@address = address
|
31
|
+
@predicate_pipeline = T.let(PredicatePipeline.find(matching_strategy_name), PredicatePipeline)
|
32
|
+
@result = result
|
33
|
+
@message_format = message_format
|
34
|
+
end
|
35
|
+
|
36
|
+
sig { returns(T::Array[PredicatePipeline::PredicateConfig]) }
|
37
|
+
def pipeline
|
38
|
+
predicate_pipeline.pipeline.reject do |predicate_config|
|
39
|
+
unsupported_fields.include?(predicate_config.field)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
sig { returns(T.nilable(FullAddressValidatorBase)) }
|
44
|
+
def full_address_validator
|
45
|
+
predicate_pipeline.full_address_validator&.new(
|
46
|
+
address: address,
|
47
|
+
result: result,
|
48
|
+
message_format: message_format,
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
sig do
|
53
|
+
returns(T::Array[Symbol])
|
54
|
+
end
|
55
|
+
def unsupported_fields
|
56
|
+
@unsupported_fields ||= T.let(
|
57
|
+
begin
|
58
|
+
unsupported_fields = []
|
59
|
+
unsupported_fields += address1_format == :extended ? [:address1] : [:street_name, :street_number]
|
60
|
+
unsupported_fields += address2_format == :extended ? [:address2] : [:line2, :neighborhood]
|
61
|
+
unsupported_fields
|
62
|
+
end,
|
63
|
+
T.nilable(T::Array[T.untyped]),
|
64
|
+
)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
sig { returns(Symbol) }
|
70
|
+
def address1_format
|
71
|
+
T.let(
|
72
|
+
[:street_name, :street_number].all? do |field|
|
73
|
+
address.send(field).nil?
|
74
|
+
end ? :standard : :extended,
|
75
|
+
Symbol,
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
sig { returns(Symbol) }
|
80
|
+
def address2_format
|
81
|
+
T.let(
|
82
|
+
[:neighborhood, :line2].all? do |field|
|
83
|
+
address.send(field).nil?
|
84
|
+
end ? :standard : :extended,
|
85
|
+
Symbol,
|
86
|
+
)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -12,9 +12,21 @@ module AtlasEngine
|
|
12
12
|
sig { returns(T.nilable(String)) }
|
13
13
|
attr_accessor :address1
|
14
14
|
|
15
|
+
sig { returns(T.nilable(String)) }
|
16
|
+
attr_accessor :street_name
|
17
|
+
|
18
|
+
sig { returns(T.nilable(String)) }
|
19
|
+
attr_accessor :street_number
|
20
|
+
|
15
21
|
sig { returns(T.nilable(String)) }
|
16
22
|
attr_accessor :address2
|
17
23
|
|
24
|
+
sig { returns(T.nilable(String)) }
|
25
|
+
attr_accessor :line2
|
26
|
+
|
27
|
+
sig { returns(T.nilable(String)) }
|
28
|
+
attr_accessor :neighborhood
|
29
|
+
|
18
30
|
sig { returns(T.nilable(String)) }
|
19
31
|
attr_accessor :city
|
20
32
|
|
@@ -30,16 +42,25 @@ module AtlasEngine
|
|
30
42
|
sig do
|
31
43
|
params(
|
32
44
|
address1: T.nilable(String),
|
45
|
+
street_name: T.nilable(String),
|
46
|
+
street_number: T.nilable(String),
|
33
47
|
address2: T.nilable(String),
|
48
|
+
line2: T.nilable(String),
|
49
|
+
neighborhood: T.nilable(String),
|
34
50
|
city: T.nilable(String),
|
35
51
|
zip: T.nilable(String),
|
36
52
|
province_code: T.nilable(String),
|
37
53
|
country_code: T.nilable(String),
|
38
54
|
).void
|
39
55
|
end
|
40
|
-
def initialize(address1: nil,
|
56
|
+
def initialize(address1: nil, street_name: nil, street_number: nil, address2: nil, line2: nil, neighborhood: nil,
|
57
|
+
city: nil, zip: nil, province_code: nil, country_code: nil)
|
41
58
|
@address1 = address1
|
59
|
+
@street_name = street_name
|
60
|
+
@street_number = street_number
|
42
61
|
@address2 = address2
|
62
|
+
@line2 = line2
|
63
|
+
@neighborhood = neighborhood
|
43
64
|
@city = city
|
44
65
|
@zip = zip
|
45
66
|
@province_code = province_code
|
@@ -55,7 +76,11 @@ module AtlasEngine
|
|
55
76
|
{
|
56
77
|
id: id,
|
57
78
|
address1: address1,
|
79
|
+
street_name: street_name,
|
80
|
+
street_number: street_number,
|
58
81
|
address2: address2,
|
82
|
+
line2: line2,
|
83
|
+
neighborhood: neighborhood,
|
59
84
|
city: city,
|
60
85
|
zip: zip,
|
61
86
|
province_code: province_code,
|
@@ -28,6 +28,12 @@ module AtlasEngine
|
|
28
28
|
sig { returns(T.nilable(FullAddressValidatorBase)) }
|
29
29
|
attr_reader :full_address_validator
|
30
30
|
|
31
|
+
sig { returns(T::Array[Symbol]) }
|
32
|
+
attr_reader :unsupported_fields
|
33
|
+
|
34
|
+
sig { returns(MessageFormat) }
|
35
|
+
attr_reader :message_format
|
36
|
+
|
31
37
|
FIELD_MAP = T.let(
|
32
38
|
{
|
33
39
|
country: "country_code",
|
@@ -36,6 +42,10 @@ module AtlasEngine
|
|
36
42
|
city: "city",
|
37
43
|
address1: "address1",
|
38
44
|
address2: "address2",
|
45
|
+
street_name: "street_name",
|
46
|
+
street_number: "street_number",
|
47
|
+
neighborhood: "neighborhood",
|
48
|
+
line2: "line2",
|
39
49
|
phone: "phone",
|
40
50
|
},
|
41
51
|
T::Hash[Symbol, String],
|
@@ -47,13 +57,15 @@ module AtlasEngine
|
|
47
57
|
matching_strategy: Strategies,
|
48
58
|
locale: String,
|
49
59
|
context: T::Hash[T.untyped, T.untyped],
|
60
|
+
message_format: MessageFormat,
|
50
61
|
).void
|
51
62
|
end
|
52
63
|
def initialize(
|
53
64
|
address:,
|
54
65
|
matching_strategy:,
|
55
66
|
locale: "en",
|
56
|
-
context: {}
|
67
|
+
context: {},
|
68
|
+
message_format: MessageFormat::Instructional
|
57
69
|
)
|
58
70
|
@address = T.let(address, AbstractAddress)
|
59
71
|
@address1 = T.let(address.address1, T.nilable(String))
|
@@ -65,9 +77,9 @@ module AtlasEngine
|
|
65
77
|
@country_code = T.let(address.country_code, T.nilable(String))
|
66
78
|
@context = T.let(context, T::Hash[T.untyped, T.untyped])
|
67
79
|
@matching_strategy = T.let(matching_strategy, Strategies)
|
80
|
+
@message_format = T.let(message_format, MessageFormat)
|
68
81
|
|
69
82
|
matching_strategy_name = matching_strategy.serialize
|
70
|
-
@predicate_pipeline = T.let(PredicatePipeline.find(matching_strategy_name), PredicatePipeline)
|
71
83
|
|
72
84
|
@result = T.let(
|
73
85
|
Result.new(
|
@@ -78,14 +90,14 @@ module AtlasEngine
|
|
78
90
|
),
|
79
91
|
Result,
|
80
92
|
)
|
93
|
+
pipeline_builder = PredicatePipelineBuilder.new(matching_strategy_name:, address:, result:, message_format:)
|
81
94
|
|
82
|
-
@
|
83
|
-
|
84
|
-
|
85
|
-
result: @result,
|
86
|
-
),
|
87
|
-
T.nilable(FullAddressValidatorBase),
|
95
|
+
@pipeline = T.let(
|
96
|
+
pipeline_builder.pipeline,
|
97
|
+
T::Array[AtlasEngine::AddressValidation::PredicatePipeline::PredicateConfig],
|
88
98
|
)
|
99
|
+
@unsupported_fields = T.let(pipeline_builder.unsupported_fields, T::Array[Symbol])
|
100
|
+
@full_address_validator = T.let(pipeline_builder.full_address_validator, T.nilable(FullAddressValidatorBase))
|
89
101
|
end
|
90
102
|
|
91
103
|
sig { override.returns(Result) }
|
@@ -113,15 +125,20 @@ module AtlasEngine
|
|
113
125
|
pipeline_address = Address.from_address(address: address)
|
114
126
|
local_concerns = {}
|
115
127
|
cache = Validators::Predicates::Cache.new(pipeline_address)
|
116
|
-
@
|
128
|
+
@pipeline.each do |predicate_config|
|
117
129
|
break if local_concerns[:country].present?
|
118
130
|
|
119
|
-
local_concerns[
|
120
|
-
next if local_concerns[
|
131
|
+
local_concerns[predicate_config.field] = [] if local_concerns[predicate_config.field].nil?
|
132
|
+
next if local_concerns[predicate_config.field].present?
|
121
133
|
|
122
|
-
concern =
|
134
|
+
concern = predicate_config.class_name.new(
|
135
|
+
field: predicate_config.field,
|
136
|
+
address: pipeline_address,
|
137
|
+
cache: cache,
|
138
|
+
message_format: message_format,
|
139
|
+
).evaluate
|
123
140
|
|
124
|
-
local_concerns[
|
141
|
+
local_concerns[predicate_config.field] << concern if concern.present?
|
125
142
|
end
|
126
143
|
local_concerns
|
127
144
|
end
|
@@ -129,7 +146,7 @@ module AtlasEngine
|
|
129
146
|
sig { params(local_concerns: T::Hash[Symbol, T::Array[Concern]]).void }
|
130
147
|
def populate_result(local_concerns)
|
131
148
|
local_concerns.keys.each do |field|
|
132
|
-
if local_concerns[field]&.empty? && [:address2, :phone].exclude?(field)
|
149
|
+
if local_concerns[field]&.empty? && [:address2, :phone].concat(unsupported_fields).exclude?(field)
|
133
150
|
result.validation_scope << T.must(FIELD_MAP[field])
|
134
151
|
end
|
135
152
|
|
@@ -14,10 +14,11 @@ module AtlasEngine
|
|
14
14
|
address_comparison: AddressComparison,
|
15
15
|
matching_strategy: AddressValidation::MatchingStrategies,
|
16
16
|
result: Result,
|
17
|
+
message_format: MessageFormat,
|
17
18
|
).void
|
18
19
|
end
|
19
|
-
def initialize(address_comparison:, matching_strategy:, result:)
|
20
|
-
super(address: address_comparison.address, result: result)
|
20
|
+
def initialize(address_comparison:, matching_strategy:, result:, message_format:)
|
21
|
+
super(address: address_comparison.address, result: result, message_format: message_format)
|
21
22
|
@address_comparison = address_comparison
|
22
23
|
@candidate = address_comparison.candidate
|
23
24
|
@matching_strategy = matching_strategy
|
@@ -56,11 +57,11 @@ module AtlasEngine
|
|
56
57
|
|
57
58
|
sig { void }
|
58
59
|
def add_concerns_without_suggestions
|
59
|
-
concern = InvalidZipConcernBuilder.for(address, [])
|
60
|
+
concern = InvalidZipConcernBuilder.for(address, [], message_format)
|
60
61
|
result.concerns << concern if concern
|
61
62
|
|
62
63
|
if ConcernBuilder.too_many_unmatched_components?(address, unmatched_components.keys)
|
63
|
-
result.concerns << UnknownAddressConcernBuilder.new(address).build
|
64
|
+
result.concerns << UnknownAddressConcernBuilder.new(address, message_format).build
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
@@ -79,6 +80,7 @@ module AtlasEngine
|
|
79
80
|
matched_components: matched_components_to_validate.keys,
|
80
81
|
address: address,
|
81
82
|
suggestion_ids: [suggestion.id].compact,
|
83
|
+
message_format: message_format,
|
82
84
|
).build
|
83
85
|
result.concerns << concern
|
84
86
|
end
|
@@ -167,7 +169,9 @@ module AtlasEngine
|
|
167
169
|
|
168
170
|
original_street = T.must(unmatched_components_to_validate[:street]).left_sequence.raw_value
|
169
171
|
|
170
|
-
if address.
|
172
|
+
if address.street_name.present?
|
173
|
+
:street_name
|
174
|
+
elsif address.address1.to_s.include?(original_street)
|
171
175
|
:address1
|
172
176
|
elsif address.address2.to_s.include?(original_street)
|
173
177
|
:address2
|
data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result_base.rb
CHANGED
@@ -11,10 +11,11 @@ module AtlasEngine
|
|
11
11
|
|
12
12
|
abstract!
|
13
13
|
|
14
|
-
sig { params(address: AbstractAddress, result: Result).void }
|
15
|
-
def initialize(address:, result:)
|
14
|
+
sig { params(address: AbstractAddress, result: Result, message_format: MessageFormat).void }
|
15
|
+
def initialize(address:, result:, message_format: MessageFormat::Instructional)
|
16
16
|
@address = address
|
17
17
|
@result = result
|
18
|
+
@message_format = message_format
|
18
19
|
end
|
19
20
|
|
20
21
|
sig { void }
|
@@ -22,7 +23,7 @@ module AtlasEngine
|
|
22
23
|
|
23
24
|
private
|
24
25
|
|
25
|
-
attr_reader :result, :address
|
26
|
+
attr_reader :result, :address, :message_format
|
26
27
|
|
27
28
|
sig { void }
|
28
29
|
def update_result_scope
|