active_shipping 1.6.1 → 1.6.2
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/.gitignore +1 -0
- data/lib/active_shipping/carriers/fedex.rb +25 -10
- data/lib/active_shipping/carriers/ups.rb +40 -5
- data/lib/active_shipping/carriers/usps.rb +1 -1
- data/lib/active_shipping/version.rb +1 -1
- data/test/remote/ups_test.rb +39 -0
- data/test/remote/usps_test.rb +3 -3
- data/test/test_helper.rb +9 -0
- data/test/unit/carriers/fedex_test.rb +37 -5
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 838209b9accf6cfb537ac16786e8683d18155073
|
4
|
+
data.tar.gz: 75036f0188503179ddb089ee25f99dc8b9fa4538
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d3e7c5b1b9cf6a46986c02725ebda6324724cd0d1c073f7fcded221314bf1ec6ebe360105f60c39e72f3612143d1749e0be36b648b135dc03eef97857098577
|
7
|
+
data.tar.gz: fd34ef65e9404b1255c04a4e4867e6ad1fa3e0089ddbf1e73e4ff7b43209dae66f3f9e4e71d171d117fe2718c2cff406500fc9506dc3331d478af2668384eafb
|
data/.gitignore
CHANGED
@@ -143,7 +143,7 @@ module ActiveShipping
|
|
143
143
|
end
|
144
144
|
|
145
145
|
def find_rates(origin, destination, packages, options = {})
|
146
|
-
options = @options.
|
146
|
+
options = @options.merge(options)
|
147
147
|
packages = Array(packages)
|
148
148
|
|
149
149
|
rate_request = build_rate_request(origin, destination, packages, options)
|
@@ -154,7 +154,7 @@ module ActiveShipping
|
|
154
154
|
end
|
155
155
|
|
156
156
|
def find_tracking_info(tracking_number, options = {})
|
157
|
-
options = @options.
|
157
|
+
options = @options.merge(options)
|
158
158
|
|
159
159
|
tracking_request = build_tracking_request(tracking_number, options)
|
160
160
|
xml = commit(save_request(tracking_request), (options[:test] || false))
|
@@ -164,7 +164,7 @@ module ActiveShipping
|
|
164
164
|
|
165
165
|
# Get Shipping labels
|
166
166
|
def create_shipment(origin, destination, packages, options = {})
|
167
|
-
options = @options.
|
167
|
+
options = @options.merge(options)
|
168
168
|
packages = Array(packages)
|
169
169
|
raise Error, "Multiple packages are not supported yet." if packages.length > 1
|
170
170
|
|
@@ -298,7 +298,11 @@ module ActiveShipping
|
|
298
298
|
xml.VariableOptions('SATURDAY_DELIVERY')
|
299
299
|
|
300
300
|
xml.RequestedShipment do
|
301
|
-
|
301
|
+
if options[:pickup_date]
|
302
|
+
xml.ShipTimestamp(options[:pickup_date].to_time.iso8601(0))
|
303
|
+
else
|
304
|
+
xml.ShipTimestamp(ship_timestamp(options[:turn_around_time]).iso8601(0))
|
305
|
+
end
|
302
306
|
|
303
307
|
freight = has_freight?(options)
|
304
308
|
|
@@ -479,8 +483,7 @@ module ActiveShipping
|
|
479
483
|
max_transit_time = rated_shipment.at('MaximumTransitTime').try(:text) if service_code == "FEDEX_GROUND"
|
480
484
|
|
481
485
|
delivery_timestamp = rated_shipment.at('DeliveryTimestamp').try(:text)
|
482
|
-
|
483
|
-
delivery_range = delivery_range_from(transit_time, max_transit_time, delivery_timestamp, options)
|
486
|
+
delivery_range = delivery_range_from(transit_time, max_transit_time, delivery_timestamp, (service_code == "GROUND_HOME_DELIVERY"), options)
|
484
487
|
|
485
488
|
currency = rated_shipment.at('RatedShipmentDetails/ShipmentRateDetail/TotalNetCharge/Currency').text
|
486
489
|
RateEstimate.new(origin, destination, @@name,
|
@@ -503,13 +506,15 @@ module ActiveShipping
|
|
503
506
|
RateResponse.new(success, message, Hash.from_xml(response), :rates => rate_estimates, :xml => response, :request => last_request, :log_xml => options[:log_xml])
|
504
507
|
end
|
505
508
|
|
506
|
-
def delivery_range_from(transit_time, max_transit_time, delivery_timestamp, options)
|
509
|
+
def delivery_range_from(transit_time, max_transit_time, delivery_timestamp, is_home_delivery, options)
|
507
510
|
delivery_range = [delivery_timestamp, delivery_timestamp]
|
508
511
|
|
509
512
|
# if there's no delivery timestamp but we do have a transit time, use it
|
510
513
|
if delivery_timestamp.blank? && transit_time.present?
|
511
514
|
transit_range = parse_transit_times([transit_time, max_transit_time.presence || transit_time])
|
512
|
-
|
515
|
+
pickup_date = options[:pickup_date] || ship_date(options[:turn_around_time])
|
516
|
+
|
517
|
+
delivery_range = transit_range.map { |days| business_days_from(pickup_date, days, is_home_delivery) }
|
513
518
|
end
|
514
519
|
|
515
520
|
delivery_range
|
@@ -528,22 +533,32 @@ module ActiveShipping
|
|
528
533
|
LabelResponse.new(success, message, response_info, {labels: labels})
|
529
534
|
end
|
530
535
|
|
531
|
-
def business_days_from(date, days)
|
536
|
+
def business_days_from(date, days, is_home_delivery=false)
|
532
537
|
future_date = date
|
533
538
|
count = 0
|
534
539
|
|
535
540
|
while count < days
|
536
541
|
future_date += 1.day
|
537
|
-
|
542
|
+
if is_home_delivery
|
543
|
+
count += 1 if home_delivery_business_day?(future_date)
|
544
|
+
else
|
545
|
+
count += 1 if business_day?(future_date)
|
546
|
+
end
|
538
547
|
end
|
539
548
|
|
540
549
|
future_date
|
541
550
|
end
|
542
551
|
|
552
|
+
#Transit times for FedEx® Ground do not include Saturdays, Sundays, or holidays.
|
543
553
|
def business_day?(date)
|
544
554
|
(1..5).include?(date.wday)
|
545
555
|
end
|
546
556
|
|
557
|
+
#Transit times for FedEx® Home Delivery, do not include Sundays, Mondays, or holidays.
|
558
|
+
def home_delivery_business_day?(date)
|
559
|
+
(2..6).include?(date.wday)
|
560
|
+
end
|
561
|
+
|
547
562
|
def parse_tracking_response(response, options)
|
548
563
|
xml = build_document(response, 'TrackReply')
|
549
564
|
|
@@ -93,6 +93,25 @@ module ActiveShipping
|
|
93
93
|
"07" => "UPS Express"
|
94
94
|
}
|
95
95
|
|
96
|
+
RETURN_SERVICE_CODES = {
|
97
|
+
"2" => "UPS Print and Mail (PNM)",
|
98
|
+
"3" => "UPS Return Service 1-Attempt (RS1)",
|
99
|
+
"5" => "UPS Return Service 3-Attempt (RS3)",
|
100
|
+
"8" => "UPS Electronic Return Label (ERL)",
|
101
|
+
"9" => "UPS Print Return Label (PRL)",
|
102
|
+
"10" => "UPS Exchange Print Return Label",
|
103
|
+
"11" => "UPS Pack & Collect Service 1-Attempt Box 1",
|
104
|
+
"12" => "UPS Pack & Collect Service 1-Attempt Box 2",
|
105
|
+
"13" => "UPS Pack & Collect Service 1-Attempt Box 3",
|
106
|
+
"14" => "UPS Pack & Collect Service 1-Attempt Box 4",
|
107
|
+
"15" => "UPS Pack & Collect Service 1-Attempt Box 5",
|
108
|
+
"16" => "UPS Pack & Collect Service 3-Attempt Box 1",
|
109
|
+
"17" => "UPS Pack & Collect Service 3-Attempt Box 2",
|
110
|
+
"18" => "UPS Pack & Collect Service 3-Attempt Box 3",
|
111
|
+
"19" => "UPS Pack & Collect Service 3-Attempt Box 4",
|
112
|
+
"20" => "UPS Pack & Collect Service 3-Attempt Box 5",
|
113
|
+
}
|
114
|
+
|
96
115
|
TRACKING_STATUS_CODES = HashWithIndifferentAccess.new(
|
97
116
|
'I' => :in_transit,
|
98
117
|
'D' => :delivered,
|
@@ -111,6 +130,7 @@ module ActiveShipping
|
|
111
130
|
DEFAULT_SERVICE_NAME_TO_CODE = Hash[UPS::DEFAULT_SERVICES.to_a.map(&:reverse)]
|
112
131
|
DEFAULT_SERVICE_NAME_TO_CODE['UPS 2nd Day Air'] = "02"
|
113
132
|
DEFAULT_SERVICE_NAME_TO_CODE['UPS 3 Day Select'] = "12"
|
133
|
+
DEFAULT_SERVICE_NAME_TO_CODE['UPS Next Day Air Early'] = "14"
|
114
134
|
|
115
135
|
SHIPMENT_DELIVERY_CONFIRMATION_CODES = {
|
116
136
|
delivery_confirmation_signature_required: 1,
|
@@ -313,8 +333,11 @@ module ActiveShipping
|
|
313
333
|
# * delivery_confirmation: Can be set to any key from SHIPMENT_DELIVERY_CONFIRMATION_CODES. Can also be set on package level via package.options
|
314
334
|
def build_shipment_request(origin, destination, packages, options={})
|
315
335
|
packages = Array(packages)
|
336
|
+
shipper = options[:shipper] || origin
|
316
337
|
options[:international] = origin.country.name != destination.country.name
|
317
|
-
options[:imperial] ||= IMPERIAL_COUNTRIES.include?(
|
338
|
+
options[:imperial] ||= IMPERIAL_COUNTRIES.include?(shipper.country_code(:alpha2))
|
339
|
+
options[:return] = options[:return_service_code].present?
|
340
|
+
options[:reason_for_export] ||= ("RETURN" if options[:return])
|
318
341
|
|
319
342
|
if allow_package_level_reference_numbers(origin, destination)
|
320
343
|
if options[:reference_numbers]
|
@@ -349,7 +372,7 @@ module ActiveShipping
|
|
349
372
|
build_location_node(xml, 'ShipTo', destination, options)
|
350
373
|
build_location_node(xml, 'ShipFrom', origin, options)
|
351
374
|
# Required element. The company whose account is responsible for the label(s).
|
352
|
-
build_location_node(xml, 'Shipper',
|
375
|
+
build_location_node(xml, 'Shipper', shipper, options)
|
353
376
|
|
354
377
|
if options[:saturday_delivery]
|
355
378
|
xml.ShipmentServiceOptions do
|
@@ -416,7 +439,9 @@ module ActiveShipping
|
|
416
439
|
end
|
417
440
|
|
418
441
|
if options[:international]
|
419
|
-
|
442
|
+
unless options[:return]
|
443
|
+
build_location_node(xml, 'SoldTo', options[:sold_to] || destination, options)
|
444
|
+
end
|
420
445
|
|
421
446
|
if origin.country_code(:alpha2) == 'US' && ['CA', 'PR'].include?(destination.country_code(:alpha2))
|
422
447
|
# Required for shipments from the US to Puerto Rico or Canada
|
@@ -432,6 +457,12 @@ module ActiveShipping
|
|
432
457
|
end
|
433
458
|
end
|
434
459
|
|
460
|
+
if options[:return]
|
461
|
+
xml.ReturnService do
|
462
|
+
xml.Code(options[:return_service_code])
|
463
|
+
end
|
464
|
+
end
|
465
|
+
|
435
466
|
xml.ShipmentServiceOptions do
|
436
467
|
if delivery_confirmation = options[:delivery_confirmation]
|
437
468
|
xml.DeliveryConfirmation do
|
@@ -631,9 +662,13 @@ module ActiveShipping
|
|
631
662
|
|
632
663
|
def build_package_node(xml, package, options = {})
|
633
664
|
xml.Package do
|
634
|
-
|
635
665
|
# not implemented: * Shipment/Package/PackagingType element
|
636
|
-
|
666
|
+
|
667
|
+
#return requires description
|
668
|
+
if options[:return]
|
669
|
+
contents_description = package.options[:description]
|
670
|
+
xml.Description(contents_description) if contents_description
|
671
|
+
end
|
637
672
|
|
638
673
|
xml.PackagingType do
|
639
674
|
xml.Code('02')
|
@@ -171,7 +171,7 @@ module ActiveShipping
|
|
171
171
|
SERVICE_NAME_SUBSTITUTIONS = /#{ESCAPING_AND_SYMBOLS}|#{LEADING_USPS}|#{TRAILING_ASTERISKS}/
|
172
172
|
|
173
173
|
def find_tracking_info(tracking_number, options = {})
|
174
|
-
options = @options.
|
174
|
+
options = @options.merge(options)
|
175
175
|
tracking_request = build_tracking_request(tracking_number, options)
|
176
176
|
response = commit(:track, tracking_request, options[:test] || false)
|
177
177
|
parse_tracking_response(response).first
|
data/test/remote/ups_test.rb
CHANGED
@@ -359,4 +359,43 @@ class RemoteUPSTest < Minitest::Test
|
|
359
359
|
def test_maximum_address_field_length
|
360
360
|
assert_equal 35, @carrier.maximum_address_field_length
|
361
361
|
end
|
362
|
+
|
363
|
+
def test_obtain_return_label
|
364
|
+
response = @carrier.create_shipment(
|
365
|
+
location_fixtures[:beverly_hills_with_name],
|
366
|
+
location_fixtures[:real_google_as_commercial],
|
367
|
+
#package descriptions are required for returns
|
368
|
+
package_fixtures.values_at(:books),
|
369
|
+
{
|
370
|
+
:shipper => location_fixtures[:new_york],
|
371
|
+
:return_service_code => '9',
|
372
|
+
:test => true
|
373
|
+
}
|
374
|
+
)
|
375
|
+
|
376
|
+
assert response.success?
|
377
|
+
|
378
|
+
assert_instance_of ActiveShipping::LabelResponse, response
|
379
|
+
end
|
380
|
+
|
381
|
+
def test_obtain_international_return_label
|
382
|
+
response = @carrier.create_shipment(
|
383
|
+
location_fixtures[:ottawa_with_name],
|
384
|
+
#international return requires destination to have: phone number, name
|
385
|
+
location_fixtures[:real_google_with_name_phone],
|
386
|
+
#package descriptions are required for returns
|
387
|
+
package_fixtures.values_at(:books),
|
388
|
+
{
|
389
|
+
#international return requires shipper to have: phone, name
|
390
|
+
:shipper => location_fixtures[:new_york_with_name],
|
391
|
+
:service_code => '07',
|
392
|
+
:return_service_code => '9',
|
393
|
+
:test => true,
|
394
|
+
}
|
395
|
+
)
|
396
|
+
|
397
|
+
assert response.success?
|
398
|
+
|
399
|
+
assert_instance_of ActiveShipping::LabelResponse, response
|
400
|
+
end
|
362
401
|
end
|
data/test/remote/usps_test.rb
CHANGED
@@ -12,11 +12,11 @@ class RemoteUSPSTest < Minitest::Test
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_tracking
|
15
|
-
response = @carrier.find_tracking_info('
|
15
|
+
response = @carrier.find_tracking_info('LN757696446US', test: false)
|
16
16
|
assert response.success?, response.message
|
17
|
-
assert_equal
|
17
|
+
assert_equal 13,response.shipment_events.size
|
18
18
|
assert_equal 'DELIVERED', response.shipment_events.last.message
|
19
|
-
assert_equal Time.parse('2015-
|
19
|
+
assert_equal Time.parse('2015-11-30 13:02:00 UTC'), response.actual_delivery_date
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_tracking_with_bad_number
|
data/test/test_helper.rb
CHANGED
@@ -152,6 +152,15 @@ module ActiveShipping::Test
|
|
152
152
|
:address1 => '1600 Amphitheatre Parkway',
|
153
153
|
:zip => '94043',
|
154
154
|
:address_type => 'commercial'),
|
155
|
+
:real_google_with_name_phone => Location.new(
|
156
|
+
:name => 'Sergey Brin',
|
157
|
+
:country => 'US',
|
158
|
+
:city => 'Mountain View',
|
159
|
+
:state => 'CA',
|
160
|
+
:address1 => '1600 Amphitheatre Parkway',
|
161
|
+
:zip => '94043',
|
162
|
+
:phone => '1-650-253-0000',
|
163
|
+
:address_type => 'commercial'),
|
155
164
|
:real_google_as_residential => Location.new(
|
156
165
|
:country => 'US',
|
157
166
|
:city => 'Mountain View',
|
@@ -15,19 +15,31 @@ class FedExTest < Minitest::Test
|
|
15
15
|
end
|
16
16
|
|
17
17
|
def test_business_days
|
18
|
-
today = DateTime.civil(2013, 3, 12, 0, 0, 0, "-4")
|
18
|
+
today = DateTime.civil(2013, 3, 12, 0, 0, 0, "-4") #Tuesday
|
19
19
|
|
20
20
|
Timecop.freeze(today) do
|
21
21
|
assert_equal DateTime.civil(2013, 3, 13, 0, 0, 0, "-4"), @carrier.send(:business_days_from, today, 1)
|
22
22
|
assert_equal DateTime.civil(2013, 3, 15, 0, 0, 0, "-4"), @carrier.send(:business_days_from, today, 3)
|
23
|
+
assert_equal DateTime.civil(2013, 3, 18, 0, 0, 0, "-4"), @carrier.send(:business_days_from, today, 4)
|
23
24
|
assert_equal DateTime.civil(2013, 3, 19, 0, 0, 0, "-4"), @carrier.send(:business_days_from, today, 5)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
|
28
|
+
def test_home_delivery_business_days
|
29
|
+
today = DateTime.civil(2013, 3, 12, 0, 0, 0, "-4") #Tuesday
|
30
|
+
|
31
|
+
Timecop.freeze(today) do
|
32
|
+
assert_equal DateTime.civil(2013, 3, 13, 0, 0, 0, "-4"), @carrier.send(:business_days_from, today, 1, true)
|
33
|
+
assert_equal DateTime.civil(2013, 3, 15, 0, 0, 0, "-4"), @carrier.send(:business_days_from, today, 3, true)
|
34
|
+
assert_equal DateTime.civil(2013, 3, 16, 0, 0, 0, "-4"), @carrier.send(:business_days_from, today, 4, true)
|
35
|
+
assert_equal DateTime.civil(2013, 3, 19, 0, 0, 0, "-4"), @carrier.send(:business_days_from, today, 5, true)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
27
39
|
def test_turn_around_time_default
|
28
40
|
mock_response = xml_fixture('fedex/ottawa_to_beverly_hills_rate_response').gsub('<v6:DeliveryTimestamp>2011-07-29</v6:DeliveryTimestamp>', '')
|
29
41
|
|
30
|
-
today = DateTime.civil(2013, 3, 11, 0, 0, 0, "-4")
|
42
|
+
today = DateTime.civil(2013, 3, 11, 0, 0, 0, "-4") #Monday
|
31
43
|
|
32
44
|
Timecop.freeze(today) do
|
33
45
|
delivery_date = Date.today + 7.days # FIVE_DAYS in fixture response, plus weekend
|
@@ -240,19 +252,39 @@ class FedExTest < Minitest::Test
|
|
240
252
|
|
241
253
|
@carrier.expects(:commit).returns(mock_response)
|
242
254
|
|
243
|
-
today = DateTime.civil(2015, 06,
|
255
|
+
today = DateTime.civil(2015, 06, 04, 0, 0, 0, "-4") #Thursday
|
244
256
|
|
245
257
|
Timecop.freeze(today) do
|
246
258
|
rate_estimates = @carrier.find_rates( location_fixtures[:ottawa],
|
247
259
|
location_fixtures[:beverly_hills],
|
248
260
|
package_fixtures.values_at(:book, :wii), :test => true)
|
249
261
|
|
250
|
-
# the above fixture will specify a transit time of 3 days
|
251
|
-
|
262
|
+
# the above fixture will specify a transit time of 3 days
|
263
|
+
# for ground home, sunday and monday are non-biz days
|
264
|
+
# so it is delivered on Tuesday
|
265
|
+
delivery_date = Date.today + 3 + 2
|
252
266
|
assert_equal delivery_date, rate_estimates.rates.first.delivery_date
|
253
267
|
end
|
254
268
|
end
|
255
269
|
|
270
|
+
def test_delivery_date_from_ground_home_transit_time_on_saturday
|
271
|
+
mock_response = xml_fixture('fedex/raterequest_response_with_ground_home_delivery')
|
272
|
+
|
273
|
+
@carrier.expects(:commit).returns(mock_response)
|
274
|
+
|
275
|
+
today = DateTime.civil(2015, 06, 03, 0, 0, 0, "-4") #Wednesday
|
276
|
+
|
277
|
+
Timecop.freeze(today) do
|
278
|
+
rate_estimates = @carrier.find_rates( location_fixtures[:ottawa],
|
279
|
+
location_fixtures[:beverly_hills],
|
280
|
+
package_fixtures.values_at(:book, :wii), :test => true)
|
281
|
+
|
282
|
+
# the above fixture will specify a transit time of 3 days
|
283
|
+
# since ground home delivers on Saturday, there is no delay
|
284
|
+
delivery_date = Date.today + 3
|
285
|
+
assert_equal delivery_date, rate_estimates.rates.first.delivery_date
|
286
|
+
end
|
287
|
+
end
|
256
288
|
|
257
289
|
def test_failure_to_parse_invalid_xml_results_in_a_useful_error
|
258
290
|
mock_response = xml_fixture('fedex/invalid_fedex_reply')
|
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.6.
|
4
|
+
version: 1.6.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: 2015-
|
14
|
+
date: 2015-12-03 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: quantified
|