atlas_engine 0.1.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 (298) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +123 -0
  3. data/Rakefile +20 -0
  4. data/app/assets/config/atlas_engine_manifest.js +3 -0
  5. data/app/assets/stylesheets/atlas_engine/application.css +15 -0
  6. data/app/concerns/atlas_engine/handles_blob.rb +26 -0
  7. data/app/concerns/atlas_engine/handles_interruption.rb +22 -0
  8. data/app/controllers/atlas_engine/application_controller.rb +7 -0
  9. data/app/controllers/atlas_engine/connectivity_controller.rb +21 -0
  10. data/app/controllers/atlas_engine/country_imports_controller.rb +73 -0
  11. data/app/controllers/atlas_engine/graphql_controller.rb +59 -0
  12. data/app/countries/atlas_engine/ar/country_profile.yml +9 -0
  13. data/app/countries/atlas_engine/at/address_importer/corrections/open_address/city_corrector.rb +23 -0
  14. data/app/countries/atlas_engine/at/country_profile.yml +24 -0
  15. data/app/countries/atlas_engine/at/index_configuration.yml +63 -0
  16. data/app/countries/atlas_engine/at/synonyms.yml +6 -0
  17. data/app/countries/atlas_engine/at/validation_transcriber/address_parser.rb +58 -0
  18. data/app/countries/atlas_engine/au/address_importer/open_address/filter.rb +26 -0
  19. data/app/countries/atlas_engine/au/address_importer/open_address/mapper.rb +41 -0
  20. data/app/countries/atlas_engine/au/country_profile.yml +13 -0
  21. data/app/countries/atlas_engine/au/synonyms.yml +209 -0
  22. data/app/countries/atlas_engine/au/validation_transcriber/address_parser.rb +121 -0
  23. data/app/countries/atlas_engine/be/country_profile.yml +12 -0
  24. data/app/countries/atlas_engine/bm/address_importer/corrections/open_address/city_alias_corrector.rb +38 -0
  25. data/app/countries/atlas_engine/bm/address_importer/open_address/mapper.rb +40 -0
  26. data/app/countries/atlas_engine/bm/country_profile.yml +12 -0
  27. data/app/countries/atlas_engine/br/country_profile.yml +4 -0
  28. data/app/countries/atlas_engine/ca/country_profile.yml +7 -0
  29. data/app/countries/atlas_engine/ca/synonyms.yml +1615 -0
  30. data/app/countries/atlas_engine/ch/address_importer/corrections/open_address/city_corrector.rb +29 -0
  31. data/app/countries/atlas_engine/ch/address_importer/corrections/open_address/locale_corrector.rb +74 -0
  32. data/app/countries/atlas_engine/ch/address_importer/open_address/mapper.rb +40 -0
  33. data/app/countries/atlas_engine/ch/country_profile.yml +15 -0
  34. data/app/countries/atlas_engine/ch/locales/de/country_profile.yml +15 -0
  35. data/app/countries/atlas_engine/ch/locales/de/index_configuration.yml +63 -0
  36. data/app/countries/atlas_engine/ch/locales/de/synonyms.yml +7 -0
  37. data/app/countries/atlas_engine/ch/locales/fr/synonyms.yml +21 -0
  38. data/app/countries/atlas_engine/cz/country_profile.yml +6 -0
  39. data/app/countries/atlas_engine/de/country_profile.yml +19 -0
  40. data/app/countries/atlas_engine/de/index_configuration.yml +64 -0
  41. data/app/countries/atlas_engine/de/synonyms.yml +2 -0
  42. data/app/countries/atlas_engine/de/validation_transcriber/address_parser.rb +19 -0
  43. data/app/countries/atlas_engine/dk/country_profile.yml +6 -0
  44. data/app/countries/atlas_engine/dk/synonyms.yml +3 -0
  45. data/app/countries/atlas_engine/dk/validation_transcriber/address_parser.rb +21 -0
  46. data/app/countries/atlas_engine/fo/country_profile.yml +5 -0
  47. data/app/countries/atlas_engine/fr/address_importer/corrections/open_address/city_corrector.rb +28 -0
  48. data/app/countries/atlas_engine/fr/country_profile.yml +13 -0
  49. data/app/countries/atlas_engine/fr/synonyms.yml +21 -0
  50. data/app/countries/atlas_engine/fr/validation_transcriber/address_parser.rb +34 -0
  51. data/app/countries/atlas_engine/gb/address_validation/es/query_builder.rb +98 -0
  52. data/app/countries/atlas_engine/gb/country_profile.yml +10 -0
  53. data/app/countries/atlas_engine/gb/validation_transcriber/full_address_parser.rb +164 -0
  54. data/app/countries/atlas_engine/gb/validation_transcriber/parsed_address.rb +120 -0
  55. data/app/countries/atlas_engine/gg/address_validation/validators/full_address/restrictions/unsupported_city.rb +39 -0
  56. data/app/countries/atlas_engine/gg/country_profile.yml +7 -0
  57. data/app/countries/atlas_engine/ie/country_profile.yml +3 -0
  58. data/app/countries/atlas_engine/it/address_importer/corrections/open_address/city_corrector.rb +27 -0
  59. data/app/countries/atlas_engine/it/address_importer/corrections/open_address/province_corrector.rb +29 -0
  60. data/app/countries/atlas_engine/it/address_importer/open_address/mapper.rb +42 -0
  61. data/app/countries/atlas_engine/it/country_profile.yml +11 -0
  62. data/app/countries/atlas_engine/jp/address_validation/es/data_mapper.rb +63 -0
  63. data/app/countries/atlas_engine/jp/country_profile.yml +6 -0
  64. data/app/countries/atlas_engine/kr/address_importer/open_address/mapper.rb +41 -0
  65. data/app/countries/atlas_engine/kr/country_profile.yml +11 -0
  66. data/app/countries/atlas_engine/li/address_importer/corrections/open_address/city_corrector.rb +25 -0
  67. data/app/countries/atlas_engine/li/country_profile.yml +21 -0
  68. data/app/countries/atlas_engine/li/index_configuration.yml +63 -0
  69. data/app/countries/atlas_engine/li/synonyms.yml +6 -0
  70. data/app/countries/atlas_engine/lt/country_profile.yml +6 -0
  71. data/app/countries/atlas_engine/lt/synonyms.yml +7 -0
  72. data/app/countries/atlas_engine/lt/validation_transcriber/address_parser.rb +24 -0
  73. data/app/countries/atlas_engine/lu/address_importer/corrections/open_address/locale_corrector.rb +54 -0
  74. data/app/countries/atlas_engine/lu/country_profile.yml +12 -0
  75. data/app/countries/atlas_engine/nl/address_importer/corrections/open_address/city_corrector.rb +25 -0
  76. data/app/countries/atlas_engine/nl/country_profile.yml +18 -0
  77. data/app/countries/atlas_engine/nl/index_configuration.yml +52 -0
  78. data/app/countries/atlas_engine/nl/synonyms.yml +92 -0
  79. data/app/countries/atlas_engine/nl/validation_transcriber/address_parser.rb +85 -0
  80. data/app/countries/atlas_engine/no/country_profile.yml +5 -0
  81. data/app/countries/atlas_engine/nz/country_profile.yml +3 -0
  82. data/app/countries/atlas_engine/pl/country_profile.yml +5 -0
  83. data/app/countries/atlas_engine/pl/validation_transcriber/address_parser.rb +19 -0
  84. data/app/countries/atlas_engine/pt/address_importer/corrections/open_address/city_corrector.rb +32 -0
  85. data/app/countries/atlas_engine/pt/address_importer/open_address/mapper.rb +39 -0
  86. data/app/countries/atlas_engine/pt/country_profile.yml +10 -0
  87. data/app/countries/atlas_engine/pt/synonyms.yml +7 -0
  88. data/app/countries/atlas_engine/sa/country_profile.yml +10 -0
  89. data/app/countries/atlas_engine/se/country_profile.yml +5 -0
  90. data/app/countries/atlas_engine/tt/address_importer/open_address/mapper.rb +38 -0
  91. data/app/countries/atlas_engine/tt/country_profile.yml +7 -0
  92. data/app/countries/atlas_engine/us/country_profile.yml +12 -0
  93. data/app/countries/atlas_engine/us/synonyms.yml +350 -0
  94. data/app/graphql/atlas_engine/errors/locale_unsupported_error.rb +17 -0
  95. data/app/graphql/atlas_engine/schema.graphql +1293 -0
  96. data/app/graphql/atlas_engine/schema.rb +23 -0
  97. data/app/graphql/atlas_engine/types/address_validation/address_input.rb +51 -0
  98. data/app/graphql/atlas_engine/types/address_validation/concern_type.rb +20 -0
  99. data/app/graphql/atlas_engine/types/address_validation/enums/concern_enum.rb +15 -0
  100. data/app/graphql/atlas_engine/types/address_validation/field_type.rb +15 -0
  101. data/app/graphql/atlas_engine/types/address_validation/suggestion_type.rb +21 -0
  102. data/app/graphql/atlas_engine/types/base_argument.rb +9 -0
  103. data/app/graphql/atlas_engine/types/base_enum.rb +9 -0
  104. data/app/graphql/atlas_engine/types/base_field.rb +10 -0
  105. data/app/graphql/atlas_engine/types/base_input_object.rb +9 -0
  106. data/app/graphql/atlas_engine/types/base_interface.rb +10 -0
  107. data/app/graphql/atlas_engine/types/base_object.rb +9 -0
  108. data/app/graphql/atlas_engine/types/base_scalar.rb +9 -0
  109. data/app/graphql/atlas_engine/types/base_union.rb +9 -0
  110. data/app/graphql/atlas_engine/types/matching_strategy_type.rb +12 -0
  111. data/app/graphql/atlas_engine/types/mutation_type.rb +9 -0
  112. data/app/graphql/atlas_engine/types/query_type.rb +61 -0
  113. data/app/graphql/atlas_engine/types/validation_supported_country.rb +12 -0
  114. data/app/graphql/atlas_engine/types/validation_type.rb +22 -0
  115. data/app/helpers/atlas_engine/address_importer/import_log_helper.rb +66 -0
  116. data/app/helpers/atlas_engine/application_helper.rb +7 -0
  117. data/app/helpers/atlas_engine/locale_format_helper.rb +40 -0
  118. data/app/helpers/atlas_engine/log_base.rb +32 -0
  119. data/app/helpers/atlas_engine/log_helper.rb +24 -0
  120. data/app/helpers/atlas_engine/metrics_helper.rb +25 -0
  121. data/app/jobs/atlas_engine/address_importer/clear_records_job.rb +39 -0
  122. data/app/jobs/atlas_engine/address_importer/open_address/geo_json_import_job.rb +212 -0
  123. data/app/jobs/atlas_engine/address_importer/open_address/geo_json_import_launcher_job.rb +67 -0
  124. data/app/jobs/atlas_engine/address_importer/open_address/prepares_geo_json_file.rb +41 -0
  125. data/app/jobs/atlas_engine/address_importer/resumable_import_job.rb +49 -0
  126. data/app/jobs/atlas_engine/address_importer/street_backfill_job.rb +63 -0
  127. data/app/jobs/atlas_engine/application_job.rb +10 -0
  128. data/app/jobs/atlas_engine/concerns/address_importer/handles_errors.rb +43 -0
  129. data/app/lib/atlas_engine/concern_formatter.rb +40 -0
  130. data/app/lib/atlas_engine/restrictions/base.rb +20 -0
  131. data/app/lib/atlas_engine/restrictions/unsupported_script.rb +31 -0
  132. data/app/lib/atlas_engine/validation_transcriber/address_parser_base.rb +201 -0
  133. data/app/lib/atlas_engine/validation_transcriber/address_parser_factory.rb +27 -0
  134. data/app/lib/atlas_engine/validation_transcriber/address_parser_north_america.rb +39 -0
  135. data/app/lib/atlas_engine/validation_transcriber/address_parser_oceanic.rb +17 -0
  136. data/app/lib/atlas_engine/validation_transcriber/address_parser_preprocessor.rb +132 -0
  137. data/app/lib/atlas_engine/validation_transcriber/address_parsing_helper.rb +38 -0
  138. data/app/lib/atlas_engine/validation_transcriber/address_parsings.rb +54 -0
  139. data/app/lib/atlas_engine/validation_transcriber/constants.rb +50 -0
  140. data/app/lib/atlas_engine/validation_transcriber/english_street_parser.rb +59 -0
  141. data/app/lib/atlas_engine/validation_transcriber/formatter.rb +46 -0
  142. data/app/lib/atlas_engine/validation_transcriber/french_street_parser.rb +50 -0
  143. data/app/lib/atlas_engine/validation_transcriber/province_code_normalizer.rb +45 -0
  144. data/app/lib/atlas_engine/validation_transcriber/street_parser.rb +18 -0
  145. data/app/lib/atlas_engine/validation_transcriber/zip_normalizer.rb +23 -0
  146. data/app/mailers/atlas_engine/application_mailer.rb +9 -0
  147. data/app/models/atlas_engine/address_importer/corrections/corrector.rb +33 -0
  148. data/app/models/atlas_engine/address_importer/import_events_notifier/base.rb +35 -0
  149. data/app/models/atlas_engine/address_importer/import_events_notifier/notifier.rb +26 -0
  150. data/app/models/atlas_engine/address_importer/open_address/default_mapper.rb +46 -0
  151. data/app/models/atlas_engine/address_importer/open_address/feature_helper.rb +110 -0
  152. data/app/models/atlas_engine/address_importer/open_address/filter.rb +17 -0
  153. data/app/models/atlas_engine/address_importer/open_address/loader.rb +27 -0
  154. data/app/models/atlas_engine/address_importer/open_address/transformer.rb +39 -0
  155. data/app/models/atlas_engine/address_importer/open_address.rb +10 -0
  156. data/app/models/atlas_engine/address_importer/validation/base_validator.rb +86 -0
  157. data/app/models/atlas_engine/address_importer/validation/default_validator.rb +27 -0
  158. data/app/models/atlas_engine/address_importer/validation/field_validations/city.rb +47 -0
  159. data/app/models/atlas_engine/address_importer/validation/field_validations/interface.rb +29 -0
  160. data/app/models/atlas_engine/address_importer/validation/field_validations/province.rb +73 -0
  161. data/app/models/atlas_engine/address_importer/validation/field_validations/zip.rb +84 -0
  162. data/app/models/atlas_engine/address_importer/validation/validator.rb +17 -0
  163. data/app/models/atlas_engine/address_importer/validation/wrapper.rb +70 -0
  164. data/app/models/atlas_engine/address_number.rb +36 -0
  165. data/app/models/atlas_engine/address_number_range.rb +200 -0
  166. data/app/models/atlas_engine/address_validation/abstract_address.rb +49 -0
  167. data/app/models/atlas_engine/address_validation/address.rb +47 -0
  168. data/app/models/atlas_engine/address_validation/candidate.rb +109 -0
  169. data/app/models/atlas_engine/address_validation/candidate_tuple.rb +15 -0
  170. data/app/models/atlas_engine/address_validation/concern.rb +74 -0
  171. data/app/models/atlas_engine/address_validation/concern_producer.rb +19 -0
  172. data/app/models/atlas_engine/address_validation/concern_queue.rb +20 -0
  173. data/app/models/atlas_engine/address_validation/concern_record.rb +122 -0
  174. data/app/models/atlas_engine/address_validation/datastore_base.rb +27 -0
  175. data/app/models/atlas_engine/address_validation/errors.rb +13 -0
  176. data/app/models/atlas_engine/address_validation/es/candidate_selector.rb +70 -0
  177. data/app/models/atlas_engine/address_validation/es/data_mappers/decompounding_data_mapper.rb +39 -0
  178. data/app/models/atlas_engine/address_validation/es/data_mappers/default_data_mapper.rb +110 -0
  179. data/app/models/atlas_engine/address_validation/es/datastore.rb +229 -0
  180. data/app/models/atlas_engine/address_validation/es/default_query_builder.rb +30 -0
  181. data/app/models/atlas_engine/address_validation/es/query_builder.rb +160 -0
  182. data/app/models/atlas_engine/address_validation/es/term_vectors.rb +78 -0
  183. data/app/models/atlas_engine/address_validation/es/validators/full_address.rb +123 -0
  184. data/app/models/atlas_engine/address_validation/es/validators/full_address_street.rb +18 -0
  185. data/app/models/atlas_engine/address_validation/es/validators/restriction_evaluator.rb +37 -0
  186. data/app/models/atlas_engine/address_validation/field.rb +30 -0
  187. data/app/models/atlas_engine/address_validation/full_address_validator_base.rb +27 -0
  188. data/app/models/atlas_engine/address_validation/log_emitter.rb +66 -0
  189. data/app/models/atlas_engine/address_validation/matching_strategies.rb +16 -0
  190. data/app/models/atlas_engine/address_validation/normalizer.rb +38 -0
  191. data/app/models/atlas_engine/address_validation/predicate_pipeline.rb +80 -0
  192. data/app/models/atlas_engine/address_validation/request.rb +12 -0
  193. data/app/models/atlas_engine/address_validation/result.rb +154 -0
  194. data/app/models/atlas_engine/address_validation/runs_validation.rb +16 -0
  195. data/app/models/atlas_engine/address_validation/session.rb +47 -0
  196. data/app/models/atlas_engine/address_validation/statsd_emitter.rb +72 -0
  197. data/app/models/atlas_engine/address_validation/strategies.rb +10 -0
  198. data/app/models/atlas_engine/address_validation/suggestion.rb +97 -0
  199. data/app/models/atlas_engine/address_validation/token/comparator.rb +44 -0
  200. data/app/models/atlas_engine/address_validation/token/comparison.rb +76 -0
  201. data/app/models/atlas_engine/address_validation/token/sequence/comparator.rb +158 -0
  202. data/app/models/atlas_engine/address_validation/token/sequence/comparison.rb +166 -0
  203. data/app/models/atlas_engine/address_validation/token/sequence.rb +147 -0
  204. data/app/models/atlas_engine/address_validation/token/synonyms.rb +77 -0
  205. data/app/models/atlas_engine/address_validation/token.rb +113 -0
  206. data/app/models/atlas_engine/address_validation/validator.rb +147 -0
  207. data/app/models/atlas_engine/address_validation/validators/full_address/address_comparison.rb +97 -0
  208. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result.rb +164 -0
  209. data/app/models/atlas_engine/address_validation/validators/full_address/candidate_result_base.rb +46 -0
  210. data/app/models/atlas_engine/address_validation/validators/full_address/comparison_helper.rb +135 -0
  211. data/app/models/atlas_engine/address_validation/validators/full_address/components_to_validate.rb +88 -0
  212. data/app/models/atlas_engine/address_validation/validators/full_address/concern_builder.rb +127 -0
  213. data/app/models/atlas_engine/address_validation/validators/full_address/exclusions/exclusion_base.rb +23 -0
  214. data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_concern_builder.rb +42 -0
  215. data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_country_concern.rb +37 -0
  216. data/app/models/atlas_engine/address_validation/validators/full_address/invalid_zip_for_province_concern.rb +37 -0
  217. data/app/models/atlas_engine/address_validation/validators/full_address/no_candidate_result.rb +26 -0
  218. data/app/models/atlas_engine/address_validation/validators/full_address/number_comparison.rb +31 -0
  219. data/app/models/atlas_engine/address_validation/validators/full_address/postal_code_matcher.rb +60 -0
  220. data/app/models/atlas_engine/address_validation/validators/full_address/result_updater.rb +42 -0
  221. data/app/models/atlas_engine/address_validation/validators/full_address/suggestion_builder.rb +140 -0
  222. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_address_concern.rb +30 -0
  223. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_province_concern.rb +38 -0
  224. data/app/models/atlas_engine/address_validation/validators/full_address/unknown_zip_for_address_concern.rb +32 -0
  225. data/app/models/atlas_engine/address_validation/validators/full_address/unmatched_field_concern.rb +84 -0
  226. data/app/models/atlas_engine/address_validation/validators/full_address/unsupported_script_result.rb +22 -0
  227. data/app/models/atlas_engine/address_validation/validators/predicates/cache.rb +38 -0
  228. data/app/models/atlas_engine/address_validation/validators/predicates/city/present.rb +36 -0
  229. data/app/models/atlas_engine/address_validation/validators/predicates/country/exists.rb +34 -0
  230. data/app/models/atlas_engine/address_validation/validators/predicates/country/valid_for_zip.rb +60 -0
  231. data/app/models/atlas_engine/address_validation/validators/predicates/no_emojis.rb +38 -0
  232. data/app/models/atlas_engine/address_validation/validators/predicates/no_html_tags.rb +39 -0
  233. data/app/models/atlas_engine/address_validation/validators/predicates/no_url.rb +38 -0
  234. data/app/models/atlas_engine/address_validation/validators/predicates/not_exceed_max_length.rb +34 -0
  235. data/app/models/atlas_engine/address_validation/validators/predicates/not_exceed_max_token_count.rb +63 -0
  236. data/app/models/atlas_engine/address_validation/validators/predicates/phone/valid.rb +41 -0
  237. data/app/models/atlas_engine/address_validation/validators/predicates/predicate.rb +37 -0
  238. data/app/models/atlas_engine/address_validation/validators/predicates/province/exists.rb +43 -0
  239. data/app/models/atlas_engine/address_validation/validators/predicates/province/valid_for_country.rb +48 -0
  240. data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1.rb +45 -0
  241. data/app/models/atlas_engine/address_validation/validators/predicates/street/building_number_in_address1_or_address2.rb +43 -0
  242. data/app/models/atlas_engine/address_validation/validators/predicates/street/present.rb +35 -0
  243. data/app/models/atlas_engine/address_validation/validators/predicates/zip/present.rb +58 -0
  244. data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_country.rb +45 -0
  245. data/app/models/atlas_engine/address_validation/validators/predicates/zip/valid_for_province.rb +55 -0
  246. data/app/models/atlas_engine/address_validation/validators/predicates/zip/zip_base.rb +25 -0
  247. data/app/models/atlas_engine/address_validation/zip_truncator.rb +32 -0
  248. data/app/models/atlas_engine/application_record.rb +8 -0
  249. data/app/models/atlas_engine/coded_error.rb +18 -0
  250. data/app/models/atlas_engine/coded_errors.rb +17 -0
  251. data/app/models/atlas_engine/country_import.rb +44 -0
  252. data/app/models/atlas_engine/country_profile.rb +270 -0
  253. data/app/models/atlas_engine/country_profile_ingestion_subset.rb +42 -0
  254. data/app/models/atlas_engine/country_profile_subset_base.rb +22 -0
  255. data/app/models/atlas_engine/country_profile_validation_subset.rb +48 -0
  256. data/app/models/atlas_engine/country_repository.rb +110 -0
  257. data/app/models/atlas_engine/elasticsearch/client.rb +116 -0
  258. data/app/models/atlas_engine/elasticsearch/client_interface.rb +89 -0
  259. data/app/models/atlas_engine/elasticsearch/repository.rb +246 -0
  260. data/app/models/atlas_engine/elasticsearch/repository_interface.rb +82 -0
  261. data/app/models/atlas_engine/elasticsearch/response.rb +20 -0
  262. data/app/models/atlas_engine/event.rb +12 -0
  263. data/app/models/atlas_engine/field_decompounder.rb +36 -0
  264. data/app/models/atlas_engine/index_configuration_factory.rb +188 -0
  265. data/app/models/atlas_engine/post_address.rb +114 -0
  266. data/app/models/atlas_engine/post_address_importer.rb +34 -0
  267. data/app/models/atlas_engine/services/service_helper.rb +21 -0
  268. data/app/models/atlas_engine/services/validation.rb +65 -0
  269. data/app/models/atlas_engine/services/validation_eligibility.rb +18 -0
  270. data/app/models/atlas_engine/street.rb +34 -0
  271. data/app/tasks/maintenance/atlas_engine/elasticsearch_index_create_task.rb +106 -0
  272. data/app/tasks/maintenance/atlas_engine/geo_json_import_task.rb +29 -0
  273. data/app/views/atlas_engine/connectivity/index.html.erb +50 -0
  274. data/app/views/atlas_engine/country_imports/index.html.erb +49 -0
  275. data/app/views/atlas_engine/country_imports/show.html.erb +73 -0
  276. data/app/views/layouts/atlas_engine/application.html.erb +15 -0
  277. data/config/initializers/1.ruby_patches.rb +18 -0
  278. data/config/initializers/sorbet.rb +5 -0
  279. data/config/initializers/worldwide.rb +5 -0
  280. data/config/locales/internal/en.yml +14 -0
  281. data/config/routes.rb +17 -0
  282. data/db/data/address_synonyms/index_configurations/default.yml +141 -0
  283. data/db/data/country_profiles/default.yml +23 -0
  284. data/db/data/transcriber.yml +760 -0
  285. data/db/data/validation_pipelines/es.yml +58 -0
  286. data/db/data/validation_pipelines/es_street.yml +58 -0
  287. data/db/data/validation_pipelines/local.yml +60 -0
  288. data/db/migrate/20230919173037_create_atlas_engine_post_addresses.rb +25 -0
  289. data/db/migrate/20231117142735_add_building_and_unit_ranges_column.rb +7 -0
  290. data/db/migrate/20231117143536_create_atlas_engine_country_imports.rb +11 -0
  291. data/db/migrate/20231117145844_create_atlas_engine_events_table.rb +13 -0
  292. data/db/migrate/20231123153554_add_unique_index_to_atlas_engine_post_addresses.rb +14 -0
  293. data/db/migrate/20231123154658_add_index_to_post_addresses_on_source_id_locale_country_code.rb +12 -0
  294. data/lib/atlas_engine/engine.rb +10 -0
  295. data/lib/atlas_engine/version.rb +6 -0
  296. data/lib/atlas_engine.rb +66 -0
  297. data/lib/tasks/atlas_engine/address_importer.rake +20 -0
  298. metadata +553 -0
@@ -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 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
@@ -0,0 +1,32 @@
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
@@ -0,0 +1,84 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module FullAddress
8
+ class UnmatchedFieldConcern < AddressValidation::Concern
9
+ include ConcernFormatter
10
+ attr_reader :component, :matched_components, :address, :unmatched_field
11
+
12
+ COMPONENTS_TO_LABELS = {
13
+ zip: "ZIP",
14
+ province_code: "state",
15
+ city: "city",
16
+ street: "street name",
17
+ }.freeze
18
+
19
+ SHORTENED_COMPONENT_NAMES = {
20
+ province_code: :province,
21
+ }.freeze
22
+
23
+ sig do
24
+ params(
25
+ unmatched_component: Symbol,
26
+ matched_components: T::Array[Symbol],
27
+ address: AbstractAddress,
28
+ suggestion_ids: T::Array[String],
29
+ unmatched_field: T.nilable(Symbol),
30
+ ).void
31
+ end
32
+ def initialize(unmatched_component, matched_components, address, suggestion_ids, unmatched_field = nil)
33
+ @component = unmatched_component
34
+ @matched_components = matched_components
35
+ @address = address
36
+ @unmatched_field = unmatched_field
37
+
38
+ super(
39
+ code: code,
40
+ field_names: field_names,
41
+ message: message,
42
+ type: T.must(Concern::TYPES[:warning]),
43
+ type_level: 3,
44
+ suggestion_ids: suggestion_ids
45
+ )
46
+ end
47
+
48
+ sig { returns(String) }
49
+ def message
50
+ "Enter a valid #{COMPONENTS_TO_LABELS[component]} for #{valid_address_component_values.join(", ")}"
51
+ end
52
+
53
+ sig { returns(Symbol) }
54
+ def code
55
+ "#{shortened_component_name}_inconsistent".to_sym
56
+ end
57
+
58
+ sig { returns(T::Array[Symbol]) }
59
+ def field_names
60
+ [field_name]
61
+ end
62
+
63
+ private
64
+
65
+ sig { returns(T::Array[String]) }
66
+ def valid_address_component_values
67
+ matched_components.last(2).map do |component|
68
+ component == :province_code ? province_name : address[component]
69
+ end
70
+ end
71
+
72
+ sig { returns(Symbol) }
73
+ def shortened_component_name
74
+ SHORTENED_COMPONENT_NAMES[component] || component
75
+ end
76
+
77
+ def field_name
78
+ unmatched_field || shortened_component_name
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,22 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module FullAddress
8
+ class UnsupportedScriptResult < CandidateResultBase
9
+ extend T::Sig
10
+
11
+ sig { void }
12
+ def update_result
13
+ concern = InvalidZipConcernBuilder.for(session.address, [])
14
+ result.concerns << concern if concern
15
+
16
+ update_result_scope
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ 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 Predicates
8
+ class Cache
9
+ extend T::Sig
10
+
11
+ sig { params(address: Address).void }
12
+ def initialize(address)
13
+ @address = address
14
+ @empty_region = Worldwide::Region.new(iso_code: "ZZ")
15
+ end
16
+
17
+ sig { returns(Worldwide::Region) }
18
+ def country
19
+ if @address.country_code.present?
20
+ @country ||= Worldwide.region(code: @address.country_code)
21
+ else
22
+ @empty_region
23
+ end
24
+ end
25
+
26
+ sig { returns(Worldwide::Region) }
27
+ def province
28
+ if @address.province_code.present?
29
+ @province ||= country.zone(code: @address.province_code)
30
+ else
31
+ @empty_region
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ module City
9
+ class Present < Predicate
10
+ sig { override.returns(T.nilable(Concern)) }
11
+ def evaluate
12
+ return unless @cache.country.country?
13
+ return if @cache.country.field(key: :city).autofill(locale: :en).present?
14
+
15
+ build_concern if @address.city.blank?
16
+ end
17
+
18
+ private
19
+
20
+ sig { returns(Concern) }
21
+ def build_concern
22
+ Concern.new(
23
+ field_names: [:city],
24
+ code: :city_blank,
25
+ type: T.must(Concern::TYPES[:error]),
26
+ type_level: 3,
27
+ suggestion_ids: [],
28
+ message: @cache.country.field(key: :city).error(code: :blank).to_s,
29
+ )
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,34 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ module Country
9
+ class Exists < Predicate
10
+ sig { override.returns(T.nilable(Concern)) }
11
+ def evaluate
12
+ build_concern unless @address.country_code.present? &&
13
+ @cache.country.country?
14
+ end
15
+
16
+ private
17
+
18
+ sig { returns(Concern) }
19
+ def build_concern
20
+ Concern.new(
21
+ field_names: [:country],
22
+ code: :country_blank,
23
+ type: T.must(Concern::TYPES[:error]),
24
+ type_level: 3,
25
+ suggestion_ids: [],
26
+ message: Worldwide.region(code: "US").field(key: :country).error(code: :blank),
27
+ )
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,60 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ module Country
9
+ class ValidForZip < Predicate
10
+ sig { override.returns(T.nilable(Concern)) }
11
+ def evaluate
12
+ return unless @cache.country.country?
13
+ return if @address.zip.blank?
14
+
15
+ suggested_country = Worldwide::Zip.find_country(
16
+ country_code: @address.country_code,
17
+ zip: @address.zip,
18
+ )
19
+
20
+ return if suggested_country.nil? ||
21
+ suggested_country.iso_code == @address.country_code
22
+
23
+ build_concern(build_suggestion(suggested_country.iso_code))
24
+ end
25
+
26
+ private
27
+
28
+ sig { params(suggestion: Suggestion).returns(Concern) }
29
+ def build_concern(suggestion)
30
+ Concern.new(
31
+ field_names: [:country, :zip],
32
+ code: :country_invalid_for_zip,
33
+ type: T.must(Concern::TYPES[:error]),
34
+ type_level: 1,
35
+ suggestion_ids: [T.must(suggestion.id)],
36
+ message: @cache.country.field(key: :zip).error(
37
+ code: :invalid_for_country,
38
+ options: { country: @cache.country.full_name },
39
+ ),
40
+ suggestion: suggestion,
41
+ )
42
+ end
43
+
44
+ sig { params(suggested_country_code: String).returns(Suggestion) }
45
+ def build_suggestion(suggested_country_code)
46
+ Suggestion.new(
47
+ address1: address1,
48
+ address2: address2,
49
+ city: city,
50
+ zip: zip,
51
+ province_code: province_code,
52
+ country_code: suggested_country_code,
53
+ )
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,38 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ class NoEmojis < Predicate
9
+ sig { override.returns(T.nilable(Concern)) }
10
+ def evaluate
11
+ return unless @cache.country.country?
12
+
13
+ build_concern if contains_blocked_codepoints?(address.send(@field))
14
+ end
15
+
16
+ private
17
+
18
+ sig { returns(Concern) }
19
+ def build_concern
20
+ Concern.new(
21
+ field_names: [@field],
22
+ code: "#{@field}_contains_emojis".to_sym,
23
+ type: T.must(Concern::TYPES[:error]),
24
+ type_level: 3,
25
+ suggestion_ids: [],
26
+ message: @cache.country.field(key: @field)&.error(code: :contains_emojis).to_s,
27
+ )
28
+ end
29
+
30
+ sig { params(field_value: T.nilable(String)).returns(T::Boolean) }
31
+ def contains_blocked_codepoints?(field_value)
32
+ field_value.to_s.codepoints.any? { |x| (x > 0xffff) || (0x2190 <= x && x <= 0x2bff) }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,39 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ class NoHtmlTags < Predicate
9
+ sig { override.returns(T.nilable(Concern)) }
10
+ def evaluate
11
+ return unless @cache.country.country?
12
+
13
+ build_concern if contains_html_tags(address.send(@field))
14
+ end
15
+
16
+ private
17
+
18
+ sig { returns(Concern) }
19
+ def build_concern
20
+ Concern.new(
21
+ field_names: [@field],
22
+ code: "#{@field}_contains_html_tags".to_sym,
23
+ type: T.must(Concern::TYPES[:error]),
24
+ type_level: 3,
25
+ suggestion_ids: [],
26
+ message: @cache.country.field(key: @field).error(code: :contains_html_tags).to_s,
27
+ )
28
+ end
29
+
30
+ sig { params(field_value: T.nilable(String)).returns(T::Boolean) }
31
+ def contains_html_tags(field_value)
32
+ sanitized_field_value = ActionView::Base.full_sanitizer.sanitize(field_value)
33
+ field_value.to_s != HTMLEntities.new.decode(sanitized_field_value)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,38 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ class NoUrl < Predicate
9
+ sig { override.returns(T.nilable(Concern)) }
10
+ def evaluate
11
+ return unless @cache.country.country?
12
+
13
+ build_concern if contains_url(address.send(@field))
14
+ end
15
+
16
+ private
17
+
18
+ sig { returns(Concern) }
19
+ def build_concern
20
+ Concern.new(
21
+ field_names: [@field],
22
+ code: "#{@field}_contains_url".to_sym,
23
+ type: T.must(Concern::TYPES[:error]),
24
+ type_level: 3,
25
+ suggestion_ids: [],
26
+ message: @cache.country.field(key: @field).error(code: :contains_url).to_s,
27
+ )
28
+ end
29
+
30
+ sig { params(field_value: T.nilable(String)).returns(T::Boolean) }
31
+ def contains_url(field_value)
32
+ field_value.to_s.scan(%r{(http|https)?:\/\/|[\w-]{2,63}\.[a-zA-Z]{2,63}/}).any?
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,34 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ class NotExceedMaxLength < Predicate
9
+ MAX_COMPONENT_LENGTH = 255
10
+ sig { override.returns(T.nilable(Concern)) }
11
+ def evaluate
12
+ return unless @cache.country.country?
13
+
14
+ build_concern if address.send(@field).to_s.length > MAX_COMPONENT_LENGTH
15
+ end
16
+
17
+ private
18
+
19
+ sig { returns(Concern) }
20
+ def build_concern
21
+ Concern.new(
22
+ field_names: [@field],
23
+ code: "#{@field}_too_long".to_sym,
24
+ type: T.must(Concern::TYPES[:error]),
25
+ type_level: 3,
26
+ suggestion_ids: [],
27
+ message: @cache.country.field(key: @field)&.error(code: :too_long).to_s,
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,63 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ class NotExceedMaxTokenCount < Predicate
9
+ MAX_TOKEN_COUNT = 15
10
+
11
+ sig { override.returns(T.nilable(Concern)) }
12
+ def evaluate
13
+ tokens = extract_address_tokens_from(address.send(@field))
14
+ build_concern if tokens.present? && tokens.count >= MAX_TOKEN_COUNT
15
+ end
16
+
17
+ private
18
+
19
+ sig { returns(Concern) }
20
+ def build_concern
21
+ message_field = @cache.country.field(key: @field)
22
+ message_arguments = {
23
+ code: :contains_too_many_words,
24
+ options: { word_count: MAX_TOKEN_COUNT },
25
+ }
26
+ if @field.in?([:address1, :address2])
27
+ build_specific_concern(
28
+ type: :warning,
29
+ message: message_field.warning(**message_arguments).to_s,
30
+ )
31
+ else
32
+ build_specific_concern(
33
+ type: :error,
34
+ message: message_field.error(**message_arguments).to_s,
35
+ )
36
+ end
37
+ end
38
+
39
+ sig { params(type: Symbol, message: String).returns(Concern) }
40
+ def build_specific_concern(type:, message:)
41
+ Concern.new(
42
+ field_names: [@field],
43
+ code: "#{@field}_contains_too_many_words".to_sym,
44
+ type: T.must(Concern::TYPES[type]),
45
+ type_level: 3,
46
+ suggestion_ids: [],
47
+ message: message,
48
+ )
49
+ end
50
+
51
+ sig { params(value: T.nilable(String)).returns(T::Array[String]) }
52
+ def extract_address_tokens_from(value)
53
+ Annex29.segment_words(value).filter_map do |substring|
54
+ next unless substring.match?(/\w/)
55
+
56
+ substring
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,41 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ module Phone
9
+ class Valid < Predicate
10
+ sig { override.returns(T.nilable(Concern)) }
11
+ def evaluate
12
+ return if @address.country_code.blank?
13
+ return unless @cache.country.country?
14
+ return if @address.phone.blank?
15
+
16
+ phone = Worldwide::Phone.new(number: @address.phone, country_code: @address.country_code)
17
+
18
+ return if phone.valid?
19
+
20
+ build_concern
21
+ end
22
+
23
+ private
24
+
25
+ sig { returns(Concern) }
26
+ def build_concern
27
+ Concern.new(
28
+ field_names: [:phone],
29
+ code: :phone_invalid,
30
+ type: T.must(Concern::TYPES[:error]),
31
+ type_level: 3,
32
+ suggestion_ids: [],
33
+ message: @cache.country.field(key: :phone).error(code: :invalid).to_s,
34
+ )
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,37 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ class Predicate
9
+ extend T::Helpers
10
+ extend T::Sig
11
+ abstract!
12
+
13
+ sig { returns(Symbol) }
14
+ attr_reader :field
15
+
16
+ sig { returns(Address) }
17
+ attr_reader :address
18
+
19
+ sig { returns(Cache) }
20
+ attr_reader :cache
21
+
22
+ delegate :address1, :address2, :city, :zip, :province_code, :country_code, to: :address
23
+
24
+ sig { params(field: Symbol, address: Address, cache: Cache).void }
25
+ def initialize(field:, address:, cache: Cache.new(address))
26
+ @field = field
27
+ @address = address
28
+ @cache = cache
29
+ end
30
+
31
+ sig { abstract.returns(T.nilable(Concern)) }
32
+ def evaluate; end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,43 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module AtlasEngine
5
+ module AddressValidation
6
+ module Validators
7
+ module Predicates
8
+ module Province
9
+ class Exists < Predicate
10
+ sig { override.returns(T.nilable(Concern)) }
11
+ def evaluate
12
+ return unless @cache.country.country?
13
+ return if address.province_code.present? ||
14
+ country_has_no_provinces ||
15
+ @cache.country.province_optional?
16
+
17
+ build_concern
18
+ end
19
+
20
+ private
21
+
22
+ sig { returns(Concern) }
23
+ def build_concern
24
+ Concern.new(
25
+ field_names: [:province],
26
+ code: :province_blank,
27
+ type: T.must(Concern::TYPES[:error]),
28
+ type_level: 3,
29
+ suggestion_ids: [],
30
+ message: @cache.country.field(key: :province)&.error(code: :blank).to_s,
31
+ )
32
+ end
33
+
34
+ sig { returns(T::Boolean) }
35
+ def country_has_no_provinces
36
+ @cache.country.zones.blank? || @cache.country.hide_provinces_from_addresses
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end