active_shipping 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,11 @@
1
+ ### v0.10.1
2
+ - Canada Post PWS: Makes wrapper act more consistently with the rest of the API [jnormore]
3
+ - UPS: Adds insurance charge to package object declarations [pbonnell]
4
+ - USPS: Improves how unavailable delivery information is handled [cyu]
5
+ - Shipment Packer: Prevents packing errors and consistently return an array when packing [christianblais]
6
+ - General: Improves tests such that they work with ruby 2.0 [Sirupsen]
7
+
8
+
1
9
  2011/04/21:
2
10
  * USPS updated to use new APIs [james]
3
11
  * new :gift boolean option for Package [james]
data/README.markdown CHANGED
@@ -122,6 +122,16 @@ After you've pushed your well-tested changes to your github fork, make a pull re
122
122
  * Cody Fauser (<http://codyfauser.com>)
123
123
  * Jimmy Baker (<http://jimmyville.com/>)
124
124
  * William Lang (<http://williamlang.net/>)
125
+ * Cameron Fowler
126
+ * Christopher Saunders (<http://christophersaunders.ca>)
127
+ * Denis Odorcic
128
+ * Dennis O'Connor
129
+ * Dennis Theisen
130
+ * Edward Ocampo-Gooding
131
+ * Isaac Kearse
132
+ * John Duff
133
+ * Nigel Ramsay
134
+ * Philip Arndt
125
135
 
126
136
  ## Legal Mumbo Jumbo
127
137
 
@@ -49,3 +49,4 @@ require 'active_shipping/shipping/shipment_event'
49
49
  require 'active_shipping/shipping/shipment_packer'
50
50
  require 'active_shipping/shipping/carrier'
51
51
  require 'active_shipping/shipping/carriers'
52
+ require 'active_shipping/shipping/errors'
@@ -237,6 +237,7 @@ module ActiveMerchant
237
237
  # rating
238
238
 
239
239
  def build_rates_request(origin, destination, line_items = [], options = {}, package = nil, services = [])
240
+ line_items = Array(line_items)
240
241
  xml = XmlNode.new('mailing-scenario', :xmlns => "http://www.canadapost.ca/ws/ship/rate") do |node|
241
242
  node << customer_number_node(options)
242
243
  node << contract_id_node(options)
@@ -329,9 +330,9 @@ module ActiveMerchant
329
330
  # :show_postage_rate
330
331
  # :cod, :cod_amount, :insurance, :insurance_amount, :signature_required, :pa18, :pa19, :hfp, :dns, :lad
331
332
  #
332
- def build_shipment_request(origin_hash, destination_hash, package, line_items = [], options = {})
333
- origin = Location.new(sanitize_zip(origin_hash))
334
- destination = Location.new(sanitize_zip(destination_hash))
333
+ def build_shipment_request(origin, destination, package, line_items = [], options = {})
334
+ origin = sanitize_location(origin)
335
+ destination = sanitize_location(destination)
335
336
 
336
337
  xml = XmlNode.new('non-contract-shipment', :xmlns => "http://www.canadapost.ca/ws/ncshipment") do |root_node|
337
338
  root_node << XmlNode.new('delivery-spec') do |node|
@@ -652,13 +653,13 @@ module ActiveMerchant
652
653
  end
653
654
  end
654
655
 
655
- def origin_node(location_hash)
656
- origin = Location.new(sanitize_zip(location_hash))
656
+ def origin_node(location)
657
+ origin = sanitize_location(location)
657
658
  XmlNode.new("origin-postal-code", origin.zip)
658
659
  end
659
660
 
660
- def destination_node(location_hash)
661
- destination = Location.new(sanitize_zip(location_hash))
661
+ def destination_node(location)
662
+ destination = sanitize_location(location)
662
663
  case destination.country_code
663
664
  when 'CA'
664
665
  XmlNode.new('destination') do |node|
@@ -739,6 +740,12 @@ module ActiveMerchant
739
740
  DateTime.strptime((options[:shipping_date] || Time.now).to_s, "%Y-%m-%d")
740
741
  end
741
742
 
743
+ def sanitize_location(location)
744
+ location_hash = location.is_a?(Location) ? location.to_hash : location
745
+ location_hash = sanitize_zip(location_hash)
746
+ Location.new(location_hash)
747
+ end
748
+
742
749
  def sanitize_zip(hash)
743
750
  [:postal_code, :zip].each do |attr|
744
751
  hash[attr].gsub!(/\s+/,'') if hash[attr]
@@ -265,7 +265,7 @@ module ActiveMerchant
265
265
  rate_estimates = []
266
266
  success, message = nil
267
267
 
268
- xml = REXML::Document.new(response)
268
+ xml = build_document(response)
269
269
  root_node = xml.elements['RateReply']
270
270
 
271
271
  success = response_success?(xml)
@@ -330,7 +330,7 @@ module ActiveMerchant
330
330
  end
331
331
 
332
332
  def parse_tracking_response(response, options)
333
- xml = REXML::Document.new(response)
333
+ xml = build_document(response)
334
334
  root_node = xml.elements['TrackReply']
335
335
 
336
336
  success = response_success?(xml)
@@ -462,6 +462,12 @@ module ActiveMerchant
462
462
 
463
463
  Location.new(args)
464
464
  end
465
+
466
+ def build_document(xml)
467
+ REXML::Document.new(xml)
468
+ rescue REXML::ParseException => e
469
+ raise ActiveMerchant::Shipping::ResponseContentError.new(e, xml)
470
+ end
465
471
  end
466
472
  end
467
473
  end
@@ -208,6 +208,9 @@ module ActiveMerchant
208
208
  package_weight << XmlNode.new("UnitOfMeasurement") do |units|
209
209
  units << XmlNode.new("Code", imperial ? 'LBS' : 'KGS')
210
210
  end
211
+ if package.value.present? && package.currency.present?
212
+ add_insured_node( package_node, currency:package.currency, value:(package.value.to_i/100) )
213
+ end
211
214
 
212
215
  value = ((imperial ? package.lbs : package.kgs).to_f*1000).round/1000.0 # 3 decimals
213
216
  package_weight << XmlNode.new("Weight", [value,0.1].max)
@@ -273,6 +276,21 @@ module ActiveMerchant
273
276
  end
274
277
  end
275
278
 
279
+ def add_insured_node(*args)
280
+ params, package_node = args.extract_options!, args[0]
281
+ currency, value = params[:currency], params[:value].to_i
282
+ package_node << XmlNode.new("PackageServiceOptions") do |package_service_options|
283
+ package_service_options << XmlNode.new("DeclaredValue") do |declared_value|
284
+ declared_value << XmlNode.new("CurrencyCode", currency)
285
+ declared_value << XmlNode.new("MonetaryValue", (value.to_i))
286
+ end
287
+ package_service_options << XmlNode.new("InsuredValue") do |declared_value|
288
+ declared_value << XmlNode.new("CurrencyCode", currency)
289
+ declared_value << XmlNode.new("MonetaryValue", (value.to_i))
290
+ end
291
+ end
292
+ end
293
+
276
294
  def parse_rate_response(origin, destination, packages, response, options={})
277
295
  rates = []
278
296
 
@@ -287,10 +305,10 @@ module ActiveMerchant
287
305
  service_code = rated_shipment.get_text('Service/Code').to_s
288
306
  days_to_delivery = rated_shipment.get_text('GuaranteedDaysToDelivery').to_s.to_i
289
307
  days_to_delivery = nil if days_to_delivery == 0
290
-
291
308
  rate_estimates << RateEstimate.new(origin, destination, @@name,
292
309
  service_name_for(origin, service_code),
293
310
  :total_price => rated_shipment.get_text('TotalCharges/MonetaryValue').to_s.to_f,
311
+ :insurance_price => rated_shipment.get_text('ServiceOptionsCharges/MonetaryValue').to_s.to_f,
294
312
  :currency => rated_shipment.get_text('TotalCharges/CurrencyCode').to_s,
295
313
  :service_code => service_code,
296
314
  :packages => packages,
@@ -125,6 +125,18 @@ module ActiveMerchant
125
125
  "WS" => "Western Samoa"
126
126
  }
127
127
 
128
+ STATUS_NODE_PATTERNS = %w(
129
+ */*/TrackSummary
130
+ Error/Description
131
+ */TrackInfo/Error/Description
132
+ )
133
+
134
+ RESPONSE_ERROR_MESSAGES = [
135
+ /There is no record of that mail item/,
136
+ /This Information has not been included in this Test Server\./,
137
+ /Delivery status information is not available/
138
+ ]
139
+
128
140
  def find_tracking_info(tracking_number, options={})
129
141
  options = @options.update(options)
130
142
  tracking_request = build_tracking_request(tracking_number, options)
@@ -584,12 +596,16 @@ module ActiveMerchant
584
596
  end
585
597
 
586
598
  def response_status_node(document)
587
- document.elements['*/*/TrackSummary'] || document.elements['Error/Description']
599
+ STATUS_NODE_PATTERNS.each do |pattern|
600
+ if node = document.elements[pattern]
601
+ return node
602
+ end
603
+ end
588
604
  end
589
605
 
590
606
  def response_success?(document)
591
607
  summary = response_status_node(document).get_text.to_s
592
- !(summary =~ /There is no record of that mail item/ || summary =~ /This Information has not been included in this Test Server\./)
608
+ !RESPONSE_ERROR_MESSAGES.detect { |re| summary =~ re }
593
609
  end
594
610
 
595
611
  def response_message(document)
@@ -0,0 +1,9 @@
1
+ module ActiveMerchant
2
+ module Shipping
3
+ class ResponseContentError < StandardError
4
+ def initialize(exception, content_body)
5
+ super("#{exception.message} \n\n#{content_body}")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -14,6 +14,7 @@ module ActiveMerchant #:nodoc:
14
14
  attr_reader :delivery_date # Usually only available for express shipments
15
15
  attr_reader :delivery_range # Min and max delivery estimate in days
16
16
  attr_reader :negotiated_rate
17
+ attr_reader :insurance_price
17
18
 
18
19
  def initialize(origin, destination, carrier, service_name, options={})
19
20
  @origin, @destination, @carrier, @service_name = origin, destination, carrier, service_name
@@ -29,6 +30,7 @@ module ActiveMerchant #:nodoc:
29
30
  @delivery_range = options[:delivery_range] ? options[:delivery_range].map { |date| date_for(date) }.compact : []
30
31
  @shipping_date = date_for(options[:shipping_date])
31
32
  @delivery_date = @delivery_range.last
33
+ @insurance_price = Package.cents_from(options[:insurance_price])
32
34
  end
33
35
 
34
36
  def total_price
@@ -10,8 +10,11 @@ module ActiveMerchant
10
10
  # maximum_weight - maximum weight in grams
11
11
  # currency - ISO currency code
12
12
  def self.pack(items, dimensions, maximum_weight, currency)
13
- items = items.map(&:symbolize_keys).map { |item| [item] * item[:quantity].to_i }.flatten
14
13
  packages = []
14
+
15
+ return packages if items.empty?
16
+
17
+ items = items.map(&:symbolize_keys).map { |item| [item] * item[:quantity].to_i }.flatten
15
18
  state = :package_empty
16
19
 
17
20
  while state != :packing_finished
@@ -1,3 +1,3 @@
1
1
  module ActiveShipping
2
- VERSION = "0.10.0"
2
+ VERSION = "0.10.1"
3
3
  end
@@ -1,6 +1,5 @@
1
1
  require 'rake'
2
2
  require 'rake/testtask'
3
- require 'rake/rdoctask'
4
3
 
5
4
  desc 'Default: run unit tests.'
6
5
  task :default => :test
@@ -8,14 +7,7 @@ task :default => :test
8
7
  desc 'Test the plugin.'
9
8
  Rake::TestTask.new(:test) do |t|
10
9
  t.libs << 'lib'
10
+ t.libs << 'test'
11
11
  t.pattern = 'test/**/*_test.rb'
12
12
  t.verbose = true
13
13
  end
14
-
15
- desc 'Generate documentation for the calculations plugin.'
16
- Rake::RDocTask.new(:rdoc) do |rdoc|
17
- rdoc.rdoc_dir = 'rdoc'
18
- rdoc.title = 'Quantified'
19
- rdoc.options << '--line-numbers --inline-source'
20
- rdoc.rdoc_files.include('lib/**/*.rb')
21
- end
@@ -38,6 +38,10 @@ module Quantified
38
38
  def system
39
39
  self.class.units_to_systems[unit]
40
40
  end
41
+
42
+ def coerce(other)
43
+ [other, self.amount]
44
+ end
41
45
 
42
46
  def method_missing(meth, *args)
43
47
  if args.size == 1 && self.class == (other = args.first).class
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require 'test_helper'
2
2
  require 'quantified/length'
3
3
 
4
4
  class LengthTest < Test::Unit::TestCase
@@ -40,17 +40,15 @@ class LengthTest < Test::Unit::TestCase
40
40
  end
41
41
 
42
42
  def test_convert_yards_to_millimetres
43
- assert Length.new(914.4, :millimetres).eql?(Length.new(1, :yards).to_millimetres)
43
+ assert_in_epsilon Length.new(914.4, :millimetres).to_f, Length.new(1, :yards).to_millimetres.to_f
44
44
  end
45
45
 
46
46
  def test_convert_millimetres_to_yards
47
- assert Length.new(1, :yards).eql?(Length.new(914.4, :millimetres).to_yards)
47
+ assert_in_epsilon Length.new(1, :yards).to_f, Length.new(914.4, :millimetres).to_yards.to_f
48
48
  end
49
49
 
50
50
  def test_convert_metres_to_inches
51
- assert_equal 1.inches, (0.0254).metres.to_inches
52
- assert 1.inches.eql?((0.0254).metres.to_inches)
53
- assert 1.inches.eql?((0.0254).metres.in_inches)
51
+ assert_in_epsilon 1.inches.to_f, (0.0254).metres.to_inches.to_f
54
52
  end
55
53
 
56
54
  def test_comparison_with_numeric
@@ -89,4 +87,4 @@ class LengthTest < Test::Unit::TestCase
89
87
  assert_equal :metric, 2.centimetres.system
90
88
  assert_equal :imperial, 2.feet.system
91
89
  end
92
- end
90
+ end
@@ -1,4 +1,4 @@
1
- require File.dirname(__FILE__) + '/test_helper'
1
+ require 'test_helper'
2
2
  require 'quantified/mass'
3
3
 
4
4
  class MassTest < Test::Unit::TestCase
@@ -85,4 +85,12 @@ class MassTest < Test::Unit::TestCase
85
85
  assert_equal [:grams, :milligrams, :kilograms], Mass.units(:metric)
86
86
  assert_equal [:ounces, :pounds, :stones, :short_tons], Mass.units(:imperial)
87
87
  end
88
- end
88
+
89
+ def test_right_side_comparison_with_fixnum
90
+ assert Mass.new(14, :grams) < 20
91
+ end
92
+
93
+ def test_left_side_comparison_with_fixnum
94
+ assert 20 > Mass.new(14, :grams)
95
+ end
96
+ end
@@ -1,4 +1,5 @@
1
1
  require 'test/unit'
2
+
2
3
  begin
3
4
  require 'active_support/inflector'
4
5
  rescue LoadError => e
@@ -8,3 +9,12 @@ rescue LoadError => e
8
9
  end
9
10
 
10
11
  require File.dirname(__FILE__) + '/../lib/quantified'
12
+
13
+
14
+ class Test::Unit::TestCase
15
+ EPSILON = 0.00001
16
+
17
+ def assert_in_epsilon(expected, actual, msg = nil)
18
+ assert_in_delta expected, actual, EPSILON, msg
19
+ end
20
+ end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: active_shipping
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.10.0
5
+ version: 0.10.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - James MacAulay
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2013-07-23 00:00:00.000000000 Z
15
+ date: 2013-08-23 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  prerelease: false
@@ -94,6 +94,22 @@ dependencies:
94
94
  - !ruby/object:Gem::Version
95
95
  version: 1.5.1
96
96
  none: false
97
+ - !ruby/object:Gem::Dependency
98
+ prerelease: false
99
+ name: minitest
100
+ type: :development
101
+ version_requirements: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ~>
104
+ - !ruby/object:Gem::Version
105
+ version: 4.7.5
106
+ none: false
107
+ requirement: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ~>
110
+ - !ruby/object:Gem::Version
111
+ version: 4.7.5
112
+ none: false
97
113
  - !ruby/object:Gem::Dependency
98
114
  prerelease: false
99
115
  name: rake
@@ -116,15 +132,15 @@ dependencies:
116
132
  type: :development
117
133
  version_requirements: !ruby/object:Gem::Requirement
118
134
  requirements:
119
- - - ! '>='
135
+ - - ~>
120
136
  - !ruby/object:Gem::Version
121
- version: '0'
137
+ version: 0.14.0
122
138
  none: false
123
139
  requirement: !ruby/object:Gem::Requirement
124
140
  requirements:
125
- - - ! '>='
141
+ - - ~>
126
142
  - !ruby/object:Gem::Version
127
- version: '0'
143
+ version: 0.14.0
128
144
  none: false
129
145
  - !ruby/object:Gem::Dependency
130
146
  prerelease: false
@@ -179,6 +195,7 @@ files:
179
195
  - lib/active_shipping/shipping/carriers/usps.rb
180
196
  - lib/active_shipping/shipping/carriers/usps.rb.orig
181
197
  - lib/active_shipping/shipping/carriers.rb
198
+ - lib/active_shipping/shipping/errors.rb
182
199
  - lib/active_shipping/shipping/location.rb
183
200
  - lib/active_shipping/shipping/package.rb
184
201
  - lib/active_shipping/shipping/rate_estimate.rb
@@ -225,7 +242,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
225
242
  - !ruby/object:Gem::Version
226
243
  segments:
227
244
  - 0
228
- hash: -3915278247980377542
245
+ hash: 4495588430750097686
229
246
  version: '0'
230
247
  none: false
231
248
  required_rubygems_version: !ruby/object:Gem::Requirement