active_shipping 0.9.11 → 0.9.12
Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
2011/04/21:
|
2
|
+
* USPS updated to use new APIs [james]
|
3
|
+
* new :gift boolean option for Package [james]
|
4
|
+
* Location's :address_type can be "po_box" [james]
|
5
|
+
|
6
|
+
Earlier:
|
1
7
|
* New Zealand Post [AbleTech]
|
2
8
|
* Include address name for rate requests to Shipwire if provided [dennis]
|
3
9
|
* Add support for address name to Location [dennis]
|
@@ -29,8 +29,8 @@ module ActiveMerchant
|
|
29
29
|
TEST_RESOURCE = 'ShippingAPITest.dll'
|
30
30
|
|
31
31
|
API_CODES = {
|
32
|
-
:us_rates => '
|
33
|
-
:world_rates => '
|
32
|
+
:us_rates => 'RateV4',
|
33
|
+
:world_rates => 'IntlRateV2',
|
34
34
|
:test => 'CarrierPickupAvailability'
|
35
35
|
}
|
36
36
|
USE_SSL = {
|
@@ -180,7 +180,7 @@ module ActiveMerchant
|
|
180
180
|
end
|
181
181
|
|
182
182
|
def world_rates(origin, destination, packages, options={})
|
183
|
-
request = build_world_rate_request(packages, destination
|
183
|
+
request = build_world_rate_request(packages, destination)
|
184
184
|
# never use test mode; rate requests just won't work on test servers
|
185
185
|
parse_rate_response origin, destination, packages, commit(:world_rates,request,false), options
|
186
186
|
end
|
@@ -204,7 +204,7 @@ module ActiveMerchant
|
|
204
204
|
# "machinability" entirely.
|
205
205
|
def build_us_rate_request(packages, origin_zip, destination_zip, options={})
|
206
206
|
packages = Array(packages)
|
207
|
-
request = XmlNode.new('
|
207
|
+
request = XmlNode.new('RateV4Request', :USERID => @options[:login]) do |rate_request|
|
208
208
|
packages.each_with_index do |p,id|
|
209
209
|
rate_request << XmlNode.new('Package', :ID => id.to_s) do |package|
|
210
210
|
package << XmlNode.new('Service', US_SERVICES[options[:service] || :all])
|
@@ -212,9 +212,7 @@ module ActiveMerchant
|
|
212
212
|
package << XmlNode.new('ZipDestination', strip_zip(destination_zip))
|
213
213
|
package << XmlNode.new('Pounds', 0)
|
214
214
|
package << XmlNode.new('Ounces', "%0.1f" % [p.ounces,1].max)
|
215
|
-
|
216
|
-
package << XmlNode.new('Container', CONTAINERS[p.options[:container]])
|
217
|
-
end
|
215
|
+
package << XmlNode.new('Container', CONTAINERS[p.options[:container]])
|
218
216
|
package << XmlNode.new('Size', USPS.size_code_for(p))
|
219
217
|
package << XmlNode.new('Width', p.inches(:width))
|
220
218
|
package << XmlNode.new('Length', p.inches(:length))
|
@@ -241,21 +239,34 @@ module ActiveMerchant
|
|
241
239
|
#
|
242
240
|
# package.options[:mail_type] -- one of [:package, :postcard, :matter_for_the_blind, :envelope].
|
243
241
|
# Defaults to :package.
|
244
|
-
def build_world_rate_request(packages,
|
245
|
-
country = COUNTRY_NAME_CONVERSIONS[
|
246
|
-
request = XmlNode.new('
|
242
|
+
def build_world_rate_request(packages, destination)
|
243
|
+
country = COUNTRY_NAME_CONVERSIONS[destination.country.code(:alpha2).value] || destination.country.name
|
244
|
+
request = XmlNode.new('IntlRateV2Request', :USERID => @options[:login]) do |rate_request|
|
247
245
|
packages.each_index do |id|
|
248
246
|
p = packages[id]
|
249
247
|
rate_request << XmlNode.new('Package', :ID => id.to_s) do |package|
|
250
248
|
package << XmlNode.new('Pounds', 0)
|
251
249
|
package << XmlNode.new('Ounces', [p.ounces,1].max.ceil) #takes an integer for some reason, must be rounded UP
|
252
250
|
package << XmlNode.new('MailType', MAIL_TYPES[p.options[:mail_type]] || 'Package')
|
253
|
-
|
254
|
-
|
251
|
+
package << XmlNode.new('GXG') do |gxg|
|
252
|
+
gxg << XmlNode.new('POBoxFlag', destination.po_box? ? 'Y' : 'N')
|
253
|
+
gxg << XmlNode.new('GiftFlag', p.gift? ? 'Y' : 'N')
|
254
|
+
end
|
255
|
+
value = if p.value && p.value > 0 && p.currency && p.currency != 'USD'
|
256
|
+
0.0
|
257
|
+
else
|
258
|
+
(p.value || 0) / 100.0
|
255
259
|
end
|
260
|
+
package << XmlNode.new('ValueOfContents', value)
|
256
261
|
package << XmlNode.new('Country') do |node|
|
257
262
|
node.cdata = country
|
258
263
|
end
|
264
|
+
package << XmlNode.new('Container', p.cylinder? ? 'NONRECTANGULAR' : 'RECTANGULAR')
|
265
|
+
package << XmlNode.new('Size', USPS.size_code_for(p))
|
266
|
+
package << XmlNode.new('Width', [p.inches(:width), 0.01].max)
|
267
|
+
package << XmlNode.new('Length', [p.inches(:length), 0.01].max)
|
268
|
+
package << XmlNode.new('Height', [p.inches(:height), 0.01].max)
|
269
|
+
package << XmlNode.new('Girth', [p.inches(:girth), 0.01].max)
|
259
270
|
end
|
260
271
|
end
|
261
272
|
end
|
@@ -285,41 +296,49 @@ module ActiveMerchant
|
|
285
296
|
rate_hash = rates_from_response_node(xml, packages)
|
286
297
|
unless rate_hash
|
287
298
|
success = false
|
288
|
-
message = "Unknown root node in XML response: '#{
|
299
|
+
message = "Unknown root node in XML response: '#{xml.root.name}'"
|
289
300
|
end
|
290
301
|
end
|
291
302
|
|
292
303
|
end
|
293
304
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
305
|
+
if success
|
306
|
+
rate_estimates = rate_hash.keys.map do |service_name|
|
307
|
+
RateEstimate.new(origin,destination,@@name,"USPS #{service_name}",
|
308
|
+
:package_rates => rate_hash[service_name][:package_rates],
|
309
|
+
:service_code => rate_hash[service_name][:service_code],
|
310
|
+
:currency => 'USD')
|
311
|
+
end
|
312
|
+
rate_estimates.reject! {|e| e.package_count != packages.length}
|
313
|
+
rate_estimates = rate_estimates.sort_by(&:total_price)
|
299
314
|
end
|
300
|
-
rate_estimates.reject! {|e| e.package_count != packages.length}
|
301
|
-
rate_estimates = rate_estimates.sort_by(&:total_price)
|
302
315
|
|
303
316
|
RateResponse.new(success, message, Hash.from_xml(response), :rates => rate_estimates, :xml => response, :request => last_request)
|
304
317
|
end
|
305
318
|
|
306
319
|
def rates_from_response_node(response_node, packages)
|
307
320
|
rate_hash = {}
|
308
|
-
return false unless (root_node = response_node.elements['/
|
309
|
-
domestic = (root_node.name == '
|
321
|
+
return false unless (root_node = response_node.elements['/IntlRateV2Response | /RateV4Response'])
|
322
|
+
domestic = (root_node.name == 'RateV4Response')
|
310
323
|
|
311
324
|
domestic_elements = ['Postage', 'CLASSID', 'MailService', 'Rate']
|
312
325
|
international_elements = ['Service', 'ID', 'SvcDescription', 'Postage']
|
313
326
|
service_node, service_code_node, service_name_node, rate_node = domestic ? domestic_elements : international_elements
|
314
327
|
|
315
328
|
root_node.each_element('Package') do |package_node|
|
316
|
-
|
329
|
+
this_package = packages[package_node.attributes['ID'].to_i]
|
317
330
|
|
318
331
|
package_node.each_element(service_node) do |service_response_node|
|
319
332
|
service_name = service_response_node.get_text(service_name_node).to_s
|
320
333
|
|
321
|
-
#
|
322
|
-
service_name.gsub!(/&lt
|
334
|
+
# strips the double-escaped HTML for trademark symbols from service names
|
335
|
+
service_name.gsub!(/&lt;\S*&gt;/,'')
|
336
|
+
# ...leading "USPS"
|
337
|
+
service_name.gsub!(/^USPS/,'')
|
338
|
+
# ...trailing asterisks
|
339
|
+
service_name.gsub!(/\*+$/,'')
|
340
|
+
# ...surrounding spaces
|
341
|
+
service_name.strip!
|
323
342
|
|
324
343
|
# aggregate specific package rates into a service-centric RateEstimate
|
325
344
|
# first package with a given service name will initialize these;
|
@@ -327,7 +346,7 @@ module ActiveMerchant
|
|
327
346
|
this_service = rate_hash[service_name] ||= {}
|
328
347
|
this_service[:service_code] ||= service_response_node.attributes[service_code_node]
|
329
348
|
package_rates = this_service[:package_rates] ||= []
|
330
|
-
this_package_rate = {:package =>
|
349
|
+
this_package_rate = {:package => this_package,
|
331
350
|
:rate => Package.cents_from(service_response_node.get_text(rate_node).to_s.to_f)}
|
332
351
|
|
333
352
|
package_rates << this_package_rate if package_valid_for_service(this_package,service_response_node)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Shipping #:nodoc:
|
3
3
|
class Location
|
4
|
+
ADDRESS_TYPES = %w{residential commercial po_box}
|
4
5
|
|
5
6
|
attr_reader :options,
|
6
7
|
:country,
|
@@ -34,8 +35,12 @@ module ActiveMerchant #:nodoc:
|
|
34
35
|
@address3 = options[:address3]
|
35
36
|
@phone = options[:phone]
|
36
37
|
@fax = options[:fax]
|
37
|
-
|
38
|
-
|
38
|
+
if options[:address_type].present?
|
39
|
+
@address_type = options[:address_type].to_s
|
40
|
+
unless ADDRESS_TYPES.include?(@address_type)
|
41
|
+
raise ArgumentError.new("address_type must be one of #{ADDRESS_TYPES.map(&:inspect).join(', ')}")
|
42
|
+
end
|
43
|
+
end
|
39
44
|
end
|
40
45
|
|
41
46
|
def self.from(object, options={})
|
@@ -68,7 +73,7 @@ module ActiveMerchant #:nodoc:
|
|
68
73
|
end
|
69
74
|
end
|
70
75
|
end
|
71
|
-
attributes.delete(:address_type) unless
|
76
|
+
attributes.delete(:address_type) unless ADDRESS_TYPES.include?(attributes[:address_type].to_s)
|
72
77
|
self.new(attributes.update(options))
|
73
78
|
end
|
74
79
|
|
@@ -76,8 +81,9 @@ module ActiveMerchant #:nodoc:
|
|
76
81
|
@country.nil? ? nil : @country.code(format).value
|
77
82
|
end
|
78
83
|
|
79
|
-
def residential?;
|
80
|
-
def commercial?;
|
84
|
+
def residential?; @address_type == 'residential' end
|
85
|
+
def commercial?; @address_type == 'commercial' end
|
86
|
+
def po_box?; @address_type == 'po_box' end
|
81
87
|
|
82
88
|
def to_s
|
83
89
|
prettyprint.gsub(/\n/, ' ')
|
@@ -32,6 +32,7 @@ module ActiveMerchant #:nodoc:
|
|
32
32
|
@value = Package.cents_from(options[:value])
|
33
33
|
@currency = options[:currency] || (options[:value].currency if options[:value].respond_to?(:currency))
|
34
34
|
@cylinder = (options[:cylinder] || options[:tube]) ? true : false
|
35
|
+
@gift = options[:gift] ? true : false
|
35
36
|
end
|
36
37
|
|
37
38
|
def cylinder?
|
@@ -39,6 +40,8 @@ module ActiveMerchant #:nodoc:
|
|
39
40
|
end
|
40
41
|
alias_method :tube?, :cylinder?
|
41
42
|
|
43
|
+
def gift?; @gift end
|
44
|
+
|
42
45
|
def ounces(options={})
|
43
46
|
weight(options).in_ounces.amount
|
44
47
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_shipping
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 35
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 9
|
9
|
-
-
|
10
|
-
version: 0.9.
|
9
|
+
- 12
|
10
|
+
version: 0.9.12
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- James MacAulay
|
@@ -18,7 +18,7 @@ autorequire:
|
|
18
18
|
bindir: bin
|
19
19
|
cert_chain: []
|
20
20
|
|
21
|
-
date: 2011-
|
21
|
+
date: 2011-04-21 00:00:00 -04:00
|
22
22
|
default_executable:
|
23
23
|
dependencies:
|
24
24
|
- !ruby/object:Gem::Dependency
|
@@ -146,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
146
146
|
requirements: []
|
147
147
|
|
148
148
|
rubyforge_project: active_shipping
|
149
|
-
rubygems_version: 1.
|
149
|
+
rubygems_version: 1.6.2
|
150
150
|
signing_key:
|
151
151
|
specification_version: 3
|
152
152
|
summary: Shipping API extension for Active Merchant
|