belpost 0.4.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +13 -0
- data/lib/belpost/api_service.rb +3 -1
- data/lib/belpost/client.rb +71 -0
- data/lib/belpost/configuration.rb +25 -2
- data/lib/belpost/validations/address_schema.rb +30 -0
- data/lib/belpost/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5555f3f61fcb03030a1e5fd226abac810104277326db2ee42b505656ff0f3ce8
|
4
|
+
data.tar.gz: 585c4832344b4cfa9a654e4605926bacd605bf854e77e21391910de03d3d22db
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eaf547611c62aa03df55771a57d4405ea1352b04cf9fe3fddd04f1120b3df24a100a38e4f449e7dcadffa1a7b1bd58101212425d263d7e168b448712af597d5c
|
7
|
+
data.tar.gz: 4eb26318bd0e28467e50a31caa184880fab8276e331efcd7240723124ebf3795615d47eca35516f7f0d5048dbf3bb44663bb25182815d807fd4aef9d59313899
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [0.7.0] - 2025-04-01
|
4
|
+
### Added
|
5
|
+
- Added postal code search functionality via `search_postcode` method
|
6
|
+
- Support for searching postal codes by city, street, and building number
|
7
|
+
- Added comprehensive tests for the new postal code search endpoint
|
8
|
+
|
9
|
+
## [0.6.0] - 2025-04-01
|
10
|
+
### Added
|
11
|
+
- Added search addresses search functionality via `find_address_by_string` method
|
12
|
+
|
13
|
+
## [0.5.1] - 2025-04-01
|
14
|
+
### Fixed
|
15
|
+
- Improved error handling for invalid timeout environment variable
|
16
|
+
- Added fallback for BELPOST_API_URL environment variable to make tests more robust
|
17
|
+
- Fixed Configuration class by implementing `validate!` and `to_h` methods
|
18
|
+
|
19
|
+
## [0.5.0] - 2025-04-01
|
20
|
+
### Added
|
21
|
+
- Added address search functionality via `find_address_by_string` method
|
22
|
+
- Support for query parameters in GET requests
|
23
|
+
|
3
24
|
## [0.4.0] - 2025-04-01
|
4
25
|
### Added
|
5
26
|
- Added configuration via environment variables
|
data/README.md
CHANGED
@@ -295,6 +295,19 @@ hs_codes = client.fetch_hs_codes
|
|
295
295
|
puts hs_codes
|
296
296
|
```
|
297
297
|
|
298
|
+
### Searching for postal codes
|
299
|
+
|
300
|
+
```ruby
|
301
|
+
client = Belpost::Client.new
|
302
|
+
postcodes = client.search_postcode(
|
303
|
+
city: "Витебск",
|
304
|
+
street: "Ильинского",
|
305
|
+
building: "51/1", # optional
|
306
|
+
limit: 50 # optional, default: 50, range: 1-200
|
307
|
+
)
|
308
|
+
puts postcodes
|
309
|
+
```
|
310
|
+
|
298
311
|
## Error handling
|
299
312
|
|
300
313
|
The client may throw the following exceptions:
|
data/lib/belpost/api_service.rb
CHANGED
@@ -23,10 +23,12 @@ module Belpost
|
|
23
23
|
# Performs a GET request to the specified path.
|
24
24
|
#
|
25
25
|
# @param path [String] The API endpoint path.
|
26
|
+
# @param params [Hash] The query parameters (default: {}).
|
26
27
|
# @return [Models::ApiResponse] The parsed JSON response from the API.
|
27
|
-
def get(path)
|
28
|
+
def get(path, params = {})
|
28
29
|
Retry.with_retry do
|
29
30
|
uri = URI("#{@base_url}#{path}")
|
31
|
+
uri.query = URI.encode_www_form(params) unless params.empty?
|
30
32
|
request = Net::HTTP::Get.new(uri)
|
31
33
|
add_headers(request)
|
32
34
|
|
data/lib/belpost/client.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require_relative "api_service"
|
4
4
|
require_relative "models/parcel"
|
5
5
|
require_relative "models/api_response"
|
6
|
+
require_relative "validations/address_schema"
|
6
7
|
|
7
8
|
module Belpost
|
8
9
|
# Main client class for interacting with the BelPost API.
|
@@ -67,5 +68,75 @@ module Belpost
|
|
67
68
|
response = @api_service.get("/api/v1/business/postal-deliveries/countries")
|
68
69
|
response.to_h
|
69
70
|
end
|
71
|
+
|
72
|
+
# Allows you to find an address by a string.
|
73
|
+
#
|
74
|
+
# Accepts a string with an address in any form and returns found addresses (up to 50 records).
|
75
|
+
# Building numbers should be specified without spaces: "building number""letter""building".
|
76
|
+
# The letter should be uppercase, and "building" (or "корп", "кор", "к") should be replaced with "/".
|
77
|
+
# Example: "город Минск улица Автодоровская 3Е корпус 4" should be transformed to "город Минск улица Автодоровская 3Е/4".
|
78
|
+
#
|
79
|
+
# @param address [String] The address string to search for.
|
80
|
+
# @return [Array<Hash>] An array of found addresses with postcode, region, city, street and other information.
|
81
|
+
# @raise [Belpost::ApiError] If the API returns an error response.
|
82
|
+
# @raise [Belpost::InvalidRequestError] If the address parameter is missing or has an incorrect format.
|
83
|
+
def find_address_by_string(address)
|
84
|
+
raise ValidationError, "Address must be filled" if address.nil?
|
85
|
+
raise ValidationError, "Address must be a string" unless address.is_a?(String)
|
86
|
+
raise ValidationError, "Address must be filled" if address.empty?
|
87
|
+
|
88
|
+
formatted_address = format_address(address)
|
89
|
+
response = @api_service.get("/api/v1/business/geo-directory/search-address", { search: formatted_address })
|
90
|
+
response.to_h
|
91
|
+
end
|
92
|
+
|
93
|
+
# Searches for postal codes by city, street, and building number.
|
94
|
+
#
|
95
|
+
# @param city [String] The city name (required)
|
96
|
+
# @param street [String] The street name (required)
|
97
|
+
# @param building [String] The building number (optional)
|
98
|
+
# @param limit [Integer] Maximum number of results (optional, default: 50, range: 1-200)
|
99
|
+
# @return [Array<Hash>] An array of found addresses with postcode, region, city, street and other information
|
100
|
+
# @raise [Belpost::ValidationError] If required parameters are missing or invalid
|
101
|
+
# @raise [Belpost::ApiError] If the API returns an error response
|
102
|
+
def search_postcode(city:, street:, building: nil, limit: 50)
|
103
|
+
raise ValidationError, "City must be filled" if city.nil?
|
104
|
+
raise ValidationError, "City must be a string" unless city.is_a?(String)
|
105
|
+
raise ValidationError, "City must be filled" if city.empty?
|
106
|
+
raise ValidationError, "Street must be filled" if street.nil?
|
107
|
+
raise ValidationError, "Street must be a string" unless street.is_a?(String)
|
108
|
+
raise ValidationError, "Street must be filled" if street.empty?
|
109
|
+
raise ValidationError, "Building must be a string" if building && !building.is_a?(String)
|
110
|
+
raise ValidationError, "Limit must be between 1 and 200" if limit < 1 || limit > 200
|
111
|
+
|
112
|
+
params = { city: city, street: street }
|
113
|
+
params[:building] = format_building_number(building) if building
|
114
|
+
params[:limit] = limit
|
115
|
+
|
116
|
+
response = @api_service.get("/api/v1/business/geo-directory/postcode", params)
|
117
|
+
response.to_h
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def format_address(address)
|
123
|
+
address.gsub(/\s+/, " ")
|
124
|
+
.gsub(/\s*корпус\s*(\d+)\s*/i, '/\1')
|
125
|
+
.gsub(/\s*корп\s*(\d+)\s*/i, '/\1')
|
126
|
+
.gsub(/\s*кор\s*(\d+)\s*/i, '/\1')
|
127
|
+
.gsub(/\s*к\s*(\d+)\s*/i, '/\1')
|
128
|
+
.strip
|
129
|
+
end
|
130
|
+
|
131
|
+
def format_building_number(building)
|
132
|
+
return building unless building
|
133
|
+
|
134
|
+
building.gsub(/\s+/, " ")
|
135
|
+
.gsub(/\s*корпус\s*(\d+)\s*/i, '/\1')
|
136
|
+
.gsub(/\s*корп\s*(\d+)\s*/i, '/\1')
|
137
|
+
.gsub(/\s*кор\s*(\d+)\s*/i, '/\1')
|
138
|
+
.gsub(/\s*к\s*(\d+)\s*/i, '/\1')
|
139
|
+
.strip
|
140
|
+
end
|
70
141
|
end
|
71
142
|
end
|
@@ -7,9 +7,32 @@ module Belpost
|
|
7
7
|
attr_accessor :base_url, :jwt_token, :timeout
|
8
8
|
|
9
9
|
def initialize
|
10
|
-
@base_url = ENV.fetch("BELPOST_API_URL")
|
10
|
+
@base_url = ENV.fetch("BELPOST_API_URL", "https://api.belpost.by")
|
11
11
|
@jwt_token = ENV.fetch("BELPOST_JWT_TOKEN", nil)
|
12
|
-
|
12
|
+
|
13
|
+
# Convert timeout to integer with a fallback to default
|
14
|
+
begin
|
15
|
+
@timeout = Integer(ENV.fetch("BELPOST_TIMEOUT", 10))
|
16
|
+
rescue ArgumentError
|
17
|
+
@timeout = 10
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Validates that all required configuration is present
|
22
|
+
# @raise [Belpost::ConfigurationError] If required configuration is missing
|
23
|
+
def validate!
|
24
|
+
raise ConfigurationError, "Base URL is required" if base_url.nil?
|
25
|
+
raise ConfigurationError, "JWT token is required" if jwt_token.nil?
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a hash representation of the configuration
|
29
|
+
# @return [Hash] The configuration as a hash
|
30
|
+
def to_h
|
31
|
+
{
|
32
|
+
base_url: base_url,
|
33
|
+
jwt_token: jwt_token,
|
34
|
+
timeout: timeout
|
35
|
+
}
|
13
36
|
end
|
14
37
|
end
|
15
38
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry-validation"
|
4
|
+
|
5
|
+
module Belpost
|
6
|
+
module Validation
|
7
|
+
# Schema for validating and formatting address strings
|
8
|
+
class AddressSchema < Dry::Validation::Contract
|
9
|
+
params do
|
10
|
+
required(:address).filled(:string)
|
11
|
+
end
|
12
|
+
|
13
|
+
rule(:address) do
|
14
|
+
# Remove extra spaces
|
15
|
+
address = value.gsub(/\s+/, " ").strip
|
16
|
+
|
17
|
+
# Replace building indicators with "/"
|
18
|
+
address = address.gsub(/\s+(корпус|корп|кор|к)\s+/, "/")
|
19
|
+
|
20
|
+
# Ensure building number format (no spaces between number, letter, and building)
|
21
|
+
address = address.gsub(/(\d+)\s*([А-Я])\s*(\d+)/, '\1\2/\3')
|
22
|
+
|
23
|
+
# Ensure letter is uppercase
|
24
|
+
address = address.gsub(/(\d+)([а-я])(\/\d+)/) { |m| "#{$1}#{$2.upcase}#{$3}" }
|
25
|
+
|
26
|
+
key.failure(address)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/belpost/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: belpost
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- KuberLite
|
@@ -64,6 +64,7 @@ files:
|
|
64
64
|
- lib/belpost/models/parcel.rb
|
65
65
|
- lib/belpost/models/parcel_builder.rb
|
66
66
|
- lib/belpost/retry.rb
|
67
|
+
- lib/belpost/validations/address_schema.rb
|
67
68
|
- lib/belpost/validations/parcel_schema.rb
|
68
69
|
- lib/belpost/version.rb
|
69
70
|
homepage: https://github.com/KuberLite/belpost
|