costa_rica_address_utils 0.3.2 → 0.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +1 -1
- data/README.md +8 -2
- data/lib/costa_rica_address_utils/costa_rica.rb +81 -0
- data/lib/costa_rica_address_utils/guatemala.rb +62 -0
- data/lib/costa_rica_address_utils/version.rb +1 -1
- data/lib/costa_rica_address_utils.rb +41 -92
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e88494ff983e9e75ca80537f1d42f97bd31a0ce606f17a450bc7a4a6ec6dd7db
|
|
4
|
+
data.tar.gz: 914e71a23e8a05acbf39aa99a8d85c87decd700403e420fcc02324f448409308
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 35c91696f8bf675e556daf9b1393bcade9d4fa3ebe03fdab5bfbebbf9402cf128966078ab23e4256d5d672160c4ba40f0fb27ee52b9b9c9053be2e51e75eda34
|
|
7
|
+
data.tar.gz: 1a943483975c277de9b5287e356a9bbf50c7fbcc4666444108725f77bb4943842fad28b661c85906af838f2a0fce9b03bc015bff7b0f0797b00c0cc0bd01b064
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [0.4.0]
|
|
4
|
+
|
|
5
|
+
* Move existing logic for main module to its own module called `CostaRica`
|
|
6
|
+
* Create new module `Guatemala` for Guatemala address logic
|
|
7
|
+
* New method `for_country` to explicitly use methods for each country
|
|
8
|
+
* Extract method `build_address_from_provider` as a global method instead of per region to build an address from an external provider (Shopify, Brightpearl, etc)
|
|
9
|
+
|
|
10
|
+
> To avoid breaking calls of older versions, if the methods are called directly with `CostaRicaAddressUtils` it will automatically use the methods from `CostaRica` module.
|
|
11
|
+
|
|
3
12
|
## [0.3.2]
|
|
4
13
|
|
|
5
14
|
* Add missing accents from GT dataset on top level items
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -40,11 +40,17 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
|
|
40
40
|
|
|
41
41
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
## Release
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
To release a new version follow these steps:,
|
|
46
|
+
1. Update CHANGELOG.md with the new version changes
|
|
47
|
+
2. Update the version number in `version.rb`
|
|
48
|
+
3. Execute bundle to update version on `Gemfile.lock` automatically
|
|
49
|
+
4. Commit the changes and change the branch to `main`
|
|
50
|
+
5. Run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
46
51
|
|
|
47
52
|
> Remember to execute `bundle exec rake release` on `main` branch
|
|
53
|
+
> `Gemfile.lock` update for version is done after running `bundle install` with the `version.rb` updated
|
|
48
54
|
|
|
49
55
|
## Contributing
|
|
50
56
|
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require 'json'
|
|
2
|
+
|
|
3
|
+
# TODO: find way to optimize dataset loading
|
|
4
|
+
|
|
5
|
+
module CostaRicaAddressUtils
|
|
6
|
+
module CostaRica
|
|
7
|
+
JSON_FILE_PATH = File.join(File.dirname(__FILE__), '..', '..', 'data', 'locations_dataset.json')
|
|
8
|
+
|
|
9
|
+
# Load the JSON file and parse it into a Ruby object for general usage
|
|
10
|
+
LOCATIONS_DATASET = JSON.parse(File.read(JSON_FILE_PATH))
|
|
11
|
+
|
|
12
|
+
class Error < StandardError; end
|
|
13
|
+
# Your code goes here...
|
|
14
|
+
|
|
15
|
+
# Fetch the address data from provided input, return options for subaddresses on each level and zip code if full address is valid
|
|
16
|
+
def fetch_address_data(province:, canton: nil, district: nil)
|
|
17
|
+
raise CostaRicaAddressUtils::InvalidData, 'Province is required' if province.nil? || province.empty?
|
|
18
|
+
|
|
19
|
+
province_data = LOCATIONS_DATASET[province]
|
|
20
|
+
canton_data = !!province_data ? province_data['cantons'][canton] : nil
|
|
21
|
+
district_data = !!canton_data ? canton_data['districts'][district] : nil
|
|
22
|
+
|
|
23
|
+
canton_options = !!province_data ? province_data['cantons'].keys : [] # Cantons options, only if province is valid
|
|
24
|
+
district_options = !!canton_data ? canton_data['districts'].keys : [] # Districts options, only if canton is valid
|
|
25
|
+
zip = (!!district_data && district_data['zip_code']) || nil # Zip code, only if full address is valid
|
|
26
|
+
|
|
27
|
+
{
|
|
28
|
+
zip: zip,
|
|
29
|
+
# Names options
|
|
30
|
+
province_options: LOCATIONS_DATASET.keys,
|
|
31
|
+
canton_options: canton_options,
|
|
32
|
+
district_options: district_options
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Get one address information from a zip code
|
|
37
|
+
def fetch_address_from_zip(zip_code)
|
|
38
|
+
return nil unless zip_valid?(zip_code)
|
|
39
|
+
|
|
40
|
+
zip_code_s = zip_code.to_s
|
|
41
|
+
LOCATIONS_DATASET.each do |province, province_data|
|
|
42
|
+
province_data['cantons'].each do |canton, canton_data|
|
|
43
|
+
canton_data['districts'].each do |district, district_data|
|
|
44
|
+
if district_data['zip_code'] == zip_code_s
|
|
45
|
+
return {
|
|
46
|
+
province: province,
|
|
47
|
+
canton: canton,
|
|
48
|
+
district: district,
|
|
49
|
+
zip: zip_code_s
|
|
50
|
+
}
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
nil
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def fetch_address_from_zip!(zip_code)
|
|
60
|
+
raise "Zip code provided #{zip_code} is invalid. Must be a 5 digits number" unless zip_valid?(zip_code)
|
|
61
|
+
|
|
62
|
+
fetch_address_from_zip(zip_code)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def address_valid?(province:, canton:, district:)
|
|
66
|
+
is_valid = true
|
|
67
|
+
begin
|
|
68
|
+
data = fetch_address_data(province: province, canton: canton, district: district)
|
|
69
|
+
is_valid = !!data[:zip] # Is valid if matched to a zip code
|
|
70
|
+
rescue CostaRicaAddressUtils::InvalidData => e
|
|
71
|
+
is_valid = false
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
is_valid
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def zip_valid?(zip_code)
|
|
78
|
+
!!zip_code && zip_code.to_s.length == 5
|
|
79
|
+
end
|
|
80
|
+
end # CostaRica
|
|
81
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module CostaRicaAddressUtils
|
|
4
|
+
module Guatemala
|
|
5
|
+
# Guatemala-specific implementation
|
|
6
|
+
JSON_FILE_PATH = File.join(File.dirname(__FILE__), '..', '..', 'data', 'guatemala_dataset.json')
|
|
7
|
+
LOCATIONS_DATASET = JSON.parse(File.read(JSON_FILE_PATH))
|
|
8
|
+
|
|
9
|
+
# Your Guatemala-specific methods here
|
|
10
|
+
|
|
11
|
+
# For a given address of 2 levels, return options for each level found and zip code if full address is valid
|
|
12
|
+
def self.fetch_address_data(department:, municipality:)
|
|
13
|
+
raise CostaRicaAddressUtils::InvalidData, 'Department is required' if department.nil? || department.empty?
|
|
14
|
+
|
|
15
|
+
department_data = LOCATIONS_DATASET[department]
|
|
16
|
+
municipality_data = !!department_data ? department_data['locationsLevel2'][municipality] : nil
|
|
17
|
+
|
|
18
|
+
# Municipality options(lv2), only if department(lv1) is valid
|
|
19
|
+
municipality_options = !!department_data ? department_data['locationsLevel2'].keys : []
|
|
20
|
+
zip = (!!municipality_data && municipality_data['zipCode']) || nil # Zip code, only if full address is valid
|
|
21
|
+
|
|
22
|
+
{
|
|
23
|
+
zip: zip,
|
|
24
|
+
# Names options
|
|
25
|
+
department_options: LOCATIONS_DATASET.keys,
|
|
26
|
+
municipality_options: municipality_options
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Get one address information from a zip code
|
|
31
|
+
def self.fetch_address_from_zip(zip_code)
|
|
32
|
+
return nil unless zip_valid?(zip_code)
|
|
33
|
+
|
|
34
|
+
zip_code_s = zip_code.to_s
|
|
35
|
+
LOCATIONS_DATASET.each do |department, department_data|
|
|
36
|
+
department_data['locationsLevel2'].each do |municipality, municipality_data|
|
|
37
|
+
if municipality_data['zipCode'] == zip_code_s
|
|
38
|
+
return {
|
|
39
|
+
department: department,
|
|
40
|
+
municipality: municipality,
|
|
41
|
+
zip: zip_code_s
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
nil
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.address_valid?(department:, municipality:)
|
|
51
|
+
is_valid = true
|
|
52
|
+
begin
|
|
53
|
+
data = fetch_address_data(department: department, municipality: municipality)
|
|
54
|
+
is_valid = !!data[:zip] # Is valid if matched to a zip code
|
|
55
|
+
rescue CostaRicaAddressUtils::InvalidData => e
|
|
56
|
+
is_valid = false
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
is_valid
|
|
60
|
+
end
|
|
61
|
+
end # Guatemala
|
|
62
|
+
end # CostaRicaAddressUtils
|
|
@@ -1,118 +1,67 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
# TODO find way to optimize dataset loading
|
|
3
|
-
require 'json'
|
|
4
|
-
require_relative "costa_rica_address_utils/version"
|
|
5
|
-
require_relative "costa_rica_address_utils/errors"
|
|
6
2
|
|
|
7
|
-
|
|
3
|
+
require_relative 'costa_rica_address_utils/version'
|
|
4
|
+
require_relative 'costa_rica_address_utils/errors'
|
|
5
|
+
require_relative 'costa_rica_address_utils/costa_rica'
|
|
6
|
+
require_relative 'costa_rica_address_utils/guatemala'
|
|
8
7
|
|
|
9
|
-
module CostaRicaAddressUtils
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
module CostaRicaAddressUtils # rubocop:disable Style/Documentation
|
|
9
|
+
# Backwards compatibility before usage of for_country
|
|
10
|
+
# Old version will be able to call methods with CostaRicaAddressUtils directly
|
|
11
|
+
extend CostaRicaAddressUtils::CostaRica
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
SUPPORTED_COUNTRIES = %i[costa_rica guatemala].freeze
|
|
14
|
+
VALID_INPUT_PROVIDERS = %i[shopify brightpearl].freeze
|
|
16
15
|
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
raise InvalidData, "Province is required" if province.nil? || province.empty?
|
|
16
|
+
# TODO: merge the methods from both countries using new dataset for costa rica instead of previous one
|
|
17
|
+
# Newer files contains a standarized format for fields.
|
|
20
18
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return {
|
|
30
|
-
zip: zip,
|
|
31
|
-
# Names options
|
|
32
|
-
province_options: LOCATIONS_DATASET.keys,
|
|
33
|
-
canton_options: canton_options,
|
|
34
|
-
district_options: district_options,
|
|
35
|
-
}
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
# Get one address information from a zip code
|
|
39
|
-
def self.fetch_address_from_zip(zip_code)
|
|
40
|
-
return nil unless zip_valid?(zip_code)
|
|
41
|
-
zip_code_s = zip_code.to_s
|
|
42
|
-
LOCATIONS_DATASET.each do |province, province_data|
|
|
43
|
-
province_data["cantons"].each do |canton, canton_data|
|
|
44
|
-
canton_data["districts"].each do |district, district_data|
|
|
45
|
-
if district_data["zip_code"] == zip_code_s
|
|
46
|
-
return {
|
|
47
|
-
province: province,
|
|
48
|
-
canton: canton,
|
|
49
|
-
district: district,
|
|
50
|
-
zip: zip_code_s,
|
|
51
|
-
}
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
return nil
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def self.fetch_address_from_zip!(zip_code)
|
|
61
|
-
raise "Zip code provided #{zip_code} is invalid. Must be a 5 digits number" unless zip_valid?(zip_code)
|
|
62
|
-
fetch_address_from_zip(zip_code)
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
def self.address_valid?(province:, canton:, district:)
|
|
66
|
-
is_valid = true
|
|
67
|
-
begin
|
|
68
|
-
data = fetch_address_data(province: province, canton: canton, district: district)
|
|
69
|
-
is_valid = !!data[:zip] # Is valid if matched to a zip code
|
|
70
|
-
rescue InvalidData => e
|
|
71
|
-
is_valid = false
|
|
19
|
+
def self.for_country(country)
|
|
20
|
+
case country.to_sym
|
|
21
|
+
when :costa_rica
|
|
22
|
+
CostaRicaAddressUtils::CostaRica
|
|
23
|
+
when :guatemala
|
|
24
|
+
CostaRicaAddressUtils::Guatemala
|
|
25
|
+
else
|
|
26
|
+
raise ArgumentError, "Unsupported country: #{country}. Supported countries are: #{SUPPORTED_COUNTRIES}"
|
|
72
27
|
end
|
|
73
|
-
|
|
74
|
-
return is_valid
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def self.zip_valid?(zip_code)
|
|
78
|
-
!!zip_code && zip_code.to_s.length == 5
|
|
79
28
|
end
|
|
80
29
|
|
|
81
30
|
# Build a Costa Rica address from an address of an external provider (Shopify, Brightpearl, etc)
|
|
82
31
|
# https://shopify.dev/api/admin-graphql/2022-10/objects/mailingaddress
|
|
83
32
|
# https://api-docs.brightpearl.com/contact/postal-address/get.html
|
|
84
|
-
|
|
33
|
+
# Standarized format locationLevelX for the address Province/Department, Municipality/Canton, District/Parish
|
|
34
|
+
# since they are named differently in each country
|
|
35
|
+
def self.build_address_from_provider(address:, provider:)
|
|
85
36
|
case provider
|
|
86
37
|
when :shopify
|
|
87
|
-
|
|
38
|
+
{
|
|
88
39
|
name: address.name, # Customer name
|
|
89
40
|
address1: address.address1,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
41
|
+
|
|
42
|
+
locationLevel1: address.province,
|
|
43
|
+
locationLevel2: address.city,
|
|
44
|
+
locationLevel3: address.address2,
|
|
94
45
|
zip: address.zip,
|
|
95
46
|
|
|
96
47
|
national_id: address.company,
|
|
97
|
-
phone: address.phone
|
|
48
|
+
phone: address.phone
|
|
98
49
|
}
|
|
99
50
|
when :brightpearl
|
|
100
|
-
|
|
101
|
-
name: address[
|
|
102
|
-
address1: address[
|
|
103
|
-
|
|
104
|
-
province: address["addressLine4"],
|
|
105
|
-
canton: address["addressLine3"],
|
|
106
|
-
district: address["addressLine2"],
|
|
107
|
-
zip: address["postalCode"],
|
|
51
|
+
{
|
|
52
|
+
name: address['addressFullName'], # Customer name
|
|
53
|
+
address1: address['addressLine1'],
|
|
108
54
|
|
|
109
|
-
|
|
110
|
-
|
|
55
|
+
locationLevel1: address['addressLine4'],
|
|
56
|
+
locationLevel2: address['addressLine3'],
|
|
57
|
+
locationLevel3: address['addressLine2'],
|
|
58
|
+
zip: address['postalCode'],
|
|
59
|
+
|
|
60
|
+
national_id: address['companyName'],
|
|
61
|
+
phone: address['telephone']
|
|
111
62
|
}
|
|
112
63
|
else
|
|
113
|
-
raise InvalidData("Invalid provider, valid providers are: #{
|
|
64
|
+
raise InvalidData("Invalid provider, valid providers are: #{VALID_INPUT_PROVIDERS}")
|
|
114
65
|
end
|
|
115
66
|
end
|
|
116
|
-
|
|
117
|
-
private
|
|
118
|
-
end # module CostaRicaAddressUtils
|
|
67
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: costa_rica_address_utils
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- vicvans20
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2025-01-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: byebug
|
|
@@ -45,7 +45,9 @@ files:
|
|
|
45
45
|
- data/guatemala_dataset.json
|
|
46
46
|
- data/locations_dataset.json
|
|
47
47
|
- lib/costa_rica_address_utils.rb
|
|
48
|
+
- lib/costa_rica_address_utils/costa_rica.rb
|
|
48
49
|
- lib/costa_rica_address_utils/errors.rb
|
|
50
|
+
- lib/costa_rica_address_utils/guatemala.rb
|
|
49
51
|
- lib/costa_rica_address_utils/version.rb
|
|
50
52
|
- sig/costa_rica_address_utils.rbs
|
|
51
53
|
homepage: https://github.com/vicvans20/costa_rica_address_utils
|