atlas_engine 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +123 -0
- data/Rakefile +20 -0
- data/app/assets/config/atlas_engine_manifest.js +3 -0
- data/app/assets/stylesheets/atlas_engine/application.css +15 -0
- data/app/concerns/atlas_engine/handles_blob.rb +26 -0
- data/app/concerns/atlas_engine/handles_interruption.rb +22 -0
- data/app/controllers/atlas_engine/application_controller.rb +7 -0
- data/app/controllers/atlas_engine/connectivity_controller.rb +21 -0
- data/app/controllers/atlas_engine/country_imports_controller.rb +73 -0
- data/app/controllers/atlas_engine/graphql_controller.rb +59 -0
- data/app/countries/atlas_engine/ar/country_profile.yml +9 -0
- data/app/countries/atlas_engine/at/address_importer/corrections/open_address/city_corrector.rb +23 -0
- data/app/countries/atlas_engine/at/country_profile.yml +24 -0
- data/app/countries/atlas_engine/at/index_configuration.yml +63 -0
- data/app/countries/atlas_engine/at/synonyms.yml +6 -0
- data/app/countries/atlas_engine/at/validation_transcriber/address_parser.rb +58 -0
- data/app/countries/atlas_engine/au/address_importer/open_address/filter.rb +26 -0
- data/app/countries/atlas_engine/au/address_importer/open_address/mapper.rb +41 -0
- data/app/countries/atlas_engine/au/country_profile.yml +13 -0
- data/app/countries/atlas_engine/au/synonyms.yml +209 -0
- data/app/countries/atlas_engine/au/validation_transcriber/address_parser.rb +121 -0
- data/app/countries/atlas_engine/be/country_profile.yml +12 -0
- data/app/countries/atlas_engine/bm/address_importer/corrections/open_address/city_alias_corrector.rb +38 -0
- data/app/countries/atlas_engine/bm/address_importer/open_address/mapper.rb +40 -0
- data/app/countries/atlas_engine/bm/country_profile.yml +12 -0
- data/app/countries/atlas_engine/br/country_profile.yml +4 -0
- data/app/countries/atlas_engine/ca/country_profile.yml +7 -0
- data/app/countries/atlas_engine/ca/synonyms.yml +1615 -0
- data/app/countries/atlas_engine/ch/address_importer/corrections/open_address/city_corrector.rb +29 -0
- data/app/countries/atlas_engine/ch/address_importer/corrections/open_address/locale_corrector.rb +74 -0
- data/app/countries/atlas_engine/ch/address_importer/open_address/mapper.rb +40 -0
- data/app/countries/atlas_engine/ch/country_profile.yml +15 -0
- data/app/countries/atlas_engine/ch/locales/de/country_profile.yml +15 -0
- data/app/countries/atlas_engine/ch/locales/de/index_configuration.yml +63 -0
- data/app/countries/atlas_engine/ch/locales/de/synonyms.yml +7 -0
- data/app/countries/atlas_engine/ch/locales/fr/synonyms.yml +21 -0
- data/app/countries/atlas_engine/cz/country_profile.yml +6 -0
- data/app/countries/atlas_engine/de/country_profile.yml +19 -0
- data/app/countries/atlas_engine/de/index_configuration.yml +64 -0
- data/app/countries/atlas_engine/de/synonyms.yml +2 -0
- data/app/countries/atlas_engine/de/validation_transcriber/address_parser.rb +19 -0
- data/app/countries/atlas_engine/dk/country_profile.yml +6 -0
- data/app/countries/atlas_engine/dk/synonyms.yml +3 -0
- data/app/countries/atlas_engine/dk/validation_transcriber/address_parser.rb +21 -0
- data/app/countries/atlas_engine/fo/country_profile.yml +5 -0
- data/app/countries/atlas_engine/fr/address_importer/corrections/open_address/city_corrector.rb +28 -0
- data/app/countries/atlas_engine/fr/country_profile.yml +13 -0
- data/app/countries/atlas_engine/fr/synonyms.yml +21 -0
- data/app/countries/atlas_engine/fr/validation_transcriber/address_parser.rb +34 -0
- data/app/countries/atlas_engine/gb/address_validation/es/query_builder.rb +98 -0
- data/app/countries/atlas_engine/gb/country_profile.yml +10 -0
- data/app/countries/atlas_engine/gb/validation_transcriber/full_address_parser.rb +164 -0
- data/app/countries/atlas_engine/gb/validation_transcriber/parsed_address.rb +120 -0
- data/app/countries/atlas_engine/gg/address_validation/validators/full_address/restrictions/unsupported_city.rb +39 -0
- data/app/countries/atlas_engine/gg/country_profile.yml +7 -0
- data/app/countries/atlas_engine/ie/country_profile.yml +3 -0
- data/app/countries/atlas_engine/it/address_importer/corrections/open_address/city_corrector.rb +27 -0
- data/app/countries/atlas_engine/it/address_importer/corrections/open_address/province_corrector.rb +29 -0
- data/app/countries/atlas_engine/it/address_importer/open_address/mapper.rb +42 -0
- data/app/countries/atlas_engine/it/country_profile.yml +11 -0
- data/app/countries/atlas_engine/jp/address_validation/es/data_mapper.rb +63 -0
- data/app/countries/atlas_engine/jp/country_profile.yml +6 -0
- data/app/countries/atlas_engine/kr/address_importer/open_address/mapper.rb +41 -0
- data/app/countries/atlas_engine/kr/country_profile.yml +11 -0
- data/app/countries/atlas_engine/li/address_importer/corrections/open_address/city_corrector.rb +25 -0
- data/app/countries/atlas_engine/li/country_profile.yml +21 -0
- data/app/countries/atlas_engine/li/index_configuration.yml +63 -0
- data/app/countries/atlas_engine/li/synonyms.yml +6 -0
- data/app/countries/atlas_engine/lt/country_profile.yml +6 -0
- data/app/countries/atlas_engine/lt/synonyms.yml +7 -0
- data/app/countries/atlas_engine/lt/validation_transcriber/address_parser.rb +24 -0
- data/app/countries/atlas_engine/lu/address_importer/corrections/open_address/locale_corrector.rb +54 -0
- data/app/countries/atlas_engine/lu/country_profile.yml +12 -0
- data/app/countries/atlas_engine/nl/address_importer/corrections/open_address/city_corrector.rb +25 -0
- data/app/countries/atlas_engine/nl/country_profile.yml +18 -0
- data/app/countries/atlas_engine/nl/index_configuration.yml +52 -0
- data/app/countries/atlas_engine/nl/synonyms.yml +92 -0
- data/app/countries/atlas_engine/nl/validation_transcriber/address_parser.rb +85 -0
- data/app/countries/atlas_engine/no/country_profile.yml +5 -0
- data/app/countries/atlas_engine/nz/country_profile.yml +3 -0
- data/app/countries/atlas_engine/pl/country_profile.yml +5 -0
- data/app/countries/atlas_engine/pl/validation_transcriber/address_parser.rb +19 -0
- data/app/countries/atlas_engine/pt/address_importer/corrections/open_address/city_corrector.rb +32 -0
- data/app/countries/atlas_engine/pt/address_importer/open_address/mapper.rb +39 -0
- data/app/countries/atlas_engine/pt/country_profile.yml +10 -0
- data/app/countries/atlas_engine/pt/synonyms.yml +7 -0
- data/app/countries/atlas_engine/sa/country_profile.yml +10 -0
- data/app/countries/atlas_engine/se/country_profile.yml +5 -0
- data/app/countries/atlas_engine/tt/address_importer/open_address/mapper.rb +38 -0
- data/app/countries/atlas_engine/tt/country_profile.yml +7 -0
- data/app/countries/atlas_engine/us/country_profile.yml +12 -0
- data/app/countries/atlas_engine/us/synonyms.yml +350 -0
- data/app/graphql/atlas_engine/errors/locale_unsupported_error.rb +17 -0
- data/app/graphql/atlas_engine/schema.graphql +1293 -0
- data/app/graphql/atlas_engine/schema.rb +23 -0
- data/app/graphql/atlas_engine/types/address_validation/address_input.rb +51 -0
- data/app/graphql/atlas_engine/types/address_validation/concern_type.rb +20 -0
- data/app/graphql/atlas_engine/types/address_validation/enums/concern_enum.rb +15 -0
- data/app/graphql/atlas_engine/types/address_validation/field_type.rb +15 -0
- data/app/graphql/atlas_engine/types/address_validation/suggestion_type.rb +21 -0
- data/app/graphql/atlas_engine/types/base_argument.rb +9 -0
- data/app/graphql/atlas_engine/types/base_enum.rb +9 -0
- data/app/graphql/atlas_engine/types/base_field.rb +10 -0
- data/app/graphql/atlas_engine/types/base_input_object.rb +9 -0
- data/app/graphql/atlas_engine/types/base_interface.rb +10 -0
- data/app/graphql/atlas_engine/types/base_object.rb +9 -0
- data/app/graphql/atlas_engine/types/base_scalar.rb +9 -0
- data/app/graphql/atlas_engine/types/base_union.rb +9 -0
- data/app/graphql/atlas_engine/types/matching_strategy_type.rb +12 -0
- data/app/graphql/atlas_engine/types/mutation_type.rb +9 -0
- data/app/graphql/atlas_engine/types/query_type.rb +61 -0
- data/app/graphql/atlas_engine/types/validation_supported_country.rb +12 -0
- data/app/graphql/atlas_engine/types/validation_type.rb +22 -0
- data/app/helpers/atlas_engine/address_importer/import_log_helper.rb +66 -0
- data/app/helpers/atlas_engine/application_helper.rb +7 -0
- data/app/helpers/atlas_engine/locale_format_helper.rb +40 -0
- data/app/helpers/atlas_engine/log_base.rb +32 -0
- data/app/helpers/atlas_engine/log_helper.rb +24 -0
- data/app/helpers/atlas_engine/metrics_helper.rb +25 -0
- data/app/jobs/atlas_engine/address_importer/clear_records_job.rb +39 -0
- data/app/jobs/atlas_engine/address_importer/open_address/geo_json_import_job.rb +212 -0
- data/app/jobs/atlas_engine/address_importer/open_address/geo_json_import_launcher_job.rb +67 -0
- data/app/jobs/atlas_engine/address_importer/open_address/prepares_geo_json_file.rb +41 -0
- data/app/jobs/atlas_engine/address_importer/resumable_import_job.rb +49 -0
- data/app/jobs/atlas_engine/address_importer/street_backfill_job.rb +63 -0
- data/app/jobs/atlas_engine/application_job.rb +10 -0
- data/app/jobs/atlas_engine/concerns/address_importer/handles_errors.rb +43 -0
- data/app/lib/atlas_engine/concern_formatter.rb +40 -0
- data/app/lib/atlas_engine/restrictions/base.rb +20 -0
- data/app/lib/atlas_engine/restrictions/unsupported_script.rb +31 -0
- data/app/lib/atlas_engine/validation_transcriber/address_parser_base.rb +201 -0
- data/app/lib/atlas_engine/validation_transcriber/address_parser_factory.rb +27 -0
- data/app/lib/atlas_engine/validation_transcriber/address_parser_north_america.rb +39 -0
- data/app/lib/atlas_engine/validation_transcriber/address_parser_oceanic.rb +17 -0
- data/app/lib/atlas_engine/validation_transcriber/address_parser_preprocessor.rb +132 -0
- data/app/lib/atlas_engine/validation_transcriber/address_parsing_helper.rb +38 -0
- data/app/lib/atlas_engine/validation_transcriber/address_parsings.rb +54 -0
- data/app/lib/atlas_engine/validation_transcriber/constants.rb +50 -0
- data/app/lib/atlas_engine/validation_transcriber/english_street_parser.rb +59 -0
- data/app/lib/atlas_engine/validation_transcriber/formatter.rb +46 -0
- data/app/lib/atlas_engine/validation_transcriber/french_street_parser.rb +50 -0
- data/app/lib/atlas_engine/validation_transcriber/province_code_normalizer.rb +45 -0
- data/app/lib/atlas_engine/validation_transcriber/street_parser.rb +18 -0
- data/app/lib/atlas_engine/validation_transcriber/zip_normalizer.rb +23 -0
- data/app/mailers/atlas_engine/application_mailer.rb +9 -0
- data/app/models/atlas_engine/address_importer/corrections/corrector.rb +33 -0
- data/app/models/atlas_engine/address_importer/import_events_notifier/base.rb +35 -0
- data/app/models/atlas_engine/address_importer/import_events_notifier/notifier.rb +26 -0
- data/app/models/atlas_engine/address_importer/open_address/default_mapper.rb +46 -0
- data/app/models/atlas_engine/address_importer/open_address/feature_helper.rb +110 -0
- data/app/models/atlas_engine/address_importer/open_address/filter.rb +17 -0
- data/app/models/atlas_engine/address_importer/open_address/loader.rb +27 -0
- data/app/models/atlas_engine/address_importer/open_address/transformer.rb +39 -0
- data/app/models/atlas_engine/address_importer/open_address.rb +10 -0
- data/app/models/atlas_engine/address_importer/validation/base_validator.rb +86 -0
- data/app/models/atlas_engine/address_importer/validation/default_validator.rb +27 -0
- data/app/models/atlas_engine/address_importer/validation/field_validations/city.rb +47 -0
- data/app/models/atlas_engine/address_importer/validation/field_validations/interface.rb +29 -0
- data/app/models/atlas_engine/address_importer/validation/field_validations/province.rb +73 -0
- data/app/models/atlas_engine/address_importer/validation/field_validations/zip.rb +84 -0
- data/app/models/atlas_engine/address_importer/validation/validator.rb +17 -0
- data/app/models/atlas_engine/address_importer/validation/wrapper.rb +70 -0
- data/app/models/atlas_engine/address_number.rb +36 -0
- data/app/models/atlas_engine/address_number_range.rb +200 -0
- data/app/models/atlas_engine/address_validation/abstract_address.rb +49 -0
- data/app/models/atlas_engine/address_validation/address.rb +47 -0
- data/app/models/atlas_engine/address_validation/candidate.rb +109 -0
- data/app/models/atlas_engine/address_validation/candidate_tuple.rb +15 -0
- data/app/models/atlas_engine/address_validation/concern.rb +74 -0
- data/app/models/atlas_engine/address_validation/concern_producer.rb +19 -0
- data/app/models/atlas_engine/address_validation/concern_queue.rb +20 -0
- data/app/models/atlas_engine/address_validation/concern_record.rb +122 -0
- data/app/models/atlas_engine/address_validation/datastore_base.rb +27 -0
- data/app/models/atlas_engine/address_validation/errors.rb +13 -0
- data/app/models/atlas_engine/address_validation/es/candidate_selector.rb +70 -0
- data/app/models/atlas_engine/address_validation/es/data_mappers/decompounding_data_mapper.rb +39 -0
- data/app/models/atlas_engine/address_validation/es/data_mappers/default_data_mapper.rb +110 -0
- data/app/models/atlas_engine/address_validation/es/datastore.rb +229 -0
- data/app/models/atlas_engine/address_validation/es/default_query_builder.rb +30 -0
- data/app/models/atlas_engine/address_validation/es/query_builder.rb +160 -0
- data/app/models/atlas_engine/address_validation/es/term_vectors.rb +78 -0
- data/app/models/atlas_engine/address_validation/es/validators/full_address.rb +123 -0
- data/app/models/atlas_engine/address_validation/es/validators/full_address_street.rb +18 -0
- data/app/models/atlas_engine/address_validation/es/validators/restriction_evaluator.rb +37 -0
- data/app/models/atlas_engine/address_validation/field.rb +30 -0
- data/app/models/atlas_engine/address_validation/full_address_validator_base.rb +27 -0
- data/app/models/atlas_engine/address_validation/log_emitter.rb +66 -0
- data/app/models/atlas_engine/address_validation/matching_strategies.rb +16 -0
- data/app/models/atlas_engine/address_validation/normalizer.rb +38 -0
- data/app/models/atlas_engine/address_validation/predicate_pipeline.rb +80 -0
- data/app/models/atlas_engine/address_validation/request.rb +12 -0
- data/app/models/atlas_engine/address_validation/result.rb +154 -0
- data/app/models/atlas_engine/address_validation/runs_validation.rb +16 -0
- data/app/models/atlas_engine/address_validation/session.rb +47 -0
- data/app/models/atlas_engine/address_validation/statsd_emitter.rb +72 -0
- data/app/models/atlas_engine/address_validation/strategies.rb +10 -0
- data/app/models/atlas_engine/address_validation/suggestion.rb +97 -0
- data/app/models/atlas_engine/address_validation/token/comparator.rb +44 -0
- data/app/models/atlas_engine/address_validation/token/comparison.rb +76 -0
- data/app/models/atlas_engine/address_validation/token/sequence/comparator.rb +158 -0
- data/app/models/atlas_engine/address_validation/token/sequence/comparison.rb +166 -0
- data/app/models/atlas_engine/address_validation/token/sequence.rb +147 -0
- data/app/models/atlas_engine/address_validation/token/synonyms.rb +77 -0
- data/app/models/atlas_engine/address_validation/token.rb +113 -0
- data/app/models/atlas_engine/address_validation/validator.rb +147 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/address_comparison.rb +97 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +164 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result_base.rb +46 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/comparison_helper.rb +135 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/components_to_validate.rb +88 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/concern_builder.rb +127 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/exclusions/exclusion_base.rb +23 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb +42 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_country_concern.rb +37 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_province_concern.rb +37 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb +26 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/number_comparison.rb +31 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/postal_code_matcher.rb +60 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/result_updater.rb +42 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/suggestion_builder.rb +140 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern.rb +30 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern.rb +38 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern.rb +32 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern.rb +84 -0
- data/app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb +22 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/cache.rb +38 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/city/present.rb +36 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/country/exists.rb +34 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/country/valid_for_zip.rb +60 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/no_emojis.rb +38 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/no_html_tags.rb +39 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/no_url.rb +38 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/not_exceed_max_length.rb +34 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/not_exceed_max_token_count.rb +63 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/phone/valid.rb +41 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/predicate.rb +37 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/province/exists.rb +43 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/province/valid_for_country.rb +48 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1.rb +45 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1_or_address2.rb +43 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/street/present.rb +35 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/zip/present.rb +58 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_country.rb +45 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_province.rb +55 -0
- data/app/models/atlas_engine/address_validation/validators/predicates/zip/zip_base.rb +25 -0
- data/app/models/atlas_engine/address_validation/zip_truncator.rb +32 -0
- data/app/models/atlas_engine/application_record.rb +8 -0
- data/app/models/atlas_engine/coded_error.rb +18 -0
- data/app/models/atlas_engine/coded_errors.rb +17 -0
- data/app/models/atlas_engine/country_import.rb +44 -0
- data/app/models/atlas_engine/country_profile.rb +270 -0
- data/app/models/atlas_engine/country_profile_ingestion_subset.rb +42 -0
- data/app/models/atlas_engine/country_profile_subset_base.rb +22 -0
- data/app/models/atlas_engine/country_profile_validation_subset.rb +48 -0
- data/app/models/atlas_engine/country_repository.rb +110 -0
- data/app/models/atlas_engine/elasticsearch/client.rb +116 -0
- data/app/models/atlas_engine/elasticsearch/client_interface.rb +89 -0
- data/app/models/atlas_engine/elasticsearch/repository.rb +246 -0
- data/app/models/atlas_engine/elasticsearch/repository_interface.rb +82 -0
- data/app/models/atlas_engine/elasticsearch/response.rb +20 -0
- data/app/models/atlas_engine/event.rb +12 -0
- data/app/models/atlas_engine/field_decompounder.rb +36 -0
- data/app/models/atlas_engine/index_configuration_factory.rb +188 -0
- data/app/models/atlas_engine/post_address.rb +114 -0
- data/app/models/atlas_engine/post_address_importer.rb +34 -0
- data/app/models/atlas_engine/services/service_helper.rb +21 -0
- data/app/models/atlas_engine/services/validation.rb +65 -0
- data/app/models/atlas_engine/services/validation_eligibility.rb +18 -0
- data/app/models/atlas_engine/street.rb +34 -0
- data/app/tasks/maintenance/atlas_engine/elasticsearch_index_create_task.rb +106 -0
- data/app/tasks/maintenance/atlas_engine/geo_json_import_task.rb +29 -0
- data/app/views/atlas_engine/connectivity/index.html.erb +50 -0
- data/app/views/atlas_engine/country_imports/index.html.erb +49 -0
- data/app/views/atlas_engine/country_imports/show.html.erb +73 -0
- data/app/views/layouts/atlas_engine/application.html.erb +15 -0
- data/config/initializers/1.ruby_patches.rb +18 -0
- data/config/initializers/sorbet.rb +5 -0
- data/config/initializers/worldwide.rb +5 -0
- data/config/locales/internal/en.yml +14 -0
- data/config/routes.rb +17 -0
- data/db/data/address_synonyms/index_configurations/default.yml +141 -0
- data/db/data/country_profiles/default.yml +23 -0
- data/db/data/transcriber.yml +760 -0
- data/db/data/validation_pipelines/es.yml +58 -0
- data/db/data/validation_pipelines/es_street.yml +58 -0
- data/db/data/validation_pipelines/local.yml +60 -0
- data/db/migrate/20230919173037_create_atlas_engine_post_addresses.rb +25 -0
- data/db/migrate/20231117142735_add_building_and_unit_ranges_column.rb +7 -0
- data/db/migrate/20231117143536_create_atlas_engine_country_imports.rb +11 -0
- data/db/migrate/20231117145844_create_atlas_engine_events_table.rb +13 -0
- data/db/migrate/20231123153554_add_unique_index_to_atlas_engine_post_addresses.rb +14 -0
- data/db/migrate/20231123154658_add_index_to_post_addresses_on_source_id_locale_country_code.rb +12 -0
- data/lib/atlas_engine/engine.rb +10 -0
- data/lib/atlas_engine/version.rb +6 -0
- data/lib/atlas_engine.rb +66 -0
- data/lib/tasks/atlas_engine/address_importer.rake +20 -0
- metadata +553 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class Field
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
Name = T.type_alias { T.any(String, Symbol) }
|
10
|
+
Value = T.type_alias { T.nilable(String) }
|
11
|
+
|
12
|
+
sig { returns(Name) }
|
13
|
+
attr_reader :name
|
14
|
+
|
15
|
+
sig { returns(Value) }
|
16
|
+
attr_reader :value
|
17
|
+
|
18
|
+
sig { params(name: Name, value: Value).void }
|
19
|
+
def initialize(name:, value:)
|
20
|
+
@name = name
|
21
|
+
@value = value
|
22
|
+
end
|
23
|
+
|
24
|
+
sig { returns(T::Hash[Symbol, T.any(Name, Value)]) }
|
25
|
+
def attributes
|
26
|
+
{ name: name, value: value }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class FullAddressValidatorBase
|
7
|
+
extend T::Sig
|
8
|
+
extend T::Helpers
|
9
|
+
abstract!
|
10
|
+
|
11
|
+
sig { returns(Result) }
|
12
|
+
attr_reader :result
|
13
|
+
|
14
|
+
sig { returns(AbstractAddress) }
|
15
|
+
attr_reader :address
|
16
|
+
|
17
|
+
sig { params(address: AbstractAddress, result: Result).void }
|
18
|
+
def initialize(address:, result:)
|
19
|
+
@address = address
|
20
|
+
@result = result
|
21
|
+
end
|
22
|
+
|
23
|
+
sig { abstract.returns(Result) }
|
24
|
+
def validate; end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class LogEmitter
|
7
|
+
extend T::Sig
|
8
|
+
include LogHelper
|
9
|
+
|
10
|
+
sig { returns(AbstractAddress) }
|
11
|
+
attr_reader :address
|
12
|
+
|
13
|
+
sig { returns(AddressValidation::Result) }
|
14
|
+
attr_reader :result
|
15
|
+
|
16
|
+
sig { returns(T::Array[Symbol]) }
|
17
|
+
attr_reader :fields
|
18
|
+
|
19
|
+
sig do
|
20
|
+
params(
|
21
|
+
address: AbstractAddress,
|
22
|
+
result: AddressValidation::Result,
|
23
|
+
).void
|
24
|
+
end
|
25
|
+
def initialize(address:, result:)
|
26
|
+
@address = address
|
27
|
+
@result = result
|
28
|
+
@fields = [:country, :province, :zip, :city, :street, :phone]
|
29
|
+
end
|
30
|
+
|
31
|
+
sig { void }
|
32
|
+
def run
|
33
|
+
formatted_address = I18n.with_locale(:en) do
|
34
|
+
Worldwide.address(**address.to_h).single_line
|
35
|
+
end
|
36
|
+
data = {
|
37
|
+
country_code: address.country_code,
|
38
|
+
formatted_address: formatted_address,
|
39
|
+
concerns: concern_codes,
|
40
|
+
suggestions: result.suggestions.map(&:attributes),
|
41
|
+
candidate: result.candidate,
|
42
|
+
validation_id: result.id,
|
43
|
+
}
|
44
|
+
|
45
|
+
if concern_codes.any?
|
46
|
+
log_info("[AddressValidation] Concern(s) found when validating address", data)
|
47
|
+
else
|
48
|
+
log_info("[AddressValidation] Address validated, no concerns returned", data)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
sig { returns(T::Array[Symbol]) }
|
53
|
+
def concern_codes
|
54
|
+
fields.flat_map do |field|
|
55
|
+
if field.equal?(:street)
|
56
|
+
result.concerns.select do |c|
|
57
|
+
c.attributes[:code] =~ /^(missing_building_number|address1|address2|street).*/
|
58
|
+
end
|
59
|
+
else
|
60
|
+
result.concerns.select { |c| c.attributes[:code] =~ /^#{field}.*/ }
|
61
|
+
end
|
62
|
+
end.map(&:code)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class MatchingStrategies < T::Enum
|
7
|
+
include Strategies
|
8
|
+
|
9
|
+
enums do
|
10
|
+
Es = new("es")
|
11
|
+
EsStreet = new("es_street")
|
12
|
+
Local = new("local")
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
module Normalizer
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig do
|
10
|
+
params(
|
11
|
+
string: String,
|
12
|
+
).returns(String)
|
13
|
+
end
|
14
|
+
def normalize(string)
|
15
|
+
string
|
16
|
+
.gsub("Æ", "AE")
|
17
|
+
.gsub("Œ", "OE")
|
18
|
+
.gsub("æ", "ae")
|
19
|
+
.gsub("œ", "oe")
|
20
|
+
.gsub(" ", " ")
|
21
|
+
# normalizes Arabic characters
|
22
|
+
.tr("آ", "ا")
|
23
|
+
.tr("أ", "ا")
|
24
|
+
.tr("إ", "ا")
|
25
|
+
.tr("ئ", "ي")
|
26
|
+
.tr("ة", "ه")
|
27
|
+
.tr("ى", "ي")
|
28
|
+
# removes Arabic stretching characters and diacritics
|
29
|
+
.gsub(/[\u064B|\u064C|\u064D|\u064E|\u064F|\u0650|\u0651|\u0652|\u0640]/, "")
|
30
|
+
# TODO: Strip hyphens for USPS not zip
|
31
|
+
.gsub(/[!@%&"'*,.();:]/, "")
|
32
|
+
.downcase
|
33
|
+
.tr(T.unsafe(AtlasEngine::ValidationTranscriber::Constants.instance).with_diacritics,
|
34
|
+
T.unsafe(AtlasEngine::ValidationTranscriber::Constants.instance).without_diacritics)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class PredicatePipeline < FrozenRecord::Base
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
VALIDATION_PIPELINES_ROOT = T.let(File.join(AtlasEngine::Engine.root, "db/data/validation_pipelines"), String)
|
10
|
+
|
11
|
+
module Backend
|
12
|
+
extend FrozenRecord::Backends::Yaml
|
13
|
+
|
14
|
+
class << self
|
15
|
+
extend T::Sig
|
16
|
+
|
17
|
+
sig { params(file_path: String).returns(T.untyped) }
|
18
|
+
def load(file_path)
|
19
|
+
# FrozenRecord's default is to operate on a single YAML file containing all the records.
|
20
|
+
# A custom backend like ours, that uses separate files, must load all of them and return an array.
|
21
|
+
Dir[File.join(PredicatePipeline.pipeline_path, "*.yml")].map do |validation_pipeline|
|
22
|
+
super(validation_pipeline)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class << self
|
29
|
+
extend T::Sig
|
30
|
+
|
31
|
+
sig { returns(String) }
|
32
|
+
def pipeline_path
|
33
|
+
@pipeline_path ||= T.let(VALIDATION_PIPELINES_ROOT, T.nilable(String))
|
34
|
+
end
|
35
|
+
|
36
|
+
sig { params(pipeline_path: String).void }
|
37
|
+
attr_writer :pipeline_path
|
38
|
+
end
|
39
|
+
|
40
|
+
self.base_path = VALIDATION_PIPELINES_ROOT
|
41
|
+
self.backend = Backend
|
42
|
+
|
43
|
+
sig { returns(T::Array[PredicateConfig]) }
|
44
|
+
def pipeline
|
45
|
+
attributes.dig("pipeline").map do |config|
|
46
|
+
PredicateConfig.new(
|
47
|
+
class_name: config["class"].constantize,
|
48
|
+
field: config["field"].to_sym,
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
sig { returns(T.nilable(T::Class[FullAddressValidatorBase])) }
|
54
|
+
def full_address_validator
|
55
|
+
attributes.dig("full_address_validator")&.constantize
|
56
|
+
end
|
57
|
+
|
58
|
+
class PredicateConfig
|
59
|
+
extend T::Sig
|
60
|
+
|
61
|
+
sig { returns(Symbol) }
|
62
|
+
attr_reader :field
|
63
|
+
|
64
|
+
sig { returns(T::Class[Validators::Predicates::Predicate]) }
|
65
|
+
attr_reader :class_name
|
66
|
+
|
67
|
+
sig do
|
68
|
+
params(
|
69
|
+
class_name: T::Class[Validators::Predicates::Predicate],
|
70
|
+
field: Symbol,
|
71
|
+
).void
|
72
|
+
end
|
73
|
+
def initialize(class_name:, field:)
|
74
|
+
@field = field
|
75
|
+
@class_name = class_name
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class Request < T::Struct
|
7
|
+
const :address, AbstractAddress
|
8
|
+
const :locale, String, default: "en"
|
9
|
+
const :matching_strategy, T.nilable(T.any(String, Symbol)), default: nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class Result
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
SORTED_VALIDATION_SCOPES = T.let(
|
10
|
+
[:country_code, :province_code, :zip, :city, :address1, :address2, :phone].freeze,
|
11
|
+
T::Array[Symbol],
|
12
|
+
)
|
13
|
+
|
14
|
+
sig { returns(T.nilable(String)) }
|
15
|
+
attr_accessor :client_request_id
|
16
|
+
|
17
|
+
sig { returns(T.nilable(String)) }
|
18
|
+
attr_accessor :origin
|
19
|
+
|
20
|
+
sig { returns(T::Array[Field]) }
|
21
|
+
attr_accessor :fields
|
22
|
+
|
23
|
+
sig { returns(T::Array[Concern]) }
|
24
|
+
attr_accessor :concerns
|
25
|
+
|
26
|
+
sig { returns(T::Array[Suggestion]) }
|
27
|
+
attr_accessor :suggestions
|
28
|
+
|
29
|
+
sig { returns(T::Array[String]) }
|
30
|
+
attr_accessor :validation_scope
|
31
|
+
|
32
|
+
sig { returns(String) }
|
33
|
+
attr_accessor :locale
|
34
|
+
|
35
|
+
sig { returns(T.nilable(String)) }
|
36
|
+
attr_accessor :candidate
|
37
|
+
|
38
|
+
sig { returns(T::Array[Errors]) }
|
39
|
+
attr_accessor :errors
|
40
|
+
|
41
|
+
sig { returns(String) }
|
42
|
+
attr_reader :id
|
43
|
+
|
44
|
+
sig { returns(T.nilable(String)) }
|
45
|
+
attr_reader :matching_strategy
|
46
|
+
|
47
|
+
alias_attribute :components, :fields
|
48
|
+
|
49
|
+
sig do
|
50
|
+
params(
|
51
|
+
client_request_id: T.nilable(String),
|
52
|
+
origin: T.nilable(String),
|
53
|
+
fields: T::Array[Field],
|
54
|
+
concerns: T::Array[Concern],
|
55
|
+
suggestions: T::Array[Suggestion],
|
56
|
+
validation_scope: T::Array[String],
|
57
|
+
errors: T::Array[Errors],
|
58
|
+
locale: String,
|
59
|
+
candidate: T.nilable(String),
|
60
|
+
matching_strategy: T.nilable(String),
|
61
|
+
).void
|
62
|
+
end
|
63
|
+
def initialize(
|
64
|
+
client_request_id: nil,
|
65
|
+
origin: nil,
|
66
|
+
fields: [],
|
67
|
+
concerns: [],
|
68
|
+
suggestions: [],
|
69
|
+
validation_scope: [],
|
70
|
+
errors: [],
|
71
|
+
locale: "en",
|
72
|
+
candidate: nil,
|
73
|
+
matching_strategy: nil
|
74
|
+
)
|
75
|
+
@origin = origin
|
76
|
+
@client_request_id = client_request_id
|
77
|
+
@fields = fields
|
78
|
+
@concerns = concerns
|
79
|
+
@suggestions = suggestions
|
80
|
+
@validation_scope = validation_scope
|
81
|
+
@errors = errors
|
82
|
+
@locale = locale
|
83
|
+
@candidate = candidate
|
84
|
+
@matching_strategy = matching_strategy
|
85
|
+
|
86
|
+
# For now, this UUID isn't predicated on anything and is random.
|
87
|
+
# There could be need in the future to help make this unique on all requests.
|
88
|
+
# For now, what is important is that it one is simply generated and assigned.
|
89
|
+
@id = T.let(generate_id, String)
|
90
|
+
end
|
91
|
+
|
92
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
93
|
+
def attributes
|
94
|
+
{
|
95
|
+
id: id,
|
96
|
+
fields: fields.map(&:attributes),
|
97
|
+
concerns: concerns.map(&:attributes),
|
98
|
+
suggestions: suggestions.map(&:attributes),
|
99
|
+
validation_scope: validation_scope,
|
100
|
+
locale: locale,
|
101
|
+
}
|
102
|
+
end
|
103
|
+
|
104
|
+
sig do
|
105
|
+
params(
|
106
|
+
code: Symbol,
|
107
|
+
type: String,
|
108
|
+
type_level: Integer,
|
109
|
+
suggestion_ids: T::Array[String],
|
110
|
+
field_names: T::Array[Symbol],
|
111
|
+
message: String,
|
112
|
+
).returns(Concern)
|
113
|
+
end
|
114
|
+
def add_concern(code:, type:, type_level:, suggestion_ids:, field_names:, message:)
|
115
|
+
new_concern = Concern.new(
|
116
|
+
field_names: field_names,
|
117
|
+
code: code,
|
118
|
+
type: type,
|
119
|
+
type_level: type_level,
|
120
|
+
suggestion_ids: suggestion_ids,
|
121
|
+
message: message,
|
122
|
+
)
|
123
|
+
concerns << new_concern
|
124
|
+
new_concern
|
125
|
+
end
|
126
|
+
|
127
|
+
sig do
|
128
|
+
params(suggestions_to_add: T::Array[Suggestion]).returns(T::Array[T::Array[Suggestion]])
|
129
|
+
end
|
130
|
+
def add_suggestions(suggestions_to_add)
|
131
|
+
suggestions_to_add.map { |suggestion| suggestions << suggestion }
|
132
|
+
end
|
133
|
+
|
134
|
+
sig { returns(String) }
|
135
|
+
def completion_service
|
136
|
+
"AddressValidation"
|
137
|
+
end
|
138
|
+
|
139
|
+
sig { returns(T::Hash[Symbol, T.nilable(String)]) }
|
140
|
+
def address
|
141
|
+
fields.each_with_object({}) do |field, hash|
|
142
|
+
hash[field.name.to_sym] = field.value.to_s
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
sig { returns(String) }
|
149
|
+
def generate_id
|
150
|
+
Digest::UUID.uuid_v4
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
module RunsValidation
|
7
|
+
extend T::Sig
|
8
|
+
extend T::Helpers
|
9
|
+
|
10
|
+
interface!
|
11
|
+
|
12
|
+
sig { abstract.returns(Result) }
|
13
|
+
def run; end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,47 @@
|
|
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
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# typed: true
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class StatsdEmitter
|
7
|
+
extend T::Sig
|
8
|
+
attr_reader :address, :result, :components
|
9
|
+
|
10
|
+
sig { params(address: AbstractAddress, result: Result, components: T.nilable(T::Array[Symbol])).void }
|
11
|
+
def initialize(address:, result:,
|
12
|
+
components: [:country, :province, :zip, :city, :street, :building_number, :phone])
|
13
|
+
@address = address
|
14
|
+
@result = result
|
15
|
+
@components = components
|
16
|
+
end
|
17
|
+
|
18
|
+
sig { void }
|
19
|
+
def run
|
20
|
+
components.each do |component|
|
21
|
+
emit(component)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
sig { params(component: Symbol).void }
|
26
|
+
def emit(component)
|
27
|
+
concerns = component_concerns(component)
|
28
|
+
ending_breadcrumb = concerns.present? ? "invalid" : "valid"
|
29
|
+
|
30
|
+
country_code = if address.country_code.blank? || !Worldwide.region(code: address.country_code).country?
|
31
|
+
"no_country"
|
32
|
+
else
|
33
|
+
Worldwide.region(code: address.country_code).iso_code
|
34
|
+
end
|
35
|
+
|
36
|
+
I18n.with_locale("en") do
|
37
|
+
tags = {
|
38
|
+
country: country_code,
|
39
|
+
component: component,
|
40
|
+
}.compact
|
41
|
+
|
42
|
+
if concerns.empty?
|
43
|
+
StatsD.increment("AddressValidation.#{ending_breadcrumb}", tags: tags)
|
44
|
+
else
|
45
|
+
concerns.each do |concern|
|
46
|
+
tags.merge!(concern.attributes.slice(:code, :type))
|
47
|
+
|
48
|
+
StatsD.increment("AddressValidation.#{ending_breadcrumb}", tags: tags)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
|
56
|
+
sig { params(component: Symbol).returns(T::Array[Concern]) }
|
57
|
+
def component_concerns(component)
|
58
|
+
if component.equal?(:street)
|
59
|
+
result.concerns.select do |c|
|
60
|
+
c.attributes[:code] =~ /^(address1|address2|street).*/
|
61
|
+
end
|
62
|
+
elsif component.equal?(:building_number)
|
63
|
+
result.concerns.select do |c|
|
64
|
+
c.attributes[:code] =~ /^(missing_building_number).*/
|
65
|
+
end
|
66
|
+
else
|
67
|
+
result.concerns.select { |c| c.attributes[:code] =~ /^#{component}.*/ }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module AtlasEngine
|
5
|
+
module AddressValidation
|
6
|
+
class Suggestion
|
7
|
+
extend T::Sig
|
8
|
+
|
9
|
+
sig { returns(T.nilable(String)) }
|
10
|
+
attr_reader :id
|
11
|
+
|
12
|
+
sig { returns(T.nilable(String)) }
|
13
|
+
attr_accessor :address1
|
14
|
+
|
15
|
+
sig { returns(T.nilable(String)) }
|
16
|
+
attr_accessor :address2
|
17
|
+
|
18
|
+
sig { returns(T.nilable(String)) }
|
19
|
+
attr_accessor :city
|
20
|
+
|
21
|
+
sig { returns(T.nilable(String)) }
|
22
|
+
attr_accessor :zip
|
23
|
+
|
24
|
+
sig { params(province_code: T.nilable(String)).returns(T.nilable(String)) }
|
25
|
+
attr_writer :province_code
|
26
|
+
|
27
|
+
sig { returns(T.nilable(String)) }
|
28
|
+
attr_accessor :country_code
|
29
|
+
|
30
|
+
sig do
|
31
|
+
params(
|
32
|
+
address1: T.nilable(String),
|
33
|
+
address2: T.nilable(String),
|
34
|
+
city: T.nilable(String),
|
35
|
+
zip: T.nilable(String),
|
36
|
+
province_code: T.nilable(String),
|
37
|
+
country_code: T.nilable(String),
|
38
|
+
).void
|
39
|
+
end
|
40
|
+
def initialize(address1: nil, address2: nil, city: nil, zip: nil, province_code: nil, country_code: nil)
|
41
|
+
@address1 = address1
|
42
|
+
@address2 = address2
|
43
|
+
@city = city
|
44
|
+
@zip = zip
|
45
|
+
@province_code = province_code
|
46
|
+
@original_country_code = country_code
|
47
|
+
@country_code = country_code
|
48
|
+
|
49
|
+
# generate_id uses the values of the attributes to calculate the UUID, so must be called after they're set
|
50
|
+
@id = T.let(generate_id, String)
|
51
|
+
end
|
52
|
+
|
53
|
+
sig { returns(T::Hash[Symbol, T.untyped]) }
|
54
|
+
def attributes
|
55
|
+
{
|
56
|
+
id: id,
|
57
|
+
address1: address1,
|
58
|
+
address2: address2,
|
59
|
+
city: city,
|
60
|
+
zip: zip,
|
61
|
+
province_code: province_code,
|
62
|
+
province: province,
|
63
|
+
country_code: country_code,
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
sig { returns(T.nilable(String)) }
|
68
|
+
def province
|
69
|
+
return if @original_country_code.nil? || @province_code.nil?
|
70
|
+
|
71
|
+
province = Worldwide.region(code: @original_country_code)&.zone(code: @province_code)
|
72
|
+
province.province? ? province.full_name : nil
|
73
|
+
end
|
74
|
+
|
75
|
+
sig { returns(T.nilable(String)) }
|
76
|
+
def province_code
|
77
|
+
return @province_code if @province_code.blank?
|
78
|
+
|
79
|
+
# This hack is required since checkout-web is using province codes differently for Japan Vs Other countries
|
80
|
+
# Japan province codes are expected as full ISO codes (JP-14)
|
81
|
+
# while other countries are expected as 2 digit subdivision codes (e.g. ON)
|
82
|
+
# we can remove this logic if the client can accept 2 digit subdivision codes / ISO codes as standard response
|
83
|
+
province = Worldwide.region(code: @original_country_code)&.zone(code: @province_code)
|
84
|
+
return @province_code unless province.province?
|
85
|
+
|
86
|
+
province.legacy_code
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
sig { returns(String) }
|
92
|
+
def generate_id
|
93
|
+
Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, attributes.except(:id).to_s)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|