active_shipping 0.12.4 → 0.12.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/lib/active_shipping.rb +2 -1
  3. data/lib/active_shipping/shipping/base.rb +2 -2
  4. data/lib/active_shipping/shipping/carrier.rb +16 -13
  5. data/lib/active_shipping/shipping/carriers/benchmark_carrier.rb +3 -4
  6. data/lib/active_shipping/shipping/carriers/bogus_carrier.rb +1 -3
  7. data/lib/active_shipping/shipping/carriers/canada_post.rb +33 -44
  8. data/lib/active_shipping/shipping/carriers/canada_post_pws.rb +72 -81
  9. data/lib/active_shipping/shipping/carriers/fedex.rb +118 -109
  10. data/lib/active_shipping/shipping/carriers/kunaki.rb +33 -32
  11. data/lib/active_shipping/shipping/carriers/new_zealand_post.rb +9 -16
  12. data/lib/active_shipping/shipping/carriers/shipwire.rb +36 -35
  13. data/lib/active_shipping/shipping/carriers/stamps.rb +39 -51
  14. data/lib/active_shipping/shipping/carriers/ups.rb +280 -116
  15. data/lib/active_shipping/shipping/carriers/ups.rb.orig +456 -0
  16. data/lib/active_shipping/shipping/carriers/usps.rb +145 -100
  17. data/lib/active_shipping/shipping/carriers/usps.rb.orig +616 -0
  18. data/lib/active_shipping/shipping/errors.rb +1 -1
  19. data/lib/active_shipping/shipping/label_response.rb +25 -0
  20. data/lib/active_shipping/shipping/location.rb +18 -16
  21. data/lib/active_shipping/shipping/package.rb +51 -54
  22. data/lib/active_shipping/shipping/rate_estimate.rb +10 -12
  23. data/lib/active_shipping/shipping/rate_response.rb +3 -7
  24. data/lib/active_shipping/shipping/response.rb +6 -9
  25. data/lib/active_shipping/shipping/shipment_event.rb +2 -4
  26. data/lib/active_shipping/shipping/shipment_packer.rb +32 -17
  27. data/lib/active_shipping/shipping/shipping_response.rb +2 -4
  28. data/lib/active_shipping/shipping/tracking_response.rb +3 -5
  29. data/lib/active_shipping/version.rb +1 -1
  30. data/lib/vendor/quantified/lib/quantified/attribute.rb +79 -80
  31. data/lib/vendor/quantified/lib/quantified/length.rb +5 -5
  32. data/lib/vendor/quantified/lib/quantified/mass.rb +4 -4
  33. data/lib/vendor/quantified/test/length_test.rb +19 -15
  34. data/lib/vendor/quantified/test/mass_test.rb +14 -14
  35. data/lib/vendor/quantified/test/test_helper.rb +1 -2
  36. data/lib/vendor/test_helper.rb +0 -1
  37. data/lib/vendor/xml_node/benchmark/bench_generation.rb +2 -4
  38. data/lib/vendor/xml_node/lib/xml_node.rb +54 -55
  39. data/lib/vendor/xml_node/test/test_generating.rb +23 -28
  40. data/lib/vendor/xml_node/test/test_parsing.rb +5 -8
  41. metadata +6 -25
  42. checksums.yaml.gz.sig +0 -1
  43. data.tar.gz.sig +0 -0
  44. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f283611b274ba965863f5320de5a30dda94bffc9
4
- data.tar.gz: e770521d4940a107e28fe80ffdf4ce2b1c2f5838
3
+ metadata.gz: 1976e71d35364954a7b796b394000fa996d3e0b1
4
+ data.tar.gz: 0c143eefaaf19b10cfaba63e01110164024b3bae
5
5
  SHA512:
6
- metadata.gz: 20b52260419ce6a9ffcd2b67229af8303430bedb36fdabb21126cfb3b4dcb48df65868c7a4e3380947b8087b16ff790e102b5c7f7dbcd6afe920105701903d72
7
- data.tar.gz: 0546189f408a9b687b584d90600cf20c420f68cc2e9cd381180ad4794be44ee322ea338424b4f38c5fca11489560dda22f0da5be1fa1e0c19006b05a1b8b8db0
6
+ metadata.gz: 312abbbb1fd246d4f6221cbf4fa7f70101465d118ff18bc2c588be8f276904e90ee9a9666d90b745a3d29c6abe1cc615230f188e7a6acb759374977a88ce2838
7
+ data.tar.gz: db9d8dccf1c806d521188f99fff5b72eb7704da60359bb4239fa293e21be21e646373a0d42fd5df901b597e224bcb5ccd7d7a0c617607c2375242456df1a8843
@@ -25,7 +25,7 @@ $:.unshift File.dirname(__FILE__)
25
25
 
26
26
  begin
27
27
  require 'active_support/all'
28
- rescue LoadError => e
28
+ rescue LoadError
29
29
  require 'rubygems'
30
30
  gem "activesupport", ">= 2.3.5"
31
31
  require "active_support/all"
@@ -42,6 +42,7 @@ require 'active_shipping/shipping/response'
42
42
  require 'active_shipping/shipping/rate_response'
43
43
  require 'active_shipping/shipping/tracking_response'
44
44
  require 'active_shipping/shipping/shipping_response'
45
+ require 'active_shipping/shipping/label_response'
45
46
  require 'active_shipping/shipping/package'
46
47
  require 'active_shipping/shipping/location'
47
48
  require 'active_shipping/shipping/rate_estimate'
@@ -3,9 +3,9 @@ module ActiveMerchant
3
3
  module Base
4
4
  mattr_accessor :mode
5
5
  self.mode = :production
6
-
6
+
7
7
  def self.carrier(name)
8
- ActiveMerchant::Shipping::Carriers.all.find {|c| c.name.downcase == name.to_s.downcase} ||
8
+ ActiveMerchant::Shipping::Carriers.all.find { |c| c.name.downcase == name.to_s.downcase } ||
9
9
  raise(NameError, "unknown carrier #{name}")
10
10
  end
11
11
  end
@@ -1,18 +1,17 @@
1
1
  module ActiveMerchant
2
2
  module Shipping
3
3
  class Carrier
4
-
5
4
  include RequiresParameters
6
5
  include PostsData
7
6
  include Quantified
8
-
7
+
9
8
  attr_reader :last_request
10
9
  attr_accessor :test_mode
11
10
  alias_method :test_mode?, :test_mode
12
-
11
+
13
12
  # Credentials should be in options hash under keys :login, :password and/or :key.
14
13
  def initialize(options = {})
15
- requirements.each {|key| requires!(options, key)}
14
+ requirements.each { |key| requires!(options, key) }
16
15
  @options = options
17
16
  @last_request = nil
18
17
  @test_mode = @options[:test]
@@ -22,33 +21,37 @@ module ActiveMerchant
22
21
  def requirements
23
22
  []
24
23
  end
25
-
24
+
26
25
  # Override with whatever you need to get the rates
27
26
  def find_rates(origin, destination, packages, options = {})
28
27
  end
29
-
28
+
29
+ # Override with whatever you need to get a shipping label
30
+ def create_shipment(origin, destination, packages, options = {})
31
+ end
32
+
30
33
  # Validate credentials with a call to the API. By default this just does a find_rates call
31
34
  # with the orgin and destination both as the carrier's default_location. Override to provide
32
35
  # alternate functionality, such as checking for test_mode to use test servers, etc.
33
36
  def valid_credentials?
34
37
  location = self.class.default_location
35
- find_rates(location,location,Package.new(100, [5,15,30]), :test => test_mode)
38
+ find_rates(location, location, Package.new(100, [5, 15, 30]), :test => test_mode)
36
39
  rescue ActiveMerchant::Shipping::ResponseError
37
40
  false
38
41
  else
39
42
  true
40
43
  end
41
-
44
+
42
45
  def maximum_weight
43
46
  Mass.new(150, :pounds)
44
47
  end
45
-
48
+
46
49
  protected
47
-
50
+
48
51
  def node_text_or_nil(xml_node)
49
52
  xml_node ? xml_node.text : nil
50
53
  end
51
-
54
+
52
55
  # Override in subclasses for non-U.S.-based carriers.
53
56
  def self.default_location
54
57
  Location.new( :country => 'US',
@@ -60,7 +63,7 @@ module ActiveMerchant
60
63
  :phone => '1-310-285-1013',
61
64
  :fax => '1-310-275-8159')
62
65
  end
63
-
66
+
64
67
  # Use after building the request to save for later inspection. Probably won't ever be overridden.
65
68
  def save_request(r)
66
69
  @last_request = r
@@ -72,7 +75,7 @@ module ActiveMerchant
72
75
  days.times do
73
76
  begin
74
77
  date = date + 1
75
- end until ![0,6].include?(date.wday)
78
+ end while [0, 6].include?(date.wday)
76
79
  end
77
80
  date
78
81
  end
@@ -7,7 +7,7 @@ module ActiveMerchant
7
7
  class BenchmarkCarrier < Carrier
8
8
  cattr_reader :name
9
9
  @@name = "Benchmark Carrier"
10
-
10
+
11
11
  def find_rates(origin, destination, packages, options = {})
12
12
  origin = Location.from(origin)
13
13
  destination = Location.from(destination)
@@ -18,17 +18,16 @@ module ActiveMerchant
18
18
  bogus_estimate = RateEstimate.new(
19
19
  origin, destination, @@name,
20
20
  "Free Benchmark Shipping", :total_price => 0, :currency => 'USD',
21
- :packages => packages, :delivery_range => [Time.now.utc.strftime("%Y-%d-%m"), Time.now.utc.strftime("%Y-%d-%m")]
21
+ :packages => packages, :delivery_range => [Time.now.utc.strftime("%Y-%d-%m"), Time.now.utc.strftime("%Y-%d-%m")]
22
22
  )
23
23
  RateResponse.new(true, "Success (delayed #{delay_time} seconds)", {:rate => 'free'}, :rates => [bogus_estimate], :xml => "<rate>free</rate>")
24
24
  end
25
-
25
+
26
26
  private
27
27
 
28
28
  def generate_simulated_lag(max_delay = 30)
29
29
  sleep Random.rand * max_delay
30
30
  end
31
-
32
31
  end
33
32
  end
34
33
  end
@@ -3,14 +3,12 @@ module ActiveMerchant
3
3
  class BogusCarrier < Carrier
4
4
  cattr_reader :name
5
5
  @@name = "Bogus Carrier"
6
-
7
-
6
+
8
7
  def find_rates(origin, destination, packages, options = {})
9
8
  origin = Location.from(origin)
10
9
  destination = Location.from(destination)
11
10
  packages = Array(packages)
12
11
  end
13
-
14
12
  end
15
13
  end
16
14
  end
@@ -2,37 +2,32 @@ require 'cgi'
2
2
 
3
3
  module ActiveMerchant
4
4
  module Shipping
5
-
6
5
  class CanadaPost < Carrier
7
-
8
6
  # NOTE!
9
7
  # A Merchant CPC Id must be assigned to you by Canada Post
10
8
  # CPC_DEMO_XML is just a public domain account for testing
11
-
9
+
12
10
  class CanadaPostRateResponse < RateResponse
13
-
14
11
  attr_reader :boxes, :postal_outlets
15
-
12
+
16
13
  def initialize(success, message, params = {}, options = {})
17
14
  @boxes = options[:boxes]
18
15
  @postal_outlets = options[:postal_outlets]
19
16
  super
20
17
  end
21
-
22
18
  end
23
-
19
+
24
20
  cattr_reader :name, :name_french
25
21
  @@name = "Canada Post"
26
22
  @@name_french = "Postes Canada"
27
-
23
+
28
24
  Box = Struct.new(:name, :weight, :expediter_weight, :length, :width, :height, :packedItems)
29
25
  PackedItem = Struct.new(:quantity, :description)
30
26
  PostalOutlet = Struct.new(:sequence_no, :distance, :name, :business_name, :postal_address, :business_hours)
31
-
32
- DEFAULT_TURN_AROUND_TIME = 24
27
+
33
28
  URL = "http://sellonline.canadapost.ca:30000"
34
- DOCTYPE = '<!DOCTYPE eparcel SYSTEM "http://sellonline.canadapost.ca/DevelopersResources/protocolV3/eParcel.dtd">'
35
-
29
+ DOCTYPE = '<!DOCTYPE eparcel SYSTEM "http://sellonline.canadapost.ca/DevelopersResources/protocolV3/eParcel.dtd">'
30
+
36
31
  RESPONSE_CODES = {
37
32
  '1' => "All calculation was done",
38
33
  '2' => "Default shipping rates are returned due to a problem during the processing of the request.",
@@ -78,25 +73,24 @@ module ActiveMerchant
78
73
  '-6002' => "Unable to write to the database",
79
74
  '-50000' => "Internal problem - Please contact Sell Online Help Desk"
80
75
  }
81
-
76
+
82
77
  NON_ISO_COUNTRY_NAMES = {
83
78
  'Russian Federation' => 'Russia'
84
79
  }
85
80
 
86
-
87
81
  def requirements
88
82
  [:login]
89
83
  end
90
-
84
+
91
85
  def find_rates(origin, destination, line_items = [], options = {})
92
86
  rate_request = build_rate_request(origin, destination, line_items, options)
93
87
  commit(rate_request, origin, destination, options)
94
88
  end
95
-
89
+
96
90
  def maximum_weight
97
91
  Mass.new(30, :kilograms)
98
92
  end
99
-
93
+
100
94
  def self.default_location
101
95
  {
102
96
  :country => 'CA',
@@ -108,15 +102,15 @@ module ActiveMerchant
108
102
  end
109
103
 
110
104
  protected
111
-
105
+
112
106
  def commit(request, origin, destination, options = {})
113
- response = parse_rate_response(ssl_post(URL, request), origin, destination, options)
107
+ parse_rate_response(ssl_post(URL, request), origin, destination, options)
114
108
  end
115
-
109
+
116
110
  private
117
-
111
+
118
112
  def build_rate_request(origin, destination, line_items = [], options = {})
119
- line_items = [line_items] if !line_items.is_a?(Array)
113
+ line_items = [line_items] unless line_items.is_a?(Array)
120
114
  origin = origin.is_a?(Location) ? origin : Location.new(origin)
121
115
  destination = destination.is_a?(Location) ? destination : Location.new(destination)
122
116
 
@@ -126,14 +120,14 @@ module ActiveMerchant
126
120
 
127
121
  request << XmlNode.new('merchantCPCID', @options[:login])
128
122
  request << XmlNode.new('fromPostalCode', origin.postal_code)
129
- request << XmlNode.new('turnAroundTime', options[:turn_around_time] ? options[:turn_around_time] : DEFAULT_TURN_AROUND_TIME)
123
+ request << XmlNode.new('turnAroundTime', options[:turn_around_time]) if options[:turn_around_time]
130
124
  request << XmlNode.new('itemsPrice', dollar_amount(line_items.map(&:value).compact.sum))
131
125
 
132
- #line items
126
+ # line items
133
127
  request << build_line_items(line_items)
134
128
 
135
- #delivery info
136
- #NOTE: These tags MUST be after line items
129
+ # delivery info
130
+ # NOTE: These tags MUST be after line items
137
131
  request << XmlNode.new('city', destination.city)
138
132
  request << XmlNode.new('provOrState', destination.province)
139
133
  request << XmlNode.new('country', handle_non_iso_country_names(destination.country))
@@ -157,11 +151,11 @@ module ActiveMerchant
157
151
  service_code = product.attribute('id').to_s
158
152
 
159
153
  rate_estimates << RateEstimate.new(origin, destination, @@name, service_name,
160
- :service_code => service_code,
161
- :total_price => product.get_text('rate').to_s,
162
- :currency => 'CAD',
163
- :shipping_date => product.get_text('shippingDate').to_s,
164
- :delivery_range => [product.get_text('deliveryDate').to_s] * 2
154
+ :service_code => service_code,
155
+ :total_price => product.get_text('rate').to_s,
156
+ :currency => 'CAD',
157
+ :shipping_date => product.get_text('shippingDate').to_s,
158
+ :delivery_range => [product.get_text('deliveryDate').to_s] * 2
165
159
  )
166
160
  end
167
161
 
@@ -190,14 +184,14 @@ module ActiveMerchant
190
184
  postal_outlet.name = outlet.get_text('outletName').to_s
191
185
  postal_outlet.business_name = outlet.get_text('businessName').to_s
192
186
 
193
- postal_outlet.postal_address = Location.new({
187
+ postal_outlet.postal_address = Location.new(
194
188
  :address1 => outlet.get_text('postalAddress/addressLine').to_s,
195
189
  :postal_code => outlet.get_text('postalAddress/postal_code').to_s,
196
190
  :city => outlet.get_text('postalAddress/municipality').to_s,
197
191
  :province => outlet.get_text('postalAddress/province').to_s,
198
192
  :country => 'Canada',
199
193
  :phone_number => outlet.get_text('phoneNumber').to_s
200
- })
194
+ )
201
195
 
202
196
  postal_outlet.business_hours = outlet.elements.collect('businessHours') do |hour|
203
197
  { :day_of_week => hour.get_text('dayOfWeek').to_s, :time => hour.get_text('time').to_s }
@@ -216,7 +210,7 @@ module ActiveMerchant
216
210
  value = xml.get_text('eparcel/ratesAndServicesResponse/statusCode').to_s
217
211
  value == '1' || value == '2'
218
212
  end
219
-
213
+
220
214
  def response_message(xml)
221
215
  if response_success?(xml)
222
216
  xml.get_text('eparcel/ratesAndServicesResponse/statusMessage').to_s
@@ -224,7 +218,7 @@ module ActiveMerchant
224
218
  xml.get_text('eparcel/error/statusMessage').to_s
225
219
  end
226
220
  end
227
-
221
+
228
222
  # <!-- List of items in the shopping -->
229
223
  # <!-- cart -->
230
224
  # <!-- Each item is defined by : -->
@@ -233,12 +227,10 @@ module ActiveMerchant
233
227
  # <!-- - weight (mandatory) -->
234
228
  # <!-- - description (mandatory) -->
235
229
  # <!-- - ready to ship (optional) -->
236
-
230
+
237
231
  def build_line_items(line_items)
238
- xml_line_items = XmlNode.new('lineItems') do |line_items_node|
239
-
232
+ XmlNode.new('lineItems') do |line_items_node|
240
233
  line_items.each do |line_item|
241
-
242
234
  line_items_node << XmlNode.new('item') do |item|
243
235
  item << XmlNode.new('quantity', 1)
244
236
  item << XmlNode.new('weight', line_item.kilograms)
@@ -247,19 +239,16 @@ module ActiveMerchant
247
239
  item << XmlNode.new('height', line_item.cm(:height).to_s)
248
240
  item << XmlNode.new('description', line_item.options[:description] || ' ')
249
241
  item << XmlNode.new('readyToShip', line_item.options[:ready_to_ship] || nil)
250
-
251
242
  # By setting the 'readyToShip' tag to true, Sell Online will not pack this item in the boxes defined in the merchant profile.
252
243
  end
253
244
  end
254
245
  end
255
-
256
- xml_line_items
257
246
  end
258
-
247
+
259
248
  def dollar_amount(cents)
260
249
  "%0.2f" % (cents / 100.0)
261
250
  end
262
-
251
+
263
252
  def handle_non_iso_country_names(country)
264
253
  NON_ISO_COUNTRY_NAMES[country.to_s] || country
265
254
  end
@@ -2,7 +2,6 @@ require 'cgi'
2
2
 
3
3
  module ActiveMerchant
4
4
  module Shipping
5
-
6
5
  class CanadaPostPWS < Carrier
7
6
  @@name = "Canada Post PWS"
8
7
 
@@ -38,14 +37,14 @@ module ActiveMerchant
38
37
  RATE_MIMETYPE = "application/vnd.cpc.ship.rate+xml"
39
38
  TRACK_MIMETYPE = "application/vnd.cpc.track+xml"
40
39
  REGISTER_MIMETYPE = "application/vnd.cpc.registration+xml"
41
-
40
+
42
41
  LANGUAGE = {
43
42
  'en' => 'en-CA',
44
43
  'fr' => 'fr-CA'
45
44
  }
46
-
47
- SHIPPING_OPTIONS = [:d2po, :d2po_office_id, :cov, :cov_amount, :cod, :cod_amount, :cod_includes_shipping,
48
- :cod_method_of_payment, :so, :dc, :dns, :pa18, :pa19, :hfp, :lad,
45
+
46
+ SHIPPING_OPTIONS = [:d2po, :d2po_office_id, :cov, :cov_amount, :cod, :cod_amount, :cod_includes_shipping,
47
+ :cod_method_of_payment, :so, :dc, :dns, :pa18, :pa19, :hfp, :lad,
49
48
  :rase, :rts, :aban]
50
49
 
51
50
  RATES_OPTIONS = [:cov, :cov_amount, :cod, :so, :dc, :dns, :pa18, :pa19, :hfp, :lad]
@@ -61,11 +60,11 @@ module ActiveMerchant
61
60
  @customer_number = options[:customer_number]
62
61
  super(options)
63
62
  end
64
-
63
+
65
64
  def requirements
66
65
  [:api_key, :secret]
67
66
  end
68
-
67
+
69
68
  def find_rates(origin, destination, line_items = [], options = {}, package = nil, services = [])
70
69
  url = endpoint + "rs/ship/price"
71
70
  request = build_rates_request(origin, destination, line_items, options, package, services)
@@ -74,7 +73,7 @@ module ActiveMerchant
74
73
  rescue ActiveMerchant::ResponseError, ActiveMerchant::Shipping::ResponseError => e
75
74
  error_response(e.response.body, CPPWSRateResponse)
76
75
  end
77
-
76
+
78
77
  def find_tracking_info(pin, options = {})
79
78
  response = ssl_get(tracking_url(pin), headers(options, TRACK_MIMETYPE))
80
79
  parse_tracking_response(response)
@@ -82,12 +81,12 @@ module ActiveMerchant
82
81
  if e.response
83
82
  error_response(e.response.body, CPPWSTrackingResponse)
84
83
  else
85
- CPPWSTrackingResponse.new(false, e.message, {}, {:carrier => @@name})
84
+ CPPWSTrackingResponse.new(false, e.message, {}, :carrier => @@name)
86
85
  end
87
- rescue InvalidPinFormatError => e
88
- CPPWSTrackingResponse.new(false, "Invalid Pin Format", {}, {:carrier => @@name})
86
+ rescue InvalidPinFormatError
87
+ CPPWSTrackingResponse.new(false, "Invalid Pin Format", {}, :carrier => @@name)
89
88
  end
90
-
89
+
91
90
  # line_items should be a list of PackageItem's
92
91
  def create_shipment(origin, destination, package, line_items = [], options = {})
93
92
  request_body = build_shipment_request(origin, destination, package, line_items, options)
@@ -95,20 +94,20 @@ module ActiveMerchant
95
94
  parse_shipment_response(response)
96
95
  rescue ActiveMerchant::ResponseError, ActiveMerchant::Shipping::ResponseError => e
97
96
  error_response(e.response.body, CPPWSShippingResponse)
98
- rescue MissingCustomerNumberError => e
99
- CPPWSShippingResponse.new(false, "Missing Customer Number", {}, {:carrier => @@name})
97
+ rescue MissingCustomerNumberError
98
+ CPPWSShippingResponse.new(false, "Missing Customer Number", {}, :carrier => @@name)
100
99
  end
101
100
 
102
101
  def retrieve_shipment(shipping_id, options = {})
103
102
  response = ssl_post(shipment_url(shipping_id, options), nil, headers(options, SHIPMENT_MIMETYPE, SHIPMENT_MIMETYPE))
104
- shipping_response = parse_shipment_response(response)
103
+ parse_shipment_response(response)
105
104
  end
106
105
 
107
106
  def find_shipment_receipt(shipping_id, options = {})
108
107
  response = ssl_get(shipment_receipt_url(shipping_id, options), headers(options, SHIPMENT_MIMETYPE, SHIPMENT_MIMETYPE))
109
- shipping_response = parse_shipment_receipt_response(response)
108
+ parse_shipment_receipt_response(response)
110
109
  end
111
-
110
+
112
111
  def retrieve_shipping_label(shipping_response, options = {})
113
112
  raise MissingShippingNumberError unless shipping_response && shipping_response.shipping_id
114
113
  ssl_get(shipping_response.label_url, headers(options, "application/pdf"))
@@ -116,7 +115,7 @@ module ActiveMerchant
116
115
 
117
116
  def register_merchant(options = {})
118
117
  url = endpoint + "ot/token"
119
- response = ssl_post(url, nil, headers({}, REGISTER_MIMETYPE, REGISTER_MIMETYPE).merge({"Content-Length" => "0"}))
118
+ response = ssl_post(url, nil, headers({}, REGISTER_MIMETYPE, REGISTER_MIMETYPE).merge("Content-Length" => "0"))
120
119
  parse_register_token_response(response)
121
120
  rescue ActiveMerchant::ResponseError, ActiveMerchant::Shipping::ResponseError => e
122
121
  error_response(e.response.body, CPPWSRegisterResponse)
@@ -154,7 +153,7 @@ module ActiveMerchant
154
153
  rescue ActiveMerchant::ResponseError, ActiveMerchant::Shipping::ResponseError => e
155
154
  error_response(e.response.body, CPPWSRateResponse)
156
155
  end
157
-
156
+
158
157
  def maximum_weight
159
158
  Mass.new(MAX_WEIGHT, :kilograms)
160
159
  end
@@ -163,8 +162,8 @@ module ActiveMerchant
163
162
 
164
163
  def parse_services_response(response)
165
164
  doc = REXML::Document.new(REXML::Text::unnormalize(response))
166
- service_nodes = doc.elements['services'].elements.collect('service') {|node| node }
167
- services = service_nodes.inject({}) do |result, node|
165
+ service_nodes = doc.elements['services'].elements.collect('service') { |node| node }
166
+ service_nodes.inject({}) do |result, node|
168
167
  service_code = node.get_text("service-code").to_s
169
168
  service_name = node.get_text("service-name").to_s
170
169
  service_link = node.elements["link"].attributes['href']
@@ -176,7 +175,6 @@ module ActiveMerchant
176
175
  }
177
176
  result
178
177
  end
179
- services
180
178
  end
181
179
 
182
180
  def parse_service_options_response(response)
@@ -186,7 +184,7 @@ module ActiveMerchant
186
184
  service_name = service_node.get_text("service-name").to_s
187
185
  options_node = service_node.elements['options']
188
186
  unless options_node.blank?
189
- option_nodes = options_node.elements.collect('option') {|node| node}
187
+ option_nodes = options_node.elements.collect('option') { |node| node }
190
188
  options = option_nodes.inject([]) do |result, node|
191
189
  option = {
192
190
  :code => node.get_text("option-code").to_s,
@@ -209,7 +207,7 @@ module ActiveMerchant
209
207
  :min_height => dimensions_node.elements["height"].attributes['min'].to_f,
210
208
  :max_height => dimensions_node.elements["height"].attributes['max'].to_f,
211
209
  :min_width => dimensions_node.elements["width"].attributes['min'].to_f,
212
- :max_width => dimensions_node.elements["width"].attributes['max'].to_f,
210
+ :max_width => dimensions_node.elements["width"].attributes['max'].to_f
213
211
  }
214
212
 
215
213
  {
@@ -223,8 +221,8 @@ module ActiveMerchant
223
221
  def parse_option_response(response)
224
222
  doc = REXML::Document.new(REXML::Text::unnormalize(response))
225
223
  option_node = doc.elements['option']
226
- conflicts = option_node.elements['conflicting-options'].elements.collect('option-code') {|node| node.get_text.to_s} unless option_node.elements['conflicting-options'].blank?
227
- prereqs = option_node.elements['prerequisite-options'].elements.collect('option-code') {|node| node.get_text.to_s} unless option_node.elements['prerequisite-options'].blank?
224
+ conflicts = option_node.elements['conflicting-options'].elements.collect('option-code') { |node| node.get_text.to_s } unless option_node.elements['conflicting-options'].blank?
225
+ prereqs = option_node.elements['prerequisite-options'].elements.collect('option-code') { |node| node.get_text.to_s } unless option_node.elements['prerequisite-options'].blank?
228
226
  option = {
229
227
  :code => option_node.get_text('option-code').to_s,
230
228
  :name => option_node.get_text('option-name').to_s,
@@ -262,7 +260,7 @@ module ActiveMerchant
262
260
  doc = REXML::Document.new(REXML::Text::unnormalize(response))
263
261
  raise ActiveMerchant::Shipping::ResponseError, "No Quotes" unless doc.elements['price-quotes']
264
262
 
265
- quotes = doc.elements['price-quotes'].elements.collect('price-quote') {|node| node }
263
+ quotes = doc.elements['price-quotes'].elements.collect('price-quote') { |node| node }
266
264
  rates = quotes.map do |node|
267
265
  service_name = node.get_text("service-name").to_s
268
266
  service_code = node.get_text("service-code").to_s
@@ -279,14 +277,13 @@ module ActiveMerchant
279
277
  CPPWSRateResponse.new(true, "", {}, :rates => rates)
280
278
  end
281
279
 
282
-
283
280
  # tracking
284
-
281
+
285
282
  def parse_tracking_response(response)
286
283
  doc = REXML::Document.new(REXML::Text::unnormalize(response))
287
284
  raise ActiveMerchant::Shipping::ResponseError, "No Tracking" unless root_node = doc.elements['tracking-detail']
288
285
 
289
- events = root_node.elements['significant-events'].elements.collect('occurrence') {|node| node }
286
+ events = root_node.elements['significant-events'].elements.collect('occurrence') { |node| node }
290
287
 
291
288
  shipment_events = build_tracking_events(events)
292
289
  change_date = root_node.get_text('changed-expected-date').to_s
@@ -307,7 +304,7 @@ module ActiveMerchant
307
304
  :destination => destination,
308
305
  :customer_number => root_node.get_text('mailed-by-customer-number').to_s
309
306
  }
310
-
307
+
311
308
  CPPWSTrackingResponse.new(true, "", {}, options)
312
309
  end
313
310
 
@@ -320,12 +317,11 @@ module ActiveMerchant
320
317
  time = Time.utc(timestamp.utc.year, timestamp.utc.month, timestamp.utc.day, timestamp.utc.hour, timestamp.utc.min, timestamp.utc.sec)
321
318
  message = event.get_text('event-description').to_s
322
319
  location = [event.get_text('event-retail-name'), event.get_text('event-site'), event.get_text('event-province')].compact.join(", ")
323
- name = event.get_text('event-identifier').to_s
320
+ name = event.get_text('event-identifier').to_s
324
321
  ShipmentEvent.new(name, time, location, message)
325
322
  end
326
323
  end
327
324
 
328
-
329
325
  # shipping
330
326
 
331
327
  # options
@@ -334,7 +330,7 @@ module ActiveMerchant
334
330
  # :packing_instructions
335
331
  # :show_postage_rate
336
332
  # :cod, :cod_amount, :insurance, :insurance_amount, :signature_required, :pa18, :pa19, :hfp, :dns, :lad
337
- #
333
+ #
338
334
  def build_shipment_request(origin, destination, package, line_items = [], options = {})
339
335
  origin = sanitize_location(origin)
340
336
  destination = sanitize_location(destination)
@@ -368,11 +364,10 @@ module ActiveMerchant
368
364
  node << XmlNode.new('contact-phone', location.phone)
369
365
  node << XmlNode.new('address-details') do |innernode|
370
366
  innernode << XmlNode.new('address-line-1', location.address1)
371
- address2 = [location.address2, location.address3].reject(&:blank?).join(", ")
372
- innernode << XmlNode.new('address-line-2', address2) unless address2.blank?
367
+ innernode << XmlNode.new('address-line-2', location.address2_and_3) unless location.address2_and_3.blank?
373
368
  innernode << XmlNode.new('city', location.city)
374
- innernode << XmlNode.new('prov-state', location.province)
375
- #innernode << XmlNode.new('country-code', location.country_code)
369
+ innernode << XmlNode.new('prov-state', location.province)
370
+ # innernode << XmlNode.new('country-code', location.country_code)
376
371
  innernode << XmlNode.new('postal-zip-code', location.postal_code)
377
372
  end
378
373
  end
@@ -385,8 +380,7 @@ module ActiveMerchant
385
380
  node << XmlNode.new('client-voice-number', location.phone)
386
381
  node << XmlNode.new('address-details') do |innernode|
387
382
  innernode << XmlNode.new('address-line-1', location.address1)
388
- address2 = [location.address2, location.address3].reject(&:blank?).join(", ")
389
- innernode << XmlNode.new('address-line-2', address2) unless address2.blank?
383
+ innernode << XmlNode.new('address-line-2', location.address2_and_3) unless location.address2_and_3.blank?
390
384
  innernode << XmlNode.new('city', location.city)
391
385
  innernode << XmlNode.new('prov-state', location.province) unless location.province.blank?
392
386
  innernode << XmlNode.new('country-code', location.country_code)
@@ -412,7 +406,7 @@ module ActiveMerchant
412
406
  def shipment_preferences_node(options)
413
407
  XmlNode.new('preferences') do |node|
414
408
  node << XmlNode.new('show-packing-instructions', options[:packing_instructions] || true)
415
- node << XmlNode.new('show-postage-rate', options[:show_postage_rate] || false)
409
+ node << XmlNode.new('show-postage-rate', options[:show_postage_rate] || false)
416
410
  node << XmlNode.new('show-insured-value', true)
417
411
  end
418
412
  end
@@ -428,17 +422,17 @@ module ActiveMerchant
428
422
 
429
423
  XmlNode.new('customs') do |node|
430
424
  currency = options[:currency] || "CAD"
431
- node << XmlNode.new('currency',currency)
432
- node << XmlNode.new('conversion-from-cad',options[:conversion_from_cad].to_s) if currency != 'CAD' && options[:conversion_from_cad]
433
- node << XmlNode.new('reason-for-export','SOG') # SOG - Sale of Goods
434
- node << XmlNode.new('other-reason',options[:customs_other_reason]) if (options[:customs_reason_for_export] && options[:customs_other_reason])
435
- node << XmlNode.new('additional-customs-info',options[:customs_addition_info]) if options[:customs_addition_info]
425
+ node << XmlNode.new('currency', currency)
426
+ node << XmlNode.new('conversion-from-cad', options[:conversion_from_cad].to_s) if currency != 'CAD' && options[:conversion_from_cad]
427
+ node << XmlNode.new('reason-for-export', 'SOG') # SOG - Sale of Goods
428
+ node << XmlNode.new('other-reason', options[:customs_other_reason]) if options[:customs_reason_for_export] && options[:customs_other_reason]
429
+ node << XmlNode.new('additional-customs-info', options[:customs_addition_info]) if options[:customs_addition_info]
436
430
  node << XmlNode.new('sku-list') do |sku|
437
431
  line_items.each do |line_item|
438
432
  sku << XmlNode.new('item') do |item|
439
433
  item << XmlNode.new('hs-tariff-code', line_item.hs_code) if line_item.hs_code && !line_item.hs_code.empty?
440
434
  item << XmlNode.new('sku', line_item.sku) if line_item.sku && !line_item.sku.empty?
441
- item << XmlNode.new('customs-description', line_item.name.slice(0,44))
435
+ item << XmlNode.new('customs-description', line_item.name.slice(0, 44))
442
436
  item << XmlNode.new('unit-weight', '%#2.3f' % sanitize_weight_kg(line_item.kg))
443
437
  item << XmlNode.new('customs-value-per-unit', '%.2f' % sanitize_price_from_cents(line_item.value))
444
438
  item << XmlNode.new('customs-number-of-units', line_item.quantity)
@@ -447,20 +441,20 @@ module ActiveMerchant
447
441
  end
448
442
  end
449
443
  end
450
-
444
+
451
445
  end
452
446
  end
453
447
 
454
- def shipment_parcel_node(package, options ={})
448
+ def shipment_parcel_node(package, options = {})
455
449
  weight = sanitize_weight_kg(package.kilograms.to_f)
456
450
  XmlNode.new('parcel-characteristics') do |el|
457
451
  el << XmlNode.new('weight', "%#2.3f" % weight)
458
452
  pkg_dim = package.cm
459
- if pkg_dim && !pkg_dim.select{|x| x != 0}.empty?
453
+ if pkg_dim && !pkg_dim.select { |x| x != 0 }.empty?
460
454
  el << XmlNode.new('dimensions') do |dim|
461
- dim << XmlNode.new('length', '%.1f' % ((pkg_dim[2]*10).round / 10.0)) if pkg_dim.size >= 3
462
- dim << XmlNode.new('width', '%.1f' % ((pkg_dim[1]*10).round / 10.0)) if pkg_dim.size >= 2
463
- dim << XmlNode.new('height', '%.1f' % ((pkg_dim[0]*10).round / 10.0)) if pkg_dim.size >= 1
455
+ dim << XmlNode.new('length', '%.1f' % ((pkg_dim[2] * 10).round / 10.0)) if pkg_dim.size >= 3
456
+ dim << XmlNode.new('width', '%.1f' % ((pkg_dim[1] * 10).round / 10.0)) if pkg_dim.size >= 2
457
+ dim << XmlNode.new('height', '%.1f' % ((pkg_dim[0] * 10).round / 10.0)) if pkg_dim.size >= 1
464
458
  end
465
459
  end
466
460
  el << XmlNode.new('document', false)
@@ -469,10 +463,9 @@ module ActiveMerchant
469
463
  end
470
464
  end
471
465
 
472
-
473
466
  def parse_shipment_response(response)
474
467
  doc = REXML::Document.new(REXML::Text::unnormalize(response))
475
- raise ActiveMerchant::Shipping::ResponseError, "No Shipping" unless root_node = doc.elements['non-contract-shipment-info']
468
+ raise ActiveMerchant::Shipping::ResponseError, "No Shipping" unless root_node = doc.elements['non-contract-shipment-info']
476
469
  options = {
477
470
  :shipping_id => root_node.get_text('shipment-id').to_s,
478
471
  :tracking_number => root_node.get_text('tracking-pin').to_s,
@@ -485,7 +478,7 @@ module ActiveMerchant
485
478
 
486
479
  def parse_register_token_response(response)
487
480
  doc = REXML::Document.new(REXML::Text::unnormalize(response))
488
- raise ActiveMerchant::Shipping::ResponseError, "No Registration Token" unless root_node = doc.elements['token']
481
+ raise ActiveMerchant::Shipping::ResponseError, "No Registration Token" unless root_node = doc.elements['token']
489
482
  options = {
490
483
  :token_id => root_node.get_text('token-id').to_s
491
484
  }
@@ -526,13 +519,13 @@ module ActiveMerchant
526
519
  :expected_transit_days => service_standard_node.get_text("expected-transit-time").to_s.to_i,
527
520
  :expected_delivery_date => service_standard_node.get_text("expected-delivery-date").to_s
528
521
  }
529
- option_nodes = root.elements['priced-options'].elements.collect('priced-option') {|node| node} unless root.elements['priced-options'].blank?
522
+ option_nodes = root.elements['priced-options'].elements.collect('priced-option') { |node| node } unless root.elements['priced-options'].blank?
530
523
 
531
524
  receipt[:priced_options] = if option_nodes
532
525
  option_nodes.inject({}) do |result, node|
533
526
  result[node.get_text("option-code").to_s] = node.get_text("option-price").to_s.to_f
534
527
  result
535
- end
528
+ end
536
529
  else
537
530
  []
538
531
  end
@@ -542,10 +535,10 @@ module ActiveMerchant
542
535
 
543
536
  def error_response(response, response_klass)
544
537
  doc = REXML::Document.new(REXML::Text::unnormalize(response))
545
- messages = doc.elements['messages'].elements.collect('message') {|node| node }
546
- message = messages.map {|m| m.get_text('description').to_s }.join(", ")
547
- code = messages.map {|m| m.get_text('code').to_s }.join(", ")
548
- response_klass.new(false, message, {}, {:carrier => @@name, :code => code})
538
+ messages = doc.elements['messages'].elements.collect('message') { |node| node }
539
+ message = messages.map { |m| m.get_text('description').to_s }.join(", ")
540
+ code = messages.map { |m| m.get_text('code').to_s }.join(", ")
541
+ response_klass.new(false, message, {}, :carrier => @@name, :code => code)
549
542
  end
550
543
 
551
544
  def log(msg)
@@ -556,7 +549,7 @@ module ActiveMerchant
556
549
 
557
550
  def tracking_url(pin)
558
551
  case pin.length
559
- when 12,13,16
552
+ when 12, 13, 16
560
553
  endpoint + "vis/track/pin/%s/detail" % pin
561
554
  when 15
562
555
  endpoint + "vis/track/dnc/%s/detail" % pin
@@ -574,7 +567,7 @@ module ActiveMerchant
574
567
  end
575
568
  end
576
569
 
577
- def shipment_url(shipping_id, options={})
570
+ def shipment_url(shipping_id, options = {})
578
571
  raise MissingCustomerNumberError unless customer_number = options[:customer_number]
579
572
  if @platform_id.present?
580
573
  endpoint + "rs/#{customer_number}-#{@platform_id}/ncshipment/#{shipping_id}"
@@ -583,7 +576,7 @@ module ActiveMerchant
583
576
  end
584
577
  end
585
578
 
586
- def shipment_receipt_url(shipping_id, options={})
579
+ def shipment_receipt_url(shipping_id, options = {})
587
580
  raise MissingCustomerNumberError unless customer_number = options[:customer_number]
588
581
  if @platform_id.present?
589
582
  endpoint + "rs/#{customer_number}-#{@platform_id}/ncshipment/#{shipping_id}/receipt"
@@ -592,7 +585,7 @@ module ActiveMerchant
592
585
  end
593
586
  end
594
587
 
595
- def services_url(country=nil, service_code=nil)
588
+ def services_url(country = nil, service_code = nil)
596
589
  url = endpoint + "rs/ship/service"
597
590
  url += "/#{service_code}" if service_code
598
591
  url += "?country=#{country}" if country
@@ -610,11 +603,11 @@ module ActiveMerchant
610
603
  "Basic %s" % Base64.encode64("#{@options[:api_key]}:#{@options[:secret]}")
611
604
  end
612
605
  end
613
-
606
+
614
607
  def headers(customer_credentials, accept = nil, content_type = nil)
615
608
  headers = {
616
609
  'Authorization' => encoded_authorization(customer_credentials),
617
- 'Accept-Language' => language
610
+ 'Accept-Language' => language
618
611
  }
619
612
  headers['Accept'] = accept if accept
620
613
  headers['Content-Type'] = content_type if content_type
@@ -638,17 +631,17 @@ module ActiveMerchant
638
631
  XmlNode.new("expected-mailing-date", date_as_string)
639
632
  end
640
633
 
641
- def parcel_node(line_items, package = nil, options ={})
634
+ def parcel_node(line_items, package = nil, options = {})
642
635
  weight = sanitize_weight_kg(package && !package.kilograms.zero? ? package.kilograms.to_f : line_items.sum(&:kilograms).to_f)
643
636
  XmlNode.new('parcel-characteristics') do |el|
644
637
  el << XmlNode.new('weight', "%#2.3f" % weight)
645
638
  if package
646
639
  pkg_dim = package.cm
647
- if pkg_dim && !pkg_dim.select{|x| x != 0}.empty?
640
+ if pkg_dim && !pkg_dim.select { |x| x != 0 }.empty?
648
641
  el << XmlNode.new('dimensions') do |dim|
649
- dim << XmlNode.new('length', '%.1f' % ((pkg_dim[2]*10).round / 10.0)) if pkg_dim.size >= 3
650
- dim << XmlNode.new('width', '%.1f' % ((pkg_dim[1]*10).round / 10.0)) if pkg_dim.size >= 2
651
- dim << XmlNode.new('height', '%.1f' % ((pkg_dim[0]*10).round / 10.0)) if pkg_dim.size >= 1
642
+ dim << XmlNode.new('length', '%.1f' % ((pkg_dim[2] * 10).round / 10.0)) if pkg_dim.size >= 3
643
+ dim << XmlNode.new('width', '%.1f' % ((pkg_dim[1] * 10).round / 10.0)) if pkg_dim.size >= 2
644
+ dim << XmlNode.new('height', '%.1f' % ((pkg_dim[0] * 10).round / 10.0)) if pkg_dim.size >= 1
652
645
  end
653
646
  end
654
647
  end
@@ -691,7 +684,7 @@ module ActiveMerchant
691
684
 
692
685
  def services_node(services)
693
686
  XmlNode.new('services') do |node|
694
- services.each {|code| node << XmlNode.new('service-code', code)}
687
+ services.each { |code| node << XmlNode.new('service-code', code) }
695
688
  end
696
689
  end
697
690
 
@@ -731,7 +724,7 @@ module ActiveMerchant
731
724
  end
732
725
  end
733
726
  end
734
-
727
+
735
728
  def expected_date_from_node(node)
736
729
  if service = node.elements['service-standard']
737
730
  expected_date = service.get_text("expected-delivery-date").to_s
@@ -753,17 +746,17 @@ module ActiveMerchant
753
746
 
754
747
  def sanitize_zip(hash)
755
748
  [:postal_code, :zip].each do |attr|
756
- hash[attr].gsub!(/\s+/,'') if hash[attr]
749
+ hash[attr].gsub!(/\s+/, '') if hash[attr]
757
750
  end
758
751
  hash
759
752
  end
760
753
 
761
754
  def sanitize_weight_kg(kg)
762
- return kg == 0 ? 0.001 : kg;
755
+ kg == 0 ? 0.001 : kg
763
756
  end
764
757
 
765
758
  def sanitize_price_from_cents(value)
766
- return value == 0 ? 0.01 : value.round / 100.0
759
+ value == 0 ? 0.01 : value.round / 100.0
767
760
  end
768
761
 
769
762
  def origin_hash_for(root_node)
@@ -819,14 +812,13 @@ module ActiveMerchant
819
812
  end
820
813
 
821
814
  def delivered?
822
- ! delivered_event.nil?
815
+ !delivered_event.nil?
823
816
  end
824
817
 
825
818
  def actual_delivery_time
826
819
  delivered_event.time if delivered?
827
820
  end
828
821
 
829
-
830
822
  private
831
823
 
832
824
  def delivered_event
@@ -878,6 +870,5 @@ module ActiveMerchant
878
870
  class MissingCustomerNumberError < StandardError; end
879
871
  class MissingShippingNumberError < StandardError; end
880
872
  class MissingTokenIdError < StandardError; end
881
-
882
873
  end
883
874
  end