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.
- checksums.yaml +4 -4
- data/lib/active_shipping.rb +2 -1
- data/lib/active_shipping/shipping/base.rb +2 -2
- data/lib/active_shipping/shipping/carrier.rb +16 -13
- data/lib/active_shipping/shipping/carriers/benchmark_carrier.rb +3 -4
- data/lib/active_shipping/shipping/carriers/bogus_carrier.rb +1 -3
- data/lib/active_shipping/shipping/carriers/canada_post.rb +33 -44
- data/lib/active_shipping/shipping/carriers/canada_post_pws.rb +72 -81
- data/lib/active_shipping/shipping/carriers/fedex.rb +118 -109
- data/lib/active_shipping/shipping/carriers/kunaki.rb +33 -32
- data/lib/active_shipping/shipping/carriers/new_zealand_post.rb +9 -16
- data/lib/active_shipping/shipping/carriers/shipwire.rb +36 -35
- data/lib/active_shipping/shipping/carriers/stamps.rb +39 -51
- data/lib/active_shipping/shipping/carriers/ups.rb +280 -116
- data/lib/active_shipping/shipping/carriers/ups.rb.orig +456 -0
- data/lib/active_shipping/shipping/carriers/usps.rb +145 -100
- data/lib/active_shipping/shipping/carriers/usps.rb.orig +616 -0
- data/lib/active_shipping/shipping/errors.rb +1 -1
- data/lib/active_shipping/shipping/label_response.rb +25 -0
- data/lib/active_shipping/shipping/location.rb +18 -16
- data/lib/active_shipping/shipping/package.rb +51 -54
- data/lib/active_shipping/shipping/rate_estimate.rb +10 -12
- data/lib/active_shipping/shipping/rate_response.rb +3 -7
- data/lib/active_shipping/shipping/response.rb +6 -9
- data/lib/active_shipping/shipping/shipment_event.rb +2 -4
- data/lib/active_shipping/shipping/shipment_packer.rb +32 -17
- data/lib/active_shipping/shipping/shipping_response.rb +2 -4
- data/lib/active_shipping/shipping/tracking_response.rb +3 -5
- data/lib/active_shipping/version.rb +1 -1
- data/lib/vendor/quantified/lib/quantified/attribute.rb +79 -80
- data/lib/vendor/quantified/lib/quantified/length.rb +5 -5
- data/lib/vendor/quantified/lib/quantified/mass.rb +4 -4
- data/lib/vendor/quantified/test/length_test.rb +19 -15
- data/lib/vendor/quantified/test/mass_test.rb +14 -14
- data/lib/vendor/quantified/test/test_helper.rb +1 -2
- data/lib/vendor/test_helper.rb +0 -1
- data/lib/vendor/xml_node/benchmark/bench_generation.rb +2 -4
- data/lib/vendor/xml_node/lib/xml_node.rb +54 -55
- data/lib/vendor/xml_node/test/test_generating.rb +23 -28
- data/lib/vendor/xml_node/test/test_parsing.rb +5 -8
- metadata +6 -25
- checksums.yaml.gz.sig +0 -1
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
module ActiveMerchant #:nodoc:
|
2
|
+
module Shipping
|
3
|
+
# This is UPS specific for now; the hash is not at all generic
|
4
|
+
# or common between carriers.
|
5
|
+
|
6
|
+
class LabelResponse < Response
|
7
|
+
attr :params # maybe?
|
8
|
+
|
9
|
+
def initialize(success, message, params = {}, options = {})
|
10
|
+
@params = params
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def labels
|
15
|
+
return @labels if @labels
|
16
|
+
packages = params["ShipmentResults"]["PackageResults"]
|
17
|
+
packages = [packages] if Hash === packages
|
18
|
+
@labels = packages.map do |package|
|
19
|
+
{ :tracking_number => package["TrackingNumber"],
|
20
|
+
:image => package["LabelImage"] }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Shipping #:nodoc:
|
3
3
|
class Location
|
4
|
-
ADDRESS_TYPES = %w
|
5
|
-
|
4
|
+
ADDRESS_TYPES = %w(residential commercial po_box)
|
5
|
+
|
6
6
|
attr_reader :options,
|
7
7
|
:country,
|
8
8
|
:postal_code,
|
@@ -16,14 +16,14 @@ module ActiveMerchant #:nodoc:
|
|
16
16
|
:fax,
|
17
17
|
:address_type,
|
18
18
|
:company_name
|
19
|
-
|
19
|
+
|
20
20
|
alias_method :zip, :postal_code
|
21
21
|
alias_method :postal, :postal_code
|
22
22
|
alias_method :state, :province
|
23
23
|
alias_method :territory, :province
|
24
24
|
alias_method :region, :province
|
25
25
|
alias_method :company, :company_name
|
26
|
-
|
26
|
+
|
27
27
|
def initialize(options = {})
|
28
28
|
@country = (options[:country].nil? or options[:country].is_a?(ActiveMerchant::Country)) ?
|
29
29
|
options[:country] :
|
@@ -41,8 +41,8 @@ module ActiveMerchant #:nodoc:
|
|
41
41
|
|
42
42
|
self.address_type = options[:address_type]
|
43
43
|
end
|
44
|
-
|
45
|
-
def self.from(object, options={})
|
44
|
+
|
45
|
+
def self.from(object, options = {})
|
46
46
|
return object if object.is_a? ActiveMerchant::Shipping::Location
|
47
47
|
attr_mappings = {
|
48
48
|
:name => [:name],
|
@@ -74,13 +74,13 @@ module ActiveMerchant #:nodoc:
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
attributes.delete(:address_type) unless ADDRESS_TYPES.include?(attributes[:address_type].to_s)
|
77
|
-
|
77
|
+
new(attributes.update(options))
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
def country_code(format = :alpha2)
|
81
81
|
@country.nil? ? nil : @country.code(format).value
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
def residential?; @address_type == 'residential' end
|
85
85
|
def commercial?; @address_type == 'commercial' end
|
86
86
|
def po_box?; @address_type == 'po_box' end
|
@@ -109,7 +109,7 @@ module ActiveMerchant #:nodoc:
|
|
109
109
|
}
|
110
110
|
end
|
111
111
|
|
112
|
-
def to_xml(options={})
|
112
|
+
def to_xml(options = {})
|
113
113
|
options[:root] ||= "location"
|
114
114
|
to_hash.to_xml(options)
|
115
115
|
end
|
@@ -117,15 +117,15 @@ module ActiveMerchant #:nodoc:
|
|
117
117
|
def to_s
|
118
118
|
prettyprint.gsub(/\n/, ' ')
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
121
|
def prettyprint
|
122
122
|
chunks = []
|
123
|
-
chunks << [@name, @address1
|
124
|
-
chunks << [@city
|
123
|
+
chunks << [@name, @address1, @address2, @address3].reject(&:blank?).join("\n")
|
124
|
+
chunks << [@city, @province, @postal_code].reject(&:blank?).join(', ')
|
125
125
|
chunks << @country
|
126
|
-
chunks.reject
|
126
|
+
chunks.reject(&:blank?).join("\n")
|
127
127
|
end
|
128
|
-
|
128
|
+
|
129
129
|
def inspect
|
130
130
|
string = prettyprint
|
131
131
|
string << "\nPhone: #{@phone}" unless @phone.blank?
|
@@ -144,7 +144,9 @@ module ActiveMerchant #:nodoc:
|
|
144
144
|
end
|
145
145
|
end
|
146
146
|
|
147
|
+
def address2_and_3
|
148
|
+
[address2, address3].reject(&:blank?).join(", ")
|
149
|
+
end
|
147
150
|
end
|
148
|
-
|
149
151
|
end
|
150
152
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Shipping #:nodoc:
|
3
|
-
# A package item is a unique item(s) that is physically in a package.
|
4
|
-
# A single package can have many items. This is only required
|
3
|
+
# A package item is a unique item(s) that is physically in a package.
|
4
|
+
# A single package can have many items. This is only required
|
5
5
|
# for shipping methods (label creation) right now.
|
6
6
|
class PackageItem
|
7
7
|
include Quantified
|
@@ -12,8 +12,8 @@ module ActiveMerchant #:nodoc:
|
|
12
12
|
@name = name
|
13
13
|
|
14
14
|
imperial = (options[:units] == :imperial) ||
|
15
|
-
|
16
|
-
|
15
|
+
(grams_or_ounces.respond_to?(:unit) && m.unit.to_sym == :imperial)
|
16
|
+
|
17
17
|
@unit_system = imperial ? :imperial : :metric
|
18
18
|
|
19
19
|
@weight = attribute_from_metric_or_imperial(grams_or_ounces, Mass, :grams, :ounces)
|
@@ -36,28 +36,28 @@ module ActiveMerchant #:nodoc:
|
|
36
36
|
@unit_system == :imperial ? m.in_ounces : m
|
37
37
|
end
|
38
38
|
when :billable
|
39
|
-
[
|
39
|
+
[weight, weight(:type => :volumetric)].max
|
40
40
|
end
|
41
41
|
end
|
42
42
|
alias_method :mass, :weight
|
43
43
|
|
44
|
-
def ounces(options={})
|
44
|
+
def ounces(options = {})
|
45
45
|
weight(options).in_ounces.amount
|
46
46
|
end
|
47
47
|
alias_method :oz, :ounces
|
48
|
-
|
49
|
-
def grams(options={})
|
48
|
+
|
49
|
+
def grams(options = {})
|
50
50
|
weight(options).in_grams.amount
|
51
51
|
end
|
52
52
|
alias_method :g, :grams
|
53
|
-
|
54
|
-
def pounds(options={})
|
53
|
+
|
54
|
+
def pounds(options = {})
|
55
55
|
weight(options).in_pounds.amount
|
56
56
|
end
|
57
57
|
alias_method :lb, :pounds
|
58
58
|
alias_method :lbs, :pounds
|
59
|
-
|
60
|
-
def kilograms(options={})
|
59
|
+
|
60
|
+
def kilograms(options = {})
|
61
61
|
weight(options).in_kilograms.amount
|
62
62
|
end
|
63
63
|
alias_method :kg, :kilograms
|
@@ -72,12 +72,11 @@ module ActiveMerchant #:nodoc:
|
|
72
72
|
return klass.new(obj, (@unit_system == :imperial ? imperial_unit : metric_unit))
|
73
73
|
end
|
74
74
|
end
|
75
|
-
|
76
75
|
end
|
77
76
|
|
78
77
|
class Package
|
79
78
|
include Quantified
|
80
|
-
|
79
|
+
|
81
80
|
cattr_accessor :default_options
|
82
81
|
attr_reader :options, :value, :currency
|
83
82
|
|
@@ -88,36 +87,35 @@ module ActiveMerchant #:nodoc:
|
|
88
87
|
options = @@default_options.update(options) if @@default_options
|
89
88
|
options.symbolize_keys!
|
90
89
|
@options = options
|
91
|
-
|
92
|
-
@dimensions = [dimensions].flatten.reject {|d| d.nil?}
|
93
90
|
|
94
|
-
|
91
|
+
@dimensions = [dimensions].flatten.reject(&:nil?)
|
92
|
+
|
95
93
|
imperial = (options[:units] == :imperial) ||
|
96
|
-
|
97
|
-
|
94
|
+
([grams_or_ounces, *dimensions].all? { |m| m.respond_to?(:unit) && m.unit.to_sym == :imperial })
|
95
|
+
|
98
96
|
weight_imperial = dimensions_imperial = imperial if options.include?(:units)
|
99
97
|
|
100
98
|
if options.include?(:weight_units)
|
101
99
|
weight_imperial = (options[:weight_units] == :imperial) ||
|
102
|
-
|
100
|
+
(grams_or_ounces.respond_to?(:unit) && m.unit.to_sym == :imperial)
|
103
101
|
end
|
104
102
|
|
105
103
|
if options.include?(:dim_units)
|
106
104
|
dimensions_imperial = (options[:dim_units] == :imperial) ||
|
107
|
-
|
105
|
+
(dimensions && dimensions.all? { |m| m.respond_to?(:unit) && m.unit.to_sym == :imperial })
|
108
106
|
end
|
109
|
-
|
107
|
+
|
110
108
|
@weight_unit_system = weight_imperial ? :imperial : :metric
|
111
109
|
@dimensions_unit_system = dimensions_imperial ? :imperial : :metric
|
112
|
-
|
110
|
+
|
113
111
|
@weight = attribute_from_metric_or_imperial(grams_or_ounces, Mass, @weight_unit_system, :grams, :ounces)
|
114
|
-
|
112
|
+
|
115
113
|
if @dimensions.blank?
|
116
114
|
@dimensions = [Length.new(0, (dimensions_imperial ? :inches : :centimetres))] * 3
|
117
115
|
else
|
118
116
|
process_dimensions
|
119
117
|
end
|
120
|
-
|
118
|
+
|
121
119
|
@value = Package.cents_from(options[:value])
|
122
120
|
@currency = options[:currency] || (options[:value].currency if options[:value].respond_to?(:currency))
|
123
121
|
@cylinder = (options[:cylinder] || options[:tube]) ? true : false
|
@@ -125,7 +123,7 @@ module ActiveMerchant #:nodoc:
|
|
125
123
|
@oversized = options[:oversized] ? true : false
|
126
124
|
@unpackaged = options[:unpackaged] ? true : false
|
127
125
|
end
|
128
|
-
|
126
|
+
|
129
127
|
def unpackaged?
|
130
128
|
@unpackaged
|
131
129
|
end
|
@@ -133,48 +131,48 @@ module ActiveMerchant #:nodoc:
|
|
133
131
|
def oversized?
|
134
132
|
@oversized
|
135
133
|
end
|
136
|
-
|
134
|
+
|
137
135
|
def cylinder?
|
138
136
|
@cylinder
|
139
137
|
end
|
140
138
|
alias_method :tube?, :cylinder?
|
141
|
-
|
139
|
+
|
142
140
|
def gift?; @gift end
|
143
|
-
|
144
|
-
def ounces(options={})
|
141
|
+
|
142
|
+
def ounces(options = {})
|
145
143
|
weight(options).in_ounces.amount
|
146
144
|
end
|
147
145
|
alias_method :oz, :ounces
|
148
|
-
|
149
|
-
def grams(options={})
|
146
|
+
|
147
|
+
def grams(options = {})
|
150
148
|
weight(options).in_grams.amount
|
151
149
|
end
|
152
150
|
alias_method :g, :grams
|
153
|
-
|
154
|
-
def pounds(options={})
|
151
|
+
|
152
|
+
def pounds(options = {})
|
155
153
|
weight(options).in_pounds.amount
|
156
154
|
end
|
157
155
|
alias_method :lb, :pounds
|
158
156
|
alias_method :lbs, :pounds
|
159
|
-
|
160
|
-
def kilograms(options={})
|
157
|
+
|
158
|
+
def kilograms(options = {})
|
161
159
|
weight(options).in_kilograms.amount
|
162
160
|
end
|
163
161
|
alias_method :kg, :kilograms
|
164
162
|
alias_method :kgs, :kilograms
|
165
|
-
|
166
|
-
def inches(measurement=nil)
|
167
|
-
@inches ||= @dimensions.map {|m| m.in_inches.amount }
|
163
|
+
|
164
|
+
def inches(measurement = nil)
|
165
|
+
@inches ||= @dimensions.map { |m| m.in_inches.amount }
|
168
166
|
measurement.nil? ? @inches : measure(measurement, @inches)
|
169
167
|
end
|
170
168
|
alias_method :in, :inches
|
171
|
-
|
172
|
-
def centimetres(measurement=nil)
|
173
|
-
@centimetres ||= @dimensions.map {|m| m.in_centimetres.amount }
|
169
|
+
|
170
|
+
def centimetres(measurement = nil)
|
171
|
+
@centimetres ||= @dimensions.map { |m| m.in_centimetres.amount }
|
174
172
|
measurement.nil? ? @centimetres : measure(measurement, @centimetres)
|
175
173
|
end
|
176
174
|
alias_method :cm, :centimetres
|
177
|
-
|
175
|
+
|
178
176
|
def weight(options = {})
|
179
177
|
case options[:type]
|
180
178
|
when nil, :actual
|
@@ -185,11 +183,11 @@ module ActiveMerchant #:nodoc:
|
|
185
183
|
@weight_unit_system == :imperial ? m.in_ounces : m
|
186
184
|
end
|
187
185
|
when :billable
|
188
|
-
[
|
186
|
+
[weight, weight(:type => :volumetric)].max
|
189
187
|
end
|
190
188
|
end
|
191
189
|
alias_method :mass, :weight
|
192
|
-
|
190
|
+
|
193
191
|
def self.cents_from(money)
|
194
192
|
return nil if money.nil?
|
195
193
|
if money.respond_to?(:cents)
|
@@ -205,7 +203,7 @@ module ActiveMerchant #:nodoc:
|
|
205
203
|
end
|
206
204
|
end
|
207
205
|
end
|
208
|
-
|
206
|
+
|
209
207
|
private
|
210
208
|
|
211
209
|
def attribute_from_metric_or_imperial(obj, klass, unit_system, metric_unit, imperial_unit)
|
@@ -215,20 +213,20 @@ module ActiveMerchant #:nodoc:
|
|
215
213
|
return klass.new(obj, (unit_system == :imperial ? imperial_unit : metric_unit))
|
216
214
|
end
|
217
215
|
end
|
218
|
-
|
216
|
+
|
219
217
|
def measure(measurement, ary)
|
220
218
|
case measurement
|
221
|
-
when Fixnum then ary[measurement]
|
219
|
+
when Fixnum then ary[measurement]
|
222
220
|
when :x, :max, :length, :long then ary[2]
|
223
221
|
when :y, :mid, :width, :wide then ary[1]
|
224
|
-
when :z, :min, :height
|
225
|
-
when :girth, :around
|
222
|
+
when :z, :min, :height, :depth, :high, :deep then ary[0]
|
223
|
+
when :girth, :around, :circumference
|
226
224
|
self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 2) : (2 * ary[0]) + (2 * ary[1])
|
227
|
-
when :volume then self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 4)**2 * ary[2] : measure(:box_volume,ary)
|
225
|
+
when :volume then self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 4)**2 * ary[2] : measure(:box_volume, ary)
|
228
226
|
when :box_volume then ary[0] * ary[1] * ary[2]
|
229
227
|
end
|
230
228
|
end
|
231
|
-
|
229
|
+
|
232
230
|
def process_dimensions
|
233
231
|
@dimensions = @dimensions.map do |l|
|
234
232
|
attribute_from_metric_or_imperial(l, Length, @dimensions_unit_system, :centimetres, :inches)
|
@@ -236,11 +234,10 @@ module ActiveMerchant #:nodoc:
|
|
236
234
|
# [1,2] => [1,1,2]
|
237
235
|
# [5] => [5,5,5]
|
238
236
|
# etc..
|
239
|
-
2.downto(@dimensions.length) do |
|
237
|
+
2.downto(@dimensions.length) do |_n|
|
240
238
|
@dimensions.unshift(@dimensions[0])
|
241
239
|
end
|
242
240
|
end
|
243
|
-
|
244
241
|
end
|
245
242
|
end
|
246
243
|
end
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Shipping #:nodoc:
|
3
|
-
|
4
3
|
class RateEstimate
|
5
4
|
attr_reader :origin # Location objects
|
6
5
|
attr_reader :destination
|
@@ -9,20 +8,20 @@ module ActiveMerchant #:nodoc:
|
|
9
8
|
attr_reader :service_name # name of service ("First Class Ground", etc.)
|
10
9
|
attr_reader :service_code
|
11
10
|
attr_reader :currency # 'USD', 'CAD', etc.
|
12
|
-
|
11
|
+
# http://en.wikipedia.org/wiki/ISO_4217
|
13
12
|
attr_reader :shipping_date
|
14
13
|
attr_reader :delivery_date # Usually only available for express shipments
|
15
14
|
attr_reader :delivery_range # Min and max delivery estimate in days
|
16
15
|
attr_reader :negotiated_rate
|
17
16
|
attr_reader :insurance_price
|
18
17
|
|
19
|
-
def initialize(origin, destination, carrier, service_name, options={})
|
18
|
+
def initialize(origin, destination, carrier, service_name, options = {})
|
20
19
|
@origin, @destination, @carrier, @service_name = origin, destination, carrier, service_name
|
21
20
|
@service_code = options[:service_code]
|
22
21
|
if options[:package_rates]
|
23
|
-
@package_rates = options[:package_rates].map {|p| p.update(
|
22
|
+
@package_rates = options[:package_rates].map { |p| p.update(:rate => Package.cents_from(p[:rate])) }
|
24
23
|
else
|
25
|
-
@package_rates = Array(options[:packages]).map {|p| {:package => p}}
|
24
|
+
@package_rates = Array(options[:packages]).map { |p| {:package => p} }
|
26
25
|
end
|
27
26
|
@total_price = Package.cents_from(options[:total_price])
|
28
27
|
@negotiated_rate = options[:negotiated_rate] ? Package.cents_from(options[:negotiated_rate]) : nil
|
@@ -34,15 +33,13 @@ module ActiveMerchant #:nodoc:
|
|
34
33
|
end
|
35
34
|
|
36
35
|
def total_price
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
raise ArgumentError.new("RateEstimate must have a total_price set, or have a full set of valid package rates.")
|
41
|
-
end
|
36
|
+
@total_price || @package_rates.sum { |p| p[:rate] }
|
37
|
+
rescue NoMethodError
|
38
|
+
raise ArgumentError.new("RateEstimate must have a total_price set, or have a full set of valid package rates.")
|
42
39
|
end
|
43
40
|
alias_method :price, :total_price
|
44
41
|
|
45
|
-
def add(package,rate=nil)
|
42
|
+
def add(package, rate = nil)
|
46
43
|
cents = Package.cents_from(rate)
|
47
44
|
raise ArgumentError.new("New packages must have valid rate information since this RateEstimate has no total_price set.") if cents.nil? and total_price.nil?
|
48
45
|
@package_rates << {:package => package, :rate => cents}
|
@@ -50,7 +47,7 @@ module ActiveMerchant #:nodoc:
|
|
50
47
|
end
|
51
48
|
|
52
49
|
def packages
|
53
|
-
package_rates.map {|p| p[:package]}
|
50
|
+
package_rates.map { |p| p[:package] }
|
54
51
|
end
|
55
52
|
|
56
53
|
def package_count
|
@@ -58,6 +55,7 @@ module ActiveMerchant #:nodoc:
|
|
58
55
|
end
|
59
56
|
|
60
57
|
private
|
58
|
+
|
61
59
|
def date_for(date)
|
62
60
|
date && DateTime.strptime(date.to_s, "%Y-%m-%d")
|
63
61
|
rescue ArgumentError
|
@@ -1,19 +1,15 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Shipping
|
3
|
-
|
4
3
|
class RateResponse < Response
|
5
|
-
|
6
4
|
attr_reader :rates
|
7
|
-
|
5
|
+
|
8
6
|
def initialize(success, message, params = {}, options = {})
|
9
7
|
@rates = Array(options[:estimates] || options[:rates] || options[:rate_estimates])
|
10
8
|
super
|
11
9
|
end
|
12
|
-
|
10
|
+
|
13
11
|
alias_method :estimates, :rates
|
14
12
|
alias_method :rate_estimates, :rates
|
15
|
-
|
16
13
|
end
|
17
|
-
|
18
14
|
end
|
19
|
-
end
|
15
|
+
end
|