active_shipping 1.7.1 → 1.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/dev.yml +2 -2
- data/lib/active_shipping/carrier.rb +15 -0
- data/lib/active_shipping/carriers/fedex.rb +3 -1
- data/lib/active_shipping/carriers/ups.rb +28 -26
- data/lib/active_shipping/location.rb +4 -0
- data/lib/active_shipping/shipment_event.rb +5 -0
- data/lib/active_shipping/tracking_response.rb +16 -1
- data/lib/active_shipping/version.rb +1 -1
- data/test/remote/ups_test.rb +29 -0
- data/test/unit/carriers/fedex_test.rb +26 -0
- data/test/unit/carriers/ups_test.rb +5 -4
- data/test/unit/location_test.rb +7 -0
- data/test/unit/shipment_event_test.rb +20 -0
- data/test/unit/tracking_response_test.rb +41 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a721187cba1984ab9a456dea8c660c81d2a1aa68
|
4
|
+
data.tar.gz: 4b6ba4b2a8bedd5434f611d81d2ba74df92fab5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fecbfa0feaf36671db206bb30fb3e981b5c079183d45ebd8a2c096a41ba4d66f516b69d443ed3e08b54c1af4fa070ce618fb9f3fc89ce48bf2e19fafcec0d2b
|
7
|
+
data.tar.gz: 80a224c59f08ba748989a2aacc4ddcacd529296c43c4d0caa370339a26d60d1d2c29d860ce4e0c1d5719e2f791aef2b05589b44055b45228400fd47fef24fae7
|
data/dev.yml
CHANGED
@@ -7,6 +7,7 @@ module ActiveShipping
|
|
7
7
|
#
|
8
8
|
# @see #find_rates
|
9
9
|
# @see #create_shipment
|
10
|
+
# @see #cancel_shipment
|
10
11
|
# @see #find_tracking_info
|
11
12
|
#
|
12
13
|
# @!attribute test_mode
|
@@ -67,6 +68,20 @@ module ActiveShipping
|
|
67
68
|
raise NotImplementedError, "#create_shipment is not supported by #{self.class.name}."
|
68
69
|
end
|
69
70
|
|
71
|
+
# Cancels a shipment with a carrier.
|
72
|
+
#
|
73
|
+
# @note Override with whatever you need to cancel a shipping label
|
74
|
+
#
|
75
|
+
# @param shipment_id [String] The unique identifier of the shipment to cancel.
|
76
|
+
# This can be shipment_id or tracking number depending on carrier. Up to you and
|
77
|
+
# the carrier
|
78
|
+
# @param options [Hash] Carrier-specific parameters.
|
79
|
+
# @return [ActiveShipping::ShipmentResponse] The response from the carrier. This
|
80
|
+
# response in most cases has a cancellation id.
|
81
|
+
def cancel_shipment(shipment_id, options = {})
|
82
|
+
raise NotImplementedError, "#cancel_shipment is not supported by #{self.class.name}."
|
83
|
+
end
|
84
|
+
|
70
85
|
# Retrieves tracking information for a previous shipment
|
71
86
|
#
|
72
87
|
# @note Override with whatever you need to get a shipping label
|
@@ -134,6 +134,8 @@ module ActiveShipping
|
|
134
134
|
'TR' => :transfer
|
135
135
|
)
|
136
136
|
|
137
|
+
DEFAULT_LABEL_STOCK_TYPE = 'PAPER_7X4.75'
|
138
|
+
|
137
139
|
def self.service_name_for_code(service_code)
|
138
140
|
SERVICE_TYPES[service_code] || "FedEx #{service_code.titleize.sub(/Fedex /, '')}"
|
139
141
|
end
|
@@ -218,7 +220,7 @@ module ActiveShipping
|
|
218
220
|
xml.LabelSpecification do
|
219
221
|
xml.LabelFormatType('COMMON2D')
|
220
222
|
xml.ImageType('PNG')
|
221
|
-
xml.LabelStockType(
|
223
|
+
xml.LabelStockType(options[:label_stock_type] || DEFAULT_LABEL_STOCK_TYPE)
|
222
224
|
end
|
223
225
|
|
224
226
|
xml.RateRequestTypes('ACCOUNT')
|
@@ -318,7 +318,7 @@ module ActiveShipping
|
|
318
318
|
# Build XML node to request a shipping label for the given packages.
|
319
319
|
#
|
320
320
|
# options:
|
321
|
-
# * origin_account:
|
321
|
+
# * origin_account: account number for the shipper
|
322
322
|
# * customer_context: a "guid like substance" -- according to UPS
|
323
323
|
# * shipper: who is sending the package and where it should be returned
|
324
324
|
# if it is undeliverable.
|
@@ -332,6 +332,7 @@ module ActiveShipping
|
|
332
332
|
# * prepay: if truthy the shipper will be bill immediatly. Otherwise the shipper is billed when the label is used.
|
333
333
|
# * negotiated_rates: if truthy negotiated rates will be requested from ups. Only valid if shipper account has negotiated rates.
|
334
334
|
# * delivery_confirmation: Can be set to any key from SHIPMENT_DELIVERY_CONFIRMATION_CODES. Can also be set on package level via package.options
|
335
|
+
# * bill_third_party: When truthy, bill an account other than the shipper's. Specified by billing_(account, zip and country)
|
335
336
|
def build_shipment_request(origin, destination, packages, options={})
|
336
337
|
packages = Array(packages)
|
337
338
|
shipper = options[:shipper] || origin
|
@@ -381,7 +382,7 @@ module ActiveShipping
|
|
381
382
|
end
|
382
383
|
end
|
383
384
|
|
384
|
-
if options[:
|
385
|
+
if options[:negotiated_rates]
|
385
386
|
xml.RateInformation do
|
386
387
|
xml.NegotiatedRatesIndicator
|
387
388
|
end
|
@@ -397,23 +398,7 @@ module ActiveShipping
|
|
397
398
|
if options[:prepay]
|
398
399
|
xml.PaymentInformation do
|
399
400
|
xml.Prepaid do
|
400
|
-
xml
|
401
|
-
xml.AccountNumber(options[:origin_account])
|
402
|
-
end
|
403
|
-
end
|
404
|
-
end
|
405
|
-
elsif options[:bill_third_party]
|
406
|
-
xml.PaymentInformation do
|
407
|
-
xml.BillThirdParty do
|
408
|
-
xml.BillThirdPartyShipper do
|
409
|
-
xml.AccountNumber(options[:billing_account])
|
410
|
-
xml.ThirdParty do
|
411
|
-
xml.Address do
|
412
|
-
xml.PostalCode(options[:billing_zip])
|
413
|
-
xml.CountryCode(options[:billing_country])
|
414
|
-
end
|
415
|
-
end
|
416
|
-
end
|
401
|
+
build_billing_info_node(xml, options)
|
417
402
|
end
|
418
403
|
end
|
419
404
|
else
|
@@ -422,18 +407,14 @@ module ActiveShipping
|
|
422
407
|
# Type '01' means 'Transportation'
|
423
408
|
# This node specifies who will be billed for transportation.
|
424
409
|
xml.Type('01')
|
425
|
-
xml
|
426
|
-
xml.AccountNumber(options[:origin_account])
|
427
|
-
end
|
410
|
+
build_billing_info_node(xml, options)
|
428
411
|
end
|
429
|
-
if options[:terms_of_shipment] == 'DDP'
|
412
|
+
if options[:terms_of_shipment] == 'DDP' && options[:international]
|
430
413
|
# DDP stands for delivery duty paid and means the shipper will cover duties and taxes
|
431
414
|
# Otherwise UPS will charge the receiver
|
432
415
|
xml.ShipmentCharge do
|
433
416
|
xml.Type('02') # Type '02' means 'Duties and Taxes'
|
434
|
-
xml.
|
435
|
-
xml.AccountNumber(options[:origin_account])
|
436
|
-
end
|
417
|
+
build_billing_info_node(xml, options.merge(bill_to_consignee: true))
|
437
418
|
end
|
438
419
|
end
|
439
420
|
end
|
@@ -762,6 +743,27 @@ module ActiveShipping
|
|
762
743
|
end
|
763
744
|
end
|
764
745
|
|
746
|
+
def build_billing_info_node(xml, options={})
|
747
|
+
if options[:bill_third_party]
|
748
|
+
xml.BillThirdParty do
|
749
|
+
node_type = options[:bill_to_consignee] ? :BillThirdPartyConsignee : :BillThirdPartyShipper
|
750
|
+
xml.public_send(node_type) do
|
751
|
+
xml.AccountNumber(options[:billing_account])
|
752
|
+
xml.ThirdParty do
|
753
|
+
xml.Address do
|
754
|
+
xml.PostalCode(options[:billing_zip])
|
755
|
+
xml.CountryCode(options[:billing_country])
|
756
|
+
end
|
757
|
+
end
|
758
|
+
end
|
759
|
+
end
|
760
|
+
else
|
761
|
+
xml.BillShipper do
|
762
|
+
xml.AccountNumber(options[:origin_account])
|
763
|
+
end
|
764
|
+
end
|
765
|
+
end
|
766
|
+
|
765
767
|
def build_document(xml, expected_root_tag)
|
766
768
|
document = Nokogiri.XML(xml)
|
767
769
|
if document.root.nil? || document.root.name != expected_root_tag
|
@@ -13,5 +13,10 @@ module ActiveShipping
|
|
13
13
|
def status
|
14
14
|
@status ||= name.downcase.gsub("\s", "_").to_sym
|
15
15
|
end
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
attributes = %i(name time location message type_code)
|
19
|
+
attributes.all? { |attr| self.public_send(attr) == other.public_send(attr) }
|
20
|
+
end
|
16
21
|
end
|
17
22
|
end
|
@@ -31,7 +31,7 @@ module ActiveShipping
|
|
31
31
|
#
|
32
32
|
# @!attribute attempted_delivery_date
|
33
33
|
# @return [Date, Time]
|
34
|
-
#
|
34
|
+
#
|
35
35
|
# @!attribute delivery_signature
|
36
36
|
# @return [String]
|
37
37
|
#
|
@@ -101,5 +101,20 @@ module ActiveShipping
|
|
101
101
|
alias_method :scheduled_delivery_time, :scheduled_delivery_date
|
102
102
|
alias_method :actual_delivery_time, :actual_delivery_date
|
103
103
|
alias_method :attempted_delivery_time, :attempted_delivery_date
|
104
|
+
|
105
|
+
def ==(other)
|
106
|
+
attributes = %i(carrier carrier_name status status_code status_description ship_time scheduled_delivery_date
|
107
|
+
actual_delivery_date attempted_delivery_date delivery_signature tracking_number shipper_address
|
108
|
+
origin destination
|
109
|
+
)
|
110
|
+
|
111
|
+
attributes.all? { |attr| self.public_send(attr) == other.public_send(attr) } && compare_shipment_events(other)
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
# Ensure order doesn't matter when comparing shipment_events
|
116
|
+
def compare_shipment_events(other)
|
117
|
+
shipment_events.sort_by(&:time) == other.shipment_events.sort_by(&:time)
|
118
|
+
end
|
104
119
|
end
|
105
120
|
end
|
data/test/remote/ups_test.rb
CHANGED
@@ -267,6 +267,35 @@ class RemoteUPSTest < Minitest::Test
|
|
267
267
|
assert_instance_of ActiveShipping::LabelResponse, response
|
268
268
|
end
|
269
269
|
|
270
|
+
def test_obtain_international_shipping_label_with_bill_third_party
|
271
|
+
begin
|
272
|
+
bill_third_party_credentials = credentials(:ups_third_party_billing)
|
273
|
+
rescue NoCredentialsFound => e
|
274
|
+
skip(e.message)
|
275
|
+
end
|
276
|
+
|
277
|
+
response = @carrier.create_shipment(
|
278
|
+
location_fixtures[:new_york_with_name],
|
279
|
+
location_fixtures[:ottawa_with_name],
|
280
|
+
package_fixtures.values_at(:books),
|
281
|
+
{
|
282
|
+
:service_code => '07',
|
283
|
+
:bill_third_party => true,
|
284
|
+
:billing_account => bill_third_party_credentials[:account],
|
285
|
+
:billing_zip => bill_third_party_credentials[:zip],
|
286
|
+
:billing_country => bill_third_party_credentials[:country_code],
|
287
|
+
:test => true,
|
288
|
+
}
|
289
|
+
)
|
290
|
+
assert response.success?
|
291
|
+
|
292
|
+
# All behavior specific to how a LabelResponse behaves in the
|
293
|
+
# context of UPS label data is a matter for unit tests. If
|
294
|
+
# the data changes substantially, the create_shipment
|
295
|
+
# ought to raise an exception and this test will fail.
|
296
|
+
assert_instance_of ActiveShipping::LabelResponse, response
|
297
|
+
end
|
298
|
+
|
270
299
|
def test_delivery_date_estimates_within_zip
|
271
300
|
today = Date.current
|
272
301
|
|
@@ -601,6 +601,32 @@ class FedExTest < Minitest::Test
|
|
601
601
|
assert_equal result.search('RequestedPackageLineItems/CustomerReferences/Value').text, "FOO-123"
|
602
602
|
end
|
603
603
|
|
604
|
+
def test_create_shipment_default_label_stock_type
|
605
|
+
packages = package_fixtures.values_at(:wii)
|
606
|
+
|
607
|
+
result = Nokogiri::XML(@carrier.send(:build_shipment_request,
|
608
|
+
location_fixtures[:beverly_hills],
|
609
|
+
location_fixtures[:annapolis],
|
610
|
+
packages,
|
611
|
+
:test => true))
|
612
|
+
|
613
|
+
assert_equal result.search('RequestedShipment/LabelSpecification/LabelStockType').text, FedEx::DEFAULT_LABEL_STOCK_TYPE
|
614
|
+
end
|
615
|
+
|
616
|
+
def test_create_shipment_label_stock_type
|
617
|
+
label_stock_type = 'PAPER_4X6'
|
618
|
+
packages = package_fixtures.values_at(:wii)
|
619
|
+
|
620
|
+
result = Nokogiri::XML(@carrier.send(:build_shipment_request,
|
621
|
+
location_fixtures[:beverly_hills],
|
622
|
+
location_fixtures[:annapolis],
|
623
|
+
packages,
|
624
|
+
:test => true,
|
625
|
+
:label_stock_type => label_stock_type))
|
626
|
+
|
627
|
+
assert_equal result.search('RequestedShipment/LabelSpecification/LabelStockType').text, label_stock_type
|
628
|
+
end
|
629
|
+
|
604
630
|
def test_maximum_address_field_length
|
605
631
|
assert_equal 35, @carrier.maximum_address_field_length
|
606
632
|
end
|
@@ -365,9 +365,9 @@ class UPSTest < Minitest::Test
|
|
365
365
|
:billing_zip => expected_postal_code_number,
|
366
366
|
:billing_country => expected_country_code)
|
367
367
|
|
368
|
-
assert_equal expected_account_number, response.search('ShipmentConfirmRequest/Shipment/
|
369
|
-
assert_equal expected_postal_code_number, response.search('/ShipmentConfirmRequest/Shipment/
|
370
|
-
assert_equal expected_country_code, response.search('/ShipmentConfirmRequest/Shipment/
|
368
|
+
assert_equal expected_account_number, response.search('ShipmentConfirmRequest/Shipment/ItemizedPaymentInformation/ShipmentCharge/BillThirdParty/BillThirdPartyShipper/AccountNumber').text
|
369
|
+
assert_equal expected_postal_code_number, response.search('/ShipmentConfirmRequest/Shipment/ItemizedPaymentInformation/ShipmentCharge/BillThirdParty/BillThirdPartyShipper/ThirdParty/Address/PostalCode').text
|
370
|
+
assert_equal expected_country_code, response.search('/ShipmentConfirmRequest/Shipment/ItemizedPaymentInformation/ShipmentCharge/BillThirdParty/BillThirdPartyShipper/ThirdParty/Address/CountryCode').text
|
371
371
|
end
|
372
372
|
|
373
373
|
def test_label_request_negotiated_rates_presence
|
@@ -377,7 +377,8 @@ class UPSTest < Minitest::Test
|
|
377
377
|
package_fixtures.values_at(:chocolate_stuff),
|
378
378
|
:test => true,
|
379
379
|
:saturday_delivery => true,
|
380
|
-
:origin_account => 'A01B23' # without this option, a negotiated rate will not be requested
|
380
|
+
:origin_account => 'A01B23', # without this option, a negotiated rate will not be requested
|
381
|
+
:negotiated_rates => true,
|
381
382
|
)
|
382
383
|
|
383
384
|
negotiated_rates = response.search '/ShipmentConfirmRequest/Shipment/RateInformation/NegotiatedRatesIndicator'
|
data/test/unit/location_test.rb
CHANGED
@@ -125,4 +125,11 @@ class LocationTest < Minitest::Test
|
|
125
125
|
location = Location.from(:address3 => address3)
|
126
126
|
assert_equal 'Victory Lane', location.address2_and_3
|
127
127
|
end
|
128
|
+
|
129
|
+
def test_equality
|
130
|
+
location_1 = location_fixtures[:ottawa]
|
131
|
+
location_2 = Location.from(location_1.to_hash)
|
132
|
+
|
133
|
+
assert_equal location_1, location_2
|
134
|
+
end
|
128
135
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class ShipmentEventTest < Minitest::Test
|
4
|
+
def test_equality
|
5
|
+
options1 = [
|
6
|
+
'ARRIVED AT UNIT',
|
7
|
+
DateTime.new(2016, 5, 12, 5, 45),
|
8
|
+
Location.new(city: 'SAN JOSE', state: 'CA', postal_code: '90001', country: 'US'),
|
9
|
+
'ARRIVED AT UNIT',
|
10
|
+
'07'
|
11
|
+
]
|
12
|
+
# Copies options to create new DateTime and Location objects to check for similar distinct objects
|
13
|
+
options2 = options1.dup
|
14
|
+
|
15
|
+
shipment_event_1 = ShipmentEvent.new(*options1)
|
16
|
+
shipment_event_2 = ShipmentEvent.new(*options2)
|
17
|
+
|
18
|
+
assert_equal shipment_event_1, shipment_event_2
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TrackingResponseTest < Minitest::Test
|
4
|
+
def test_equality
|
5
|
+
options1 = {
|
6
|
+
carrier: 'usps',
|
7
|
+
status: 'DELIVERED',
|
8
|
+
status_code: 'I0',
|
9
|
+
status_description: 'DELIVERED',
|
10
|
+
actual_delivery_date: DateTime.new(2016, 5, 14, 13, 20),
|
11
|
+
tracking_number: 'TRACKINGNUMBER1234ABC',
|
12
|
+
shipment_events: [
|
13
|
+
ShipmentEvent.new(
|
14
|
+
'DELIVERED',
|
15
|
+
DateTime.new(2016, 5, 14, 13, 20),
|
16
|
+
Location.new(city: 'LOS ANGELES', state: 'CA', postal_code: '90210', country: 'US'),
|
17
|
+
'DELIVERED',
|
18
|
+
'I0'
|
19
|
+
),
|
20
|
+
ShipmentEvent.new(
|
21
|
+
'ARRIVED AT UNIT',
|
22
|
+
DateTime.new(2016, 5, 12, 5, 45),
|
23
|
+
Location.new(city: 'SAN JOSE', state: 'CA', postal_code: '90001', country: 'US'),
|
24
|
+
'ARRIVED AT UNIT',
|
25
|
+
'07'
|
26
|
+
)
|
27
|
+
],
|
28
|
+
destination: Location.new(postal_code: '90210'),
|
29
|
+
origin: Location.new(postal_code: '00001')
|
30
|
+
}
|
31
|
+
# Deep copies options1 to create new ShipmentEvent, Location, etc. objects to check for similar distinct objects
|
32
|
+
options2 = Marshal.load(Marshal.dump(options1))
|
33
|
+
options2[:shipment_events][0], options2[:shipment_events][1] =
|
34
|
+
options2[:shipment_events][1], options2[:shipment_events][0]
|
35
|
+
|
36
|
+
tracking_response_1 = TrackingResponse.new(true, nil, {}, options1)
|
37
|
+
tracking_response_2 = TrackingResponse.new(true, nil, {}, options2)
|
38
|
+
|
39
|
+
assert_equal tracking_response_1, tracking_response_2
|
40
|
+
end
|
41
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_shipping
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.7.
|
4
|
+
version: 1.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James MacAulay
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2016-
|
14
|
+
date: 2016-05-19 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: quantified
|
@@ -399,7 +399,9 @@ files:
|
|
399
399
|
- test/unit/package_test.rb
|
400
400
|
- test/unit/rate_estimate_test.rb
|
401
401
|
- test/unit/response_test.rb
|
402
|
+
- test/unit/shipment_event_test.rb
|
402
403
|
- test/unit/shipment_packer_test.rb
|
404
|
+
- test/unit/tracking_response_test.rb
|
403
405
|
homepage: http://github.com/shopify/active_shipping
|
404
406
|
licenses:
|
405
407
|
- MIT
|
@@ -606,4 +608,6 @@ test_files:
|
|
606
608
|
- test/unit/package_test.rb
|
607
609
|
- test/unit/rate_estimate_test.rb
|
608
610
|
- test/unit/response_test.rb
|
611
|
+
- test/unit/shipment_event_test.rb
|
609
612
|
- test/unit/shipment_packer_test.rb
|
613
|
+
- test/unit/tracking_response_test.rb
|