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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ab948e86e9c144422b55594fc95f88034607cec2
4
- data.tar.gz: 41d45d0e901d21086d43ec7be167ae90653a2bf6
3
+ metadata.gz: a721187cba1984ab9a456dea8c660c81d2a1aa68
4
+ data.tar.gz: 4b6ba4b2a8bedd5434f611d81d2ba74df92fab5e
5
5
  SHA512:
6
- metadata.gz: 6e0984b2657b841ea40c6d98a3362fc5390d0c9ccaac2946202df6635211486738a623a425a10f1d7b5adc058028e890588035b7797403d1eba5e7cf7bb987fe
7
- data.tar.gz: c0e2bd4ffa66008a1915002c509412884aae77b3485c922e20a8078ae45934af52e3f22b2dcc741f6a26e2e266805b7b4c7b81a4d8b09b297b4c2dcc1f22d327
6
+ metadata.gz: 7fecbfa0feaf36671db206bb30fb3e981b5c079183d45ebd8a2c096a41ba4d66f516b69d443ed3e08b54c1af4fa070ce618fb9f3fc89ce48bf2e19fafcec0d2b
7
+ data.tar.gz: 80a224c59f08ba748989a2aacc4ddcacd529296c43c4d0caa370339a26d60d1d2c29d860ce4e0c1d5719e2f791aef2b05589b44055b45228400fd47fef24fae7
data/dev.yml CHANGED
@@ -2,8 +2,8 @@ name: active_shipping
2
2
 
3
3
  up:
4
4
  - ruby:
5
- version: 2.2.4
6
- build: true
5
+ package: homebrew/version/ruby22
6
+ version: 2.2.5p319
7
7
  - bundler
8
8
 
9
9
  commands:
@@ -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('PAPER_7X4.75')
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: who will pay for the shipping label
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[:origin_account]
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.BillShipper do
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.BillShipper do
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.BillShipper do
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
@@ -140,5 +140,9 @@ module ActiveShipping #:nodoc:
140
140
  def address2_and_3
141
141
  [address2, address3].reject(&:blank?).join(", ")
142
142
  end
143
+
144
+ def ==(other)
145
+ to_hash == other.to_hash
146
+ end
143
147
  end
144
148
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module ActiveShipping
2
- VERSION = "1.7.1"
2
+ VERSION = "1.7.2"
3
3
  end
@@ -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/PaymentInformation/BillThirdParty/BillThirdPartyShipper/AccountNumber').text
369
- assert_equal expected_postal_code_number, response.search('/ShipmentConfirmRequest/Shipment/PaymentInformation/BillThirdParty/BillThirdPartyShipper/ThirdParty/Address/PostalCode').text
370
- assert_equal expected_country_code, response.search('/ShipmentConfirmRequest/Shipment/PaymentInformation/BillThirdParty/BillThirdPartyShipper/ThirdParty/Address/CountryCode').text
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'
@@ -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.1
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-04-27 00:00:00.000000000 Z
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