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
@@ -1,13 +1,11 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
|
-
|
3
2
|
module Shipping #:nodoc:
|
4
|
-
|
5
3
|
class Error < ActiveMerchant::ActiveMerchantError
|
6
4
|
end
|
7
|
-
|
5
|
+
|
8
6
|
class ResponseError < Error
|
9
7
|
attr_reader :response
|
10
|
-
|
8
|
+
|
11
9
|
def initialize(response = nil)
|
12
10
|
if response.is_a? Response
|
13
11
|
super(response.message)
|
@@ -15,17 +13,16 @@ module ActiveMerchant #:nodoc:
|
|
15
13
|
else
|
16
14
|
super(response)
|
17
15
|
end
|
18
|
-
end
|
16
|
+
end
|
19
17
|
end
|
20
|
-
|
18
|
+
|
21
19
|
class Response
|
22
|
-
|
23
20
|
attr_reader :params
|
24
21
|
attr_reader :message
|
25
22
|
attr_reader :test
|
26
23
|
attr_reader :xml
|
27
24
|
attr_reader :request
|
28
|
-
|
25
|
+
|
29
26
|
def initialize(success, message, params = {}, options = {})
|
30
27
|
@success, @message, @params = success, message, params.stringify_keys
|
31
28
|
@test = options[:test] || false
|
@@ -33,7 +30,7 @@ module ActiveMerchant #:nodoc:
|
|
33
30
|
@request = options[:request]
|
34
31
|
raise ResponseError.new(self) unless success
|
35
32
|
end
|
36
|
-
|
33
|
+
|
37
34
|
def success?
|
38
35
|
@success ? true : false
|
39
36
|
end
|
@@ -1,10 +1,9 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Shipping
|
3
|
-
|
4
3
|
class ShipmentEvent
|
5
4
|
attr_reader :name, :time, :location, :message
|
6
|
-
|
7
|
-
def initialize(name, time, location, message=nil)
|
5
|
+
|
6
|
+
def initialize(name, time, location, message = nil)
|
8
7
|
@name, @time, @location, @message = name, time, location, message
|
9
8
|
end
|
10
9
|
|
@@ -16,6 +15,5 @@ module ActiveMerchant #:nodoc:
|
|
16
15
|
@status ||= name.downcase.gsub("\s", "_").to_sym
|
17
16
|
end
|
18
17
|
end
|
19
|
-
|
20
18
|
end
|
21
19
|
end
|
@@ -13,40 +13,55 @@ module ActiveMerchant
|
|
13
13
|
# maximum_weight - maximum weight in grams
|
14
14
|
# currency - ISO currency code
|
15
15
|
def self.pack(items, dimensions, maximum_weight, currency)
|
16
|
+
return [] if items.empty?
|
16
17
|
packages = []
|
17
18
|
|
18
|
-
|
19
|
+
# Naive in that it assumes weight is equally distributed across all items
|
20
|
+
# Should raise early enough in most cases
|
21
|
+
total_weight = 0
|
22
|
+
items.map!(&:symbolize_keys).each do |item|
|
23
|
+
total_weight += item[:quantity].to_i * item[:grams].to_i
|
19
24
|
|
20
|
-
|
25
|
+
if item[:grams].to_i > maximum_weight
|
26
|
+
raise OverweightItem, "The item with weight of #{item[:grams]}g is heavier than the allowable package weight of #{maximum_weight}g"
|
27
|
+
end
|
21
28
|
|
22
|
-
|
23
|
-
|
29
|
+
if total_weight > maximum_weight * EXCESS_PACKAGE_QUANTITY_THRESHOLD
|
30
|
+
raise ExcessPackageQuantity, "Unable to pack more than #{EXCESS_PACKAGE_QUANTITY_THRESHOLD} packages"
|
31
|
+
end
|
24
32
|
end
|
25
33
|
|
26
|
-
items = items.
|
27
|
-
state = :package_empty
|
34
|
+
items = items.deep_dup.sort_by! { |i| i[:grams].to_i }
|
28
35
|
|
36
|
+
state = :package_empty
|
29
37
|
while state != :packing_finished
|
30
38
|
case state
|
31
39
|
when :package_empty
|
32
40
|
package_weight, package_value = 0, 0
|
33
41
|
state = :filling_package
|
34
42
|
when :filling_package
|
35
|
-
|
36
|
-
|
43
|
+
items.each do |item|
|
44
|
+
quantity = if item[:grams].to_i <= 0
|
45
|
+
item[:quantity].to_i
|
46
|
+
else
|
47
|
+
# Grab the max amount of this item we can fit into this package
|
48
|
+
# Or, if there are fewer than the max for this item, put
|
49
|
+
# what is left into this package
|
50
|
+
[(maximum_weight - package_weight) / item[:grams].to_i, item[:quantity].to_i].min
|
51
|
+
end
|
37
52
|
|
38
|
-
|
39
|
-
|
40
|
-
end
|
53
|
+
item_weight = quantity * item[:grams].to_i
|
54
|
+
item_value = quantity * Package.cents_from(item[:price])
|
41
55
|
|
42
|
-
if (package_weight + item_weight) <= maximum_weight
|
43
56
|
package_weight += item_weight
|
44
|
-
package_value
|
45
|
-
|
46
|
-
|
47
|
-
items.unshift(item)
|
48
|
-
state = :package_full
|
57
|
+
package_value += item_value
|
58
|
+
|
59
|
+
item[:quantity] = item[:quantity].to_i - quantity
|
49
60
|
end
|
61
|
+
|
62
|
+
items.reject! { |i| i[:quantity].to_i == 0 }
|
63
|
+
|
64
|
+
state = :package_full
|
50
65
|
when :package_full
|
51
66
|
packages << ActiveMerchant::Shipping::Package.new(package_weight, dimensions, :value => package_value, :currency => currency)
|
52
67
|
state = items.any? ? :package_empty : :packing_finished
|
@@ -1,16 +1,14 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Shipping
|
3
|
-
|
4
3
|
class ShippingResponse < Response
|
5
4
|
attr_reader :shipping_id # string
|
6
5
|
attr_reader :tracking_number # string
|
7
|
-
|
6
|
+
|
8
7
|
def initialize(success, message, params = {}, options = {})
|
9
8
|
@shipping_id = options[:shipping_id]
|
10
9
|
@tracking_number = options[:tracking_number]
|
11
10
|
super
|
12
11
|
end
|
13
12
|
end
|
14
|
-
|
15
13
|
end
|
16
|
-
end
|
14
|
+
end
|
@@ -1,20 +1,19 @@
|
|
1
1
|
module ActiveMerchant #:nodoc:
|
2
2
|
module Shipping
|
3
|
-
|
4
3
|
class TrackingResponse < Response
|
5
4
|
attr_reader :carrier # symbol
|
6
5
|
attr_reader :carrier_name # string
|
7
6
|
attr_reader :status # symbol
|
8
7
|
attr_reader :status_code # string
|
9
|
-
attr_reader :status_description #string
|
8
|
+
attr_reader :status_description # string
|
10
9
|
attr_reader :ship_time # time
|
11
10
|
attr_reader :scheduled_delivery_date # time
|
12
11
|
attr_reader :actual_delivery_date # time
|
13
|
-
attr_reader :delivery_signature #string
|
12
|
+
attr_reader :delivery_signature # string
|
14
13
|
attr_reader :tracking_number # string
|
15
14
|
attr_reader :shipment_events # array of ShipmentEvents in chronological order
|
16
15
|
attr_reader :shipper_address, :origin, :destination # Location objects
|
17
|
-
|
16
|
+
|
18
17
|
def initialize(success, message, params = {}, options = {})
|
19
18
|
@carrier = options[:carrier].parameterize.to_sym
|
20
19
|
@carrier_name = options[:carrier]
|
@@ -51,6 +50,5 @@ module ActiveMerchant #:nodoc:
|
|
51
50
|
alias_method(:scheduled_delivery_time, :scheduled_delivery_date)
|
52
51
|
alias_method(:actual_delivery_time, :actual_delivery_date)
|
53
52
|
end
|
54
|
-
|
55
53
|
end
|
56
54
|
end
|
@@ -1,206 +1,205 @@
|
|
1
1
|
module Quantified
|
2
2
|
class Attribute
|
3
3
|
include Comparable
|
4
|
-
|
4
|
+
|
5
5
|
attr_reader :amount, :unit
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(amount, unit)
|
8
8
|
raise ArgumentError, "amount must be a Numeric" unless amount.is_a?(Numeric)
|
9
9
|
@amount, @unit = amount, unit.to_sym
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def to_s
|
13
13
|
"#{amount} #{unit}"
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
def inspect
|
17
17
|
"#<#{self.class.name}: #{amount} #{unit}>"
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
20
|
def ==(other)
|
21
|
-
(BigDecimal.new(
|
21
|
+
(BigDecimal.new(amount.to_s) == BigDecimal.new(other.amount.to_s) && unit == other.unit) || BigDecimal.new(self.class.convert(amount, unit, other.unit).to_s) == BigDecimal.new(other.amount.to_s)
|
22
22
|
rescue NoMethodError
|
23
|
-
|
23
|
+
amount == other
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
def eql?(other)
|
27
|
-
self.class == other.class && BigDecimal.new(
|
27
|
+
self.class == other.class && BigDecimal.new(amount.to_s) == BigDecimal.new(other.amount.to_s) && unit == other.unit
|
28
28
|
end
|
29
|
-
|
29
|
+
|
30
30
|
def <=>(other)
|
31
31
|
if self.class == other.class
|
32
|
-
self.class.convert(
|
32
|
+
self.class.convert(amount, unit, other.unit) <=> other.amount
|
33
33
|
else
|
34
|
-
|
34
|
+
amount <=> other
|
35
35
|
end
|
36
36
|
end
|
37
|
-
|
37
|
+
|
38
38
|
def system
|
39
39
|
self.class.units_to_systems[unit]
|
40
40
|
end
|
41
41
|
|
42
42
|
def coerce(other)
|
43
|
-
[other,
|
43
|
+
[other, amount]
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
def method_missing(meth, *args)
|
47
47
|
if args.size == 1 && self.class == (other = args.first).class
|
48
|
-
other_amount_in_self_units = self.class.convert(other.amount, other.unit,
|
49
|
-
self.class.new(amount.send(meth, other_amount_in_self_units),
|
48
|
+
other_amount_in_self_units = self.class.convert(other.amount, other.unit, unit)
|
49
|
+
self.class.new(amount.send(meth, other_amount_in_self_units), unit)
|
50
50
|
else
|
51
51
|
amount.send(meth, *args)
|
52
52
|
end
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
def self.conversion_rate(from, to)
|
56
|
-
return nil unless
|
57
|
-
|
58
|
-
(1.0 /
|
59
|
-
shared_conversions =
|
56
|
+
return nil unless conversions[from] and conversions[to]
|
57
|
+
conversions[from][to] ||=
|
58
|
+
(1.0 / conversions[to][from] if conversions[to][from]) || begin
|
59
|
+
shared_conversions = conversions[from].keys & conversions[to].keys
|
60
60
|
if shared_conversions.any?
|
61
61
|
primitive = shared_conversions.first
|
62
|
-
|
62
|
+
conversions[from][primitive] * (1.0 / conversions[to][primitive])
|
63
63
|
else
|
64
|
-
|
65
|
-
if
|
66
|
-
return multiple * conversion_rate(conversion) * (1.0 /
|
64
|
+
conversions[from].each do |conversion_unit, multiple|
|
65
|
+
if conversions[to].include?(conversion_unit)
|
66
|
+
return multiple * conversion_rate(conversion) * (1.0 / conversions[to][conversion_unit])
|
67
67
|
end
|
68
68
|
end
|
69
|
-
from_primitive = (
|
70
|
-
to_primitive = (
|
69
|
+
from_primitive = (conversions[from].keys & primitives).first
|
70
|
+
to_primitive = (conversions[to].keys & primitives).first
|
71
71
|
if from_primitive_to_primitive_multiple = conversion_rate(from_primitive, to_primitive)
|
72
|
-
return
|
72
|
+
return conversions[from][from_primitive] * from_primitive_to_primitive_multiple * (1.0 / conversions[to][to_primitive])
|
73
73
|
end
|
74
74
|
raise StandardError, "No conversion path from #{from} to #{to}"
|
75
75
|
end
|
76
76
|
end
|
77
77
|
end
|
78
|
-
|
79
|
-
def self.units(system=nil)
|
78
|
+
|
79
|
+
def self.units(system = nil)
|
80
80
|
if system
|
81
|
-
|
81
|
+
systems_to_units[system.to_sym].dup
|
82
82
|
else
|
83
|
-
|
83
|
+
primitives | conversions.keys
|
84
84
|
end
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
def self.non_primitives
|
88
|
-
|
88
|
+
conversions.keys
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
def self.systems
|
92
|
-
|
92
|
+
systems_to_units.keys
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
def self.add_numeric_methods?
|
96
|
-
|
96
|
+
add_numeric_methods
|
97
97
|
end
|
98
|
-
|
98
|
+
|
99
99
|
def self.numeric_methods(*args)
|
100
100
|
args.each do |arg|
|
101
101
|
add_numeric_method_for(arg.to_sym)
|
102
102
|
end
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
protected
|
106
106
|
|
107
107
|
class << self
|
108
108
|
def primitives; @primitives ||= []; end
|
109
109
|
def add_numeric_methods; @add_numeric_methods ||= false; end
|
110
|
-
|
110
|
+
attr_writer :add_numeric_methods
|
111
111
|
def conversions; @conversions ||= {}; end
|
112
|
-
|
113
|
-
|
112
|
+
attr_reader :current_system
|
113
|
+
attr_writer :current_system
|
114
114
|
def systems_to_units; @systems_to_units ||= {}; end
|
115
115
|
def units_to_systems; @units_to_systems ||= {}; end
|
116
116
|
end
|
117
117
|
|
118
|
-
|
119
118
|
def self.system(system_name, &block)
|
120
|
-
old_system =
|
119
|
+
old_system = current_system
|
121
120
|
self.current_system = system_name.to_sym
|
122
121
|
yield
|
123
122
|
self.current_system = old_system
|
124
123
|
end
|
125
|
-
|
126
|
-
def self.primitive(sym, options={})
|
124
|
+
|
125
|
+
def self.primitive(sym, options = {})
|
127
126
|
unit_sym = (options[:plural] || sym.to_s.pluralize).to_sym
|
128
|
-
|
127
|
+
primitives << unit_sym
|
129
128
|
add_to_system(unit_sym)
|
130
129
|
add_methods_for(unit_sym, options)
|
131
130
|
end
|
132
|
-
|
131
|
+
|
133
132
|
def self.add_to_system(unit_sym)
|
134
|
-
if
|
135
|
-
|
136
|
-
sys_ary =
|
133
|
+
if current_system
|
134
|
+
units_to_systems[unit_sym] ||= begin
|
135
|
+
sys_ary = systems_to_units[current_system] ||= []
|
137
136
|
sys_ary << unit_sym
|
138
|
-
|
137
|
+
current_system
|
139
138
|
end
|
140
139
|
end
|
141
140
|
end
|
142
|
-
|
143
|
-
def self.one(sym, options={})
|
141
|
+
|
142
|
+
def self.one(sym, options = {})
|
144
143
|
unit_sym = (options[:plural] || sym.to_s.pluralize).to_sym
|
145
144
|
add_to_system(unit_sym)
|
146
145
|
register_unit(unit_sym, options[:is].unit, options[:is].amount)
|
147
146
|
add_methods_for(unit_sym, options)
|
148
147
|
end
|
149
|
-
|
148
|
+
|
150
149
|
def self.register_unit(multiple_unit, other_unit, multiple)
|
151
150
|
multiple_unit, other_unit = multiple_unit.to_sym, other_unit.to_sym
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
if
|
151
|
+
conversions[multiple_unit] ||= {}
|
152
|
+
conversions[other_unit] ||= {}
|
153
|
+
|
154
|
+
if primitives.include?(multiple_unit) || primitives.include?(other_unit)
|
156
155
|
add_conversion(multiple_unit, other_unit, multiple)
|
157
156
|
else
|
158
157
|
[multiple_unit, other_unit].each do |this_unit|
|
159
|
-
|
160
|
-
if
|
158
|
+
conversions[this_unit].each do |this_other_unit, this_multiple|
|
159
|
+
if primitives.include?(this_other_unit)
|
161
160
|
add_conversion(multiple_unit, this_other_unit, multiple * this_multiple)
|
162
161
|
end
|
163
162
|
end
|
164
163
|
end
|
165
164
|
end
|
166
165
|
end
|
167
|
-
|
166
|
+
|
168
167
|
def self.add_conversion(multiple_unit, other_unit, multiple)
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
168
|
+
conversions[multiple_unit] ||= {}
|
169
|
+
conversions[multiple_unit][other_unit] = multiple
|
170
|
+
conversions[other_unit] ||= {}
|
171
|
+
conversions[other_unit][multiple_unit] = (1.0 / multiple)
|
173
172
|
end
|
174
|
-
|
173
|
+
|
175
174
|
def self.convert(amount, from, to)
|
176
175
|
from, to = from.to_sym, to.to_sym
|
177
176
|
amount * conversion_rate(from, to)
|
178
177
|
end
|
179
|
-
|
180
|
-
def self.add_methods_for(sym, options={})
|
178
|
+
|
179
|
+
def self.add_methods_for(sym, options = {})
|
181
180
|
add_conversion_method_for(sym, options)
|
182
181
|
add_numeric_method = if options.has_key?(:add_numeric_methods)
|
183
182
|
options[:add_numeric_methods]
|
184
183
|
else
|
185
|
-
|
184
|
+
add_numeric_methods
|
186
185
|
end
|
187
186
|
add_numeric_method_for(sym.to_s, options) if add_numeric_method
|
188
187
|
end
|
189
|
-
|
190
|
-
def self.add_conversion_method_for(sym, options={})
|
188
|
+
|
189
|
+
def self.add_conversion_method_for(sym, options = {})
|
191
190
|
unit_name = sym.to_s
|
192
191
|
class_eval do
|
193
192
|
define_method("to_#{unit_name}") do
|
194
|
-
return self if unit_name ==
|
195
|
-
self.class.new(self.class.convert(
|
193
|
+
return self if unit_name == unit.to_s
|
194
|
+
self.class.new(self.class.convert(amount, unit, unit_name), unit_name)
|
196
195
|
end
|
197
|
-
alias_method("in_#{unit_name}","to_#{unit_name}")
|
196
|
+
alias_method("in_#{unit_name}", "to_#{unit_name}")
|
198
197
|
end
|
199
198
|
end
|
200
|
-
|
201
|
-
def self.add_numeric_method_for(unit_name, options={})
|
199
|
+
|
200
|
+
def self.add_numeric_method_for(unit_name, options = {})
|
202
201
|
unit_name = unit_name.to_sym
|
203
|
-
raise ArgumentError, "#{unit_name.inspect} is not a unit in #{
|
202
|
+
raise ArgumentError, "#{unit_name.inspect} is not a unit in #{name}" unless units.include?(unit_name)
|
204
203
|
klass = self
|
205
204
|
Numeric.class_eval do
|
206
205
|
define_method(unit_name) do
|