active_shipping 0.12.4 → 0.12.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|