econt 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 (87) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +3 -0
  3. data/CODE_OF_CONDUCT.md +17 -0
  4. data/CONTRIBUTING.md +37 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +171 -0
  7. data/SECURITY.md +33 -0
  8. data/docs/API.md +571 -0
  9. data/docs/ENDPOINTS.md +42 -0
  10. data/docs/PUBLIC_API.md +81 -0
  11. data/docs/RELEASING.md +35 -0
  12. data/docs/RESPONSE_TESTS.md +46 -0
  13. data/docs/VCR.md +144 -0
  14. data/lib/econt/camel_case_middleware.rb +88 -0
  15. data/lib/econt/client.rb +99 -0
  16. data/lib/econt/collection.rb +59 -0
  17. data/lib/econt/error.rb +42 -0
  18. data/lib/econt/meta_resource.rb +6 -0
  19. data/lib/econt/model.rb +95 -0
  20. data/lib/econt/models/error.rb +53 -0
  21. data/lib/econt/models/hosted_file.rb +13 -0
  22. data/lib/econt/models/nomenclatures/address.rb +35 -0
  23. data/lib/econt/models/nomenclatures/address_service_info.rb +16 -0
  24. data/lib/econt/models/nomenclatures/address_service_times_response.rb +19 -0
  25. data/lib/econt/models/nomenclatures/address_validation_response.rb +19 -0
  26. data/lib/econt/models/nomenclatures/city.rb +32 -0
  27. data/lib/econt/models/nomenclatures/country.rb +16 -0
  28. data/lib/econt/models/nomenclatures/geo_location.rb +13 -0
  29. data/lib/econt/models/nomenclatures/office.rb +32 -0
  30. data/lib/econt/models/nomenclatures/quarter.rb +14 -0
  31. data/lib/econt/models/nomenclatures/serving_office_element.rb +12 -0
  32. data/lib/econt/models/nomenclatures/street.rb +14 -0
  33. data/lib/econt/models/nomenclatures/working_date_time.rb +16 -0
  34. data/lib/econt/models/nomenclatures/working_time.rb +12 -0
  35. data/lib/econt/models/payment_report/payment_report_row.rb +17 -0
  36. data/lib/econt/models/profile/cd_pay_options.rb +24 -0
  37. data/lib/econt/models/profile/client_profile.rb +29 -0
  38. data/lib/econt/models/profile/profiles_response_element.rb +16 -0
  39. data/lib/econt/models/shipments/cargo_vehicle_options.rb +16 -0
  40. data/lib/econt/models/shipments/check_possible_shipment_editions_result_element.rb +14 -0
  41. data/lib/econt/models/shipments/create_label_result_element.rb +19 -0
  42. data/lib/econt/models/shipments/customs_list_element.rb +14 -0
  43. data/lib/econt/models/shipments/delete_labels_result_element.rb +14 -0
  44. data/lib/econt/models/shipments/get_my_awb_response.rb +15 -0
  45. data/lib/econt/models/shipments/get_my_awb_result_element.rb +23 -0
  46. data/lib/econt/models/shipments/instruction.rb +20 -0
  47. data/lib/econt/models/shipments/next_shipment_element.rb +13 -0
  48. data/lib/econt/models/shipments/pack_element.rb +14 -0
  49. data/lib/econt/models/shipments/packing_list_element.rb +17 -0
  50. data/lib/econt/models/shipments/payment_addition_price.rb +14 -0
  51. data/lib/econt/models/shipments/payment_instruction.rb +11 -0
  52. data/lib/econt/models/shipments/previous_shipment.rb +14 -0
  53. data/lib/econt/models/shipments/request_courier_response.rb +13 -0
  54. data/lib/econt/models/shipments/request_courier_status.rb +14 -0
  55. data/lib/econt/models/shipments/request_courier_status_result_element.rb +14 -0
  56. data/lib/econt/models/shipments/return_instruction_params.rb +48 -0
  57. data/lib/econt/models/shipments/shipment_edition_response_element.rb +16 -0
  58. data/lib/econt/models/shipments/shipment_status.rb +64 -0
  59. data/lib/econt/models/shipments/shipment_status_result_element.rb +14 -0
  60. data/lib/econt/models/shipments/shipment_status_service.rb +16 -0
  61. data/lib/econt/models/shipments/shipment_tracking_event.rb +21 -0
  62. data/lib/econt/models/shipments/shipping_label.rb +59 -0
  63. data/lib/econt/models/shipments/shipping_label_services.rb +37 -0
  64. data/lib/econt/models/shipments/status_response.rb +11 -0
  65. data/lib/econt/models/shipments/update_label_response.rb +11 -0
  66. data/lib/econt/models/shipments/update_labels_result_element.rb +14 -0
  67. data/lib/econt/models/three_way_logistics/three_way_logistics.rb +50 -0
  68. data/lib/econt/models/three_way_logistics/three_way_logistics_response.rb +11 -0
  69. data/lib/econt/resource_attributes.rb +69 -0
  70. data/lib/econt/service_resource.rb +105 -0
  71. data/lib/econt/services/nomenclatures/address.rb +87 -0
  72. data/lib/econt/services/nomenclatures/nomenclatures.rb +122 -0
  73. data/lib/econt/services/nomenclatures.rb +11 -0
  74. data/lib/econt/services/payment_report/payment_report.rb +35 -0
  75. data/lib/econt/services/payment_report.rb +11 -0
  76. data/lib/econt/services/profile/profile.rb +45 -0
  77. data/lib/econt/services/profile.rb +11 -0
  78. data/lib/econt/services/shipments/label.rb +174 -0
  79. data/lib/econt/services/shipments/shipment.rb +109 -0
  80. data/lib/econt/services/shipments.rb +11 -0
  81. data/lib/econt/services/three_way_logistics/three_way_logistics.rb +30 -0
  82. data/lib/econt/services/three_way_logistics.rb +11 -0
  83. data/lib/econt/util.rb +63 -0
  84. data/lib/econt/version.rb +5 -0
  85. data/lib/econt.rb +118 -0
  86. data/sig/econt.rbs +465 -0
  87. metadata +166 -0
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module Nomenclatures
6
+ class Nomenclatures < ServiceResource
7
+ include Econt::Services::Nomenclatures
8
+
9
+ # List countries available for delivery.
10
+ # @note Read. Does not change shipment state.
11
+ # @return [Econt::Collection<Econt::Models::Nomenclatures::Country>]
12
+ # Check #error? before using data.
13
+ # @raise [Econt::Error] On HTTP failure.
14
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
15
+ # @see file:docs/API.md#get_countries Ruby usage and parameters
16
+ # @example After configuring Econt::Client
17
+ # nomenclatures = Econt::Services::Nomenclatures::Nomenclatures.new
18
+ # countries = nomenclatures.get_countries
19
+ def get_countries
20
+ response = post('getCountries')
21
+ collection(response, Econt::Models::Nomenclatures::Country)
22
+ # http://ee.econt.com/services/Nomenclatures/NomenclaturesService.getCountries.json(.soap?wsdl)
23
+ end
24
+
25
+ # List cities for a country.
26
+ # @note Read. Does not change shipment state.
27
+ # @param country_code [String] ISO country code, such as BGR.
28
+ # @return [Econt::Collection<Econt::Models::Nomenclatures::City>]
29
+ # Check #error? before using data.
30
+ # @raise [Econt::Error] On HTTP failure.
31
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
32
+ # @see file:docs/API.md#get_cities Ruby usage and parameters
33
+ # @example After configuring Econt::Client
34
+ # nomenclatures = Econt::Services::Nomenclatures::Nomenclatures.new
35
+ # cities = nomenclatures.get_cities(country_code: 'BGR')
36
+ def get_cities(country_code:)
37
+ response = post('getCities', body: { country_code: country_code })
38
+ collection(response, Econt::Models::Nomenclatures::City)
39
+ # http://ee.econt.com/services/Nomenclatures/NomenclaturesService.getCities.json(.soap?wsdl)
40
+ end
41
+
42
+ # Fetch cities and derive unique, sorted region names; this is a local helper, not a separate endpoint.
43
+ # @note Read. Does not change shipment state.
44
+ # @param country_code [String] Country code.
45
+ # @param language [String, nil] Only en selects English names; nil and other values select native names.
46
+ # @return [Array<String>] Unique, sorted region names; no #error? reader.
47
+ # @raise [Econt::Error] On HTTP failure.
48
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
49
+ # @see file:docs/API.md#get_regions Ruby usage and parameters
50
+ # @example After configuring Econt::Client
51
+ # nomenclatures = Econt::Services::Nomenclatures::Nomenclatures.new
52
+ # regions = nomenclatures.get_regions(country_code: 'BGR', language: 'en')
53
+ def get_regions(country_code:, language: nil)
54
+ region_field = language.to_s.casecmp('en').zero? ? :region_name_en : :region_name
55
+ cities = get_cities(country_code: country_code)
56
+ cities.filter_map { |city| city.send(region_field) }.uniq.sort
57
+ end
58
+
59
+ # List offices with optional city and reception filters.
60
+ # @note Read. Does not change shipment state.
61
+ # @param country_code [String] Country code.
62
+ # @param city_id [Integer, nil] City identifier.
63
+ # @param show_cargo_receptions [Boolean, nil] Include cargo receptions.
64
+ # @param show_lc [Boolean, nil] Carrier LC filter.
65
+ # @param serving_receptions [Boolean, nil] Carrier serving-reception filter.
66
+ # @return [Econt::Collection<Econt::Models::Nomenclatures::Office>]
67
+ # Check #error? before using data.
68
+ # @raise [Econt::Error] On HTTP failure.
69
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
70
+ # @see file:docs/API.md#get_offices Ruby usage and parameters
71
+ # @example After configuring Econt::Client
72
+ # nomenclatures = Econt::Services::Nomenclatures::Nomenclatures.new
73
+ # offices = nomenclatures.get_offices(country_code: 'BGR', city_id: 41)
74
+ def get_offices(country_code:, city_id: nil, show_cargo_receptions: nil, show_lc: nil, serving_receptions: nil)
75
+ response = post('getOffices', body: {
76
+ country_code: country_code,
77
+ city_id: city_id,
78
+ show_cargo_receptions: show_cargo_receptions,
79
+ show_lc: show_lc,
80
+ serving_receptions: serving_receptions
81
+ })
82
+ collection(response, Econt::Models::Nomenclatures::Office)
83
+ # http://ee.econt.com/services/Nomenclatures/NomenclaturesService.getOffices.json(.soap?wsdl)
84
+ end
85
+
86
+ # List streets, optionally restricted to a city.
87
+ # @note Read. Does not change shipment state.
88
+ # @param city_id [Integer, nil] City identifier.
89
+ # @return [Econt::Collection<Econt::Models::Nomenclatures::Street>]
90
+ # Check #error? before using data.
91
+ # @raise [Econt::Error] On HTTP failure.
92
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
93
+ # @see file:docs/API.md#get_streets Ruby usage and parameters
94
+ # @example After configuring Econt::Client
95
+ # nomenclatures = Econt::Services::Nomenclatures::Nomenclatures.new
96
+ # streets = nomenclatures.get_streets(city_id: 41)
97
+ def get_streets(city_id: nil)
98
+ response = post('getStreets', body: { city_id: city_id })
99
+ collection(response, Econt::Models::Nomenclatures::Street)
100
+ # http://ee.econt.com/services/Nomenclatures/NomenclaturesService.getStreets.json(.soap?wsdl)
101
+ end
102
+
103
+ # List quarters, optionally restricted to a city.
104
+ # @note Read. Does not change shipment state.
105
+ # @param city_id [Integer, nil] City identifier.
106
+ # @return [Econt::Collection<Econt::Models::Nomenclatures::Quarter>]
107
+ # Check #error? before using data.
108
+ # @raise [Econt::Error] On HTTP failure.
109
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
110
+ # @see file:docs/API.md#get_quarters Ruby usage and parameters
111
+ # @example After configuring Econt::Client
112
+ # nomenclatures = Econt::Services::Nomenclatures::Nomenclatures.new
113
+ # quarters = nomenclatures.get_quarters(city_id: 41)
114
+ def get_quarters(city_id: nil)
115
+ response = post('getQuarters', body: { city_id: city_id })
116
+ collection(response, Econt::Models::Nomenclatures::Quarter)
117
+ # http://ee.econt.com/services/Nomenclatures/NomenclaturesService.getQuarters.json(.soap?wsdl)
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module Nomenclatures
6
+ def service_url
7
+ 'Nomenclatures'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module PaymentReport
6
+ class PaymentReport < ServiceResource
7
+ include Econt::Services::PaymentReport
8
+
9
+ # POST /services/PaymentReport/PaymentReportService.PaymentReport.json(.soap?wsdl)
10
+ # Read payment reports for an optional date range.
11
+ # @note Read. Does not change shipment state.
12
+ # @param date_to [String, nil] End date in carrier format.
13
+ # @param date_from [String, nil] Start date in carrier format.
14
+ # @return [Econt::Collection, Econt::Models::PaymentReport::PaymentReportRow]
15
+ # Check #error? before using data.
16
+ # @raise [Econt::Error] On HTTP failure.
17
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
18
+ # @see file:docs/API.md#payment_report Ruby usage and parameters
19
+ # @example After configuring Econt::Client
20
+ # reports = Econt::Services::PaymentReport::PaymentReport.new
21
+ # rows = reports.payment_report(date_from: '2026-10-01', date_to: '2026-10-12')
22
+ # rows = rows.is_a?(Econt::Collection) ? rows.to_a : [rows]
23
+ def payment_report(date_to: nil, date_from: nil)
24
+ response = post('PaymentReport', body: { date_to:, date_from: })
25
+ if response.body.is_a?(Hash) && response.body.key?('PaymentReportRows')
26
+ return Econt::Collection.new(response.body, model: Econt::Models::PaymentReport::PaymentReportRow,
27
+ key: :payment_report_rows)
28
+ end
29
+
30
+ resource(response, Econt::Models::PaymentReport::PaymentReportRow)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module PaymentReport
6
+ def service_url
7
+ 'PaymentReport'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module Profile
6
+ class Profile < ServiceResource
7
+ include Econt::Services::Profile
8
+
9
+ resource_type 'Profile'
10
+
11
+ # POST /services/Profile/ProfileService.getClientProfiles.json(.soap?wsdl)
12
+ # Read account client profiles and payment settings.
13
+ # @note Read. Does not change shipment state.
14
+ # @return [Econt::Collection<Econt::Models::Profile::ProfilesResponseElement>]
15
+ # Check #error? before using data.
16
+ # @raise [Econt::Error] On HTTP failure.
17
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
18
+ # @see file:docs/API.md#get_client_profiles Ruby usage and parameters
19
+ # @example After configuring Econt::Client
20
+ # profiles = Econt::Services::Profile::Profile.new
21
+ # clients = profiles.get_client_profiles
22
+ def get_client_profiles
23
+ response = post('getClientProfiles')
24
+ collection(response, Econt::Models::Profile::ProfilesResponseElement)
25
+ end
26
+
27
+ # POST /services/Profile/ProfileService.createCDAgreement.json(.soap?wsdl)
28
+ # Create a cash-on-delivery payment agreement.
29
+ # @note Mutation. Review account permissions and cleanup before calling.
30
+ # @param cd_pay_options [Hash] CDPayOptions payload; account eligibility is carrier-controlled.
31
+ # @return [Econt::Models::Profile::CDPayOptions] Typed result; inspect #error? before using data.
32
+ # @raise [Econt::Error] On HTTP failure.
33
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
34
+ # @see file:docs/API.md#create_cd_agreement Ruby usage and parameters
35
+ # @example After configuring Econt::Client
36
+ # profiles = Econt::Services::Profile::Profile.new
37
+ # agreement = profiles.create_cd_agreement(cd_pay_options: cd_pay_options_payload)
38
+ def create_cd_agreement(cd_pay_options:)
39
+ response = post('createCDAgreement', body: { cd_pay_options: cd_pay_options })
40
+ resource(response, Econt::Models::Profile::CDPayOptions, key: :cd_pay_options)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module Profile
6
+ def service_url
7
+ 'Profile'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,174 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module Shipments
6
+ class Label < ServiceResource
7
+ include Econt::Services::Shipments
8
+
9
+ resource_type 'Label'
10
+
11
+ # POST /services/Shipments/LabelService.createLabel.json(.soap?wsdl)
12
+ # Calculate, validate, or create one shipping label.
13
+ # @note Conditional mutation. Review account permissions and cleanup before calling.
14
+ # @param label [Hash, nil] Shipping-label payload.
15
+ # @param request_courier_time_from [String, nil] Requested courier window start.
16
+ # @param request_courier_time_to [String, nil] Requested courier window end.
17
+ # @param mode [String, nil] calculate or validate are non-mutating; create and calculate_with_block have
18
+ # effects. Always choose explicitly.
19
+ # @return [Econt::Models::Shipments::CreateLabelResultElement] Typed result; inspect #error? before using data.
20
+ # @raise [Econt::Error] On HTTP failure.
21
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
22
+ # @see file:docs/API.md#create_label Ruby usage and parameters
23
+ # @example After configuring Econt::Client
24
+ # labels = Econt::Services::Shipments::Label.new
25
+ # quote = labels.create_label(label: label_payload, mode: 'calculate')
26
+ def create_label(label: nil, request_courier_time_from: nil, request_courier_time_to: nil, mode: nil)
27
+ response = post('createLabel', body: {
28
+ label: label,
29
+ request_courier_time_from: request_courier_time_from,
30
+ request_courier_time_to: request_courier_time_to,
31
+ mode: mode
32
+ })
33
+ resource(response, Econt::Models::Shipments::CreateLabelResultElement)
34
+ end
35
+
36
+ # POST /services/Shipments/LabelService.createLabels.json(.soap?wsdl)
37
+ # Calculate, validate, or create a batch of labels.
38
+ # @note Conditional mutation. Review account permissions and cleanup before calling.
39
+ # @param labels [Array<Hash>] Shipping-label payloads.
40
+ # @param run_async_and_email_result_to [String, nil] Email address for asynchronous results; the returned
41
+ # data may differ.
42
+ # @param mode [String, nil] Choose calculate, validate, or create explicitly.
43
+ # @return [Econt::Collection<Econt::Models::Shipments::CreateLabelResultElement>]
44
+ # Check #error? before using data.
45
+ # @raise [Econt::Error] On HTTP failure.
46
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
47
+ # @see file:docs/API.md#create_labels Ruby usage and parameters
48
+ # @example After configuring Econt::Client
49
+ # labels = Econt::Services::Shipments::Label.new
50
+ # quotes = labels.create_labels(labels: [label_payload], mode: 'calculate')
51
+ def create_labels(labels: [], run_async_and_email_result_to: nil, mode: nil)
52
+ response = post('createLabels', body: {
53
+ labels: labels,
54
+ run_async_and_email_result_to: run_async_and_email_result_to,
55
+ mode: mode
56
+ })
57
+ collection(response, Econt::Models::Shipments::CreateLabelResultElement)
58
+ end
59
+
60
+ # POST /services/Shipments/LabelService.deleteLabels.json(.soap?wsdl)
61
+ # Delete selected labels when allowed by carrier state and account permissions.
62
+ # @note Mutation. Review account permissions and cleanup before calling.
63
+ # @param shipment_numbers [Array<String>] Numbers of labels owned by your account.
64
+ # @return [Econt::Collection<Econt::Models::Shipments::DeleteLabelsResultElement>]
65
+ # Check #error? before using data.
66
+ # @raise [Econt::Error] On HTTP failure.
67
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
68
+ # @see file:docs/API.md#delete_labels Ruby usage and parameters
69
+ # @example After configuring Econt::Client
70
+ # labels = Econt::Services::Shipments::Label.new
71
+ # deleted = labels.delete_labels(shipment_numbers: [shipment_number])
72
+ def delete_labels(shipment_numbers: [])
73
+ response = post('deleteLabels', body: { shipment_numbers: shipment_numbers })
74
+ collection(response, Econt::Models::Shipments::DeleteLabelsResultElement)
75
+ end
76
+
77
+ # POST /services/Shipments/LabelService.updateLabel.json(.soap?wsdl)
78
+ # Update or destroy an existing label.
79
+ # @note Mutation. Review account permissions and cleanup before calling.
80
+ # @param label [Hash, nil] Existing label with its shipment number and requested changes.
81
+ # @param request_courier_time_from [String, nil] Courier window start.
82
+ # @param request_courier_time_to [String, nil] Courier window end.
83
+ # @param destroy [Boolean, nil] Whether to destroy the label.
84
+ # @param payment_addition_price [Hash, nil] PaymentAdditionPrice fields.
85
+ # @param payment_instruction [Hash, nil] PaymentInstruction fields.
86
+ # @return [Econt::Models::Shipments::UpdateLabelResponse] Typed result; inspect #error? before using data.
87
+ # @raise [Econt::Error] On HTTP failure.
88
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
89
+ # @see file:docs/API.md#update_label Ruby usage and parameters
90
+ # @example After configuring Econt::Client
91
+ # labels = Econt::Services::Shipments::Label.new
92
+ # updated = labels.update_label(label: updated_label_payload, destroy: false)
93
+ def update_label(label: nil, request_courier_time_from: nil, request_courier_time_to: nil, destroy: nil,
94
+ payment_addition_price: nil, payment_instruction: nil)
95
+ response = post('updateLabel', body: {
96
+ label: label,
97
+ request_courier_time_from: request_courier_time_from,
98
+ request_courier_time_to: request_courier_time_to,
99
+ destroy: destroy,
100
+ payment_addition_price: payment_addition_price,
101
+ payment_instruction: payment_instruction
102
+ })
103
+ resource(response, Econt::Models::Shipments::UpdateLabelResponse)
104
+ end
105
+
106
+ # POST /services/Shipments/LabelService.checkPossibleShipmentEditions.json(.soap?wsdl)
107
+ # Check which edits are permitted for existing shipments.
108
+ # @note Read. Does not change shipment state.
109
+ # @param shipment_nums [Array<Integer>] Shipment numbers in the carrier field type.
110
+ # @return [Econt::Collection<Econt::Models::Shipments::CheckPossibleShipmentEditionsResultElement>]
111
+ # Check #error? before using data.
112
+ # @raise [Econt::Error] On HTTP failure.
113
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
114
+ # @see file:docs/API.md#check_possible_shipment_editions Ruby usage and parameters
115
+ # @example After configuring Econt::Client
116
+ # labels = Econt::Services::Shipments::Label.new
117
+ # editions = labels.check_possible_shipment_editions(shipment_nums: [1234567890123])
118
+ def check_possible_shipment_editions(shipment_nums: [])
119
+ response = post('checkPossibleShipmentEditions', body: { shipment_nums: shipment_nums })
120
+ collection(response, Econt::Models::Shipments::CheckPossibleShipmentEditionsResultElement)
121
+ end
122
+
123
+ # POST /services/Shipments/LabelService.updateLabels.json(.soap?wsdl)
124
+ # Update several existing labels.
125
+ # @note Mutation. Review account permissions and cleanup before calling.
126
+ # @param labels [Array<Hash>] Existing labels and requested changes.
127
+ # @return [Econt::Collection<Econt::Models::Shipments::UpdateLabelsResultElement>]
128
+ # Check #error? before using data.
129
+ # @raise [Econt::Error] On HTTP failure.
130
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
131
+ # @see file:docs/API.md#update_labels Ruby usage and parameters
132
+ # @example After configuring Econt::Client
133
+ # labels = Econt::Services::Shipments::Label.new
134
+ # updated = labels.update_labels(labels: [updated_label_payload])
135
+ def update_labels(labels: [])
136
+ response = post('updateLabels', body: { labels: labels })
137
+ collection(response, Econt::Models::Shipments::UpdateLabelsResultElement)
138
+ end
139
+
140
+ # POST /services/Shipments/LabelService.grouping.json(.soap?wsdl)
141
+ # Group existing labels into a group label.
142
+ # @note Mutation. Review account permissions and cleanup before calling.
143
+ # @param labels [Array<Integer>] Shipment numbers to group.
144
+ # @return [Econt::Models::Shipments::ShipmentStatus] Typed result; inspect #error? before using data.
145
+ # @raise [Econt::Error] On HTTP failure.
146
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
147
+ # @see file:docs/API.md#grouping Ruby usage and parameters
148
+ # @example After configuring Econt::Client
149
+ # labels = Econt::Services::Shipments::Label.new
150
+ # group = labels.grouping(labels: [1234567890123, 1234567890124])
151
+ def grouping(labels: [])
152
+ response = post('grouping', body: { labels: labels })
153
+ resource(response, Econt::Models::Shipments::ShipmentStatus, key: :label)
154
+ end
155
+
156
+ # POST /services/Shipments/LabelService.groupingCancelation.json(.soap?wsdl)
157
+ # Cancel an existing group label.
158
+ # @note Mutation. Review account permissions and cleanup before calling.
159
+ # @param group_label [Integer, nil] Group-label shipment number.
160
+ # @return [Econt::Models::Shipments::StatusResponse] Typed result; inspect #error? before using data.
161
+ # @raise [Econt::Error] On HTTP failure.
162
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
163
+ # @see file:docs/API.md#grouping_cancelation Ruby usage and parameters
164
+ # @example After configuring Econt::Client
165
+ # labels = Econt::Services::Shipments::Label.new
166
+ # result = labels.grouping_cancelation(group_label: group_label_number)
167
+ def grouping_cancelation(group_label: nil)
168
+ response = post('groupingCancelation', body: { group_label: group_label })
169
+ resource(response, Econt::Models::Shipments::StatusResponse)
170
+ end
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module Shipments
6
+ class Shipment < ServiceResource
7
+ include Econt::Services::Shipments
8
+
9
+ resource_type 'Shipment'
10
+
11
+ # services/Shipments/ShipmentService.requestCourier.json(.soap?wsdl)
12
+ # Book a courier collection; pass the documented request fields as keywords.
13
+ # @note Mutation. Review account permissions and cleanup before calling.
14
+ # @param attributes [Hash] Courier payload as keywords: request_time_from, request_time_to, shipment_type,
15
+ # shipment_pack_count, shipment_weight, sender_client, sender_agent, sender_address, attach_shipments,
16
+ # pack12, cargo_vehicle_options.
17
+ # @return [Econt::Models::Shipments::RequestCourierResponse] Typed result; inspect #error? before using data.
18
+ # @raise [Econt::Error] On HTTP failure.
19
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
20
+ # @see file:docs/API.md#request_courier Ruby usage and parameters
21
+ # @example After configuring Econt::Client
22
+ # shipments = Econt::Services::Shipments::Shipment.new
23
+ # booking = shipments.request_courier(**courier_payload)
24
+ def request_courier(**attributes)
25
+ response = post('requestCourier', body: attributes)
26
+ resource(response, Econt::Models::Shipments::RequestCourierResponse)
27
+ end
28
+
29
+ # services/Shipments/ShipmentService.getShipmentStatuses.json(.soap?wsdl)
30
+ # Read shipment status, tracking events, and label information.
31
+ # @note Read. Does not change shipment state.
32
+ # @param shipment_numbers [Array<String>] Shipment numbers to query.
33
+ # @return [Econt::Collection<Econt::Models::Shipments::ShipmentStatusResultElement>]
34
+ # Check #error? before using data.
35
+ # @raise [Econt::Error] On HTTP failure.
36
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
37
+ # @see file:docs/API.md#get_shipment_statuses Ruby usage and parameters
38
+ # @example After configuring Econt::Client
39
+ # shipments = Econt::Services::Shipments::Shipment.new
40
+ # statuses = shipments.get_shipment_statuses(shipment_numbers: [shipment_number])
41
+ def get_shipment_statuses(shipment_numbers: [])
42
+ response = post('getShipmentStatuses', body: { shipment_numbers: shipment_numbers })
43
+ collection(response, Econt::Models::Shipments::ShipmentStatusResultElement)
44
+ end
45
+
46
+ # services/Shipments/ShipmentService.getRequestCourierStatus.json(.soap?wsdl)
47
+ # Read the status of courier collection requests.
48
+ # @note Read. Does not change shipment state.
49
+ # @param request_courier_ids [Array<Integer>] Courier request identifiers.
50
+ # @return [Econt::Collection<Econt::Models::Shipments::RequestCourierStatusResultElement>]
51
+ # Check #error? before using data.
52
+ # @raise [Econt::Error] On HTTP failure.
53
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
54
+ # @see file:docs/API.md#get_request_courier_status Ruby usage and parameters
55
+ # @example After configuring Econt::Client
56
+ # shipments = Econt::Services::Shipments::Shipment.new
57
+ # statuses = shipments.get_request_courier_status(request_courier_ids: [courier_request_id])
58
+ def get_request_courier_status(request_courier_ids: [])
59
+ response = post('getRequestCourierStatus', body: { request_courier_ids: request_courier_ids })
60
+ collection(response, Econt::Models::Shipments::RequestCourierStatusResultElement)
61
+ end
62
+
63
+ # services/Shipments/ShipmentService.getMyAWB.json(.soap?wsdl)
64
+ # List account waybills using optional date, page, and side filters.
65
+ # @note Read. Does not change shipment state.
66
+ # @param date_from [String, nil] Start date in carrier format.
67
+ # @param date_to [String, nil] End date in carrier format.
68
+ # @param page [Integer, nil] Requested page.
69
+ # @param side [String, nil] Carrier side filter; see getMyAWB documentation for allowed values.
70
+ # @return [Econt::Models::Shipments::GetMyAwbResponse] Typed result; inspect #error? before using data.
71
+ # @raise [Econt::Error] On HTTP failure.
72
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
73
+ # @see file:docs/API.md#get_my_awb Ruby usage and parameters
74
+ # @example After configuring Econt::Client
75
+ # shipments = Econt::Services::Shipments::Shipment.new
76
+ # waybills = shipments.get_my_awb(date_from: '2026-10-01', date_to: '2026-10-12', page: 1)
77
+ def get_my_awb(date_from: nil, date_to: nil, page: nil, side: nil)
78
+ body = { date_from: date_from, date_to: date_to, page: page, side: side }.compact
79
+ response = post('getMyAWB', body: body)
80
+ resource(response, Econt::Models::Shipments::GetMyAwbResponse)
81
+ end
82
+
83
+ # services/Shipments/ShipmentService.setITUCode.json(.soap?wsdl)
84
+ # Assign ITU transport metadata to a waybill.
85
+ # @note Mutation. Review account permissions and cleanup before calling.
86
+ # @param awb_barcode [String] Waybill barcode.
87
+ # @param truck_reg_num [String] Truck registration number.
88
+ # @param itu_code [String] ITU code; sent with the carrier spelling ITU_code.
89
+ # @return [Faraday::Response] Raw response; inspect #body.
90
+ # @raise [Econt::Error] On HTTP failure.
91
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
92
+ # @see file:docs/API.md#set_itu_code Ruby usage and parameters
93
+ # @example After configuring Econt::Client
94
+ # shipments = Econt::Services::Shipments::Shipment.new
95
+ # response = shipments.set_itu_code(
96
+ # awb_barcode: shipment_number, truck_reg_num: truck_registration, itu_code: itu_code
97
+ # )
98
+ # response.body
99
+ def set_itu_code(awb_barcode:, truck_reg_num:, itu_code:)
100
+ post_raw('setITUCode', body: {
101
+ 'awbBarcode' => awb_barcode,
102
+ 'truckRegNum' => truck_reg_num,
103
+ 'ITU_code' => itu_code
104
+ })
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module Shipments
6
+ def service_url
7
+ 'Shipments'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module ThreeWayLogistics
6
+ class ThreeWayLogistics < ServiceResource
7
+ include Econt::Services::ThreeWayLogistics
8
+
9
+ resource_type 'ThreeWayLogistics'
10
+
11
+ # Submit a three-way logistics request using legacy snake_case fields without camelCase conversion.
12
+ # @note Mutation. Review account permissions and cleanup before calling.
13
+ # @param attributes [Hash] Legacy request fields as keywords; see ThreeWayLogisticsRequest for available
14
+ # field names.
15
+ # @return [Econt::Models::ThreeWayLogistics::ThreeWayLogisticsResponse]
16
+ # Check #error? before using data.
17
+ # @raise [Econt::Error] On HTTP failure.
18
+ # @raise [Econt::TransportError] On connection, timeout, or TLS failure; inspect its subclass.
19
+ # @see file:docs/API.md#three_way_logistics Ruby usage and parameters
20
+ # @example After configuring Econt::Client
21
+ # logistics = Econt::Services::ThreeWayLogistics::ThreeWayLogistics.new
22
+ # result = logistics.three_way_logistics(**logistics_payload)
23
+ def three_way_logistics(**attributes)
24
+ response = post_raw('threeWayLogistics', body: attributes.transform_keys(&:to_s))
25
+ resource(response, Econt::Models::ThreeWayLogistics::ThreeWayLogisticsResponse)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Services
5
+ module ThreeWayLogistics
6
+ def service_url
7
+ 'ThreeWayLogistics'
8
+ end
9
+ end
10
+ end
11
+ end
data/lib/econt/util.rb ADDED
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ module Util
5
+ module_function
6
+
7
+ def pluralize(word)
8
+ base = underscore(word.to_s.split('::').last)
9
+
10
+ if base.end_with?('y') && !base.end_with?('ay', 'ey', 'iy', 'oy', 'uy')
11
+ "#{base[0..-2]}ies"
12
+ elsif base.end_with?('s', 'x', 'z', 'ch', 'sh')
13
+ "#{base}es"
14
+ else
15
+ "#{base}s"
16
+ end
17
+ end
18
+
19
+ def camel_case(str)
20
+ str.gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }
21
+ end
22
+
23
+ def underscore(str)
24
+ str.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
25
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase
26
+ end
27
+
28
+ def underscore_keys(hash)
29
+ return hash if primitive_value?(hash)
30
+
31
+ hash.each_with_object({}) do |(key, value), result|
32
+ result[underscore(key.to_s)] = case value
33
+ when Hash
34
+ underscore_keys(value)
35
+ when Array
36
+ value.map { |v| underscore_keys(v) }
37
+ else
38
+ value
39
+ end
40
+ end
41
+ end
42
+
43
+ def camelize_keys(hash)
44
+ hash.each_with_object({}) do |(key, value), result|
45
+ result[camel_case(key.to_s)] = case value
46
+ when Hash
47
+ camelize_keys(value)
48
+ when Array
49
+ value.map { |v| camelize_keys(v) }
50
+ else
51
+ value
52
+ end
53
+ end
54
+ end
55
+
56
+ def primitive_value?(value)
57
+ PRIMITIVE_TYPES.any? { |type| value.is_a?(type) }
58
+ end
59
+
60
+ PRIMITIVE_TYPES = [String, Symbol, Numeric, TrueClass, FalseClass, NilClass].freeze
61
+ private_constant :PRIMITIVE_TYPES
62
+ end
63
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Econt
4
+ VERSION = '0.1.0'
5
+ end