friendly_shipping 0.3.4 → 0.4.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.
- checksums.yaml +4 -4
- data/.env.template +1 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +13 -4
- data/Gemfile +1 -0
- data/README.md +21 -2
- data/friendly_shipping.gemspec +1 -1
- data/lib/friendly_shipping/api_failure.rb +3 -0
- data/lib/friendly_shipping/api_result.rb +3 -0
- data/lib/friendly_shipping/carrier.rb +6 -0
- data/lib/friendly_shipping/http_client.rb +1 -0
- data/lib/friendly_shipping/item_options.rb +11 -0
- data/lib/friendly_shipping/label.rb +17 -9
- data/lib/friendly_shipping/package_options.rb +28 -0
- data/lib/friendly_shipping/rate.rb +9 -8
- data/lib/friendly_shipping/request.rb +4 -0
- data/lib/friendly_shipping/response.rb +3 -0
- data/lib/friendly_shipping/services/ship_engine.rb +10 -11
- data/lib/friendly_shipping/services/ship_engine/label_options.rb +34 -0
- data/lib/friendly_shipping/services/ship_engine/label_package_options.rb +28 -0
- data/lib/friendly_shipping/services/ship_engine/parse_label_response.rb +6 -1
- data/lib/friendly_shipping/services/ship_engine/parse_rate_estimate_response.rb +7 -7
- data/lib/friendly_shipping/services/ship_engine/rate_estimates_options.rb +25 -0
- data/lib/friendly_shipping/services/ship_engine/serialize_label_shipment.rb +15 -14
- data/lib/friendly_shipping/services/ship_engine/serialize_rate_estimate_request.rb +2 -2
- data/lib/friendly_shipping/services/ups.rb +47 -2
- data/lib/friendly_shipping/services/ups/label_billing_options.rb +41 -0
- data/lib/friendly_shipping/services/ups/label_item_options.rb +74 -0
- data/lib/friendly_shipping/services/ups/label_options.rb +165 -0
- data/lib/friendly_shipping/services/ups/label_package_options.rb +43 -0
- data/lib/friendly_shipping/services/ups/parse_money_element.rb +128 -0
- data/lib/friendly_shipping/services/ups/parse_rate_response.rb +8 -7
- data/lib/friendly_shipping/services/ups/parse_shipment_accept_response.rb +75 -0
- data/lib/friendly_shipping/services/ups/parse_shipment_confirm_response.rb +22 -0
- data/lib/friendly_shipping/services/ups/parse_xml_response.rb +2 -1
- data/lib/friendly_shipping/services/ups/serialize_address_snippet.rb +11 -6
- data/lib/friendly_shipping/services/ups/serialize_package_node.rb +21 -6
- data/lib/friendly_shipping/services/ups/serialize_shipment_accept_request.rb +27 -0
- data/lib/friendly_shipping/services/ups/serialize_shipment_address_snippet.rb +21 -0
- data/lib/friendly_shipping/services/ups/serialize_shipment_confirm_request.rb +282 -0
- data/lib/friendly_shipping/services/ups_freight.rb +76 -0
- data/lib/friendly_shipping/services/ups_freight/generate_commodity_information.rb +33 -0
- data/lib/friendly_shipping/services/ups_freight/generate_freight_rate_request_hash.rb +72 -0
- data/lib/friendly_shipping/services/ups_freight/generate_location_hash.rb +39 -0
- data/lib/friendly_shipping/services/ups_freight/generate_ups_security_hash.rb +23 -0
- data/lib/friendly_shipping/services/ups_freight/parse_freight_rate_response.rb +53 -0
- data/lib/friendly_shipping/services/ups_freight/parse_json_response.rb +38 -0
- data/lib/friendly_shipping/services/ups_freight/rates_item_options.rb +72 -0
- data/lib/friendly_shipping/services/ups_freight/rates_options.rb +54 -0
- data/lib/friendly_shipping/services/ups_freight/rates_package_options.rb +38 -0
- data/lib/friendly_shipping/services/ups_freight/shipping_methods.rb +25 -0
- data/lib/friendly_shipping/services/usps.rb +1 -1
- data/lib/friendly_shipping/services/usps/parse_xml_response.rb +1 -1
- data/lib/friendly_shipping/services/usps/serialize_rate_request.rb +0 -4
- data/lib/friendly_shipping/shipment_options.rb +23 -0
- data/lib/friendly_shipping/shipping_method.rb +7 -0
- data/lib/friendly_shipping/version.rb +1 -1
- metadata +33 -6
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'dry/monads/result'
|
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/rates_package_options'
|
8
|
+
require 'friendly_shipping/services/ups_freight/rates_item_options'
|
9
|
+
require 'friendly_shipping/services/ups_freight/parse_freight_rate_response'
|
10
|
+
require 'friendly_shipping/services/ups_freight/generate_freight_rate_request_hash'
|
11
|
+
require 'friendly_shipping/services/ups_freight/generate_ups_security_hash'
|
12
|
+
|
13
|
+
module FriendlyShipping
|
14
|
+
module Services
|
15
|
+
class UpsFreight
|
16
|
+
include Dry::Monads::Result::Mixin
|
17
|
+
|
18
|
+
attr_reader :test, :key, :login, :password, :client
|
19
|
+
|
20
|
+
CARRIER = FriendlyShipping::Carrier.new(
|
21
|
+
id: 'ups_freight',
|
22
|
+
name: 'United Parcel Service LTL',
|
23
|
+
code: 'ups-freight',
|
24
|
+
shipping_methods: SHIPPING_METHODS
|
25
|
+
)
|
26
|
+
|
27
|
+
TEST_URL = 'https://wwwcie.ups.com'
|
28
|
+
LIVE_URL = 'https://onlinetools.ups.com'
|
29
|
+
|
30
|
+
RESOURCES = {
|
31
|
+
rates: '/rest/FreightRate'
|
32
|
+
}.freeze
|
33
|
+
|
34
|
+
def initialize(key:, login:, password:, test: true, client: HttpClient.new)
|
35
|
+
@key = key
|
36
|
+
@login = login
|
37
|
+
@password = password
|
38
|
+
@test = test
|
39
|
+
@client = client
|
40
|
+
end
|
41
|
+
|
42
|
+
def carriers
|
43
|
+
Success([CARRIER])
|
44
|
+
end
|
45
|
+
|
46
|
+
# Get rates for a shipment
|
47
|
+
# @param [Physical::Shipment] location The shipment we want to get rates for
|
48
|
+
# @param [FriendlyShipping::Services::UpsFreight::RatesOptions] options Options for obtaining rates for this shipment.
|
49
|
+
# @return [Result<ApiResult<Array<Rate>>>] The rates returned from UPS encoded in a
|
50
|
+
# `FriendlyShipping::ApiResult` object.
|
51
|
+
def rate_estimates(shipment, options:, debug: false)
|
52
|
+
freight_rate_request_hash = GenerateFreightRateRequestHash.call(shipment: shipment, options: options)
|
53
|
+
url = base_url + RESOURCES[:rates]
|
54
|
+
request = FriendlyShipping::Request.new(
|
55
|
+
url: url,
|
56
|
+
body: authentication_hash.merge(freight_rate_request_hash).to_json,
|
57
|
+
debug: debug
|
58
|
+
)
|
59
|
+
|
60
|
+
client.post(request).bind do |response|
|
61
|
+
ParseFreightRateResponse.call(response: response, request: request)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def authentication_hash
|
68
|
+
GenerateUpsSecurityHash.call(key: key, login: login, password: password)
|
69
|
+
end
|
70
|
+
|
71
|
+
def base_url
|
72
|
+
test ? TEST_URL : LIVE_URL
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FriendlyShipping
|
4
|
+
module Services
|
5
|
+
class UpsFreight
|
6
|
+
class GenerateCommodityInformation
|
7
|
+
def self.call(shipment:, options:)
|
8
|
+
shipment.packages.flat_map do |package|
|
9
|
+
package_options = options.options_for_package(package)
|
10
|
+
package.items.map do |item|
|
11
|
+
item_options = package_options.options_for_item(item)
|
12
|
+
{
|
13
|
+
# This is a required field
|
14
|
+
Description: item.description || 'Commodities',
|
15
|
+
Weight: {
|
16
|
+
UnitOfMeasurement: {
|
17
|
+
Code: 'LBS' # Only Pounds are supported
|
18
|
+
},
|
19
|
+
Value: item.weight.convert_to(:pounds).value.to_f.round(2).to_s
|
20
|
+
},
|
21
|
+
NumberOfPieces: '1', # We won't support this yet.
|
22
|
+
PackagingType: {
|
23
|
+
Code: item_options.packaging_code
|
24
|
+
},
|
25
|
+
FreightClass: item_options.freight_class
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'friendly_shipping/services/ups_freight/generate_location_hash'
|
4
|
+
|
5
|
+
module FriendlyShipping
|
6
|
+
module Services
|
7
|
+
class UpsFreight
|
8
|
+
class GenerateFreightRateRequestHash
|
9
|
+
class << self
|
10
|
+
def call(shipment:, options:)
|
11
|
+
{
|
12
|
+
FreightRateRequest: {
|
13
|
+
Request: request_options(options.customer_context),
|
14
|
+
ShipperNumber: options.shipper_number,
|
15
|
+
ShipFrom: GenerateLocationHash.call(location: shipment.origin),
|
16
|
+
ShipTo: GenerateLocationHash.call(location: shipment.destination),
|
17
|
+
PaymentInformation: payment_information(options),
|
18
|
+
Service: {
|
19
|
+
Code: options.shipping_method.service_code
|
20
|
+
},
|
21
|
+
Commodity: options.commodity_information_generator.call(shipment: shipment, options: options),
|
22
|
+
TimeInTransitIndicator: true
|
23
|
+
}.compact.merge(handling_units(shipment, options).reduce(&:merge).to_h)
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def handling_units(shipment, options)
|
30
|
+
all_package_options = shipment.packages.map { |package| options.options_for_package(package) }
|
31
|
+
all_package_options.group_by(&:handling_unit_code).map do |_handling_unit_code, options_group|
|
32
|
+
[options_group.first, options_group.length]
|
33
|
+
end.map { |package_options, quantity| handling_unit_hash(package_options, quantity) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def handling_unit_hash(package_options, quantity)
|
37
|
+
{
|
38
|
+
package_options.handling_unit_tag => {
|
39
|
+
Quantity: quantity.to_s,
|
40
|
+
Type: {
|
41
|
+
Code: package_options.handling_unit_code,
|
42
|
+
Description: package_options.handling_unit_description
|
43
|
+
}
|
44
|
+
}
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def request_options(customer_context)
|
49
|
+
return {} unless customer_context
|
50
|
+
|
51
|
+
{
|
52
|
+
TransactionReference: {
|
53
|
+
CustomerContext: customer_context
|
54
|
+
}
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def payment_information(options)
|
59
|
+
payer_address = GenerateLocationHash.call(location: options.billing_address).
|
60
|
+
merge(ShipperNumber: options.shipper_number)
|
61
|
+
{
|
62
|
+
Payer: payer_address,
|
63
|
+
ShipmentBillingOption: {
|
64
|
+
Code: options.billing_code
|
65
|
+
}
|
66
|
+
}
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FriendlyShipping
|
4
|
+
module Services
|
5
|
+
class UpsFreight
|
6
|
+
class GenerateLocationHash
|
7
|
+
class << self
|
8
|
+
def call(location:)
|
9
|
+
# We ship freight here, which will mostly be used for businesses.
|
10
|
+
# If a personal name is given, treat is as the contact person ("AttentionName")
|
11
|
+
{
|
12
|
+
Name: location.company_name,
|
13
|
+
Address: {
|
14
|
+
AddressLine: address_line(location),
|
15
|
+
City: location.city,
|
16
|
+
StateProvinceCode: location.region.code,
|
17
|
+
PostalCode: location.zip,
|
18
|
+
CountryCode: location.country.code
|
19
|
+
},
|
20
|
+
AttentionName: location.name
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def address_line(location)
|
27
|
+
[
|
28
|
+
location.address1,
|
29
|
+
location.address2,
|
30
|
+
location.address3
|
31
|
+
].compact.
|
32
|
+
reject(&:empty?).
|
33
|
+
join(", ")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FriendlyShipping
|
4
|
+
module Services
|
5
|
+
class UpsFreight
|
6
|
+
class GenerateUpsSecurityHash
|
7
|
+
def self.call(login:, password:, key:)
|
8
|
+
{
|
9
|
+
UPSSecurity: {
|
10
|
+
UsernameToken: {
|
11
|
+
Username: login,
|
12
|
+
Password: password
|
13
|
+
},
|
14
|
+
ServiceAccessToken: {
|
15
|
+
AccessLicenseNumber: key
|
16
|
+
}
|
17
|
+
}
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'friendly_shipping/rate'
|
4
|
+
require 'friendly_shipping/api_result'
|
5
|
+
require 'friendly_shipping/services/ups_freight/parse_json_response'
|
6
|
+
require 'friendly_shipping/services/ups_freight/shipping_methods'
|
7
|
+
|
8
|
+
module FriendlyShipping
|
9
|
+
module Services
|
10
|
+
class UpsFreight
|
11
|
+
class ParseFreightRateResponse
|
12
|
+
class << self
|
13
|
+
def call(request:, response:)
|
14
|
+
parsed_json = ParseJSONResponse.call(response.body, 'FreightRateResponse')
|
15
|
+
|
16
|
+
parsed_json.fmap do |json|
|
17
|
+
service_code = json.dig("FreightRateResponse", "Service", "Code")
|
18
|
+
shipping_method = SHIPPING_METHODS.detect { |sm| sm.service_code == service_code }
|
19
|
+
total_shipment_charge = json.dig("FreightRateResponse", "TotalShipmentCharge")
|
20
|
+
currency = Money::Currency.new(total_shipment_charge['CurrencyCode'])
|
21
|
+
amount = total_shipment_charge['MonetaryValue'].to_f
|
22
|
+
total_money = Money.new(amount * currency.subunit_to_unit, currency)
|
23
|
+
data = {
|
24
|
+
customer_context: json.dig("FreightRateResponse", "TransactionReference", "TransactionIdentifier"),
|
25
|
+
commodities: Array.wrap(json.dig("FreightRateResponse", "Commodity")),
|
26
|
+
response_body: json
|
27
|
+
}
|
28
|
+
|
29
|
+
days_in_transit = json.dig("FreightRateResponse", "TimeInTransit", "DaysInTransit")
|
30
|
+
if days_in_transit
|
31
|
+
data[:days_in_transit] = days_in_transit.to_i
|
32
|
+
end
|
33
|
+
|
34
|
+
FriendlyShipping::ApiResult.new(
|
35
|
+
[
|
36
|
+
FriendlyShipping::Rate.new(
|
37
|
+
amounts: {
|
38
|
+
total: total_money
|
39
|
+
},
|
40
|
+
shipping_method: shipping_method,
|
41
|
+
data: data
|
42
|
+
)
|
43
|
+
],
|
44
|
+
original_request: request,
|
45
|
+
original_response: response
|
46
|
+
)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FriendlyShipping
|
4
|
+
module Services
|
5
|
+
class UpsFreight
|
6
|
+
class ParseJSONResponse
|
7
|
+
extend Dry::Monads::Result::Mixin
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def call(response_body, expected_root_tag)
|
11
|
+
json = JSON.parse(response_body)
|
12
|
+
|
13
|
+
if request_successful?(json, expected_root_tag)
|
14
|
+
Success(json)
|
15
|
+
else
|
16
|
+
Failure(error_message(json))
|
17
|
+
end
|
18
|
+
rescue JSON::ParserError => e
|
19
|
+
Failure(e)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def request_successful?(json, expected_root_tag)
|
25
|
+
json[expected_root_tag].present?
|
26
|
+
end
|
27
|
+
|
28
|
+
def error_message(json)
|
29
|
+
detailed_error = json.dig('Fault', 'detail', 'Errors', 'ErrorDetail', 'PrimaryErrorCode')
|
30
|
+
status = detailed_error['Code']
|
31
|
+
desc = detailed_error['Description']
|
32
|
+
[status, desc].compact.join(": ").presence || 'UPS could not process the request.'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FriendlyShipping
|
4
|
+
module Services
|
5
|
+
class UpsFreight
|
6
|
+
# Options for Items in a UPS Freight shipment
|
7
|
+
#
|
8
|
+
# @attribute [Symbol] packaging How the item is packaged, one of the keys of `PACKAGING_TYPES`
|
9
|
+
# @attribute [String] freight_class The freight class of this item, for example '55' or '92.5'
|
10
|
+
# @attribute [String] nmfc_code The national motor freight corporation code for this item. Something like '13050 sub 4'
|
11
|
+
class RatesItemOptions < FriendlyShipping::ItemOptions
|
12
|
+
PACKAGING_TYPES = {
|
13
|
+
bag: { code: "BAG", description: "Bag" },
|
14
|
+
bale: { code: "BAL", description: "Bale" },
|
15
|
+
barrel: { code: "BAR", description: "Barrel" },
|
16
|
+
bundle: { code: "BDL", description: "Bundle" },
|
17
|
+
bin: { code: "BIN", description: "Bin" },
|
18
|
+
box: { code: "BOX", description: "Box" },
|
19
|
+
basket: { code: "BSK", description: "Basket" },
|
20
|
+
bunch: { code: "BUN", description: "Bunch" },
|
21
|
+
cabinet: { code: "CAB", description: "Cabinet" },
|
22
|
+
can: { code: "CAN", description: "Can" },
|
23
|
+
carrier: { code: "CAR", description: "Carrier" },
|
24
|
+
case: { code: "CAS", description: "Case" },
|
25
|
+
carboy: { code: "CBY", description: "Carboy" },
|
26
|
+
container: { code: "CON", description: "Container" },
|
27
|
+
crate: { code: "CRT", description: "Crate" },
|
28
|
+
cask: { code: "CSK", description: "Cask" },
|
29
|
+
carton: { code: "CTN", description: "Carton" },
|
30
|
+
cylinder: { code: "CYL", description: "Cylinder" },
|
31
|
+
drum: { code: "DRM", description: "Drum" },
|
32
|
+
loose: { code: "LOO", description: "Loose" },
|
33
|
+
other: { code: "OTH", description: "Other" },
|
34
|
+
pail: { code: "PAL", description: "Pail" },
|
35
|
+
pieces: { code: "PCS", description: "Pieces" },
|
36
|
+
package: { code: "PKG", description: "Package" },
|
37
|
+
pipe_line: { code: "PLN", description: "Pipe Line" },
|
38
|
+
pallet: { code: "PLT", description: "Pallet" },
|
39
|
+
rack: { code: "RCK", description: "Rack" },
|
40
|
+
reel: { code: "REL", description: "Reel" },
|
41
|
+
roll: { code: "ROL", description: "Roll" },
|
42
|
+
skid: { code: "SKD", description: "Skid" },
|
43
|
+
spool: { code: "SPL", description: "Spool" },
|
44
|
+
tube: { code: "TBE", description: "Tube" },
|
45
|
+
tank: { code: "TNK", description: "Tank" },
|
46
|
+
totes: { code: "TOT", description: "Totes" },
|
47
|
+
unit: { code: "UNT", description: "Unit" },
|
48
|
+
van_pack: { code: "VPK", description: "Van Pack" },
|
49
|
+
wrapped: { code: "WRP", description: "Wrapped" }
|
50
|
+
}.freeze
|
51
|
+
|
52
|
+
attr_reader :packaging_code,
|
53
|
+
:packaging_description,
|
54
|
+
:freight_class,
|
55
|
+
:nmfc_code
|
56
|
+
|
57
|
+
def initialize(
|
58
|
+
packaging: :carton,
|
59
|
+
freight_class: nil,
|
60
|
+
nmfc_code: nil,
|
61
|
+
**kwargs
|
62
|
+
)
|
63
|
+
@packaging_code = PACKAGING_TYPES.fetch(packaging).fetch(:code)
|
64
|
+
@packaging_description = PACKAGING_TYPES.fetch(packaging).fetch(:description)
|
65
|
+
@freight_class = freight_class
|
66
|
+
@nmfc_code = nmfc_code
|
67
|
+
super kwargs
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'friendly_shipping/services/ups_freight/rates_package_options'
|
4
|
+
require 'friendly_shipping/services/ups_freight/generate_commodity_information'
|
5
|
+
|
6
|
+
module FriendlyShipping
|
7
|
+
module Services
|
8
|
+
class UpsFreight
|
9
|
+
# Options for generating UPS Freight rates for a shipment
|
10
|
+
#
|
11
|
+
# @attribute [Physical::Location] billing_address The billing address
|
12
|
+
# @attribute [String] shipper_number The shipper number associated with the shipper
|
13
|
+
# @attribute [String] customer_context A reference to match this request with an order or shipment
|
14
|
+
# @attribute [FriendlyShipping::ShippingMethod] shipping_method The shipping method to use
|
15
|
+
# @attribute [Callable] commodity_information_generator A callable that takes a shipment
|
16
|
+
# and an options object to create an Array of commodity fields as per the UPS docs.
|
17
|
+
# @attribute [Symbol] billing One of the keys in the `BILLING_CODES` constant. How the shipment
|
18
|
+
# would be billed.
|
19
|
+
# @attribute [RatesPackageOptions] package_options Options for each of the packages/pallets in this shipment
|
20
|
+
class RatesOptions < FriendlyShipping::ShipmentOptions
|
21
|
+
BILLING_CODES = {
|
22
|
+
prepaid: '10',
|
23
|
+
third_party: '30',
|
24
|
+
freight_collect: '40'
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
attr_reader :shipper_number,
|
28
|
+
:billing_address,
|
29
|
+
:billing_code,
|
30
|
+
:customer_context,
|
31
|
+
:shipping_method,
|
32
|
+
:commodity_information_generator
|
33
|
+
|
34
|
+
def initialize(
|
35
|
+
shipper_number:,
|
36
|
+
billing_address:,
|
37
|
+
shipping_method:,
|
38
|
+
billing: :prepaid,
|
39
|
+
customer_context: nil,
|
40
|
+
commodity_information_generator: GenerateCommodityInformation,
|
41
|
+
**kwargs
|
42
|
+
)
|
43
|
+
@shipper_number = shipper_number
|
44
|
+
@billing_address = billing_address
|
45
|
+
@shipping_method = shipping_method
|
46
|
+
@billing_code = BILLING_CODES.fetch(billing)
|
47
|
+
@customer_context = customer_context
|
48
|
+
@commodity_information_generator = commodity_information_generator
|
49
|
+
super kwargs.merge(package_options_class: RatesPackageOptions)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|