belpost 0.11.1 → 0.13.1
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 +24 -0
- data/README.md +64 -0
- data/lib/belpost/api_paths.rb +2 -1
- data/lib/belpost/api_service.rb +65 -17
- data/lib/belpost/client.rb +83 -2
- data/lib/belpost/models/batch_status.rb +37 -0
- data/lib/belpost/postal_delivery_types.rb +1 -2
- 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: e4adf946e8f59bd6f7819db47ee253b758f285c1bdf6fac6ca326dea521902e1
|
4
|
+
data.tar.gz: 8e9490b37a3518193182dc6db5cf1e65c5a7f7f13fafdd6935dfd1c91d4c9c3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e32a32e6561612bee6e576851bad30ada292cce9b3a6096c8db9298ce5c30f892095b8687e0353417505732abb87664f19173eb352957993d52257d76d4b1209
|
7
|
+
data.tar.gz: d38a5cf9783d0d7cac6ddeee2f8ff5c2cd5762b9c6d3a96da7da8a89470d98d9c6f52a3706bb0033c607b67e40100ceafe12f727efed16700f20859bada631ba
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
## [0.13.0] - 2025-04-25
|
2
|
+
### Added
|
3
|
+
- Added support for committing batch mailings via `commit_batch` method
|
4
|
+
- Added ability to change batch status from "uncommitted" to "committed"
|
5
|
+
|
6
|
+
## [0.12.1] - 2025-04-24
|
7
|
+
### Added
|
8
|
+
- Added Russian translations for batch statuses:
|
9
|
+
- 'uncommitted' -> 'В обработке' (in processing)
|
10
|
+
- 'committed' -> 'Сформирована' (formed)
|
11
|
+
- New `BatchStatus` class for working with batch status values
|
12
|
+
- Added `translate_batch_status` method for translating batch status values
|
13
|
+
|
14
|
+
## [0.12.0] - 2025-04-24
|
15
|
+
### Added
|
16
|
+
- Added support for downloading batch mailing documents as ZIP archives via `download_batch_documents` method
|
17
|
+
- New `get_binary` method in ApiService to handle binary data downloads
|
18
|
+
|
19
|
+
## [0.11.2] - 2025-04-24
|
20
|
+
### Added
|
21
|
+
- Added support for generating address labels for batch mailings via `generate_batch_blanks` method
|
22
|
+
- Support for generating address labels for shipments within batches with "In processing" status
|
23
|
+
- Generation of PS112e form for batches with "is_partial_receipt" flag set to true that contain shipments with attachments
|
24
|
+
|
1
25
|
## [0.11.1] - 2025-04-24
|
2
26
|
### Changed
|
3
27
|
- Enhanced validation for batch item schema to allow empty strings for `cash_on_delivery` and `declared_value` fields
|
data/README.md
CHANGED
@@ -356,6 +356,70 @@ filtered_batches = client.list_batches(
|
|
356
356
|
)
|
357
357
|
```
|
358
358
|
|
359
|
+
### Generating address labels for a batch
|
360
|
+
|
361
|
+
```ruby
|
362
|
+
client = Belpost::Client.new
|
363
|
+
|
364
|
+
# Generate address labels for a batch with ID 17292
|
365
|
+
documents = client.generate_batch_blanks(17292)
|
366
|
+
puts documents
|
367
|
+
|
368
|
+
# The response will contain document information with the following structure:
|
369
|
+
# {
|
370
|
+
# "documents" => {
|
371
|
+
# "id" => 8660,
|
372
|
+
# "list_id" => 17292,
|
373
|
+
# "status" => "processing",
|
374
|
+
# "path" => nil,
|
375
|
+
# "expire_at" => nil,
|
376
|
+
# "created_at" => "2024-11-06 13:18:59",
|
377
|
+
# "updated_at" => "2024-11-06 16:03:36",
|
378
|
+
# "name" => "Партия (заказ) №91"
|
379
|
+
# }
|
380
|
+
# }
|
381
|
+
```
|
382
|
+
|
383
|
+
Note: Address labels can only be generated for batches with the "In processing" status. When you make this request, all address labels for shipments within the batch will be regenerated. Label generation is available if the batch has the "has_documents_label" flag set to false.
|
384
|
+
|
385
|
+
If the batch has the "is_partial_receipt" flag set to true and contains shipments with attachments, a PS112e form with attachment descriptions will be included in the response ZIP archive.
|
386
|
+
|
387
|
+
### Committing a batch
|
388
|
+
|
389
|
+
After a batch has been created and filled with items, you can commit it to change its status from "uncommitted" (or "В обработке") to "committed" (or "Сформирована").
|
390
|
+
|
391
|
+
```ruby
|
392
|
+
# Commit a batch with ID 19217
|
393
|
+
result = client.commit_batch(19217)
|
394
|
+
puts "New status: #{result["status"]}" # => "committed"
|
395
|
+
```
|
396
|
+
|
397
|
+
Note: You can only commit a batch that is currently uncommitted, has items, and includes contents if the batch has the "is_partial_receipt" flag set to true.
|
398
|
+
|
399
|
+
### Downloading batch documents
|
400
|
+
|
401
|
+
```ruby
|
402
|
+
client = Belpost::Client.new
|
403
|
+
|
404
|
+
# Generate address labels for a batch with ID 17292
|
405
|
+
documents = client.generate_batch_blanks(17292)
|
406
|
+
puts documents
|
407
|
+
|
408
|
+
# The response will contain document information with the following structure:
|
409
|
+
# {
|
410
|
+
# "documents" => {
|
411
|
+
# "id" => 8660,
|
412
|
+
# "list_id" => 17292,
|
413
|
+
# "status" => "processing",
|
414
|
+
# "path" => nil,
|
415
|
+
# "expire_at" => nil,
|
416
|
+
# "created_at" => "2024-11-06 13:18:59",
|
417
|
+
# "updated_at" => "2024-11-06 16:03:36",
|
418
|
+
# "name" => "Партия (заказ) №91"
|
419
|
+
# }
|
420
|
+
# }
|
421
|
+
```
|
422
|
+
|
359
423
|
## Error handling
|
360
424
|
|
361
425
|
The client may throw the following exceptions:
|
data/lib/belpost/api_paths.rb
CHANGED
@@ -5,13 +5,14 @@ module Belpost
|
|
5
5
|
module ApiPaths
|
6
6
|
# Batch mailing paths
|
7
7
|
BATCH_MAILING_LIST = "/api/v1/business/batch-mailing/list"
|
8
|
+
BATCH_MAILING_LIST_BY_ID = "/api/v1/business/batch-mailing/list/:id"
|
8
9
|
BATCH_MAILING_DOCUMENTS = "/api/v1/business/batch-mailing/documents"
|
9
|
-
BATCH_MAILING_ITEM = "/api/v1/business/batch-mailing/item"
|
10
10
|
BATCH_MAILING_DUPLICATE = "/api/v1/business/batch-mailing/list/:id/duplicate"
|
11
11
|
BATCH_MAILING_DUPLICATE_FULL = "/api/v1/business/batch-mailing/list/:id/duplicate-full"
|
12
12
|
BATCH_MAILING_COMMIT = "/api/v1/business/batch-mailing/list/:id/commit"
|
13
13
|
BATCH_MAILING_GENERATE_BLANK = "/api/v1/business/batch-mailing/list/:id/generate-blank"
|
14
14
|
BATCH_MAILING_LIST_ITEM = "/api/v1/business/batch-mailing/list/:id/item"
|
15
|
+
BATCH_MAILING_DOCUMENTS_DOWNLOAD = "/api/v1/batch-mailing/documents/:id/download"
|
15
16
|
|
16
17
|
# Postal deliveries paths
|
17
18
|
POSTAL_DELIVERIES = "/api/v1/business/postal-deliveries"
|
data/lib/belpost/api_service.rb
CHANGED
@@ -47,6 +47,31 @@ module Belpost
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
# Performs a GET request to the specified path and returns binary data.
|
52
|
+
#
|
53
|
+
# @param path [String] The API endpoint path.
|
54
|
+
# @param params [Hash] The query parameters (default: {}).
|
55
|
+
# @return [Hash] Hash containing binary data, status code and headers
|
56
|
+
def get_binary(path, params = {})
|
57
|
+
Retry.with_retry do
|
58
|
+
uri = URI("#{@base_url}#{path}")
|
59
|
+
uri.query = URI.encode_www_form(params) unless params.empty?
|
60
|
+
request = Net::HTTP::Get.new(uri)
|
61
|
+
add_headers(request)
|
62
|
+
request["Accept"] = "*/*" # Override Accept header to receive any content type
|
63
|
+
|
64
|
+
log_request(request)
|
65
|
+
response = execute_request(uri, request)
|
66
|
+
log_response(response, binary: true)
|
67
|
+
|
68
|
+
{
|
69
|
+
data: response.body,
|
70
|
+
status_code: response.code.to_i,
|
71
|
+
headers: response.to_hash
|
72
|
+
}
|
73
|
+
end
|
74
|
+
end
|
50
75
|
|
51
76
|
# Performs a POST request to the specified path with the given body.
|
52
77
|
#
|
@@ -188,23 +213,58 @@ module Belpost
|
|
188
213
|
end
|
189
214
|
end
|
190
215
|
|
216
|
+
# Logs the HTTP request details.
|
217
|
+
#
|
218
|
+
# @param request [Net::HTTP::Request] The HTTP request object.
|
219
|
+
def log_request(request)
|
220
|
+
@logger.info("API Request: #{request.method} #{request.uri}")
|
221
|
+
@logger.debug("Request Headers: #{request.each_header.to_h}") if request.respond_to?(:each_header)
|
222
|
+
@logger.debug("Request Body: #{request.body}") if request.body
|
223
|
+
end
|
224
|
+
|
225
|
+
# Logs the HTTP response details.
|
226
|
+
#
|
227
|
+
# @param response [Net::HTTP::Response] The HTTP response object.
|
228
|
+
# @param binary [Boolean] If this is a binary response (default: false).
|
229
|
+
def log_response(response, binary: false)
|
230
|
+
status_message = response.respond_to?(:message) ? " #{response.message}" : ""
|
231
|
+
@logger.info("API Response: #{response.code}#{status_message}")
|
232
|
+
|
233
|
+
if response.respond_to?(:each_header)
|
234
|
+
@logger.debug("Response Headers: #{response.each_header.to_h}")
|
235
|
+
elsif response.respond_to?(:to_hash)
|
236
|
+
@logger.debug("Response Headers: #{response.to_hash}")
|
237
|
+
end
|
238
|
+
|
239
|
+
if binary
|
240
|
+
@logger.debug("Response Body: [BINARY DATA]")
|
241
|
+
else
|
242
|
+
@logger.debug("Response Body: #{response.body}")
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Handles the HTTP response.
|
247
|
+
#
|
248
|
+
# @param response [Net::HTTP::Response] The HTTP response object.
|
249
|
+
# @return [Net::HTTP::Response] The HTTP response object if successful.
|
250
|
+
# @raise [Belpost::ApiError] If the API returns an error response.
|
191
251
|
def handle_response(response)
|
192
|
-
case response.code
|
193
|
-
when
|
252
|
+
case response.code.to_i
|
253
|
+
when 200..299
|
194
254
|
response
|
195
|
-
when
|
255
|
+
when 401, 403
|
196
256
|
raise AuthenticationError.new(
|
197
257
|
"Authentication failed",
|
198
258
|
status_code: response.code.to_i,
|
199
259
|
response_body: response.body
|
200
260
|
)
|
201
|
-
when
|
261
|
+
when 429
|
202
262
|
raise RateLimitError.new(
|
203
263
|
"Rate limit exceeded",
|
204
264
|
status_code: response.code.to_i,
|
205
265
|
response_body: response.body
|
206
266
|
)
|
207
|
-
when
|
267
|
+
when 400
|
208
268
|
raise InvalidRequestError.new(
|
209
269
|
"Invalid request",
|
210
270
|
status_code: response.code.to_i,
|
@@ -218,17 +278,5 @@ module Belpost
|
|
218
278
|
)
|
219
279
|
end
|
220
280
|
end
|
221
|
-
|
222
|
-
def log_request(request)
|
223
|
-
@logger.info("Making #{request.method} request to #{request.uri}")
|
224
|
-
@logger.debug("Request headers: #{request.to_hash}")
|
225
|
-
@logger.debug("Request body: #{request.body}") if request.body
|
226
|
-
end
|
227
|
-
|
228
|
-
def log_response(response)
|
229
|
-
@logger.info("Received response with status #{response.code}")
|
230
|
-
@logger.debug("Response headers: #{response.to_hash}")
|
231
|
-
@logger.debug("Response body: #{response.body}")
|
232
|
-
end
|
233
281
|
end
|
234
282
|
end
|
data/lib/belpost/client.rb
CHANGED
@@ -4,6 +4,7 @@ require_relative "api_service"
|
|
4
4
|
require_relative "models/parcel"
|
5
5
|
require_relative "models/batch"
|
6
6
|
require_relative "models/batch_item"
|
7
|
+
require_relative "models/batch_status"
|
7
8
|
require_relative "models/api_response"
|
8
9
|
require_relative "validations/address_schema"
|
9
10
|
require_relative "validations/batch_schema"
|
@@ -112,12 +113,14 @@ module Belpost
|
|
112
113
|
#
|
113
114
|
# @param id [Integer] The ID of the batch to find.
|
114
115
|
# @return [Hash] The batch data if found.
|
116
|
+
# @raise [Belpost::ValidationError] If the ID parameter is invalid
|
115
117
|
# @raise [Belpost::ApiError] If the API returns an error response.
|
116
118
|
def find_batch_by_id(id)
|
117
119
|
raise ValidationError, "ID must be provided" if id.nil?
|
118
120
|
raise ValidationError, "ID must be a positive integer" unless id.is_a?(Integer) && id.positive?
|
119
121
|
|
120
|
-
|
122
|
+
path = ApiPaths::BATCH_MAILING_LIST_BY_ID.gsub(':id', id.to_s)
|
123
|
+
response = @api_service.get(path)
|
121
124
|
response.to_h
|
122
125
|
end
|
123
126
|
|
@@ -205,7 +208,7 @@ module Belpost
|
|
205
208
|
|
206
209
|
# Validate status parameter
|
207
210
|
if status
|
208
|
-
unless
|
211
|
+
unless Models::BatchStatus.valid?(status)
|
209
212
|
raise ValidationError, "Status must be 'committed' or 'uncommitted'"
|
210
213
|
end
|
211
214
|
|
@@ -231,6 +234,84 @@ module Belpost
|
|
231
234
|
response.to_h
|
232
235
|
end
|
233
236
|
|
237
|
+
# Generates address labels for a batch mailing.
|
238
|
+
#
|
239
|
+
# This method allows generating address labels for shipments within a batch.
|
240
|
+
# Labels can only be generated for batches with the "In processing" status.
|
241
|
+
# When this request is made, all address labels for shipments within the batch will be regenerated.
|
242
|
+
# Label generation is available if the batch has the "has_documents_label" flag set to false.
|
243
|
+
#
|
244
|
+
# If the batch has the "is_partial_receipt" flag set to true and contains shipments with attachments,
|
245
|
+
# a PS112e form with attachment descriptions will be included in the response ZIP archive.
|
246
|
+
#
|
247
|
+
# If the batch has the "is_partial_receipt" flag set to true and contains shipments without attachments,
|
248
|
+
# address labels will not be generated for those shipments. Adding attachments to a shipment is mandatory
|
249
|
+
# for generating address labels in this case.
|
250
|
+
#
|
251
|
+
# @param batch_id [Integer] The ID of the batch to generate labels for
|
252
|
+
# @return [Hash] The parsed JSON response containing document information
|
253
|
+
# @raise [Belpost::ValidationError] If the batch_id parameter is invalid
|
254
|
+
# @raise [Belpost::ApiError] If the API returns an error response
|
255
|
+
def generate_batch_blanks(batch_id)
|
256
|
+
raise ValidationError, "Batch ID must be provided" if batch_id.nil?
|
257
|
+
raise ValidationError, "Batch ID must be a positive integer" unless batch_id.is_a?(Integer) && batch_id.positive?
|
258
|
+
|
259
|
+
path = ApiPaths::BATCH_MAILING_GENERATE_BLANK.gsub(':id', batch_id.to_s)
|
260
|
+
response = @api_service.post(path, {})
|
261
|
+
response.to_h
|
262
|
+
end
|
263
|
+
|
264
|
+
# Commits a batch mailing by its ID, changing status from "uncommitted" to "committed".
|
265
|
+
#
|
266
|
+
# This method can only commit a batch that is currently uncommitted, has items and
|
267
|
+
# includes contents if the batch has "is_partial_receipt" flag set to true.
|
268
|
+
#
|
269
|
+
# @param batch_id [Integer] The ID of the batch to commit
|
270
|
+
# @return [Hash] The committed batch data with updated status
|
271
|
+
# @raise [Belpost::ValidationError] If the batch_id parameter is invalid
|
272
|
+
# @raise [Belpost::ApiError] If the API returns an error response
|
273
|
+
def commit_batch(batch_id)
|
274
|
+
raise ValidationError, "Batch ID must be provided" if batch_id.nil?
|
275
|
+
raise ValidationError, "Batch ID must be a positive integer" unless batch_id.is_a?(Integer) && batch_id.positive?
|
276
|
+
|
277
|
+
path = ApiPaths::BATCH_MAILING_COMMIT.gsub(':id', batch_id.to_s)
|
278
|
+
response = @api_service.post(path, {})
|
279
|
+
response.to_h
|
280
|
+
end
|
281
|
+
|
282
|
+
# Downloads batch mailing documents as a ZIP archive.
|
283
|
+
#
|
284
|
+
# This method retrieves a ZIP archive containing all documents related to a batch mailing.
|
285
|
+
# The response contains binary data that can be saved as a ZIP file.
|
286
|
+
#
|
287
|
+
# @param document_id [Integer] The ID of the document to download
|
288
|
+
# @return [Hash] Hash containing binary data, status code and headers
|
289
|
+
# @raise [Belpost::ValidationError] If the document_id parameter is invalid
|
290
|
+
# @raise [Belpost::ApiError] If the API returns an error response
|
291
|
+
def download_batch_documents(document_id)
|
292
|
+
raise ValidationError, "Document ID must be provided" if document_id.nil?
|
293
|
+
raise ValidationError, "Document ID must be a positive integer" unless document_id.is_a?(Integer) && document_id.positive?
|
294
|
+
|
295
|
+
path = ApiPaths::BATCH_MAILING_DOCUMENTS_DOWNLOAD.gsub(':id', document_id.to_s)
|
296
|
+
response = @api_service.get_binary(path)
|
297
|
+
|
298
|
+
# Ensure we have the correct content type for a ZIP file
|
299
|
+
content_type = response[:headers]["content-type"]&.first
|
300
|
+
unless content_type && content_type.include?("application/zip")
|
301
|
+
@logger.warn("Expected ZIP file but got content type: #{content_type}")
|
302
|
+
end
|
303
|
+
|
304
|
+
response
|
305
|
+
end
|
306
|
+
|
307
|
+
# Translates a batch status code to its Russian translation
|
308
|
+
#
|
309
|
+
# @param status [String] The status code ('uncommitted' or 'committed')
|
310
|
+
# @return [String] The Russian translation or the original status if not found
|
311
|
+
def translate_batch_status(status)
|
312
|
+
Models::BatchStatus.translate(status)
|
313
|
+
end
|
314
|
+
|
234
315
|
private
|
235
316
|
|
236
317
|
def format_address(address)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Belpost
|
4
|
+
module Models
|
5
|
+
# Helper class for batch status translations and utilities
|
6
|
+
class BatchStatus
|
7
|
+
# Mapping of status codes to their Russian translations
|
8
|
+
TRANSLATIONS = {
|
9
|
+
"uncommitted" => "В обработке",
|
10
|
+
"committed" => "Сформирована"
|
11
|
+
}.freeze
|
12
|
+
|
13
|
+
# Get the Russian translation for a status
|
14
|
+
#
|
15
|
+
# @param status [String] The status code ('uncommitted' or 'committed')
|
16
|
+
# @return [String] The Russian translation or the original status if not found
|
17
|
+
def self.translate(status)
|
18
|
+
TRANSLATIONS[status] || status
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get all possible statuses
|
22
|
+
#
|
23
|
+
# @return [Array<String>] Array of all possible status values
|
24
|
+
def self.all
|
25
|
+
%w[uncommitted committed]
|
26
|
+
end
|
27
|
+
|
28
|
+
# Check if a status is valid
|
29
|
+
#
|
30
|
+
# @param status [String] The status to check
|
31
|
+
# @return [Boolean] True if valid, false otherwise
|
32
|
+
def self.valid?(status)
|
33
|
+
all.include?(status)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
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.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- KuberLite
|
@@ -77,6 +77,7 @@ files:
|
|
77
77
|
- lib/belpost/models/api_response.rb
|
78
78
|
- lib/belpost/models/batch.rb
|
79
79
|
- lib/belpost/models/batch_item.rb
|
80
|
+
- lib/belpost/models/batch_status.rb
|
80
81
|
- lib/belpost/models/customs_declaration.rb
|
81
82
|
- lib/belpost/models/parcel.rb
|
82
83
|
- lib/belpost/models/parcel_builder.rb
|