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.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.env.template +1 -0
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +13 -4
  5. data/Gemfile +1 -0
  6. data/README.md +21 -2
  7. data/friendly_shipping.gemspec +1 -1
  8. data/lib/friendly_shipping/api_failure.rb +3 -0
  9. data/lib/friendly_shipping/api_result.rb +3 -0
  10. data/lib/friendly_shipping/carrier.rb +6 -0
  11. data/lib/friendly_shipping/http_client.rb +1 -0
  12. data/lib/friendly_shipping/item_options.rb +11 -0
  13. data/lib/friendly_shipping/label.rb +17 -9
  14. data/lib/friendly_shipping/package_options.rb +28 -0
  15. data/lib/friendly_shipping/rate.rb +9 -8
  16. data/lib/friendly_shipping/request.rb +4 -0
  17. data/lib/friendly_shipping/response.rb +3 -0
  18. data/lib/friendly_shipping/services/ship_engine.rb +10 -11
  19. data/lib/friendly_shipping/services/ship_engine/label_options.rb +34 -0
  20. data/lib/friendly_shipping/services/ship_engine/label_package_options.rb +28 -0
  21. data/lib/friendly_shipping/services/ship_engine/parse_label_response.rb +6 -1
  22. data/lib/friendly_shipping/services/ship_engine/parse_rate_estimate_response.rb +7 -7
  23. data/lib/friendly_shipping/services/ship_engine/rate_estimates_options.rb +25 -0
  24. data/lib/friendly_shipping/services/ship_engine/serialize_label_shipment.rb +15 -14
  25. data/lib/friendly_shipping/services/ship_engine/serialize_rate_estimate_request.rb +2 -2
  26. data/lib/friendly_shipping/services/ups.rb +47 -2
  27. data/lib/friendly_shipping/services/ups/label_billing_options.rb +41 -0
  28. data/lib/friendly_shipping/services/ups/label_item_options.rb +74 -0
  29. data/lib/friendly_shipping/services/ups/label_options.rb +165 -0
  30. data/lib/friendly_shipping/services/ups/label_package_options.rb +43 -0
  31. data/lib/friendly_shipping/services/ups/parse_money_element.rb +128 -0
  32. data/lib/friendly_shipping/services/ups/parse_rate_response.rb +8 -7
  33. data/lib/friendly_shipping/services/ups/parse_shipment_accept_response.rb +75 -0
  34. data/lib/friendly_shipping/services/ups/parse_shipment_confirm_response.rb +22 -0
  35. data/lib/friendly_shipping/services/ups/parse_xml_response.rb +2 -1
  36. data/lib/friendly_shipping/services/ups/serialize_address_snippet.rb +11 -6
  37. data/lib/friendly_shipping/services/ups/serialize_package_node.rb +21 -6
  38. data/lib/friendly_shipping/services/ups/serialize_shipment_accept_request.rb +27 -0
  39. data/lib/friendly_shipping/services/ups/serialize_shipment_address_snippet.rb +21 -0
  40. data/lib/friendly_shipping/services/ups/serialize_shipment_confirm_request.rb +282 -0
  41. data/lib/friendly_shipping/services/ups_freight.rb +76 -0
  42. data/lib/friendly_shipping/services/ups_freight/generate_commodity_information.rb +33 -0
  43. data/lib/friendly_shipping/services/ups_freight/generate_freight_rate_request_hash.rb +72 -0
  44. data/lib/friendly_shipping/services/ups_freight/generate_location_hash.rb +39 -0
  45. data/lib/friendly_shipping/services/ups_freight/generate_ups_security_hash.rb +23 -0
  46. data/lib/friendly_shipping/services/ups_freight/parse_freight_rate_response.rb +53 -0
  47. data/lib/friendly_shipping/services/ups_freight/parse_json_response.rb +38 -0
  48. data/lib/friendly_shipping/services/ups_freight/rates_item_options.rb +72 -0
  49. data/lib/friendly_shipping/services/ups_freight/rates_options.rb +54 -0
  50. data/lib/friendly_shipping/services/ups_freight/rates_package_options.rb +38 -0
  51. data/lib/friendly_shipping/services/ups_freight/shipping_methods.rb +25 -0
  52. data/lib/friendly_shipping/services/usps.rb +1 -1
  53. data/lib/friendly_shipping/services/usps/parse_xml_response.rb +1 -1
  54. data/lib/friendly_shipping/services/usps/serialize_rate_request.rb +0 -4
  55. data/lib/friendly_shipping/shipment_options.rb +23 -0
  56. data/lib/friendly_shipping/shipping_method.rb +7 -0
  57. data/lib/friendly_shipping/version.rb +1 -1
  58. metadata +33 -6
@@ -19,6 +19,10 @@ module FriendlyShipping
19
19
  label_url = label_uri_string
20
20
  end
21
21
 
22
+ currency = parsed_json.dig('shipment_cost', 'currency')
23
+ cents = parsed_json.dig('shipment_cost', 'amount') * 100
24
+ shipment_cost = Money.new(cents, currency)
25
+
22
26
  label = FriendlyShipping::Label.new(
23
27
  id: parsed_json['label_id'],
24
28
  shipment_id: parsed_json['shipment_id'],
@@ -27,7 +31,8 @@ module FriendlyShipping
27
31
  label_href: label_url,
28
32
  label_data: label_data,
29
33
  label_format: parsed_json['label_format'].to_sym,
30
- shipment_cost: parsed_json['shipment_cost']['amount'],
34
+ shipment_cost: shipment_cost,
35
+ cost: shipment_cost,
31
36
  data: parsed_json
32
37
  )
33
38
 
@@ -10,14 +10,16 @@ module FriendlyShipping
10
10
  extend Dry::Monads::Result::Mixin
11
11
 
12
12
  class << self
13
- def call(response:, carriers:, request:)
13
+ def call(response:, request:, options:)
14
14
  parsed_json = JSON.parse(response.body)
15
15
  rates = parsed_json.map do |rate|
16
- carrier = carriers.detect { |c| c.id == rate['carrier_id'] }
16
+ carrier = options.carriers.detect { |c| c.id == rate['carrier_id'] }
17
17
  next unless carrier
18
18
 
19
- shipping_method = carrier.shipping_methods.detect { |sm| sm.service_code == rate['service_code'] }
20
- next unless shipping_method
19
+ shipping_method = FriendlyShipping::ShippingMethod.new(
20
+ carrier: carrier,
21
+ service_code: rate['service_code']
22
+ )
21
23
 
22
24
  amounts = get_amounts(rate)
23
25
  FriendlyShipping::Rate.new(
@@ -26,9 +28,7 @@ module FriendlyShipping
26
28
  remote_service_id: rate['rate_id'],
27
29
  delivery_date: Time.parse(rate['estimated_delivery_date']),
28
30
  warnings: rate['warning_messages'],
29
- errors: rate['error_messages'],
30
- original_request: request,
31
- original_response: response
31
+ errors: rate['error_messages']
32
32
  )
33
33
  end.compact
34
34
 
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'friendly_shipping/shipment_options'
4
+
5
+ module FriendlyShipping
6
+ module Services
7
+ class ShipEngine
8
+ # options for the rate estimates call
9
+ #
10
+ # @attribute carriers [Array<FriendlyShipping::Carrier] a list of the carriers we want to get IDs from.
11
+ class RateEstimatesOptions < ShipmentOptions
12
+ attr_reader :carriers
13
+
14
+ def initialize(carriers:, **kwargs)
15
+ @carriers = carriers
16
+ super kwargs
17
+ end
18
+
19
+ def carrier_ids
20
+ carriers.map(&:id)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -5,20 +5,20 @@ module FriendlyShipping
5
5
  class ShipEngine
6
6
  class SerializeLabelShipment
7
7
  class << self
8
- def call(shipment:, shipping_method:, test:)
8
+ def call(shipment:, options:, test:)
9
9
  shipment_hash = {
10
- label_format: shipment.options[:label_format].presence || "pdf",
11
- label_download_type: shipment.options[:label_download_type].presence || "url",
10
+ label_format: options.label_format,
11
+ label_download_type: options.label_download_type,
12
12
  shipment: {
13
- service_code: shipping_method.service_code,
13
+ service_code: options.shipping_method.service_code,
14
14
  ship_to: serialize_address(shipment.destination),
15
15
  ship_from: serialize_address(shipment.origin),
16
- packages: serialize_packages(shipment.packages)
16
+ packages: serialize_packages(shipment.packages, options)
17
17
  }
18
18
  }
19
19
  # A carrier might not be necessary if the service code is unique within ShipEngine.
20
- if shipping_method.carrier
21
- shipment_hash[:shipment][:carrier_id] = shipping_method.carrier.id
20
+ if options.shipping_method.carrier
21
+ shipment_hash[:shipment][:carrier_id] = options.shipping_method.carrier.id
22
22
  end
23
23
 
24
24
  if test
@@ -45,15 +45,16 @@ module FriendlyShipping
45
45
  }
46
46
  end
47
47
 
48
- def serialize_packages(packages)
48
+ def serialize_packages(packages, options)
49
49
  packages.map do |package|
50
+ package_options = options.options_for_package(package)
50
51
  package_hash = serialize_weight(package.weight)
51
- if package.container.properties[:usps_label_messages]
52
- package_hash[:label_messages] = package.container.properties[:usps_label_messages]
53
- end
54
- package_code = package.container.properties[:usps_package_code]
55
- if package_code
56
- package_hash[:package_code] = package_code
52
+ package_hash[:label_messages] = package_options.messages.map.with_index do |message, index|
53
+ ["reference#{index + 1}".to_sym, message]
54
+ end.to_h
55
+
56
+ if package_options.package_code
57
+ package_hash[:package_code] = package_options.package_code
57
58
  else
58
59
  package_hash[:dimensions] = {
59
60
  unit: 'inch',
@@ -4,9 +4,9 @@ module FriendlyShipping
4
4
  module Services
5
5
  class ShipEngine
6
6
  class SerializeRateEstimateRequest
7
- def self.call(shipment:, carriers:)
7
+ def self.call(shipment:, options:)
8
8
  {
9
- carrier_ids: carriers.map(&:id),
9
+ carrier_ids: options.carrier_ids,
10
10
  from_country_code: shipment.origin.country.alpha_2_code,
11
11
  from_postal_code: shipment.origin.zip,
12
12
  to_country_code: shipment.destination.country.alpha_2_code,
@@ -6,11 +6,16 @@ require 'friendly_shipping/services/ups/serialize_access_request'
6
6
  require 'friendly_shipping/services/ups/serialize_city_state_lookup_request'
7
7
  require 'friendly_shipping/services/ups/serialize_address_validation_request'
8
8
  require 'friendly_shipping/services/ups/serialize_rating_service_selection_request'
9
- require 'friendly_shipping/services/ups/parse_address_classification_response'
9
+ require 'friendly_shipping/services/ups/serialize_shipment_accept_request'
10
+ require 'friendly_shipping/services/ups/serialize_shipment_confirm_request'
10
11
  require 'friendly_shipping/services/ups/parse_address_validation_response'
12
+ require 'friendly_shipping/services/ups/parse_address_classification_response'
11
13
  require 'friendly_shipping/services/ups/parse_city_state_lookup_response'
12
14
  require 'friendly_shipping/services/ups/parse_rate_response'
15
+ require 'friendly_shipping/services/ups/parse_shipment_confirm_response'
16
+ require 'friendly_shipping/services/ups/parse_shipment_accept_response'
13
17
  require 'friendly_shipping/services/ups/shipping_methods'
18
+ require 'friendly_shipping/services/ups/label_options'
14
19
 
15
20
  module FriendlyShipping
16
21
  module Services
@@ -32,7 +37,9 @@ module FriendlyShipping
32
37
  RESOURCES = {
33
38
  address_validation: '/ups.app/xml/XAV',
34
39
  city_state_lookup: '/ups.app/xml/AV',
35
- rates: '/ups.app/xml/Rate'
40
+ rates: '/ups.app/xml/Rate',
41
+ ship_confirm: '/ups.app/xml/ShipConfirm',
42
+ ship_accept: '/ups.app/xml/ShipAccept',
36
43
  }.freeze
37
44
 
38
45
  def initialize(key:, login:, password:, test: true, client: HttpClient.new)
@@ -65,6 +72,44 @@ module FriendlyShipping
65
72
  end
66
73
  end
67
74
 
75
+ def labels(shipment, options:, debug: false)
76
+ ## Method body starts
77
+ ship_confirm_request_xml = SerializeShipmentConfirmRequest.call(
78
+ shipment: shipment,
79
+ options: options
80
+ )
81
+ ship_confirm_url = base_url + RESOURCES[:ship_confirm]
82
+
83
+ ship_confirm_request = FriendlyShipping::Request.new(
84
+ url: ship_confirm_url,
85
+ body: access_request_xml + ship_confirm_request_xml,
86
+ debug: debug
87
+ )
88
+
89
+ client.post(ship_confirm_request).bind do |ship_confirm_response|
90
+ ParseShipmentConfirmResponse.call(
91
+ request: ship_confirm_request,
92
+ response: ship_confirm_response
93
+ )
94
+ end.bind do |ship_confirm_result|
95
+ ship_accept_url = base_url + RESOURCES[:ship_accept]
96
+ ship_accept_request_xml = SerializeShipmentAcceptRequest.call(
97
+ digest: ship_confirm_result.data,
98
+ options: options
99
+ )
100
+
101
+ ship_accept_request = FriendlyShipping::Request.new(
102
+ url: ship_accept_url,
103
+ body: access_request_xml + ship_accept_request_xml,
104
+ debug: debug
105
+ )
106
+
107
+ client.post(ship_accept_request).bind do |ship_accept_response|
108
+ ParseShipmentAcceptResponse.call(request: ship_accept_request, response: ship_accept_response)
109
+ end
110
+ end
111
+ end
112
+
68
113
  # Validate an address.
69
114
  # @param [Physical::Location] location The address we want to verify
70
115
  # @return [Result<ApiResult<Array<Physical::Location>>>] The response data from UPS encoded in a
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module FriendlyShipping
4
+ module Services
5
+ class Ups
6
+ # Represents billing-related options for obtaining shipment labels.
7
+ # @option bill_third_party [Boolean] When truthy, bill an account other than the shipper's.
8
+ # Specified by billing_(account, zip and country)
9
+ # @option bill_to_consignee [Boolean] If billing a third party, bill the consignee instead of the 3rd party shipper
10
+ # @option prepay [Boolean] If truthy the shipper will be bill immediately. Otherwise the shipper is billed
11
+ # when the label is used. Default: false
12
+ class LabelBillingOptions
13
+ attr_reader :bill_third_party,
14
+ :bill_to_consignee,
15
+ :prepay,
16
+ :billing_account,
17
+ :billing_zip,
18
+ :billing_country,
19
+ :currency
20
+
21
+ def initialize(
22
+ bill_third_party: false,
23
+ bill_to_consignee: false,
24
+ prepay: false,
25
+ billing_account: nil,
26
+ billing_zip: nil,
27
+ billing_country: nil,
28
+ currency: nil
29
+ )
30
+ @bill_third_party = bill_third_party
31
+ @bill_to_consignee = bill_to_consignee
32
+ @prepay = prepay
33
+ @billing_account = billing_account
34
+ @billing_zip = billing_zip
35
+ @billing_country = billing_country
36
+ @currency = currency
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'friendly_shipping/item_options'
4
+
5
+ module FriendlyShipping
6
+ module Services
7
+ class Ups
8
+ class LabelItemOptions < FriendlyShipping::ItemOptions
9
+ PRODUCT_UNIT_OF_MEASURE_CODES = {
10
+ barrel: 'BA',
11
+ bundle: 'BE',
12
+ bag: 'BG',
13
+ bunch: 'BH',
14
+ box: 'BOX',
15
+ bolt: 'BT',
16
+ butt: 'BU',
17
+ canister: 'CI',
18
+ centimeter: 'CM',
19
+ container: 'CON',
20
+ crate: 'CR',
21
+ case: 'CS',
22
+ carton: 'CT',
23
+ cylinder: 'CY',
24
+ dozen: 'DOZ',
25
+ each: 'EA',
26
+ envelope: 'EN',
27
+ feet: 'FT',
28
+ kilogram: 'KG',
29
+ kilograms: 'KGS',
30
+ pound: 'LB',
31
+ pounds: 'LBS',
32
+ liter: 'L',
33
+ meter: 'M',
34
+ number: 'NMB',
35
+ packet: 'PA',
36
+ pallet: 'PAL',
37
+ piece: 'PC',
38
+ pieces: 'PCS',
39
+ proof_liters: 'PF',
40
+ package: 'PKG',
41
+ pair: 'PR',
42
+ pairs: 'PRS',
43
+ roll: 'RL',
44
+ set: 'SET',
45
+ square_meters: 'SME',
46
+ square_yards: 'SYD',
47
+ tube: 'TU',
48
+ yard: 'YD',
49
+ other: 'OTH'
50
+ }.freeze
51
+
52
+ attr_reader :commodity_code
53
+
54
+ def initialize(
55
+ commodity_code: nil,
56
+ product_unit_of_measure: :number,
57
+ **kwargs
58
+ )
59
+ @commodity_code = commodity_code
60
+ @product_unit_of_measure = product_unit_of_measure
61
+ super kwargs
62
+ end
63
+
64
+ def product_unit_of_measure_code
65
+ PRODUCT_UNIT_OF_MEASURE_CODES[product_unit_of_measure]
66
+ end
67
+
68
+ private
69
+
70
+ attr_reader :product_unit_of_measure
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'friendly_shipping/services/ups/label_package_options'
4
+ require 'friendly_shipping/services/ups/label_billing_options'
5
+
6
+ module FriendlyShipping
7
+ module Services
8
+ # Option container for a generating UPS labels for a shipment
9
+ #
10
+ # Required:
11
+ #
12
+ # @param shipping_method [FriendlyShipping::ShippingMethod] The shipping method to use. We only need the
13
+ # service_code to be set.
14
+ # @param shipper_number [String] account number for the shipper
15
+ #
16
+ # Optional:
17
+ #
18
+ # @param shipper [Physical::Location] The company sending the shipment. Defaults to the shipment's origin.
19
+ # @param customer_context [String ] Optional element to identify transactions between client and server
20
+ # @param validate_address [Boolean] Validate the city field with ZIP code and state. If false, only ZIP code
21
+ # and state are validated. Default: true
22
+ # @param negotiated_rates [Boolean] if truthy negotiated rates will be requested from ups. Only valid if
23
+ # shipper account has negotiated rates. Default: false
24
+ # @option sold_to [Physical::Location] The person or company who imports and pays any duties due on the
25
+ # current shipment. Default: The shipment's destination
26
+ # @option saturday_delivery [Boolean] should we request Saturday delivery?. Default: false
27
+ # @option label_format [String] GIF, EPL, ZPL, STARPL and SPL
28
+ # @option label_size [Array<Integer>] Dimensions of the label. Default: [4, 6]
29
+ # @option delivery_confirmation [Symbol] Can be set to any key from SHIPMENT_DELIVERY_CONFIRMATION_CODES.
30
+ # Only possible for international shipments that are not between the US and Puerto Rico.
31
+ # @option carbon_neutral [Boolean] Ship with UPS' carbon neutral program
32
+ # @option return_service_code [Symbol] If present, marks this a return label. The kind
33
+ # of return label is specified by the symbol, one of the keys in RETURN_SERVICE_CODES. Default: nil
34
+ #
35
+ # Shipment options for international shipping:
36
+ #
37
+ # @option paperless_invoice [Boolean] set to truthy if using paperless invoice to ship internationally. Default false
38
+ # @option terms_of_shipment [Symbol] used with paperless invoice to specify who pays duties and taxes.
39
+ # See TERMS_OF_SHIPMENT constant for possible options.
40
+ # @option reason_for_export [String] A reason to export the current shipment. Possible values: 'SALE', 'GIFT', 'SAMPLE',
41
+ # 'RETURN', 'REPAIR', 'INTERCOMPANYDATA', Any other reason. Default: 'SALE'.
42
+ # @option invoice_date [Date] The invoice date for the shipment
43
+ #
44
+ class Ups
45
+ class LabelOptions < FriendlyShipping::ShipmentOptions
46
+ SHIPMENT_DELIVERY_CONFIRMATION_CODES = {
47
+ delivery_confirmation_signature_required: 1,
48
+ delivery_confirmation_adult_signature_required: 2
49
+ }.freeze
50
+
51
+ TERMS_OF_SHIPMENT_CODES = {
52
+ cost_and_freight: 'CFR',
53
+ cost_insurance_and_freight: 'CIF',
54
+ carriage_and_insurance_paid: 'CIP',
55
+ carriage_paid_to: 'CPT',
56
+ delivered_at_frontier: 'DAF',
57
+ delivery_duty_paid: 'DDP',
58
+ delivery_duty_unpaid: 'DDU',
59
+ delivered_ex_quay: 'DEQ',
60
+ delivered_ex_ship: 'DES',
61
+ ex_works: 'EXW',
62
+ free_alongside_ship: 'FAS',
63
+ free_carrier: 'FCA',
64
+ free_on_board: 'FOB'
65
+ }.freeze
66
+
67
+ RETURN_SERVICE_CODES = {
68
+ ups_print_and_mail: 2, # UPS Print and Mail (PNM)
69
+ ups_return_1_attempt: 3, # UPS Return Service 1-Attempt
70
+ ups_return_3_attempt: 5, # UPS Return Service 3-Attempt (RS3)
71
+ ups_electronic_return_label: 8, # UPS Electronic Return Label (ERL)
72
+ ups_print_return_label: 9, # UPS Print Return Label (PRL)
73
+ ups_exchange_print_return: 10, # UPS Exchange Print Return Label
74
+ ups_pack_collect_1_attemt_box_1: 11, # UPS Pack & Collect Service 1-Attempt Box 1
75
+ ups_pack_collect_1_attemt_box_2: 12, # UPS Pack & Collect Service 1-Attempt Box 2
76
+ ups_pack_collect_1_attemt_box_3: 13, # UPS Pack & Collect Service 1-Attempt Box 3
77
+ ups_pack_collect_1_attemt_box_4: 14, # UPS Pack & Collect Service 1-Attempt Box 4
78
+ ups_pack_collect_1_attemt_box_5: 15, # UPS Pack & Collect Service 1-Attempt Box 5
79
+ ups_pack_collect_3_attemt_box_1: 16, # UPS Pack & Collect Service 1-Attempt Box 1
80
+ ups_pack_collect_3_attemt_box_2: 17, # UPS Pack & Collect Service 1-Attempt Box 2
81
+ ups_pack_collect_3_attemt_box_3: 18, # UPS Pack & Collect Service 1-Attempt Box 3
82
+ ups_pack_collect_3_attemt_box_4: 19, # UPS Pack & Collect Service 1-Attempt Box 4
83
+ ups_pack_collect_3_attemt_box_5: 20 # UPS Pack & Collect Service 1-Attempt Box 5
84
+ }.freeze
85
+
86
+ attr_reader :shipping_method,
87
+ :shipper_number,
88
+ :shipper,
89
+ :customer_context,
90
+ :validate_address,
91
+ :negotiated_rates,
92
+ :billing_options,
93
+ :sold_to,
94
+ :saturday_delivery,
95
+ :label_format,
96
+ :label_size,
97
+ :carbon_neutral,
98
+ :paperless_invoice,
99
+ :reason_for_export,
100
+ :invoice_date
101
+
102
+ def initialize(
103
+ shipping_method:,
104
+ shipper_number:,
105
+ shipper: nil,
106
+ customer_context: nil,
107
+ validate_address: true,
108
+ negotiated_rates: false,
109
+ billing_options: LabelBillingOptions.new,
110
+ sold_to: nil,
111
+ saturday_delivery: false,
112
+ label_format: 'GIF',
113
+ label_size: [4, 6],
114
+ delivery_confirmation: nil,
115
+ carbon_neutral: true,
116
+ return_service: nil,
117
+ paperless_invoice: false,
118
+ terms_of_shipment: nil,
119
+ reason_for_export: 'SALE',
120
+ invoice_date: nil,
121
+ package_options_class: LabelPackageOptions,
122
+ **kwargs
123
+ )
124
+ @shipping_method = shipping_method
125
+ @shipper_number = shipper_number
126
+ @shipper = shipper
127
+ @customer_context = customer_context
128
+ @validate_address = validate_address
129
+ @negotiated_rates = negotiated_rates
130
+ @billing_options = billing_options
131
+ @sold_to = sold_to
132
+ @saturday_delivery = saturday_delivery
133
+ @label_format = label_format
134
+ @label_size = label_size
135
+ @delivery_confirmation = delivery_confirmation
136
+ @carbon_neutral = carbon_neutral
137
+ @return_service = return_service
138
+ @paperless_invoice = paperless_invoice
139
+ @terms_of_shipment = terms_of_shipment
140
+ @reason_for_export = reason_for_export
141
+ @invoice_date = invoice_date
142
+ super kwargs.merge(package_options_class: package_options_class)
143
+ end
144
+
145
+ def delivery_confirmation_code
146
+ SHIPMENT_DELIVERY_CONFIRMATION_CODES[delivery_confirmation]
147
+ end
148
+
149
+ def terms_of_shipment_code
150
+ TERMS_OF_SHIPMENT_CODES[terms_of_shipment]
151
+ end
152
+
153
+ def return_service_code
154
+ RETURN_SERVICE_CODES[return_service]
155
+ end
156
+
157
+ private
158
+
159
+ attr_reader :terms_of_shipment,
160
+ :return_service,
161
+ :delivery_confirmation
162
+ end
163
+ end
164
+ end
165
+ end