easypost 3.5.1 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
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