easypost 3.5.1 → 5.2.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 (151) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +9 -0
  3. data/.github/CODEOWNERS +2 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.yml +81 -0
  5. data/.github/ISSUE_TEMPLATE/feature_request.yml +37 -0
  6. data/.github/PULL_REQUEST_TEMPLATE.md +22 -0
  7. data/.github/workflows/ci.yml +54 -5
  8. data/.gitignore +27 -17
  9. data/.gitmodules +3 -0
  10. data/CHANGELOG.md +295 -119
  11. data/Gemfile +2 -0
  12. data/Makefile +70 -0
  13. data/README.md +184 -72
  14. data/Rakefile +2 -1
  15. data/UPGRADE_GUIDE.md +181 -0
  16. data/VERSION +1 -1
  17. data/bin/easypost-irb +5 -3
  18. data/easypost.gemspec +27 -20
  19. data/lib/easypost/client.rb +179 -0
  20. data/lib/easypost/connection.rb +64 -0
  21. data/lib/easypost/constants.rb +15 -0
  22. data/lib/easypost/errors/api/api_error.rb +108 -0
  23. data/lib/easypost/errors/api/bad_request_error.rb +6 -0
  24. data/lib/easypost/errors/api/connection_error.rb +6 -0
  25. data/lib/easypost/errors/api/external_api_error.rb +18 -0
  26. data/lib/easypost/errors/api/forbidden_error.rb +6 -0
  27. data/lib/easypost/errors/api/gateway_timeout_error.rb +6 -0
  28. data/lib/easypost/errors/api/internal_server_error.rb +6 -0
  29. data/lib/easypost/errors/api/invalid_request_error.rb +6 -0
  30. data/lib/easypost/errors/api/method_not_allowed_error.rb +6 -0
  31. data/lib/easypost/errors/api/not_found_error.rb +6 -0
  32. data/lib/easypost/errors/api/payment_error.rb +6 -0
  33. data/lib/easypost/errors/api/proxy_error.rb +6 -0
  34. data/lib/easypost/errors/api/rate_limit_error.rb +6 -0
  35. data/lib/easypost/errors/api/redirect_error.rb +6 -0
  36. data/lib/easypost/errors/api/retry_error.rb +6 -0
  37. data/lib/easypost/errors/api/service_unavailable_error.rb +6 -0
  38. data/lib/easypost/errors/api/ssl_error.rb +6 -0
  39. data/lib/easypost/errors/api/timeout_error.rb +6 -0
  40. data/lib/easypost/errors/api/unauthorized_error.rb +6 -0
  41. data/lib/easypost/errors/api/unknown_api_error.rb +6 -0
  42. data/lib/easypost/errors/easy_post_error.rb +7 -0
  43. data/lib/easypost/errors/end_of_pagination_error.rb +7 -0
  44. data/lib/easypost/errors/filtering_error.rb +4 -0
  45. data/lib/easypost/errors/invalid_object_error.rb +4 -0
  46. data/lib/easypost/errors/invalid_parameter_error.rb +11 -0
  47. data/lib/easypost/errors/missing_parameter_error.rb +9 -0
  48. data/lib/easypost/errors/signature_verification_error.rb +4 -0
  49. data/lib/easypost/errors.rb +32 -0
  50. data/lib/easypost/hooks/request_context.rb +16 -0
  51. data/lib/easypost/hooks/response_context.rb +23 -0
  52. data/lib/easypost/hooks.rb +34 -0
  53. data/lib/easypost/http_client.rb +117 -0
  54. data/lib/easypost/internal_utilities.rb +66 -0
  55. data/lib/easypost/models/address.rb +5 -0
  56. data/lib/easypost/models/api_key.rb +5 -0
  57. data/lib/easypost/models/base.rb +58 -0
  58. data/lib/easypost/models/batch.rb +5 -0
  59. data/lib/easypost/models/brand.rb +5 -0
  60. data/lib/easypost/models/carbon_offset.rb +5 -0
  61. data/lib/easypost/models/carrier_account.rb +5 -0
  62. data/lib/easypost/models/carrier_type.rb +5 -0
  63. data/lib/easypost/models/customs_info.rb +5 -0
  64. data/lib/easypost/models/customs_item.rb +5 -0
  65. data/lib/easypost/models/end_shipper.rb +5 -0
  66. data/lib/easypost/models/error.rb +21 -0
  67. data/lib/easypost/models/event.rb +5 -0
  68. data/lib/easypost/models/insurance.rb +6 -0
  69. data/lib/easypost/models/order.rb +9 -0
  70. data/lib/easypost/models/parcel.rb +5 -0
  71. data/lib/easypost/models/payload.rb +5 -0
  72. data/lib/easypost/models/payment_method.rb +5 -0
  73. data/lib/easypost/models/pickup.rb +9 -0
  74. data/lib/easypost/models/pickup_rate.rb +5 -0
  75. data/lib/easypost/models/postage_label.rb +5 -0
  76. data/lib/easypost/models/rate.rb +5 -0
  77. data/lib/easypost/models/referral.rb +5 -0
  78. data/lib/easypost/models/refund.rb +5 -0
  79. data/lib/easypost/models/report.rb +5 -0
  80. data/lib/easypost/models/scan_form.rb +6 -0
  81. data/lib/easypost/models/shipment.rb +10 -0
  82. data/lib/easypost/models/tax_identifier.rb +6 -0
  83. data/lib/easypost/models/tracker.rb +5 -0
  84. data/lib/easypost/models/user.rb +5 -0
  85. data/lib/easypost/models/webhook.rb +6 -0
  86. data/lib/easypost/models.rb +36 -0
  87. data/lib/easypost/services/address.rb +50 -0
  88. data/lib/easypost/services/api_key.rb +8 -0
  89. data/lib/easypost/services/base.rb +27 -0
  90. data/lib/easypost/services/batch.rb +53 -0
  91. data/lib/easypost/services/beta_rate.rb +12 -0
  92. data/lib/easypost/services/beta_referral_customer.rb +40 -0
  93. data/lib/easypost/services/billing.rb +75 -0
  94. data/lib/easypost/services/carrier_account.rb +44 -0
  95. data/lib/easypost/services/carrier_metadata.rb +22 -0
  96. data/lib/easypost/services/carrier_type.rb +10 -0
  97. data/lib/easypost/services/customs_info.rb +17 -0
  98. data/lib/easypost/services/customs_item.rb +15 -0
  99. data/lib/easypost/services/end_shipper.rb +31 -0
  100. data/lib/easypost/services/event.rb +32 -0
  101. data/lib/easypost/services/insurance.rb +26 -0
  102. data/lib/easypost/services/order.rb +30 -0
  103. data/lib/easypost/services/parcel.rb +16 -0
  104. data/lib/easypost/services/pickup.rb +40 -0
  105. data/lib/easypost/services/rate.rb +8 -0
  106. data/lib/easypost/services/referral_customer.rb +103 -0
  107. data/lib/easypost/services/refund.rb +26 -0
  108. data/lib/easypost/services/report.rb +42 -0
  109. data/lib/easypost/services/scan_form.rb +25 -0
  110. data/lib/easypost/services/shipment.rb +106 -0
  111. data/lib/easypost/services/tracker.rb +38 -0
  112. data/lib/easypost/services/user.rb +66 -0
  113. data/lib/easypost/services/webhook.rb +34 -0
  114. data/lib/easypost/services.rb +33 -0
  115. data/lib/easypost/util.rb +160 -116
  116. data/lib/easypost/utilities/constants.rb +5 -0
  117. data/lib/easypost/utilities/json.rb +23 -0
  118. data/lib/easypost/utilities/static_mapper.rb +73 -0
  119. data/lib/easypost/utilities/system.rb +36 -0
  120. data/lib/easypost/version.rb +3 -1
  121. data/lib/easypost.rb +20 -143
  122. metadata +249 -46
  123. data/lib/easypost/address.rb +0 -58
  124. data/lib/easypost/api_key.rb +0 -2
  125. data/lib/easypost/batch.rb +0 -49
  126. data/lib/easypost/brand.rb +0 -9
  127. data/lib/easypost/carrier_account.rb +0 -5
  128. data/lib/easypost/carrier_type.rb +0 -2
  129. data/lib/easypost/customs_info.rb +0 -5
  130. data/lib/easypost/customs_item.rb +0 -5
  131. data/lib/easypost/error.rb +0 -31
  132. data/lib/easypost/event.rb +0 -7
  133. data/lib/easypost/insurance.rb +0 -2
  134. data/lib/easypost/object.rb +0 -151
  135. data/lib/easypost/order.rb +0 -28
  136. data/lib/easypost/parcel.rb +0 -2
  137. data/lib/easypost/pickup.rb +0 -26
  138. data/lib/easypost/pickup_rate.rb +0 -3
  139. data/lib/easypost/postage_label.rb +0 -2
  140. data/lib/easypost/print_job.rb +0 -2
  141. data/lib/easypost/printer.rb +0 -24
  142. data/lib/easypost/rate.rb +0 -2
  143. data/lib/easypost/refund.rb +0 -2
  144. data/lib/easypost/report.rb +0 -29
  145. data/lib/easypost/resource.rb +0 -75
  146. data/lib/easypost/scan_form.rb +0 -6
  147. data/lib/easypost/shipment.rb +0 -129
  148. data/lib/easypost/tax_identifier.rb +0 -2
  149. data/lib/easypost/tracker.rb +0 -7
  150. data/lib/easypost/user.rb +0 -56
  151. data/lib/easypost/webhook.rb +0 -29
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyPost::Hooks
4
+ def self.subscribe(type, name, block)
5
+ subscribers[type][name] = block
6
+
7
+ name
8
+ end
9
+
10
+ def self.unsubscribe(type, name)
11
+ subscribers[type].delete(name)
12
+ end
13
+
14
+ def self.unsubscribe_all(type)
15
+ subscribers.delete(type)
16
+ end
17
+
18
+ def self.notify(type, context)
19
+ subscribers[type].each_value { |subscriber| subscriber.call(context) }
20
+ end
21
+
22
+ def self.any_subscribers?(type)
23
+ !subscribers[type].empty?
24
+ end
25
+
26
+ def self.subscribers
27
+ @subscribers ||= Hash.new { |hash, key| hash[key] = {} }
28
+ end
29
+
30
+ private_class_method :subscribers
31
+ end
32
+
33
+ require_relative 'hooks/request_context'
34
+ require_relative 'hooks/response_context'
@@ -0,0 +1,117 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'securerandom'
4
+
5
+ class EasyPost::HttpClient
6
+ def initialize(base_url, config, custom_client_exec = nil)
7
+ @base_url = base_url
8
+ @config = config
9
+ @custom_client_exec = custom_client_exec
10
+ end
11
+
12
+ # Execute an HTTP request to the API.
13
+ def request(
14
+ method,
15
+ path,
16
+ headers = nil,
17
+ body = nil,
18
+ api_version = EasyPost::InternalUtilities::Constants::API_VERSION
19
+ )
20
+ # Remove leading slash from path.
21
+ path = path[1..] if path[0] == '/'
22
+
23
+ uri = URI.parse("#{@base_url}/#{api_version}/#{path}")
24
+ headers = @config[:headers].merge(headers || {})
25
+ serialized_body = JSON.dump(EasyPost::InternalUtilities.objects_to_ids(body)) if body
26
+ open_timeout = @config[:open_timeout]
27
+ read_timeout = @config[:read_timeout]
28
+ request_timestamp = Time.now
29
+ request_uuid = SecureRandom.uuid
30
+
31
+ if EasyPost::Hooks.any_subscribers?(:request)
32
+ request_context = EasyPost::Hooks::RequestContext.new(
33
+ method: method,
34
+ path: uri.to_s,
35
+ headers: headers,
36
+ request_body: body,
37
+ request_timestamp: request_timestamp,
38
+ request_uuid: request_uuid,
39
+ )
40
+ EasyPost::Hooks.notify(:request, request_context)
41
+ end
42
+
43
+ # Execute the request, return the response.
44
+
45
+ response = if @custom_client_exec
46
+ @custom_client_exec.call(method, uri, headers, open_timeout, read_timeout, serialized_body)
47
+ else
48
+ default_request_execute(method, uri, headers, open_timeout, read_timeout, serialized_body)
49
+ end
50
+ response_timestamp = Time.now
51
+
52
+ if EasyPost::Hooks.any_subscribers?(:response)
53
+ response_context = {
54
+ http_status: nil,
55
+ method: method,
56
+ path: uri.to_s,
57
+ headers: nil,
58
+ response_body: nil,
59
+ request_timestamp: request_timestamp,
60
+ response_timestamp: response_timestamp,
61
+ client_response_object: response,
62
+ request_uuid: request_uuid,
63
+ }
64
+
65
+ # If using a custom HTTP client, the user will have to infer these from the raw
66
+ # client_response_object attribute
67
+ if response.is_a?(Net::HTTPResponse)
68
+ response_body = begin
69
+ JSON.parse(response.body)
70
+ rescue JSON::ParseError
71
+ response.body
72
+ end
73
+ response_context.merge!(
74
+ {
75
+ http_status: response.code.to_i,
76
+ headers: response.each_header.to_h,
77
+ response_body: response_body,
78
+ },
79
+ )
80
+ end
81
+
82
+ EasyPost::Hooks.notify(:response, EasyPost::Hooks::ResponseContext.new(**response_context))
83
+ end
84
+
85
+ response
86
+ end
87
+
88
+ def default_request_execute(method, uri, headers, open_timeout, read_timeout, body = nil)
89
+ # Create the request, set the headers and body if necessary.
90
+ request = Net::HTTP.const_get(method.capitalize).new(uri)
91
+ headers.each { |k, v| request[k] = v }
92
+ request.body = body if body
93
+
94
+ begin
95
+ # Attempt to make the request and return the response.
96
+ Net::HTTP.start(
97
+ uri.host,
98
+ uri.port,
99
+ use_ssl: true,
100
+ read_timeout: read_timeout,
101
+ open_timeout: open_timeout,
102
+ ) do |http|
103
+ http.request(request)
104
+ end
105
+ rescue Net::ReadTimeout, Net::OpenTimeout, Errno::EHOSTUNREACH => e
106
+ # Raise a timeout error if the request times out.
107
+ raise EasyPost::Errors::TimeoutError.new(e.message)
108
+ rescue OpenSSL::SSL::SSLError => e
109
+ # Raise an SSL error if the request fails due to an SSL error.
110
+ raise EasyPost::Errors::SslError.new(e.message)
111
+ rescue StandardError => e
112
+ # Raise an unknown HTTP error if anything else causes the request to fail to complete
113
+ # (this is different from processing 4xx/5xx errors from the API)
114
+ raise EasyPost::Errors::UnknownApiError.new(e.message)
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyPost::InternalUtilities
4
+ # Convert a string to snake case
5
+ def self.to_snake_case(str)
6
+ str.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
7
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
8
+ .downcase
9
+ end
10
+
11
+ # Form-encode a multi-layer dictionary to a one-layer dictionary.
12
+ def self.form_encode_params(hash, parent_keys = [], parent_dict = {})
13
+ result = parent_dict or {}
14
+ keys = parent_keys or []
15
+
16
+ hash.each do |key, value|
17
+ if value.instance_of?(Hash)
18
+ keys << key
19
+ result = form_encode_params(value, keys, result)
20
+ else
21
+ dict_key = build_dict_key(keys + [key])
22
+ result[dict_key] = value
23
+ end
24
+ end
25
+ result
26
+ end
27
+
28
+ # Build a dict key from a list of keys.
29
+ # Example: [code, number] -> code[number]
30
+ def self.build_dict_key(keys)
31
+ result = keys[0].to_s
32
+
33
+ keys[1..].each do |key|
34
+ result += "[#{key}]"
35
+ end
36
+
37
+ result
38
+ end
39
+
40
+ # Converts an object to an object ID.
41
+ def self.objects_to_ids(obj)
42
+ case obj
43
+ when EasyPost::Models::EasyPostObject
44
+ { id: obj.id }
45
+ when Hash
46
+ result = {}
47
+ obj.each { |k, v| result[k] = objects_to_ids(v) unless v.nil? }
48
+ result
49
+ when Array
50
+ obj.map { |v| objects_to_ids(v) }
51
+ else
52
+ obj
53
+ end
54
+ end
55
+
56
+ # Normalizes a list of strings.
57
+ def self.normalize_string_list(lst)
58
+ lst = lst.is_a?(String) ? lst.split(',') : Array(lst)
59
+ lst.map(&:to_s).map(&:downcase).map(&:strip)
60
+ end
61
+ end
62
+
63
+ require_relative 'utilities/json'
64
+ require_relative 'utilities/system'
65
+ require_relative 'utilities/static_mapper'
66
+ require_relative 'utilities/constants'
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Address objects are used to represent people, places, and organizations in a number of contexts.
4
+ class EasyPost::Models::Address < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # An ApiKey object that has your EasyPost API.
4
+ class EasyPost::Models::ApiKey < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ # The base class for all JSON objects in the library.
6
+ class EasyPost::Models::Object
7
+ def initialize(data)
8
+ @values = data
9
+ add_properties(data)
10
+ end
11
+
12
+ # Convert to a string.
13
+ def to_s(*_args)
14
+ JSON.dump(@values)
15
+ end
16
+
17
+ # Convert object to hash
18
+ def to_hash
19
+ JSON.parse(JSON.dump(@values))
20
+ end
21
+
22
+ # Get element of an array.
23
+ def [](key)
24
+ @values[key.to_s]
25
+ end
26
+
27
+ # Set the element of an array.
28
+ def []=(key, value)
29
+ send(:"#{key}=", value)
30
+ end
31
+
32
+ private
33
+
34
+ def add_properties(values)
35
+ values.each do |key, _|
36
+ define_singleton_method(key) { handle_value(@values[key]) } # getter
37
+ define_singleton_method("#{key}=") { |v| @values[key] = handle_value(v) } # setter
38
+ end
39
+ end
40
+
41
+ def handle_value(val)
42
+ case val
43
+ when Hash
44
+ type = EasyPost::InternalUtilities::StaticMapper::BY_TYPE[val['object']] if val['object']
45
+ prefix = EasyPost::InternalUtilities::StaticMapper::BY_PREFIX[val['id'].split('_').first] if val['id']
46
+ cls = type || prefix || EasyPost::Models::EasyPostObject
47
+ cls.new(val)
48
+ when Array
49
+ val.map { |item| handle_value(item) }
50
+ else
51
+ val
52
+ end
53
+ end
54
+ end
55
+
56
+ # The base class for all API objects in the library that have an ID (plus optional timestamps).
57
+ class EasyPost::Models::EasyPostObject < EasyPost::Models::Object
58
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The Batch object allows you to perform operations on multiple Shipments at once.
4
+ class EasyPost::Models::Batch < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The Brand object allows you to customize the publicly-accessible html page that shows tracking details for every EasyPost tracker.
4
+ class EasyPost::Models::Brand < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The CarbonOffset object is a summary of carbon offset data for a given rate, including grams, price and currency
4
+ class EasyPost::Models::CarbonOffset < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A CarrierAccount encapsulates your credentials with the carrier.
4
+ class EasyPost::Models::CarrierAccount < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A CarrierType details the valid fields for a CarrierAccount.
4
+ class EasyPost::Models::CarrierType < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # CustomsInfo objects contain CustomsItem objects and all necessary information for the generation of customs forms required for international shipping.
4
+ class EasyPost::Models::CustomsInfo < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A CustomsItem object describes goods for international shipment and should be created then included in a CustomsInfo object.
4
+ class EasyPost::Models::CustomsItem < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # EndShipper objects are fully-qualified Address objects that require all parameters and get verified upon creation.
4
+ class EasyPost::Models::EndShipper < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # EasyPost Error object.
4
+ class EasyPost::Models::Error
5
+ attr_reader :code, :field, :message
6
+
7
+ # Initialize a new EasyPost Error
8
+ def initialize(code, field = nil, message = nil)
9
+ @code = code
10
+ @field = field
11
+ @message = message
12
+ end
13
+
14
+ # Create an EasyPost Error from an API error response.
15
+ def self.from_api_error_response(data)
16
+ code = data['code']
17
+ field = data['field'] || nil
18
+ message = data['message'] || nil
19
+ EasyPost::Models::Error.new(code, field, message)
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Webhook Events are triggered by changes in objects you've created via the API.
4
+ class EasyPost::Models::Event < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # An Insurance object represents insurance for packages purchased both via the EasyPost API as well
4
+ # as shipments purchased through third parties and later registered with EasyPost.
5
+ class EasyPost::Models::Insurance < EasyPost::Models::EasyPostObject
6
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The Order object represents a collection of packages and can be used for Multi-Piece Shipments.
4
+ class EasyPost::Models::Order < EasyPost::Models::EasyPostObject
5
+ # Get the lowest rate of an Order (can exclude by having `'!'` as the first element of your optional filter lists).
6
+ def lowest_rate(carriers = [], services = [])
7
+ EasyPost::Util.get_lowest_object_rate(self, carriers, services)
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Parcel objects represent the physical container being shipped.
4
+ class EasyPost::Models::Parcel < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Webhook Event Payloads are triggered by changes in objects you've created via the API.
4
+ class EasyPost::Models::Payload < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # PaymentMethod objects represent a payment method of a user.
4
+ class EasyPost::Models::PaymentMethod < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The Pickup object allows you to schedule a pickup from your carrier from your customer's residence or place of business.
4
+ class EasyPost::Models::Pickup < EasyPost::Models::EasyPostObject
5
+ # Get the lowest rate of a Pickup (can exclude by having `'!'` as the first element of your optional filter lists).
6
+ def lowest_rate(carriers = [], services = [])
7
+ EasyPost::Util.get_lowest_object_rate(self, carriers, services, 'pickup_rates')
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A PickupRate is the rate available for a Pickup.
4
+ class EasyPost::Models::PickupRate < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # PostageLabel is the object containing details about the shipping label.
4
+ class EasyPost::Models::PostageLabel < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A Rate object contains all the details about the rate of a Shipment.
4
+ class EasyPost::Models::Rate < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ReferralCustomer objects are User objects created from a Partner user.
4
+ class EasyPost::Models::Referral < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The Refund object contains details about the Refund of a Shipment.
4
+ class EasyPost::Models::Refund < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A Report contains a csv that is a log of all the objects created within a certain time frame.
4
+ class EasyPost::Models::Report < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A ScanForm can be created to speed up and simplify the carrier pickup process. The ScanForm is one document that can
4
+ # be scanned to mark all included tracking codes as "Accepted for Shipment" by the carrier.
5
+ class EasyPost::Models::ScanForm < EasyPost::Models::EasyPostObject
6
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The workhorse of the EasyPost API, a Shipment is made up of a "to" and "from" Address, the Parcel
4
+ # being shipped, and any customs forms required for international deliveries.
5
+ class EasyPost::Models::Shipment < EasyPost::Models::EasyPostObject
6
+ # Get the lowest rate of a Shipment (can exclude by having `'!'` as the first element of your optional filter lists).
7
+ def lowest_rate(carriers = [], services = [])
8
+ EasyPost::Util.get_lowest_object_rate(self, carriers, services)
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # TaxIdentifiers are identifying numbers or IDs that are used to charge a specific party when
4
+ # dealing with the importing or exporting of good across international borders.
5
+ class EasyPost::Models::TaxIdentifier < EasyPost::Models::EasyPostObject
6
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A Tracker object contains all of the tracking information for a package.
4
+ class EasyPost::Models::Tracker < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The User object can be used to manage your own account and to create child accounts.
4
+ class EasyPost::Models::User < EasyPost::Models::EasyPostObject
5
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Each Webhook contains the url which EasyPost will notify whenever an object in our system updates. Several types of objects are processed
4
+ # asynchronously in the EasyPost system, so whenever an object updates, an Event is sent via HTTP POST to each configured webhook URL.
5
+ class EasyPost::Models::Webhook < EasyPost::Models::EasyPostObject
6
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EasyPost::Models
4
+ end
5
+
6
+ require_relative 'models/base' # Must be imported first before the rest of child models
7
+ require_relative 'models/address'
8
+ require_relative 'models/api_key'
9
+ require_relative 'models/batch'
10
+ require_relative 'models/brand'
11
+ require_relative 'models/carbon_offset'
12
+ require_relative 'models/carrier_account'
13
+ require_relative 'models/carrier_type'
14
+ require_relative 'models/customs_info'
15
+ require_relative 'models/customs_item'
16
+ require_relative 'models/end_shipper'
17
+ require_relative 'models/error'
18
+ require_relative 'models/event'
19
+ require_relative 'models/insurance'
20
+ require_relative 'models/order'
21
+ require_relative 'models/parcel'
22
+ require_relative 'models/payload'
23
+ require_relative 'models/payment_method'
24
+ require_relative 'models/pickup_rate'
25
+ require_relative 'models/pickup'
26
+ require_relative 'models/postage_label'
27
+ require_relative 'models/rate'
28
+ require_relative 'models/referral'
29
+ require_relative 'models/refund'
30
+ require_relative 'models/report'
31
+ require_relative 'models/scan_form'
32
+ require_relative 'models/shipment'
33
+ require_relative 'models/tax_identifier'
34
+ require_relative 'models/tracker'
35
+ require_relative 'models/user'
36
+ require_relative 'models/webhook'
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ class EasyPost::Services::Address < EasyPost::Services::Service
4
+ MODEL_CLASS = EasyPost::Models::Address
5
+
6
+ # Create an address.
7
+ def create(params = {})
8
+ address = params.reject { |k, _| [:verify, :verify_strict].include?(k) }
9
+
10
+ wrapped_params = { address: address }
11
+
12
+ if params[:verify]
13
+ wrapped_params[:verify] = params[:verify]
14
+ end
15
+
16
+ if params[:verify_strict]
17
+ wrapped_params[:verify_strict] = params[:verify_strict]
18
+ end
19
+
20
+ @client.make_request(:post, 'addresses', MODEL_CLASS, params)
21
+ end
22
+
23
+ # Create and verify an Address in one call.
24
+ def create_and_verify(params = {})
25
+ wrapped_params = {}
26
+ wrapped_params[:address] = params
27
+
28
+ @client.make_request(:post, 'addresses/create_and_verify', MODEL_CLASS, wrapped_params).address
29
+ end
30
+
31
+ # Verify an Address.
32
+ def verify(id)
33
+ @client.make_request(:get, "addresses/#{id}/verify", MODEL_CLASS).address
34
+ end
35
+
36
+ # Retrieve an Address.
37
+ def retrieve(id)
38
+ @client.make_request(:get, "addresses/#{id}", MODEL_CLASS)
39
+ end
40
+
41
+ # Retrieve all Addresses.
42
+ def all(filters = {})
43
+ @client.make_request(:get, 'addresses', MODEL_CLASS, filters)
44
+ end
45
+
46
+ # Get the next page of addresses.
47
+ def get_next_page(collection, page_size = nil)
48
+ get_next_page_helper(collection, collection.addresses, 'addresses', MODEL_CLASS, page_size)
49
+ end
50
+ end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ class EasyPost::Services::ApiKey < EasyPost::Services::Service
4
+ # Retrieve all api keys.
5
+ def all
6
+ @client.make_request(:get, 'api_keys', EasyPost::Models::ApiKey)
7
+ end
8
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The base class for all services in the library.
4
+ class EasyPost::Services::Service
5
+ def initialize(client)
6
+ @client = client
7
+ end
8
+
9
+ protected
10
+
11
+ # Get next page of an object collection
12
+ def get_next_page_helper(collection, current_page_items, endpoint, cls, page_size = nil)
13
+ has_more = collection.has_more || false
14
+ unless !has_more || current_page_items.nil? || current_page_items.empty?
15
+ params = {}
16
+ params[:before_id] = current_page_items.last.id
17
+ unless page_size.nil?
18
+ params[:page_size] = page_size
19
+ end
20
+
21
+ @client.make_request(:get, endpoint, cls, params)
22
+ end
23
+
24
+ # issue with getting the next page
25
+ raise EasyPost::Errors::EndOfPaginationError.new
26
+ end
27
+ end