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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 19c7f898c4fae3541f44b1652a80084385b3b6ca
4
- data.tar.gz: a7349bb2781c99c97196978e7dd378a3c2273519
3
+ metadata.gz: 838209b9accf6cfb537ac16786e8683d18155073
4
+ data.tar.gz: 75036f0188503179ddb089ee25f99dc8b9fa4538
5
5
  SHA512:
6
- metadata.gz: 0714de5ac8bd86737faee62a0a31190ced5961f6124a9c429c94a1faa7560770fc96159debc8ee059a2ecdd3a875c03f6e29e674e36e5952ace60d70cc236ebd
7
- data.tar.gz: d92d587f63be9ec16d81a3e43ef4e9ebf26fb599c4e99f58140e94419d64ba341270ed5441661aef525a536ae4d02f3f889f969d0e6d3694db8e1fa3310cd2a2
6
+ metadata.gz: 8d3e7c5b1b9cf6a46986c02725ebda6324724cd0d1c073f7fcded221314bf1ec6ebe360105f60c39e72f3612143d1749e0be36b648b135dc03eef97857098577
7
+ data.tar.gz: fd34ef65e9404b1255c04a4e4867e6ad1fa3e0089ddbf1e73e4ff7b43209dae66f3f9e4e71d171d117fe2718c2cff406500fc9506dc3331d478af2668384eafb
data/.gitignore CHANGED
@@ -10,3 +10,4 @@ test/fixtures/live_credentials.yml
10
10
  .rbenv-version
11
11
  .yardoc/
12
12
  doc/
13
+ .idea
@@ -143,7 +143,7 @@ module ActiveShipping
143
143
  end
144
144
 
145
145
  def find_rates(origin, destination, packages, options = {})
146
- options = @options.update(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.update(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.update(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
- xml.ShipTimestamp(ship_timestamp(options[:turn_around_time]).iso8601(0))
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
- delivery_range = transit_range.map { |days| business_days_from(ship_date(options[:turn_around_time]), days) }
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
- count += 1 if business_day?(future_date)
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?(origin.country_code(:alpha2))
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', options[:shipper] || origin, options)
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
- build_location_node(xml, 'SoldTo', options[:sold_to] || destination, options)
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
- # * Shipment/Package/Description element
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.update(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
@@ -1,3 +1,3 @@
1
1
  module ActiveShipping
2
- VERSION = "1.6.1"
2
+ VERSION = "1.6.2"
3
3
  end
@@ -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
@@ -12,11 +12,11 @@ class RemoteUSPSTest < Minitest::Test
12
12
  end
13
13
 
14
14
  def test_tracking
15
- response = @carrier.find_tracking_info('LN284529912US', test: false)
15
+ response = @carrier.find_tracking_info('LN757696446US', test: false)
16
16
  assert response.success?, response.message
17
- assert_equal 9,response.shipment_events.size
17
+ assert_equal 13,response.shipment_events.size
18
18
  assert_equal 'DELIVERED', response.shipment_events.last.message
19
- assert_equal Time.parse('2015-06-01 13:36:00 UTC'), response.actual_delivery_date
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, 03, 0, 0, 0, "-4")
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, with 2 weekend days accounted for
251
- delivery_date = Date.today + 5
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.1
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-11-11 00:00:00.000000000 Z
14
+ date: 2015-12-03 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: quantified