friendly_shipping 0.7.3 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.env.template +4 -0
- data/.env.test +4 -0
- data/CHANGELOG.md +23 -0
- data/friendly_shipping.gemspec +1 -1
- data/lib/friendly_shipping/package_options.rb +4 -0
- data/lib/friendly_shipping/rate.rb +1 -1
- data/lib/friendly_shipping/services/ship_engine/label_customs_options.rb +25 -0
- data/lib/friendly_shipping/services/ship_engine/label_item_options.rb +27 -0
- data/lib/friendly_shipping/services/ship_engine/label_options.rb +5 -1
- data/lib/friendly_shipping/services/ship_engine/label_package_options.rb +2 -1
- data/lib/friendly_shipping/services/ship_engine/serialize_label_shipment.rb +37 -0
- data/lib/friendly_shipping/services/ship_engine_ltl/bad_request.rb +9 -0
- data/lib/friendly_shipping/services/ship_engine_ltl/bad_request_handler.rb +33 -0
- data/lib/friendly_shipping/services/ship_engine_ltl/item_options.rb +31 -0
- data/lib/friendly_shipping/services/ship_engine_ltl/package_options.rb +15 -0
- data/lib/friendly_shipping/services/ship_engine_ltl/parse_carrier_response.rb +49 -0
- data/lib/friendly_shipping/services/ship_engine_ltl/parse_quote_response.rb +72 -0
- data/lib/friendly_shipping/services/ship_engine_ltl/quote_options.rb +34 -0
- data/lib/friendly_shipping/services/ship_engine_ltl/serialize_packages.rb +41 -0
- data/lib/friendly_shipping/services/ship_engine_ltl/serialize_quote_request.rb +109 -0
- data/lib/friendly_shipping/services/ship_engine_ltl.rb +133 -0
- data/lib/friendly_shipping/services/ups/label_item_options.rb +4 -1
- data/lib/friendly_shipping/services/ups/label_package_options.rb +7 -3
- data/lib/friendly_shipping/services/ups/parse_rate_response.rb +3 -3
- data/lib/friendly_shipping/services/ups/parse_shipment_accept_response.rb +1 -1
- data/lib/friendly_shipping/services/ups/serialize_address_snippet.rb +5 -2
- data/lib/friendly_shipping/services/ups/serialize_package_node.rb +11 -1
- data/lib/friendly_shipping/services/ups/serialize_shipment_confirm_request.rb +11 -7
- data/lib/friendly_shipping/services/ups_freight/api_error.rb +2 -0
- data/lib/friendly_shipping/services/ups_freight/generate_location_hash.rb +10 -6
- data/lib/friendly_shipping/services/usps/parse_package_rate.rb +2 -1
- data/lib/friendly_shipping/services/usps/parse_time_in_transit_response.rb +6 -2
- data/lib/friendly_shipping/services/usps/rate_estimate_package_options.rb +4 -8
- data/lib/friendly_shipping/services/usps/shipping_methods.rb +4 -2
- data/lib/friendly_shipping/services/usps_international/parse_package_rate.rb +81 -0
- data/lib/friendly_shipping/services/usps_international/parse_rate_response.rb +86 -0
- data/lib/friendly_shipping/services/usps_international/rate_estimate_options.rb +28 -0
- data/lib/friendly_shipping/services/usps_international/rate_estimate_package_options.rb +45 -0
- data/lib/friendly_shipping/services/usps_international/serialize_rate_request.rb +75 -0
- data/lib/friendly_shipping/services/usps_international/shipping_methods.rb +38 -0
- data/lib/friendly_shipping/services/usps_international.rb +80 -0
- data/lib/friendly_shipping/version.rb +1 -1
- data/lib/friendly_shipping.rb +2 -0
- metadata +24 -3
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'friendly_shipping/services/ups/rate_estimate_package_options'
|
4
|
+
|
5
|
+
module FriendlyShipping
|
6
|
+
module Services
|
7
|
+
# Options for one package when rating
|
8
|
+
#
|
9
|
+
# @param [Symbol] box_name The type of box we want to get rates for.
|
10
|
+
# @param [Boolean] commercial_pricing Indicate whether the response should include commercial pricing rates.
|
11
|
+
# @param [Boolean] commercial_plus_pricing Indicate whether the response should include commercial pluse pricing rates.
|
12
|
+
# @param [Symbol] container_code Indicate the type of container of the package.
|
13
|
+
# @param [Symbol] mail_type Indicate the type of mail to estimate rates.
|
14
|
+
# @param [Boolean] rectangular Indicate whether the package is rectangular.
|
15
|
+
# @param [FriendlyShipping::ShippingMethod] shipping_method Describe the requested shipping method.
|
16
|
+
# @param [Symbol] transmit_dimensions Indicate whether the request should include the package dimensionals.
|
17
|
+
class UspsInternational
|
18
|
+
class RateEstimatePackageOptions < FriendlyShipping::PackageOptions
|
19
|
+
attr_reader :box_name,
|
20
|
+
:commercial_pricing,
|
21
|
+
:commercial_plus_pricing,
|
22
|
+
:container,
|
23
|
+
:mail_type,
|
24
|
+
:rectangular,
|
25
|
+
:shipping_method,
|
26
|
+
:transmit_dimensions
|
27
|
+
|
28
|
+
def initialize(**kwargs)
|
29
|
+
container_code = value_or_default(:container, :variable, kwargs) || :variable
|
30
|
+
mail_type_code = value_or_default(:mail_type, :all, kwargs) || :all
|
31
|
+
|
32
|
+
@box_name = value_or_default(:box_name, :variable, kwargs)
|
33
|
+
@commercial_pricing = value_or_default(:commercial_pricing, false, kwargs) ? 'Y' : 'N'
|
34
|
+
@commercial_plus_pricing = value_or_default(:commercial_plus_pricing, false, kwargs) ? 'Y' : 'N'
|
35
|
+
@container = CONTAINERS.fetch(container_code)
|
36
|
+
@mail_type = MAIL_TYPES.fetch(mail_type_code)
|
37
|
+
@rectangular = @container.eql?("ROLL") ? false : value_or_default(:rectangular, true, kwargs)
|
38
|
+
@shipping_method = kwargs.delete(:shipping_method)
|
39
|
+
@transmit_dimensions = value_or_default(:transmit_dimensions, true, kwargs)
|
40
|
+
super(**kwargs)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'friendly_shipping/services/usps/machinable_package'
|
4
|
+
|
5
|
+
module FriendlyShipping
|
6
|
+
module Services
|
7
|
+
class UspsInternational
|
8
|
+
class SerializeRateRequest
|
9
|
+
class << self
|
10
|
+
# @param [Physical::Shipment] shipment The shipment we want to get rates for
|
11
|
+
# shipment.packages[0].properties[:box_name] Can be :variable or a
|
12
|
+
# flat rate container defined in CONTAINERS.
|
13
|
+
# @param [String] login The USPS login code
|
14
|
+
# @param [FriendlyShipping::Services::UspsInternational::RateEstimateOptions] options The options
|
15
|
+
# object to use with this request.
|
16
|
+
# @return Array<[FriendlyShipping::Rate]> A set of Rates that this package may be sent with
|
17
|
+
def call(shipment:, login:, options:)
|
18
|
+
xml_builder = Nokogiri::XML::Builder.new do |xml|
|
19
|
+
xml.IntlRateV2Request('USERID' => login) do
|
20
|
+
xml.Revision("2")
|
21
|
+
shipment.packages.each_with_index do |package, index|
|
22
|
+
xml.Package('ID' => index) do
|
23
|
+
xml.Pounds(pounds_for(package))
|
24
|
+
xml.Ounces(ounces_for(package))
|
25
|
+
xml.Machinable(machinable(package))
|
26
|
+
package_options = options.options_for_package(package)
|
27
|
+
xml.MailType(package_options.mail_type)
|
28
|
+
xml.ValueOfContents(package.items_value)
|
29
|
+
xml.Country(shipment.destination.country)
|
30
|
+
xml.Container(package_options.container)
|
31
|
+
if package_options.transmit_dimensions && package_options.container == 'VARIABLE'
|
32
|
+
xml.Width("%<width>0.2f" % { width: package.width.convert_to(:inches).value.to_f })
|
33
|
+
xml.Length("%<length>0.2f" % { length: package.length.convert_to(:inches).value.to_f })
|
34
|
+
xml.Height("%<height>0.2f" % { height: package.height.convert_to(:inches).value.to_f })
|
35
|
+
|
36
|
+
# When girth is present, the package is treated as non-rectangular
|
37
|
+
# when calculating dimensional weight. This results in a smaller
|
38
|
+
# dimensional weight than a rectangular package would have.
|
39
|
+
unless package_options.rectangular
|
40
|
+
xml.Girth("%<girth>0.2f" % { girth: girth(package) })
|
41
|
+
end
|
42
|
+
xml.CommercialFlag(package_options.commercial_pricing)
|
43
|
+
xml.CommercialPlusFlag(package_options.commercial_plus_pricing)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
xml_builder.to_xml
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def machinable(package)
|
55
|
+
FriendlyShipping::Services::Usps::MachinablePackage.new(package).machinable? ? 'true' : 'false'
|
56
|
+
end
|
57
|
+
|
58
|
+
def ounces_for(package)
|
59
|
+
ounces = (package.weight.convert_to(:ounces).value.to_f % 16).round(2).ceil
|
60
|
+
ounces == 16 ? 15.999 : [ounces, 1].max
|
61
|
+
end
|
62
|
+
|
63
|
+
def pounds_for(package)
|
64
|
+
package.weight.convert_to(:pounds).value.to_f.floor
|
65
|
+
end
|
66
|
+
|
67
|
+
def girth(package)
|
68
|
+
width, length = package.dimensions.sort.first(2)
|
69
|
+
(width.scale(2) + length.scale(2)).convert_to(:inches).value.to_f
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FriendlyShipping
|
4
|
+
module Services
|
5
|
+
class UspsInternational
|
6
|
+
SHIPPING_METHODS = [
|
7
|
+
["1", "Priority Mail Express International"],
|
8
|
+
["2", "Priority Mail International"],
|
9
|
+
["4", "Global Express Guaranteed; (GXG)"],
|
10
|
+
["5", "Global Express Guaranteed; Document"],
|
11
|
+
["6", "Global Express Guarantee; Non-Document Rectangular"],
|
12
|
+
["7", "Global Express Guaranteed; Non-Document Non-Rectangular"],
|
13
|
+
["8", "Priority Mail International; Flat Rate Envelope"],
|
14
|
+
["9", "Priority Mail International; Medium Flat Rate Box"],
|
15
|
+
["10", "Priority Mail Express International; Flat Rate Envelope"],
|
16
|
+
["11", "Priority Mail International; Large Flat Rate Box"],
|
17
|
+
["12", "USPS GXG; Envelopes"],
|
18
|
+
["13", "First-Class Mail; International Letter"],
|
19
|
+
["14", "First-Class Mail; International Large Envelope"],
|
20
|
+
["15", "First-Class Package International Service"],
|
21
|
+
["16", "Priority Mail International; Small Flat Rate Box"],
|
22
|
+
["17", "Priority Mail Express International; Legal Flat Rate Envelope"],
|
23
|
+
["18", "Priority Mail International; Gift Card Flat Rate Envelope"],
|
24
|
+
["19", "Priority Mail International; Window Flat Rate Envelope"],
|
25
|
+
["20", "Priority Mail International; Small Flat Rate Envelope"],
|
26
|
+
["28", "Airmail M-Bag"]
|
27
|
+
].map do |code, name|
|
28
|
+
FriendlyShipping::ShippingMethod.new(
|
29
|
+
origin_countries: [Carmen::Country.coded('US')],
|
30
|
+
name: name,
|
31
|
+
service_code: code,
|
32
|
+
domestic: false,
|
33
|
+
international: true,
|
34
|
+
)
|
35
|
+
end.freeze
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
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'
|
8
|
+
|
9
|
+
module FriendlyShipping
|
10
|
+
module Services
|
11
|
+
class UspsInternational
|
12
|
+
include Dry::Monads[:result]
|
13
|
+
|
14
|
+
attr_reader :test, :login, :client
|
15
|
+
|
16
|
+
CONTAINERS = {
|
17
|
+
rectanglular: 'RECTANGULAR',
|
18
|
+
roll: 'ROLL',
|
19
|
+
variable: 'VARIABLE'
|
20
|
+
}.freeze
|
21
|
+
|
22
|
+
MAIL_TYPES = {
|
23
|
+
all: 'ALL',
|
24
|
+
airmail: 'AIRMAIL MBAG',
|
25
|
+
envelope: 'ENVELOPE',
|
26
|
+
flat_rate: 'FLATRATE',
|
27
|
+
letter: 'LETTER',
|
28
|
+
large_envelope: 'LARGEENVELOPE',
|
29
|
+
package: 'PACKAGE',
|
30
|
+
post_cards: 'POSTCARDS'
|
31
|
+
}.freeze
|
32
|
+
|
33
|
+
TEST_URL = 'https://stg-secure.shippingapis.com/ShippingAPI.dll'
|
34
|
+
LIVE_URL = 'https://secure.shippingapis.com/ShippingAPI.dll'
|
35
|
+
|
36
|
+
RESOURCES = {
|
37
|
+
rates: 'IntlRateV2',
|
38
|
+
}.freeze
|
39
|
+
|
40
|
+
def initialize(login:, test: true, client: HttpClient.new)
|
41
|
+
@login = login
|
42
|
+
@test = test
|
43
|
+
@client = client
|
44
|
+
end
|
45
|
+
|
46
|
+
# Get rate estimates from USPS International
|
47
|
+
#
|
48
|
+
# @param [Physical::Shipment] shipment
|
49
|
+
# @param [FriendlyShipping::Services::UspsInternational::RateEstimateOptions] options What options
|
50
|
+
# to use for this rate estimate call
|
51
|
+
#
|
52
|
+
# @return [Result<Array<FriendlyShipping::Rate>>] When successfully parsing, an array of rates in a Success Monad.
|
53
|
+
# When the parsing is not successful or USPS can't give us rates, a Failure monad containing something that
|
54
|
+
# can be serialized into an error message using `to_s`.
|
55
|
+
def rate_estimates(shipment, options: RateEstimateOptions.new, debug: false)
|
56
|
+
rate_request_xml = SerializeRateRequest.call(shipment: shipment, login: login, options: options)
|
57
|
+
request = build_request(api: :rates, xml: rate_request_xml, debug: debug)
|
58
|
+
client.post(request).bind do |response|
|
59
|
+
ParseRateResponse.call(response: response, request: request, shipment: shipment, options: options)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def build_request(api:, xml:, debug:)
|
66
|
+
FriendlyShipping::Request.new(
|
67
|
+
url: base_url,
|
68
|
+
http_method: "POST",
|
69
|
+
body: "API=#{RESOURCES[api]}&XML=#{CGI.escape xml}",
|
70
|
+
readable_body: xml,
|
71
|
+
debug: debug
|
72
|
+
)
|
73
|
+
end
|
74
|
+
|
75
|
+
def base_url
|
76
|
+
test ? TEST_URL : LIVE_URL
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/friendly_shipping.rb
CHANGED
@@ -17,9 +17,11 @@ require "friendly_shipping/api_result"
|
|
17
17
|
require "friendly_shipping/api_failure"
|
18
18
|
|
19
19
|
require "friendly_shipping/services/ship_engine"
|
20
|
+
require 'friendly_shipping/services/ship_engine_ltl'
|
20
21
|
require "friendly_shipping/services/ups"
|
21
22
|
require "friendly_shipping/services/ups_freight"
|
22
23
|
require "friendly_shipping/services/usps"
|
24
|
+
require "friendly_shipping/services/usps_international"
|
23
25
|
|
24
26
|
module FriendlyShipping
|
25
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: friendly_shipping
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Meyerhoff
|
8
|
+
- Matthew Bass
|
8
9
|
autorequire:
|
9
10
|
bindir: exe
|
10
11
|
cert_chain: []
|
11
|
-
date: 2023-
|
12
|
+
date: 2023-08-03 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: dry-monads
|
@@ -255,6 +256,7 @@ extra_rdoc_files: []
|
|
255
256
|
files:
|
256
257
|
- ".circleci/config.yml"
|
257
258
|
- ".env.template"
|
259
|
+
- ".env.test"
|
258
260
|
- ".github/dependabot.yml"
|
259
261
|
- ".gitignore"
|
260
262
|
- ".rspec"
|
@@ -286,6 +288,8 @@ files:
|
|
286
288
|
- lib/friendly_shipping/services/ship_engine.rb
|
287
289
|
- lib/friendly_shipping/services/ship_engine/bad_request.rb
|
288
290
|
- lib/friendly_shipping/services/ship_engine/bad_request_handler.rb
|
291
|
+
- lib/friendly_shipping/services/ship_engine/label_customs_options.rb
|
292
|
+
- lib/friendly_shipping/services/ship_engine/label_item_options.rb
|
289
293
|
- lib/friendly_shipping/services/ship_engine/label_options.rb
|
290
294
|
- lib/friendly_shipping/services/ship_engine/label_package_options.rb
|
291
295
|
- lib/friendly_shipping/services/ship_engine/parse_carrier_response.rb
|
@@ -295,6 +299,16 @@ files:
|
|
295
299
|
- lib/friendly_shipping/services/ship_engine/rate_estimates_options.rb
|
296
300
|
- lib/friendly_shipping/services/ship_engine/serialize_label_shipment.rb
|
297
301
|
- lib/friendly_shipping/services/ship_engine/serialize_rate_estimate_request.rb
|
302
|
+
- lib/friendly_shipping/services/ship_engine_ltl.rb
|
303
|
+
- lib/friendly_shipping/services/ship_engine_ltl/bad_request.rb
|
304
|
+
- lib/friendly_shipping/services/ship_engine_ltl/bad_request_handler.rb
|
305
|
+
- lib/friendly_shipping/services/ship_engine_ltl/item_options.rb
|
306
|
+
- lib/friendly_shipping/services/ship_engine_ltl/package_options.rb
|
307
|
+
- lib/friendly_shipping/services/ship_engine_ltl/parse_carrier_response.rb
|
308
|
+
- lib/friendly_shipping/services/ship_engine_ltl/parse_quote_response.rb
|
309
|
+
- lib/friendly_shipping/services/ship_engine_ltl/quote_options.rb
|
310
|
+
- lib/friendly_shipping/services/ship_engine_ltl/serialize_packages.rb
|
311
|
+
- lib/friendly_shipping/services/ship_engine_ltl/serialize_quote_request.rb
|
298
312
|
- lib/friendly_shipping/services/ups.rb
|
299
313
|
- lib/friendly_shipping/services/ups/label.rb
|
300
314
|
- lib/friendly_shipping/services/ups/label_billing_options.rb
|
@@ -372,6 +386,13 @@ files:
|
|
372
386
|
- lib/friendly_shipping/services/usps/serialize_time_in_transit_request.rb
|
373
387
|
- lib/friendly_shipping/services/usps/shipping_methods.rb
|
374
388
|
- lib/friendly_shipping/services/usps/timing_options.rb
|
389
|
+
- lib/friendly_shipping/services/usps_international.rb
|
390
|
+
- lib/friendly_shipping/services/usps_international/parse_package_rate.rb
|
391
|
+
- lib/friendly_shipping/services/usps_international/parse_rate_response.rb
|
392
|
+
- lib/friendly_shipping/services/usps_international/rate_estimate_options.rb
|
393
|
+
- lib/friendly_shipping/services/usps_international/rate_estimate_package_options.rb
|
394
|
+
- lib/friendly_shipping/services/usps_international/serialize_rate_request.rb
|
395
|
+
- lib/friendly_shipping/services/usps_international/shipping_methods.rb
|
375
396
|
- lib/friendly_shipping/shipment_options.rb
|
376
397
|
- lib/friendly_shipping/shipping_method.rb
|
377
398
|
- lib/friendly_shipping/timing.rb
|
@@ -396,7 +417,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
396
417
|
- !ruby/object:Gem::Version
|
397
418
|
version: '0'
|
398
419
|
requirements: []
|
399
|
-
rubygems_version: 3.
|
420
|
+
rubygems_version: 3.4.10
|
400
421
|
signing_key:
|
401
422
|
specification_version: 4
|
402
423
|
summary: An integration layer for shipping services
|