active_shipping 1.7.1 → 1.7.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: 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