friendly_shipping 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (124) hide show
  1. checksums.yaml +4 -4
  2. data/.circleci/config.yml +1 -1
  3. data/.rubocop.yml +6 -0
  4. data/README.md +1 -1
  5. data/friendly_shipping.gemspec +7 -7
  6. data/lib/friendly_shipping/access_token.rb +24 -0
  7. data/lib/friendly_shipping/api_error.rb +4 -2
  8. data/lib/friendly_shipping/api_error_handler.rb +4 -6
  9. data/lib/friendly_shipping/api_failure.rb +2 -11
  10. data/lib/friendly_shipping/api_result.rb +10 -0
  11. data/lib/friendly_shipping/http_client.rb +4 -10
  12. data/lib/friendly_shipping/label.rb +0 -2
  13. data/lib/friendly_shipping/services/rl/api_error.rb +0 -2
  14. data/lib/friendly_shipping/services/rl/bol_options.rb +0 -4
  15. data/lib/friendly_shipping/services/rl/item_options.rb +0 -2
  16. data/lib/friendly_shipping/services/rl/package_options.rb +0 -2
  17. data/lib/friendly_shipping/services/rl/parse_create_bol_response.rb +0 -3
  18. data/lib/friendly_shipping/services/rl/parse_invoice_response.rb +0 -3
  19. data/lib/friendly_shipping/services/rl/parse_print_bol_response.rb +0 -3
  20. data/lib/friendly_shipping/services/rl/parse_print_shipping_labels_response.rb +0 -3
  21. data/lib/friendly_shipping/services/rl/parse_rate_quote_response.rb +31 -4
  22. data/lib/friendly_shipping/services/rl/parse_transit_times_response.rb +0 -3
  23. data/lib/friendly_shipping/services/rl/rate_quote_options.rb +0 -4
  24. data/lib/friendly_shipping/services/rl/serialize_location.rb +9 -2
  25. data/lib/friendly_shipping/services/rl/shipment_options.rb +0 -2
  26. data/lib/friendly_shipping/services/rl.rb +4 -21
  27. data/lib/friendly_shipping/services/ship_engine/api_error.rb +0 -2
  28. data/lib/friendly_shipping/services/ship_engine/label_item_options.rb +0 -2
  29. data/lib/friendly_shipping/services/ship_engine/label_options.rb +0 -4
  30. data/lib/friendly_shipping/services/ship_engine/label_package_options.rb +0 -3
  31. data/lib/friendly_shipping/services/ship_engine/parse_address_validation_response.rb +3 -5
  32. data/lib/friendly_shipping/services/ship_engine/parse_carrier_response.rb +0 -2
  33. data/lib/friendly_shipping/services/ship_engine/parse_label_response.rb +0 -2
  34. data/lib/friendly_shipping/services/ship_engine/parse_rate_estimates_response.rb +2 -4
  35. data/lib/friendly_shipping/services/ship_engine/parse_rates_response.rb +2 -4
  36. data/lib/friendly_shipping/services/ship_engine/parse_void_response.rb +2 -2
  37. data/lib/friendly_shipping/services/ship_engine/rate_estimates_options.rb +0 -2
  38. data/lib/friendly_shipping/services/ship_engine/rates_item_options.rb +0 -2
  39. data/lib/friendly_shipping/services/ship_engine/rates_options.rb +0 -2
  40. data/lib/friendly_shipping/services/ship_engine/rates_package_options.rb +0 -2
  41. data/lib/friendly_shipping/services/ship_engine.rb +11 -28
  42. data/lib/friendly_shipping/services/ship_engine_ltl/parse_carrier_response.rb +1 -3
  43. data/lib/friendly_shipping/services/ship_engine_ltl/parse_quote_response.rb +1 -3
  44. data/lib/friendly_shipping/services/ship_engine_ltl.rb +5 -17
  45. data/lib/friendly_shipping/services/tforce_freight/access_token.rb +3 -18
  46. data/lib/friendly_shipping/services/tforce_freight/api_error.rb +0 -2
  47. data/lib/friendly_shipping/services/tforce_freight/generate_create_bol_request_hash.rb +2 -14
  48. data/lib/friendly_shipping/services/tforce_freight/generate_pickup_request_hash.rb +0 -2
  49. data/lib/friendly_shipping/services/tforce_freight/generate_rates_request_hash.rb +0 -2
  50. data/lib/friendly_shipping/services/tforce_freight/package_options.rb +0 -2
  51. data/lib/friendly_shipping/services/tforce_freight/parse_create_bol_response.rb +0 -4
  52. data/lib/friendly_shipping/services/tforce_freight/parse_rates_response.rb +4 -12
  53. data/lib/friendly_shipping/services/tforce_freight/parse_shipment_document.rb +0 -2
  54. data/lib/friendly_shipping/services/tforce_freight/rates_item_options.rb +0 -2
  55. data/lib/friendly_shipping/services/tforce_freight/rates_options.rb +0 -3
  56. data/lib/friendly_shipping/services/tforce_freight/rates_package_options.rb +0 -2
  57. data/lib/friendly_shipping/services/tforce_freight/shipment_options.rb +0 -2
  58. data/lib/friendly_shipping/services/tforce_freight.rb +1 -27
  59. data/lib/friendly_shipping/services/ups/label_item_options.rb +0 -2
  60. data/lib/friendly_shipping/services/ups/label_options.rb +0 -3
  61. data/lib/friendly_shipping/services/ups/label_package_options.rb +0 -2
  62. data/lib/friendly_shipping/services/ups/parse_address_validation_response.rb +1 -1
  63. data/lib/friendly_shipping/services/ups/parse_rate_response.rb +0 -4
  64. data/lib/friendly_shipping/services/ups/parse_shipment_accept_response.rb +0 -3
  65. data/lib/friendly_shipping/services/ups/parse_shipment_confirm_response.rb +0 -2
  66. data/lib/friendly_shipping/services/ups/parse_void_shipment_response.rb +0 -2
  67. data/lib/friendly_shipping/services/ups/parse_xml_response.rb +1 -1
  68. data/lib/friendly_shipping/services/ups/rate_estimate_options.rb +0 -2
  69. data/lib/friendly_shipping/services/ups/rate_estimate_package_options.rb +0 -2
  70. data/lib/friendly_shipping/services/ups/serialize_access_request.rb +0 -2
  71. data/lib/friendly_shipping/services/ups/serialize_rating_service_selection_request.rb +0 -4
  72. data/lib/friendly_shipping/services/ups/serialize_shipment_confirm_request.rb +0 -3
  73. data/lib/friendly_shipping/services/ups.rb +1 -23
  74. data/lib/friendly_shipping/services/ups_freight/api_error.rb +0 -2
  75. data/lib/friendly_shipping/services/ups_freight/generate_freight_rate_request_hash.rb +0 -4
  76. data/lib/friendly_shipping/services/ups_freight/generate_freight_ship_request_hash.rb +0 -8
  77. data/lib/friendly_shipping/services/ups_freight/parse_freight_label_response.rb +0 -3
  78. data/lib/friendly_shipping/services/ups_freight/parse_freight_rate_response.rb +0 -4
  79. data/lib/friendly_shipping/services/ups_freight/parse_shipment_document.rb +0 -2
  80. data/lib/friendly_shipping/services/ups_freight/rates_options.rb +0 -4
  81. data/lib/friendly_shipping/services/ups_freight/rates_package_options.rb +0 -2
  82. data/lib/friendly_shipping/services/ups_freight/rates_structure_options.rb +0 -2
  83. data/lib/friendly_shipping/services/ups_freight/shipment_options.rb +0 -2
  84. data/lib/friendly_shipping/services/ups_freight.rb +1 -21
  85. data/lib/friendly_shipping/services/ups_json/access_token.rb +3 -12
  86. data/lib/friendly_shipping/services/ups_json/api_error.rb +0 -2
  87. data/lib/friendly_shipping/services/ups_json/generate_city_state_lookup_payload.rb +23 -0
  88. data/lib/friendly_shipping/services/ups_json/generate_labels_payload.rb +0 -3
  89. data/lib/friendly_shipping/services/ups_json/generate_rates_payload.rb +2 -4
  90. data/lib/friendly_shipping/services/ups_json/label_item_options.rb +0 -2
  91. data/lib/friendly_shipping/services/ups_json/label_options.rb +0 -3
  92. data/lib/friendly_shipping/services/ups_json/label_package_options.rb +0 -2
  93. data/lib/friendly_shipping/services/ups_json/parse_city_state_lookup_response.rb +44 -0
  94. data/lib/friendly_shipping/services/ups_json/parse_json_response.rb +13 -6
  95. data/lib/friendly_shipping/services/ups_json/parse_labels_response.rb +4 -4
  96. data/lib/friendly_shipping/services/ups_json/parse_money_hash.rb +1 -1
  97. data/lib/friendly_shipping/services/ups_json/parse_rate_modifier_hash.rb +2 -2
  98. data/lib/friendly_shipping/services/ups_json/parse_rates_response.rb +19 -17
  99. data/lib/friendly_shipping/services/ups_json/rates_item_options.rb +0 -2
  100. data/lib/friendly_shipping/services/ups_json/rates_options.rb +0 -2
  101. data/lib/friendly_shipping/services/ups_json.rb +23 -23
  102. data/lib/friendly_shipping/services/usps/parse_rate_response.rb +0 -4
  103. data/lib/friendly_shipping/services/usps/parse_time_in_transit_response.rb +0 -3
  104. data/lib/friendly_shipping/services/usps/parse_xml_response.rb +1 -1
  105. data/lib/friendly_shipping/services/usps/rate_estimate_options.rb +0 -2
  106. data/lib/friendly_shipping/services/usps/rate_estimate_package_options.rb +0 -2
  107. data/lib/friendly_shipping/services/usps/serialize_rate_request.rb +0 -2
  108. data/lib/friendly_shipping/services/usps.rb +1 -12
  109. data/lib/friendly_shipping/services/usps_international/parse_rate_response.rb +0 -3
  110. data/lib/friendly_shipping/services/usps_international/rate_estimate_options.rb +0 -2
  111. data/lib/friendly_shipping/services/usps_international/rate_estimate_package_options.rb +0 -2
  112. data/lib/friendly_shipping/services/usps_international/serialize_rate_request.rb +0 -2
  113. data/lib/friendly_shipping/services/usps_international.rb +1 -5
  114. data/lib/friendly_shipping/services/usps_ship/access_token.rb +3 -18
  115. data/lib/friendly_shipping/services/usps_ship/api_error.rb +0 -2
  116. data/lib/friendly_shipping/services/usps_ship/machinable_package.rb +6 -4
  117. data/lib/friendly_shipping/services/usps_ship/parse_rate_estimates_response.rb +3 -3
  118. data/lib/friendly_shipping/services/usps_ship/parse_timings_response.rb +14 -12
  119. data/lib/friendly_shipping/services/usps_ship/rate_estimate_package_options.rb +0 -2
  120. data/lib/friendly_shipping/services/usps_ship/serialize_rate_estimates_request.rb +0 -2
  121. data/lib/friendly_shipping/services/usps_ship.rb +1 -15
  122. data/lib/friendly_shipping/version.rb +1 -1
  123. data/lib/friendly_shipping.rb +20 -21
  124. metadata +7 -4
@@ -1,13 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_freight/generate_location_hash'
4
- require 'friendly_shipping/services/ups_freight/generate_reference_hash'
5
- require 'friendly_shipping/services/ups_freight/generate_document_options_hash'
6
- require 'friendly_shipping/services/ups_freight/generate_email_options_hash'
7
- require 'friendly_shipping/services/ups_freight/generate_pickup_options_hash'
8
- require 'friendly_shipping/services/ups_freight/generate_delivery_options_hash'
9
- require 'friendly_shipping/services/ups_freight/generate_handling_units_hash'
10
-
11
3
  module FriendlyShipping
12
4
  module Services
13
5
  class UpsFreight
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_freight/parse_shipment_document'
4
- require 'friendly_shipping/services/ups_freight/shipment_information'
5
-
6
3
  module FriendlyShipping
7
4
  module Services
8
5
  class UpsFreight
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/rate'
4
- require 'friendly_shipping/api_result'
5
- require 'friendly_shipping/services/ups_freight/shipping_methods'
6
-
7
3
  module FriendlyShipping
8
4
  module Services
9
5
  class UpsFreight
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_freight/shipment_document'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class UpsFreight
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_freight/shipment_options'
4
- require 'friendly_shipping/services/ups_freight/rates_package_options'
5
- require 'friendly_shipping/services/ups_freight/generate_commodity_information'
6
-
7
3
  module FriendlyShipping
8
4
  module Services
9
5
  class UpsFreight
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_freight/rates_item_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class UpsFreight
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_freight/rates_package_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class UpsFreight
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/shipment_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class UpsFreight
@@ -1,26 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/monads'
4
- require 'friendly_shipping/http_client'
5
- require 'friendly_shipping/services/ups_freight/shipping_methods'
6
- require 'friendly_shipping/services/ups_freight/rates_options'
7
- require 'friendly_shipping/services/ups_freight/label_options'
8
- require 'friendly_shipping/services/ups_freight/rates_structure_options'
9
- require 'friendly_shipping/services/ups_freight/rates_package_options'
10
- require 'friendly_shipping/services/ups_freight/rates_item_options'
11
- require 'friendly_shipping/services/ups_freight/label_structure_options'
12
- require 'friendly_shipping/services/ups_freight/label_package_options'
13
- require 'friendly_shipping/services/ups_freight/label_item_options'
14
- require 'friendly_shipping/services/ups_freight/label_document_options'
15
- require 'friendly_shipping/services/ups_freight/label_email_options'
16
- require 'friendly_shipping/services/ups_freight/label_pickup_options'
17
- require 'friendly_shipping/services/ups_freight/label_delivery_options'
18
- require 'friendly_shipping/services/ups_freight/pickup_request_options'
19
- require 'friendly_shipping/services/ups_freight/parse_freight_label_response'
20
- require 'friendly_shipping/services/ups_freight/parse_freight_rate_response'
21
- require 'friendly_shipping/services/ups_freight/generate_freight_rate_request_hash'
22
- require 'friendly_shipping/services/ups_freight/generate_freight_ship_request_hash'
23
- require 'friendly_shipping/services/ups_freight/api_error'
3
+ require "json"
24
4
 
25
5
  module FriendlyShipping
26
6
  module Services
@@ -5,23 +5,14 @@ module FriendlyShipping
5
5
  class UpsJson
6
6
  # Represents an access token returned by UPS. The access token can be used to make API requests.
7
7
  # Once it expires, a new token must be created.
8
- class AccessToken
9
- # @return [Integer] the token's expiration
10
- attr_reader :expires_in
11
-
8
+ class AccessToken < FriendlyShipping::AccessToken
12
9
  # @return [Integer] the epoch time in ms when the token was issued
13
10
  attr_reader :issued_at
14
11
 
15
- # @return [String] the raw JWT token
16
- attr_reader :raw_token
17
-
18
- # @param expires_in [Integer] the token's expiration
19
12
  # @param issued_at [Integer] the time the token was issued at
20
- # @param raw_token [String] the raw JWT token
21
- def initialize(expires_in:, issued_at:, raw_token:)
22
- @expires_in = expires_in
13
+ def initialize(issued_at:, **other_kwargs)
23
14
  @issued_at = issued_at
24
- @raw_token = raw_token
15
+ super(**other_kwargs)
25
16
  end
26
17
  end
27
18
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/api_error'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class UpsJson
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FriendlyShipping
4
+ module Services
5
+ class UpsJson
6
+ class GenerateCityStateLookupPayload
7
+ def self.call(location:)
8
+ {
9
+ XAVRequest: {
10
+ RegionalRequestIndicator: "1",
11
+ AddressKeyFormat: [
12
+ {
13
+ PostcodePrimaryLow: location.zip,
14
+ CountryCode: location.country.code
15
+ }
16
+ ]
17
+ }
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_json/generate_address_hash'
4
- require 'friendly_shipping/services/ups_json/generate_package_hash'
5
-
6
3
  module FriendlyShipping
7
4
  module Services
8
5
  class UpsJson
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_json/generate_address_hash'
4
- require 'friendly_shipping/services/ups_json/generate_package_hash'
5
-
6
3
  module FriendlyShipping
7
4
  module Services
8
5
  class UpsJson
@@ -71,7 +68,8 @@ module FriendlyShipping
71
68
  }.compact
72
69
 
73
70
  if options.negotiated_rates
74
- payload[:RateRequest][:Shipment][:NegotiatedRatesIndicator] = options.negotiated_rates
71
+ payload[:RateRequest][:Shipment][:ShipmentRatingOptions] ||= {}
72
+ payload[:RateRequest][:Shipment][:ShipmentRatingOptions][:NegotiatedRatesIndicator] = "X"
75
73
  end
76
74
 
77
75
  payload
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/item_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class UpsJson
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_json/label_package_options'
4
- require 'friendly_shipping/services/ups_json/label_billing_options'
5
-
6
3
  module FriendlyShipping
7
4
  module Services
8
5
  # Option container for a generating UPS labels for a shipment
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_json/label_item_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class UpsJson
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FriendlyShipping
4
+ module Services
5
+ class UpsJson
6
+ class ParseCityStateLookupResponse
7
+ extend Dry::Monads::Result::Mixin
8
+
9
+ def self.call(request:, response:)
10
+ parsed_response = ParseJsonResponse.call(
11
+ request: request,
12
+ response: response,
13
+ expected_root_key: 'XAVResponse'
14
+ )
15
+ parsed_response.bind do |city_state_lookup_response|
16
+ if city_state_lookup_response['XAVResponse'].keys.include?('NoCandidatesIndicator')
17
+ Failure(
18
+ FriendlyShipping::ApiResult.new(
19
+ "No candidates found.",
20
+ original_request: request,
21
+ original_response: response
22
+ )
23
+ )
24
+ else
25
+ candidate = city_state_lookup_response.dig('XAVResponse', 'Candidate').first
26
+ Success(
27
+ FriendlyShipping::ApiResult.new(
28
+ Physical::Location.new(
29
+ city: candidate.dig('AddressKeyFormat', 'PoliticalDivision2'),
30
+ region: candidate.dig('AddressKeyFormat', 'PoliticalDivision1'),
31
+ country: candidate.dig('AddressKeyFormat', 'CountryCode'),
32
+ zip: candidate.dig('AddressKeyFormat', 'PostcodePrimaryLow')
33
+ ),
34
+ original_request: request,
35
+ original_response: response
36
+ )
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -6,6 +6,7 @@ module FriendlyShipping
6
6
  class ParseJsonResponse
7
7
  extend Dry::Monads::Result::Mixin
8
8
  SUCCESSFUL_RESPONSE_STATUS_CODE = '1'
9
+ UNEXPECTED_ROOT_KEY_STRING = 'Empty or unexpected root key'
9
10
 
10
11
  class << self
11
12
  def call(request:, response:, expected_root_key:)
@@ -15,23 +16,29 @@ module FriendlyShipping
15
16
  # UPS may return a 2xx status code on an unsuccessful request and include the error description in
16
17
  # the response headers, which we will consider a failure
17
18
  if api_error_message.present?
18
- wrap_failure(api_error_message, request, response)
19
+ wrap_failure(api_error(api_error_message), request, response)
19
20
  elsif response_body.nil? || response_body.keys.first != expected_root_key
20
- wrap_failure('Empty or unexpected root key', request, response)
21
+ wrap_failure(api_error(UNEXPECTED_ROOT_KEY_STRING), request, response)
21
22
  else
22
23
  Success(response_body)
23
24
  end
24
25
  rescue JSON::ParserError => e
25
26
  # when the response is not valid JSON(?!), the error description in the header is more descriptive
26
- wrap_failure(api_error_message || e, request, response)
27
+ return wrap_failure(api_error(api_error_message), request, response) if api_error_message
28
+
29
+ wrap_failure(e, request, response)
27
30
  end
28
31
 
29
32
  private
30
33
 
31
- def wrap_failure(failure, request, response)
34
+ def api_error(message)
35
+ FriendlyShipping::ApiError.new(nil, message)
36
+ end
37
+
38
+ def wrap_failure(error, request, response)
32
39
  Failure(
33
- FriendlyShipping::ApiFailure.new(
34
- failure,
40
+ FriendlyShipping::ApiResult.new(
41
+ error,
35
42
  original_request: request,
36
43
  original_response: response
37
44
  )
@@ -33,7 +33,7 @@ module FriendlyShipping
33
33
  usps_tracking_number: package["USPSPICNumber"],
34
34
  label_data: Base64.decode64(package["ShippingLabel"]["GraphicImage"]),
35
35
  label_format: package["ShippingLabel"]["ImageFormat"]["Code"],
36
- label_href: package["LabelURL"],
36
+ label_href: package["LabelURL"] || shipment_result["LabelURL"],
37
37
  cost: package_cost,
38
38
  shipment_cost: get_shipment_cost(shipment_result),
39
39
  data: {
@@ -47,9 +47,9 @@ module FriendlyShipping
47
47
 
48
48
  def build_cost_breakdown(package)
49
49
  costs = [
50
- package["BaseServiceCharge"],
51
- Array.wrap(package["ServiceOptionsCharges"]),
52
- Array.wrap(package["ItemizedCharges"])
50
+ package["BaseServiceCharge"]&.merge("Code" => "BaseServiceCharge"),
51
+ package["ServiceOptionsCharges"],
52
+ package["ItemizedCharges"]
53
53
  ].flatten
54
54
 
55
55
  costs.map { |cost| ParseMoneyHash.call(cost, "UnknownSurcharge") }.compact.to_h
@@ -15,7 +15,7 @@ module FriendlyShipping
15
15
  amount = Money.new(monetary_value * currency.subunit_to_unit, currency)
16
16
 
17
17
  surcharge_code = money_hash['Code']
18
- label = surcharge_code ? UPS_SURCHARGE_CODES[surcharge_code] : key_name
18
+ label = UPS_SURCHARGE_CODES[surcharge_code] || surcharge_code || key_name
19
19
 
20
20
  [label, amount]
21
21
  end
@@ -6,7 +6,7 @@ module FriendlyShipping
6
6
  class ParseRateModifierHash
7
7
  # @param [Hash] hash the RateModifier hash from the source JSON
8
8
  # @param [String] currency_code The currency code for this modifier's amount (i.e. 'USD')
9
- # @return [Hash]
9
+ # @return [Array] The label and the amount of the rate modifier
10
10
  def self.call(rate_modifier, currency_code:)
11
11
  return unless rate_modifier
12
12
 
@@ -20,7 +20,7 @@ module FriendlyShipping
20
20
  modifier_description = rate_modifier['ModifierDesc']
21
21
  label = "#{modifier_type} (#{modifier_description})"
22
22
 
23
- { label => amount }
23
+ [label, amount]
24
24
  end
25
25
  end
26
26
  end
@@ -32,13 +32,9 @@ module FriendlyShipping
32
32
  days_to_delivery = rated_shipment.dig('GuaranteedDelivery', 'BusinessDaysInTransit').to_i
33
33
  total_cost = ParseMoneyHash.call(rated_shipment['TotalCharges'], 'TotalCharges').last
34
34
  insurance_price = ParseMoneyHash.call(rated_shipment['ServiceOptionsCharges'], 'ServiceOptionsCharges')&.last
35
- negotiated_rate = ParseMoneyHash.call(rated_shipment.dig('NegotiatedRates', 'NetSummaryCharges', 'GrandTotal'), 'GrandTotal')&.last
36
- negotiated_charges = ParseMoneyHash.call(rated_shipment.dig('NegotiatedRates', 'ItemizedCharges'), 'ItemizedCharges')&.last
37
-
38
- itemized_charges = Array.wrap(rated_shipment['ItemizedCharges'])
39
- itemized_charges = itemized_charges.map do |charge|
40
- ParseMoneyHash.call(charge, 'MonetaryValue')
41
- end
35
+ negotiated_rate = ParseMoneyHash.call(rated_shipment.dig('NegotiatedRateCharges', 'TotalCharge'), 'TotalCharge')&.last
36
+ negotiated_charges = extract_charges(rated_shipment.dig('NegotiatedRateCharges', 'ItemizedCharges'), 'ItemizedCharges')
37
+ itemized_charges = extract_charges(rated_shipment['ItemizedCharges'], 'ItemizedCharges')
42
38
 
43
39
  rated_shipment_warnings = Array.wrap(rated_shipment['RatedShipmentAlert'])
44
40
  rated_shipment_warnings = rated_shipment_warnings.map { |alert| alert["Description"] }
@@ -74,13 +70,13 @@ module FriendlyShipping
74
70
  package_array.map do |rated_package|
75
71
  currency_code = rated_package.dig('TotalCharges', 'CurrencyCode')
76
72
  {
77
- transportation_charges: ParseMoneyHash.call(rated_package['TransportationCharges'], 'TransportationCharges'),
78
- base_service_charge: ParseMoneyHash.call(rated_package['BaseServiceCharge'], 'BaseServiceCharge'),
79
- service_options_charges: ParseMoneyHash.call(rated_package['ServiceOptionsCharges'], 'ServiceOptionsCharges'),
73
+ transportation_charges: ParseMoneyHash.call(rated_package['TransportationCharges'], 'TransportationCharges')&.last,
74
+ base_service_charge: ParseMoneyHash.call(rated_package['BaseServiceCharge'], 'BaseServiceCharge')&.last,
75
+ service_options_charges: ParseMoneyHash.call(rated_package['ServiceOptionsCharges'], 'ServiceOptionsCharges')&.last,
80
76
  itemized_charges: extract_charges(rated_package['ItemizedCharges'], 'ItemizedCharges'),
81
- total_charges: ParseMoneyHash.call(rated_package['TotalCharges'], 'TotalCharges'),
82
- negotiated_charges: extract_charges(rated_package.dig('NegotiatedRateCharges', 'ItemizedCharges'), 'ItemizedCharges'),
83
- rate_modifiers: extract_modifiers(rated_package['RateModifier'], currency_code: currency_code).inject(:merge),
77
+ total_charges: ParseMoneyHash.call(rated_package['TotalCharges'], 'TotalCharges')&.last,
78
+ negotiated_charges: extract_charges(rated_package.dig('NegotiatedCharges', 'ItemizedCharges'), 'ItemizedCharges'),
79
+ rate_modifiers: extract_modifiers(rated_package['RateModifier'], currency_code: currency_code),
84
80
  weight: BigDecimal(rated_package['Weight']),
85
81
  billing_weight: BigDecimal(rated_package.dig('BillingWeight', 'Weight'))
86
82
  }.compact
@@ -88,15 +84,21 @@ module FriendlyShipping
88
84
  end
89
85
 
90
86
  def extract_charges(charges, key_name)
87
+ non_zero_charges = {}
91
88
  Array.wrap(charges).map do |charge|
92
- ParseMoneyHash.call(charge, key_name)
93
- end.compact
89
+ parsed_charge = ParseMoneyHash.call(charge, key_name)
90
+ non_zero_charges[parsed_charge[0]] = parsed_charge[1] if parsed_charge.present?
91
+ end
92
+ non_zero_charges
94
93
  end
95
94
 
96
95
  def extract_modifiers(modifiers, currency_code:)
96
+ rate_modifiers = {}
97
97
  Array.wrap(modifiers).map do |modifier|
98
- ParseRateModifierHash.call(modifier, currency_code: currency_code)
99
- end.compact
98
+ parsed_modifier = ParseRateModifierHash.call(modifier, currency_code: currency_code)
99
+ rate_modifiers[parsed_modifier[0]] = parsed_modifier[1] if parsed_modifier.present?
100
+ end
101
+ rate_modifiers
100
102
  end
101
103
  end
102
104
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/item_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class UpsJson
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups_json/rates_package_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  # Option container for rating a shipment via UPS
@@ -1,28 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'dry/monads'
4
- require 'friendly_shipping/http_client'
5
- require 'friendly_shipping/services/ups_json/access_token'
6
- require 'friendly_shipping/services/ups_json/api_error'
7
- require 'friendly_shipping/services/ups_json/generate_address_classification_payload'
8
- require 'friendly_shipping/services/ups_json/generate_labels_payload'
9
- require 'friendly_shipping/services/ups_json/generate_rates_payload'
10
- require 'friendly_shipping/services/ups_json/generate_timings_payload'
11
- require 'friendly_shipping/services/ups_json/label'
12
- require 'friendly_shipping/services/ups_json/label_options'
13
- require 'friendly_shipping/services/ups_json/parse_address_classification_response'
14
- require 'friendly_shipping/services/ups_json/parse_json_response'
15
- require 'friendly_shipping/services/ups_json/parse_labels_response'
16
- require 'friendly_shipping/services/ups_json/parse_money_hash'
17
- require 'friendly_shipping/services/ups_json/parse_rate_modifier_hash'
18
- require 'friendly_shipping/services/ups_json/parse_rates_response'
19
- require 'friendly_shipping/services/ups_json/parse_timings_response'
20
- require 'friendly_shipping/services/ups_json/parse_void_response'
21
- require 'friendly_shipping/services/ups_json/rates_item_options'
22
- require 'friendly_shipping/services/ups_json/rates_package_options'
23
- require 'friendly_shipping/services/ups_json/rates_options'
24
- require 'friendly_shipping/services/ups_json/shipping_methods'
25
- require 'friendly_shipping/services/ups_json/timings_options'
3
+ require "json"
26
4
 
27
5
  module FriendlyShipping
28
6
  module Services
@@ -182,6 +160,28 @@ module FriendlyShipping
182
160
  end
183
161
  end
184
162
 
163
+ # Find city and state for a given ZIP code
164
+ # @param [Physical::Location] location A location object with country and ZIP code set
165
+ # @return [Result<ApiResult<Array<Physical::Location>>>] The response data from UPS encoded in a
166
+ # `Physical::Location` object. Country, City and ZIP code will be set, everything else nil.
167
+ def city_state_lookup(location, debug: false)
168
+ url = "#{base_url}/api/addressvalidation/v2/1"
169
+ headers = required_headers(access_token)
170
+ body = GenerateCityStateLookupPayload.call(location: location).to_json
171
+
172
+ request = FriendlyShipping::Request.new(
173
+ url: url,
174
+ http_method: "POST",
175
+ headers: headers,
176
+ body: body,
177
+ debug: debug
178
+ )
179
+
180
+ client.post(request).bind do |response|
181
+ ParseCityStateLookupResponse.call(response: response, request: request)
182
+ end
183
+ end
184
+
185
185
  # Void a label, aka by UPS as the Shipping Void Shipment api:
186
186
  # https://developer.ups.com/api/reference?loc=en_US#tag/Shipping_other
187
187
  # @param [Label] label The label to be voided
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/usps/parse_xml_response'
4
- require 'friendly_shipping/services/usps/parse_package_rate'
5
- require 'friendly_shipping/services/usps/choose_package_rate'
6
-
7
3
  module FriendlyShipping
8
4
  module Services
9
5
  class Usps
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/usps/parse_xml_response'
4
- require 'friendly_shipping/timing'
5
-
6
3
  module FriendlyShipping
7
4
  module Services
8
5
  class Usps
@@ -36,7 +36,7 @@ module FriendlyShipping
36
36
 
37
37
  def wrap_failure(failure, request, response)
38
38
  Failure(
39
- FriendlyShipping::ApiFailure.new(
39
+ FriendlyShipping::ApiResult.new(
40
40
  failure,
41
41
  original_request: request,
42
42
  original_response: response
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/usps/rate_estimate_package_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  # Option container for rating a shipment via USPS
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups/rate_estimate_package_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  # Options for one package when rating
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/usps/machinable_package'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class Usps
@@ -1,17 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/http_client'
4
- require 'friendly_shipping/services/usps/shipping_methods'
5
- require 'friendly_shipping/services/usps/serialize_address_validation_request'
6
- require 'friendly_shipping/services/usps/serialize_city_state_lookup_request'
7
- require 'friendly_shipping/services/usps/serialize_rate_request'
8
- require 'friendly_shipping/services/usps/serialize_time_in_transit_request'
9
- require 'friendly_shipping/services/usps/parse_address_validation_response'
10
- require 'friendly_shipping/services/usps/parse_city_state_lookup_response'
11
- require 'friendly_shipping/services/usps/parse_rate_response'
12
- require 'friendly_shipping/services/usps/parse_time_in_transit_response'
13
- require 'friendly_shipping/services/usps/timing_options'
14
- require 'friendly_shipping/services/usps/rate_estimate_options'
3
+ require 'nokogiri'
15
4
 
16
5
  module FriendlyShipping
17
6
  module Services
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/usps/parse_xml_response'
4
- require 'friendly_shipping/services/usps_international/parse_package_rate'
5
-
6
3
  module FriendlyShipping
7
4
  module Services
8
5
  class UspsInternational
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/usps_international/rate_estimate_package_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  # Option container for rating a shipment via USPS
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/ups/rate_estimate_package_options'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  # Options for one package when rating
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/services/usps/machinable_package'
4
-
5
3
  module FriendlyShipping
6
4
  module Services
7
5
  class UspsInternational
@@ -1,10 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'friendly_shipping/http_client'
4
- require 'friendly_shipping/services/usps_international/shipping_methods'
5
- require 'friendly_shipping/services/usps_international/serialize_rate_request'
6
- require 'friendly_shipping/services/usps_international/parse_rate_response'
7
- require 'friendly_shipping/services/usps_international/rate_estimate_options'
3
+ require 'nokogiri'
8
4
 
9
5
  module FriendlyShipping
10
6
  module Services