belpost 0.7.0 → 0.9.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5555f3f61fcb03030a1e5fd226abac810104277326db2ee42b505656ff0f3ce8
4
- data.tar.gz: 585c4832344b4cfa9a654e4605926bacd605bf854e77e21391910de03d3d22db
3
+ metadata.gz: 9573611d63a9e36e61ada02613b8e8764fb2a45125a17f5938f2521b0a80586d
4
+ data.tar.gz: 1db61fe84045560aac6dc7e362aeb5698413851d23851c1b2601f84ca1ff6bc3
5
5
  SHA512:
6
- metadata.gz: eaf547611c62aa03df55771a57d4405ea1352b04cf9fe3fddd04f1120b3df24a100a38e4f449e7dcadffa1a7b1bd58101212425d263d7e168b448712af597d5c
7
- data.tar.gz: 4eb26318bd0e28467e50a31caa184880fab8276e331efcd7240723124ebf3795615d47eca35516f7f0d5048dbf3bb44663bb25182815d807fd4aef9d59313899
6
+ metadata.gz: 4ee356c1da9fad9db8b62a6d5bbe135c317b4c49cd818e856f8a81e70c8452dc98deeb03ffc59dd4d108efac8434c4ed1e9ce0ba5dcca41b23485f327255a26c
7
+ data.tar.gz: 40826b94cf8e911fc7930c5dae67412f4688ccc68f43bed53d5d5317d3146c848fd0f95111e24706cca2a5907b76d54fadf3d53c93eaa6a91aef8dc11f7190f9
data/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.9.0] - 2025-04-15
4
+
5
+ ### Changed
6
+ - Refactored API paths into a separate module `Belpost::ApiPaths` for better maintainability
7
+ - Moved all hardcoded API endpoints into constants in `api_paths.rb`
8
+ - Updated all client methods to use the new API path constants
9
+ - Updated tests to use the new API path constants
10
+
11
+ ### Added
12
+ - Added batch retrieval functionality via `find_batch_by_id` method
13
+ - Support for finding batch mailings by their ID with validation
14
+ - New module `Belpost::ApiPaths` with organized API endpoint constants:
15
+ - Batch mailing paths
16
+ - Postal deliveries paths
17
+ - Geo directory paths
18
+
19
+ ## [0.8.0] - 2025-04-14
20
+ ### Added
21
+ - Added batch mailing functionality via `create_batch` method
22
+ - Support for creating batch mailings with various delivery types
23
+ - Added comprehensive validation for batch mailing data
24
+ - Added new models and schemas for batch mailing
25
+ - Added tests for batch mailing functionality
26
+
3
27
  ## [0.7.0] - 2025-04-01
4
28
  ### Added
5
29
  - Added postal code search functionality via `search_postcode` method
data/README.md CHANGED
@@ -308,6 +308,14 @@ postcodes = client.search_postcode(
308
308
  puts postcodes
309
309
  ```
310
310
 
311
+ ### Finding a batch by ID
312
+
313
+ ```ruby
314
+ client = Belpost::Client.new
315
+ batch = client.find_batch_by_id(123)
316
+ puts batch
317
+ ```
318
+
311
319
  ## Error handling
312
320
 
313
321
  The client may throw the following exceptions:
data/belpost.gemspec CHANGED
@@ -34,4 +34,5 @@ Gem::Specification.new do |spec|
34
34
 
35
35
  spec.add_dependency "dotenv"
36
36
  spec.add_dependency "dry-validation", "~> 1.0"
37
+ spec.add_dependency "dry-schema", "~> 1.0"
37
38
  end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Belpost
4
+ # Constants for API paths
5
+ module ApiPaths
6
+ # Batch mailing paths
7
+ BATCH_MAILING_LIST = "/api/v1/business/batch-mailing/list"
8
+ BATCH_MAILING_DOCUMENTS = "/api/v1/business/batch-mailing/documents"
9
+ BATCH_MAILING_ITEM = "/api/v1/business/batch-mailing/item"
10
+ BATCH_MAILING_DUPLICATE = "/api/v1/business/batch-mailing/list/:id/duplicate"
11
+ BATCH_MAILING_DUPLICATE_FULL = "/api/v1/business/batch-mailing/list/:id/duplicate-full"
12
+ BATCH_MAILING_COMMIT = "/api/v1/business/batch-mailing/list/:id/commit"
13
+ BATCH_MAILING_GENERATE_BLANK = "/api/v1/business/batch-mailing/list/:id/generate-blank"
14
+
15
+ # Postal deliveries paths
16
+ POSTAL_DELIVERIES = "/api/v1/business/postal-deliveries"
17
+ POSTAL_DELIVERIES_HS_CODES = "/api/v1/business/postal-deliveries/hs-codes/list"
18
+ POSTAL_DELIVERIES_VALIDATION = "/api/v1/business/postal-deliveries/validation"
19
+ POSTAL_DELIVERIES_COUNTRIES = "/api/v1/business/postal-deliveries/countries"
20
+
21
+ # Geo directory paths
22
+ GEO_DIRECTORY_SEARCH_ADDRESS = "/api/v1/business/geo-directory/search-address"
23
+ GEO_DIRECTORY_POSTCODE = "/api/v1/business/geo-directory/postcode"
24
+ end
25
+ end
@@ -151,7 +151,6 @@ module Belpost
151
151
  http = Net::HTTP.new(uri.host, uri.port)
152
152
  http.use_ssl = true if uri.scheme == "https"
153
153
  http.read_timeout = @timeout
154
-
155
154
  begin
156
155
  response = http.request(request)
157
156
  handle_response(response)
@@ -191,7 +190,7 @@ module Belpost
191
190
 
192
191
  def handle_response(response)
193
192
  case response.code
194
- when "200"
193
+ when "200", "201"
195
194
  response
196
195
  when "401", "403"
197
196
  raise AuthenticationError.new(
@@ -2,8 +2,11 @@
2
2
 
3
3
  require_relative "api_service"
4
4
  require_relative "models/parcel"
5
+ require_relative "models/batch"
5
6
  require_relative "models/api_response"
6
7
  require_relative "validations/address_schema"
8
+ require_relative "validations/batch_schema"
9
+ require_relative "api_paths"
7
10
 
8
11
  module Belpost
9
12
  # Main client class for interacting with the BelPost API.
@@ -23,6 +26,23 @@ module Belpost
23
26
  )
24
27
  end
25
28
 
29
+ # Creates a new batch mailing by sending a POST request to the API.
30
+ #
31
+ # @param batch_data [Hash] The data for the batch mailing.
32
+ # @return [Hash] The parsed JSON response from the API.
33
+ # @raise [Belpost::InvalidRequestError] If the request data is invalid.
34
+ # @raise [Belpost::ApiError] If the API returns an error response.
35
+ def create_batch(batch_data)
36
+ validation_result = Validation::BatchSchema.new.call(batch_data)
37
+ unless validation_result.success?
38
+ raise ValidationError, "Invalid batch data: #{validation_result.errors.to_h}"
39
+ end
40
+
41
+ batch = Models::Batch.new(batch_data)
42
+ response = @api_service.post(ApiPaths::BATCH_MAILING_LIST, batch.to_h)
43
+ response.to_h
44
+ end
45
+
26
46
  # Creates a new postal parcel by sending a POST request to the API.
27
47
  #
28
48
  # @param parcel_data [Hash] The data for the postal parcel.
@@ -36,7 +56,7 @@ module Belpost
36
56
  end
37
57
 
38
58
  parcel = Models::Parcel.new(parcel_data)
39
- response = @api_service.post("/api/v1/business/postal-deliveries", parcel.to_h)
59
+ response = @api_service.post(ApiPaths::POSTAL_DELIVERIES, parcel.to_h)
40
60
  response.to_h
41
61
  end
42
62
 
@@ -45,7 +65,7 @@ module Belpost
45
65
  # @return [Array<Hash>] The HS codes tree as an array of hashes.
46
66
  # @raise [Belpost::ApiError] If the API returns an error response.
47
67
  def fetch_hs_codes
48
- response = @api_service.get("/api/v1/business/postal-deliveries/hs-codes/list")
68
+ response = @api_service.get(ApiPaths::POSTAL_DELIVERIES_HS_CODES)
49
69
  response.to_h
50
70
  end
51
71
 
@@ -56,7 +76,7 @@ module Belpost
56
76
  # @raise [Belpost::ApiError] If the API returns an error response.
57
77
  def validate_postal_delivery(country_code)
58
78
  country_code = country_code.upcase
59
- response = @api_service.get("/api/v1/business/postal-deliveries/validation/#{country_code}")
79
+ response = @api_service.get("#{ApiPaths::POSTAL_DELIVERIES_VALIDATION}/#{country_code}")
60
80
  response.to_h
61
81
  end
62
82
 
@@ -65,7 +85,20 @@ module Belpost
65
85
  # @return [Hash] The parsed JSON response containing available countries.
66
86
  # @raise [Belpost::ApiError] If the API returns an error response.
67
87
  def fetch_available_countries
68
- response = @api_service.get("/api/v1/business/postal-deliveries/countries")
88
+ response = @api_service.get(ApiPaths::POSTAL_DELIVERIES_COUNTRIES)
89
+ response.to_h
90
+ end
91
+
92
+ # Finds a batch by its ID.
93
+ #
94
+ # @param id [Integer] The ID of the batch to find.
95
+ # @return [Hash] The batch data if found.
96
+ # @raise [Belpost::ApiError] If the API returns an error response.
97
+ def find_batch_by_id(id)
98
+ raise ValidationError, "ID must be provided" if id.nil?
99
+ raise ValidationError, "ID must be a positive integer" unless id.is_a?(Integer) && id.positive?
100
+
101
+ response = @api_service.get("#{ApiPaths::BATCH_MAILING_LIST}/#{id}")
69
102
  response.to_h
70
103
  end
71
104
 
@@ -86,7 +119,7 @@ module Belpost
86
119
  raise ValidationError, "Address must be filled" if address.empty?
87
120
 
88
121
  formatted_address = format_address(address)
89
- response = @api_service.get("/api/v1/business/geo-directory/search-address", { search: formatted_address })
122
+ response = @api_service.get(ApiPaths::GEO_DIRECTORY_SEARCH_ADDRESS, { search: formatted_address })
90
123
  response.to_h
91
124
  end
92
125
 
@@ -113,7 +146,7 @@ module Belpost
113
146
  params[:building] = format_building_number(building) if building
114
147
  params[:limit] = limit
115
148
 
116
- response = @api_service.get("/api/v1/business/geo-directory/postcode", params)
149
+ response = @api_service.get(ApiPaths::GEO_DIRECTORY_POSTCODE, params)
117
150
  response.to_h
118
151
  end
119
152
 
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Belpost
4
+ module Models
5
+ # Model class for batch mailing
6
+ class Batch
7
+ attr_reader :postal_delivery_type, :direction, :payment_type, :negotiated_rate,
8
+ :name, :card_number, :postal_items_in_ops, :category, :is_document,
9
+ :is_declared_value, :is_partial_receipt
10
+
11
+ def initialize(data)
12
+ @postal_delivery_type = data[:postal_delivery_type]
13
+ @direction = data[:direction]
14
+ @payment_type = data[:payment_type]
15
+ @negotiated_rate = data[:negotiated_rate]
16
+ @name = data[:name]
17
+ @card_number = data[:card_number]
18
+ @postal_items_in_ops = data[:postal_items_in_ops]
19
+ @category = data[:category]
20
+ @is_document = data[:is_document]
21
+ @is_declared_value = data[:is_declared_value]
22
+ @is_partial_receipt = data[:is_partial_receipt]
23
+ end
24
+
25
+ def to_h
26
+ {
27
+ postal_delivery_type: @postal_delivery_type,
28
+ direction: @direction,
29
+ payment_type: @payment_type,
30
+ negotiated_rate: @negotiated_rate,
31
+ name: @name,
32
+ card_number: @card_number,
33
+ postal_items_in_ops: @postal_items_in_ops,
34
+ category: @category,
35
+ is_document: @is_document,
36
+ is_declared_value: @is_declared_value,
37
+ is_partial_receipt: @is_partial_receipt
38
+ }.compact
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry-validation"
4
+
5
+ module Belpost
6
+ module Validation
7
+ # Schema for validating batch mailing data
8
+ class BatchSchema < Dry::Validation::Contract
9
+ params do
10
+ required(:postal_delivery_type).filled(:str?).value(
11
+ included_in?: %w[
12
+ ordered_small_package
13
+ letter_declare_value
14
+ package
15
+ ems
16
+ ordered_parcel_post
17
+ ordered_letter
18
+ ordered_postcard
19
+ small_package_declare_value
20
+ package_declare_value
21
+ ecommerce_economical
22
+ ecommerce_standard
23
+ ecommerce_elite
24
+ ecommerce_express
25
+ ecommerce_light
26
+ ecommerce_optima
27
+ ]
28
+ )
29
+
30
+ required(:direction).filled(:str?).value(
31
+ included_in?: %w[internal CIS international]
32
+ )
33
+
34
+ required(:payment_type).filled(:str?).value(
35
+ included_in?: %w[
36
+ not_specified
37
+ cash
38
+ payment_order
39
+ electronic_personal_account
40
+ 4
41
+ 5
42
+ commitment_letter
43
+ ]
44
+ )
45
+
46
+ required(:negotiated_rate).filled(:bool?)
47
+
48
+ optional(:name).maybe(:str?)
49
+ optional(:card_number).maybe(:str?)
50
+ optional(:postal_items_in_ops).maybe(:bool?)
51
+ optional(:category).maybe(:int?)
52
+ optional(:is_document).maybe(:bool?)
53
+ optional(:is_declared_value).maybe(:bool?)
54
+ optional(:is_partial_receipt).maybe(:bool?)
55
+ end
56
+ end
57
+ end
58
+ end
@@ -1,154 +1,172 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "dry/schema"
3
+ require "dry-validation"
4
4
 
5
5
  module Belpost
6
6
  # rubocop:disable Metrics/ModuleLength
7
7
  module Validation
8
8
  # Validation schema for parcel_data
9
9
  # rubocop:disable Metrics/BlockLength
10
- ParcelSchema = Dry::Schema.JSON do
11
- required(:parcel).hash do
12
- required(:type).filled(:string, included_in?: %w[package small_package small_valued_package ems])
13
- required(:attachment_type).filled(:string, included_in?: %w[products documents])
14
- required(:measures).hash do
15
- required(:weight).filled(:integer, gt?: 0)
16
- optional(:long).value(:integer, gt?: 0)
17
- optional(:width).value(:integer, gt?: 0)
18
- optional(:height).value(:integer, gt?: 0)
19
- end
20
- required(:departure).hash do
21
- required(:country).filled(:string, eql?: "BY")
22
- required(:place).filled(:string, included_in?: %w[post_office])
23
- optional(:place_uuid).maybe(:string)
24
- end
25
- required(:arrival).hash do
26
- required(:country).filled(:string)
27
- required(:place).filled(:string, included_in?: %w[post_office])
28
- optional(:place_uuid).maybe(:string)
10
+ class ParcelSchema < Dry::Validation::Contract
11
+ params do
12
+ required(:parcel).hash do
13
+ required(:type).filled(:string, included_in?: %w[package small_package small_valued_package ems])
14
+ required(:attachment_type).filled(:string, included_in?: %w[products documents])
15
+ required(:measures).hash do
16
+ required(:weight).filled(:integer, gt?: 0)
17
+ optional(:long).value(:integer, gt?: 0)
18
+ optional(:width).value(:integer, gt?: 0)
19
+ optional(:height).value(:integer, gt?: 0)
20
+ end
21
+ required(:departure).hash do
22
+ required(:country).filled(:string, eql?: "BY")
23
+ required(:place).filled(:string, included_in?: %w[post_office])
24
+ optional(:place_uuid).maybe(:string)
25
+ end
26
+ required(:arrival).hash do
27
+ required(:country).filled(:string)
28
+ required(:place).filled(:string, included_in?: %w[post_office])
29
+ optional(:place_uuid).maybe(:string)
30
+ end
31
+ optional(:s10code).maybe(:string)
29
32
  end
30
- optional(:s10code).maybe(:string)
31
- end
32
33
 
33
- optional(:addons).hash do
34
- optional(:cash_on_delivery).maybe(:hash) do
35
- required(:currency).filled(:string, eql?: "BYN")
36
- required(:value).filled(:float, gt?: 0)
37
- end
38
- optional(:declared_value).maybe(:hash) do
39
- required(:currency).filled(:string, eql?: "BYN")
40
- required(:value).filled(:float, gt?: 0)
41
- end
42
- optional(:IOSS).maybe(:string)
43
- optional(:registered_notification).maybe(:string)
44
- optional(:simple_notification).maybe(:bool)
45
- optional(:sms_notification).maybe(:bool)
46
- optional(:email_notification).maybe(:bool)
47
- optional(:priority_parcel).maybe(:bool)
48
- optional(:attachment_inventory).maybe(:bool)
49
- optional(:paid_shipping).maybe(:bool)
50
- optional(:careful_fragile).maybe(:bool)
51
- optional(:bulky).maybe(:bool)
52
- optional(:ponderous).maybe(:bool)
53
- optional(:payment_upon_receipt).maybe(:bool)
54
- optional(:hand_over_personally).maybe(:bool)
55
- optional(:return_of_documents).maybe(:bool)
56
- optional(:open_upon_delivery).maybe(:bool)
57
- optional(:delivery_to_work).maybe(:bool)
58
- optional(:time_of_delivery).maybe(:hash) do
59
- required(:type).filled(:string, included_in?: %w[level1 level2 level3 level4])
60
- optional(:time_interval).hash do
61
- required(:from).filled(:string)
62
- required(:to).filled(:string)
34
+ optional(:addons).hash do
35
+ optional(:cash_on_delivery).maybe(:hash) do
36
+ required(:currency).filled(:string, eql?: "BYN")
37
+ required(:value).filled(:float, gt?: 0)
38
+ end
39
+ optional(:declared_value).maybe(:hash) do
40
+ required(:currency).filled(:string, eql?: "BYN")
41
+ required(:value).filled(:float, gt?: 0)
42
+ end
43
+ optional(:IOSS).maybe(:string)
44
+ optional(:registered_notification).maybe(:string)
45
+ optional(:simple_notification).maybe(:bool)
46
+ optional(:sms_notification).maybe(:bool)
47
+ optional(:email_notification).maybe(:bool)
48
+ optional(:priority_parcel).maybe(:bool)
49
+ optional(:attachment_inventory).maybe(:bool)
50
+ optional(:paid_shipping).maybe(:bool)
51
+ optional(:careful_fragile).maybe(:bool)
52
+ optional(:bulky).maybe(:bool)
53
+ optional(:ponderous).maybe(:bool)
54
+ optional(:payment_upon_receipt).maybe(:bool)
55
+ optional(:hand_over_personally).maybe(:bool)
56
+ optional(:return_of_documents).maybe(:bool)
57
+ optional(:open_upon_delivery).maybe(:bool)
58
+ optional(:delivery_to_work).maybe(:bool)
59
+ optional(:time_of_delivery).maybe(:hash) do
60
+ required(:type).filled(:string, included_in?: %w[level1 level2 level3 level4])
61
+ optional(:time_interval).hash do
62
+ required(:from).filled(:string)
63
+ required(:to).filled(:string)
64
+ end
63
65
  end
64
66
  end
65
- end
66
67
 
67
- required(:sender).hash do
68
- required(:type).filled(:string, included_in?: %w[legal_person sole_proprietor])
69
- required(:info).hash do
70
- required(:organization_name).filled(:string)
71
- optional(:taxpayer_number).maybe(:string)
72
- optional(:bank).maybe(:string)
73
- optional(:IBAN).maybe(:string)
74
- optional(:BIC).maybe(:string)
75
- end
76
- required(:location).hash do
77
- required(:code).filled(:string)
78
- required(:region).filled(:string)
79
- required(:district).filled(:string)
80
- required(:locality).hash do
81
- required(:type).filled(:string)
82
- required(:name).filled(:string)
68
+ optional(:sender).hash do
69
+ required(:type).filled(:string, included_in?: %w[legal_person natural_person])
70
+ required(:info).hash do
71
+ optional(:organization_name).maybe(:string)
72
+ optional(:taxpayer_number).maybe(:string)
73
+ optional(:IBAN).maybe(:string)
74
+ optional(:BIC).maybe(:string)
75
+ optional(:bank).maybe(:string)
76
+ optional(:first_name).maybe(:string)
77
+ optional(:second_name).maybe(:string)
78
+ optional(:last_name).maybe(:string)
83
79
  end
84
- required(:road).hash do
85
- required(:type).filled(:string)
86
- required(:name).filled(:string)
80
+ required(:location).hash do
81
+ required(:code).filled(:string)
82
+ required(:region).filled(:string)
83
+ required(:district).filled(:string)
84
+ required(:locality).hash do
85
+ required(:type).filled(:string)
86
+ required(:name).filled(:string)
87
+ end
88
+ required(:road).hash do
89
+ required(:type).filled(:string)
90
+ required(:name).filled(:string)
91
+ end
92
+ required(:building).filled(:string)
93
+ optional(:housing).maybe(:string)
94
+ optional(:apartment).maybe(:string)
87
95
  end
88
- required(:building).filled(:string)
89
- optional(:housing).maybe(:string)
90
- optional(:apartment).maybe(:string)
96
+ optional(:email).maybe(:string)
97
+ optional(:phone).maybe(:string)
91
98
  end
92
- required(:email).filled(:string)
93
- required(:phone).filled(:string)
94
- end
95
99
 
96
- required(:recipient).hash do
97
- required(:type).filled(:string, included_in?: %w[natural_person legal_person sole_proprietor])
98
- required(:info).hash do
99
- optional(:organization_name).maybe(:string)
100
- optional(:first_name).maybe(:string)
101
- optional(:second_name).maybe(:string)
102
- optional(:last_name).maybe(:string)
103
- end
104
- required(:location).hash do
105
- optional(:code).maybe(:string)
106
- optional(:region).maybe(:string)
107
- optional(:district).maybe(:string)
108
- optional(:locality).maybe(:hash) do
109
- optional(:type).maybe(:string)
110
- optional(:name).maybe(:string)
100
+ optional(:recipient).hash do
101
+ required(:type).filled(:string, included_in?: %w[legal_person natural_person])
102
+ required(:info).hash do
103
+ optional(:organization_name).maybe(:string)
104
+ optional(:taxpayer_number).maybe(:string)
105
+ optional(:IBAN).maybe(:string)
106
+ optional(:BIC).maybe(:string)
107
+ optional(:bank).maybe(:string)
108
+ optional(:first_name).maybe(:string)
109
+ optional(:second_name).maybe(:string)
110
+ optional(:last_name).maybe(:string)
111
111
  end
112
- optional(:road).maybe(:hash) do
113
- optional(:type).maybe(:string)
114
- optional(:name).maybe(:string)
112
+ required(:location).hash do
113
+ required(:code).filled(:string)
114
+ required(:region).filled(:string)
115
+ required(:district).filled(:string)
116
+ required(:locality).hash do
117
+ required(:type).filled(:string)
118
+ required(:name).filled(:string)
119
+ end
120
+ required(:road).hash do
121
+ required(:type).filled(:string)
122
+ required(:name).filled(:string)
123
+ end
124
+ required(:building).filled(:string)
125
+ optional(:housing).maybe(:string)
126
+ optional(:apartment).maybe(:string)
115
127
  end
116
- optional(:building).maybe(:string)
117
- optional(:housing).maybe(:string)
118
- optional(:apartment).maybe(:string)
119
- optional(:address).maybe(:string)
128
+ optional(:email).maybe(:string)
129
+ optional(:phone).maybe(:string)
120
130
  end
121
- optional(:email).maybe(:string)
122
- required(:phone).filled(:string)
123
- end
124
131
 
125
- optional(:cp72).hash do
126
- optional(:items).array(:hash) do
127
- required(:name).filled(:string)
128
- required(:local).filled(:string)
129
- required(:unit).hash do
132
+ optional(:cp72).hash do
133
+ optional(:items).array(:hash) do
134
+ required(:name).filled(:string)
130
135
  required(:local).filled(:string)
131
- required(:en).filled(:string)
136
+ required(:unit).hash do
137
+ required(:local).filled(:string)
138
+ required(:en).filled(:string)
139
+ end
140
+ required(:count).filled(:integer, gt?: 0)
141
+ required(:weight).filled(:integer, gt?: 0)
142
+ required(:price).hash do
143
+ required(:currency).filled(:string)
144
+ required(:value).filled(:float, gt?: 0)
145
+ end
146
+ optional(:code).maybe(:string)
147
+ optional(:country).maybe(:string)
132
148
  end
133
- required(:count).filled(:integer, gt?: 0)
134
- required(:weight).filled(:integer, gt?: 0)
135
- required(:price).hash do
149
+ optional(:price).hash do
136
150
  required(:currency).filled(:string)
137
151
  required(:value).filled(:float, gt?: 0)
138
152
  end
139
- optional(:code).maybe(:string)
140
- optional(:country).maybe(:string)
141
- end
142
- optional(:price).hash do
143
- required(:currency).filled(:string)
144
- required(:value).filled(:float, gt?: 0)
153
+ optional(:category).filled(:string, included_in?: %w[gift documents sample returned_goods merchandise other])
154
+ optional(:explanation).maybe(:string)
155
+ optional(:comments).maybe(:string)
156
+ optional(:invoice).maybe(:string)
157
+ optional(:licences).array(:string)
158
+ optional(:certificates).array(:string)
145
159
  end
146
- optional(:category).filled(:string, included_in?: %w[gift documents sample returned_goods merchandise other])
147
- optional(:explanation).maybe(:string)
148
- optional(:comments).maybe(:string)
149
- optional(:invoice).maybe(:string)
150
- optional(:licences).array(:string)
151
- optional(:certificates).array(:string)
160
+ end
161
+
162
+ # Add class method to make it compatible with the tests
163
+ def self.call(params)
164
+ new.call(params)
165
+ end
166
+
167
+ # Add validation rule for organization_name when sender type is legal_person
168
+ rule('sender.info.organization_name') do
169
+ key.failure('must be filled') if values[:sender] && values[:sender][:type] == 'legal_person' && !values.dig(:sender, :info, :organization_name)
152
170
  end
153
171
  end
154
172
  # rubocop:enable Metrics/BlockLength
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Belpost
4
- VERSION = "0.7.0"
4
+ VERSION = "0.9.0"
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: belpost
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - KuberLite
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-04-01 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: dotenv
@@ -37,6 +37,20 @@ dependencies:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
39
  version: '1.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: dry-schema
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1.0'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1.0'
40
54
  description: Gem for working with the 'Belpost' delivery service via API
41
55
  email:
42
56
  - kuberlite@gmail.com
@@ -55,16 +69,19 @@ files:
55
69
  - Rakefile
56
70
  - belpost.gemspec
57
71
  - lib/belpost.rb
72
+ - lib/belpost/api_paths.rb
58
73
  - lib/belpost/api_service.rb
59
74
  - lib/belpost/client.rb
60
75
  - lib/belpost/configuration.rb
61
76
  - lib/belpost/errors.rb
62
77
  - lib/belpost/models/api_response.rb
78
+ - lib/belpost/models/batch.rb
63
79
  - lib/belpost/models/customs_declaration.rb
64
80
  - lib/belpost/models/parcel.rb
65
81
  - lib/belpost/models/parcel_builder.rb
66
82
  - lib/belpost/retry.rb
67
83
  - lib/belpost/validations/address_schema.rb
84
+ - lib/belpost/validations/batch_schema.rb
68
85
  - lib/belpost/validations/parcel_schema.rb
69
86
  - lib/belpost/version.rb
70
87
  homepage: https://github.com/KuberLite/belpost
@@ -90,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
90
107
  - !ruby/object:Gem::Version
91
108
  version: '0'
92
109
  requirements: []
93
- rubygems_version: 3.6.2
110
+ rubygems_version: 3.6.7
94
111
  specification_version: 4
95
112
  summary: Belpost API wrapper
96
113
  test_files: []