active_shipping 0.12.6 → 1.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -0
- data.tar.gz.sig +0 -0
- data/{CHANGELOG → CHANGELOG.md} +6 -2
- data/CONTRIBUTING.md +32 -0
- data/{README.markdown → README.md} +45 -61
- data/lib/active_shipping.rb +20 -28
- data/lib/active_shipping/carrier.rb +82 -0
- data/lib/active_shipping/carriers.rb +33 -0
- data/lib/active_shipping/carriers/benchmark_carrier.rb +31 -0
- data/lib/active_shipping/carriers/bogus_carrier.rb +12 -0
- data/lib/active_shipping/carriers/canada_post.rb +253 -0
- data/lib/active_shipping/carriers/canada_post_pws.rb +870 -0
- data/lib/active_shipping/carriers/fedex.rb +579 -0
- data/lib/active_shipping/carriers/kunaki.rb +164 -0
- data/lib/active_shipping/carriers/new_zealand_post.rb +262 -0
- data/lib/active_shipping/carriers/shipwire.rb +181 -0
- data/lib/active_shipping/carriers/stamps.rb +861 -0
- data/lib/active_shipping/carriers/ups.rb +648 -0
- data/lib/active_shipping/carriers/usps.rb +642 -0
- data/lib/active_shipping/errors.rb +7 -0
- data/lib/active_shipping/label_response.rb +23 -0
- data/lib/active_shipping/location.rb +149 -0
- data/lib/active_shipping/package.rb +241 -0
- data/lib/active_shipping/rate_estimate.rb +64 -0
- data/lib/active_shipping/rate_response.rb +13 -0
- data/lib/active_shipping/response.rb +41 -0
- data/lib/active_shipping/shipment_event.rb +17 -0
- data/lib/active_shipping/shipment_packer.rb +73 -0
- data/lib/active_shipping/shipping_response.rb +12 -0
- data/lib/active_shipping/tracking_response.rb +52 -0
- data/lib/active_shipping/version.rb +1 -1
- data/lib/vendor/quantified/test/length_test.rb +2 -2
- data/lib/vendor/xml_node/test/test_parsing.rb +1 -1
- metadata +58 -36
- metadata.gz.sig +0 -0
- data/lib/active_shipping/shipping/base.rb +0 -13
- data/lib/active_shipping/shipping/carrier.rb +0 -84
- data/lib/active_shipping/shipping/carriers.rb +0 -23
- data/lib/active_shipping/shipping/carriers/benchmark_carrier.rb +0 -33
- data/lib/active_shipping/shipping/carriers/bogus_carrier.rb +0 -14
- data/lib/active_shipping/shipping/carriers/canada_post.rb +0 -257
- data/lib/active_shipping/shipping/carriers/canada_post_pws.rb +0 -874
- data/lib/active_shipping/shipping/carriers/fedex.rb +0 -581
- data/lib/active_shipping/shipping/carriers/kunaki.rb +0 -166
- data/lib/active_shipping/shipping/carriers/new_zealand_post.rb +0 -262
- data/lib/active_shipping/shipping/carriers/shipwire.rb +0 -184
- data/lib/active_shipping/shipping/carriers/stamps.rb +0 -864
- data/lib/active_shipping/shipping/carriers/ups.rb +0 -650
- data/lib/active_shipping/shipping/carriers/usps.rb +0 -649
- data/lib/active_shipping/shipping/errors.rb +0 -9
- data/lib/active_shipping/shipping/label_response.rb +0 -25
- data/lib/active_shipping/shipping/location.rb +0 -152
- data/lib/active_shipping/shipping/package.rb +0 -243
- data/lib/active_shipping/shipping/rate_estimate.rb +0 -66
- data/lib/active_shipping/shipping/rate_response.rb +0 -15
- data/lib/active_shipping/shipping/response.rb +0 -43
- data/lib/active_shipping/shipping/shipment_event.rb +0 -19
- data/lib/active_shipping/shipping/shipment_packer.rb +0 -75
- data/lib/active_shipping/shipping/shipping_response.rb +0 -14
- data/lib/active_shipping/shipping/tracking_response.rb +0 -54
@@ -1,25 +0,0 @@
|
|
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,152 +0,0 @@
|
|
1
|
-
module ActiveMerchant #:nodoc:
|
2
|
-
module Shipping #:nodoc:
|
3
|
-
class Location
|
4
|
-
ADDRESS_TYPES = %w(residential commercial po_box)
|
5
|
-
|
6
|
-
attr_reader :options,
|
7
|
-
:country,
|
8
|
-
:postal_code,
|
9
|
-
:province,
|
10
|
-
:city,
|
11
|
-
:name,
|
12
|
-
:address1,
|
13
|
-
:address2,
|
14
|
-
:address3,
|
15
|
-
:phone,
|
16
|
-
:fax,
|
17
|
-
:address_type,
|
18
|
-
:company_name
|
19
|
-
|
20
|
-
alias_method :zip, :postal_code
|
21
|
-
alias_method :postal, :postal_code
|
22
|
-
alias_method :state, :province
|
23
|
-
alias_method :territory, :province
|
24
|
-
alias_method :region, :province
|
25
|
-
alias_method :company, :company_name
|
26
|
-
|
27
|
-
def initialize(options = {})
|
28
|
-
@country = (options[:country].nil? or options[:country].is_a?(ActiveMerchant::Country)) ?
|
29
|
-
options[:country] :
|
30
|
-
ActiveMerchant::Country.find(options[:country])
|
31
|
-
@postal_code = options[:postal_code] || options[:postal] || options[:zip]
|
32
|
-
@province = options[:province] || options[:state] || options[:territory] || options[:region]
|
33
|
-
@city = options[:city]
|
34
|
-
@name = options[:name]
|
35
|
-
@address1 = options[:address1]
|
36
|
-
@address2 = options[:address2]
|
37
|
-
@address3 = options[:address3]
|
38
|
-
@phone = options[:phone]
|
39
|
-
@fax = options[:fax]
|
40
|
-
@company_name = options[:company_name] || options[:company]
|
41
|
-
|
42
|
-
self.address_type = options[:address_type]
|
43
|
-
end
|
44
|
-
|
45
|
-
def self.from(object, options = {})
|
46
|
-
return object if object.is_a? ActiveMerchant::Shipping::Location
|
47
|
-
attr_mappings = {
|
48
|
-
:name => [:name],
|
49
|
-
:country => [:country_code, :country],
|
50
|
-
:postal_code => [:postal_code, :zip, :postal],
|
51
|
-
:province => [:province_code, :state_code, :territory_code, :region_code, :province, :state, :territory, :region],
|
52
|
-
:city => [:city, :town],
|
53
|
-
:address1 => [:address1, :address, :street],
|
54
|
-
:address2 => [:address2],
|
55
|
-
:address3 => [:address3],
|
56
|
-
:phone => [:phone, :phone_number],
|
57
|
-
:fax => [:fax, :fax_number],
|
58
|
-
:address_type => [:address_type],
|
59
|
-
:company_name => [:company, :company_name]
|
60
|
-
}
|
61
|
-
attributes = {}
|
62
|
-
hash_access = begin
|
63
|
-
object[:some_symbol]
|
64
|
-
true
|
65
|
-
rescue
|
66
|
-
false
|
67
|
-
end
|
68
|
-
attr_mappings.each do |pair|
|
69
|
-
pair[1].each do |sym|
|
70
|
-
if value = (object[sym] if hash_access) || (object.send(sym) if object.respond_to?(sym) && (!hash_access || !Hash.public_instance_methods.include?(sym.to_s)))
|
71
|
-
attributes[pair[0]] = value
|
72
|
-
break
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
attributes.delete(:address_type) unless ADDRESS_TYPES.include?(attributes[:address_type].to_s)
|
77
|
-
new(attributes.update(options))
|
78
|
-
end
|
79
|
-
|
80
|
-
def country_code(format = :alpha2)
|
81
|
-
@country.nil? ? nil : @country.code(format).value
|
82
|
-
end
|
83
|
-
|
84
|
-
def residential?; @address_type == 'residential' end
|
85
|
-
def commercial?; @address_type == 'commercial' end
|
86
|
-
def po_box?; @address_type == 'po_box' end
|
87
|
-
def unknown?; country_code == 'ZZ' end
|
88
|
-
|
89
|
-
def address_type=(value)
|
90
|
-
return unless value.present?
|
91
|
-
raise ArgumentError.new("address_type must be one of #{ADDRESS_TYPES.join(', ')}") unless ADDRESS_TYPES.include?(value.to_s)
|
92
|
-
@address_type = value.to_s
|
93
|
-
end
|
94
|
-
|
95
|
-
def to_hash
|
96
|
-
{
|
97
|
-
:country => country_code,
|
98
|
-
:postal_code => postal_code,
|
99
|
-
:province => province,
|
100
|
-
:city => city,
|
101
|
-
:name => name,
|
102
|
-
:address1 => address1,
|
103
|
-
:address2 => address2,
|
104
|
-
:address3 => address3,
|
105
|
-
:phone => phone,
|
106
|
-
:fax => fax,
|
107
|
-
:address_type => address_type,
|
108
|
-
:company_name => company_name
|
109
|
-
}
|
110
|
-
end
|
111
|
-
|
112
|
-
def to_xml(options = {})
|
113
|
-
options[:root] ||= "location"
|
114
|
-
to_hash.to_xml(options)
|
115
|
-
end
|
116
|
-
|
117
|
-
def to_s
|
118
|
-
prettyprint.gsub(/\n/, ' ')
|
119
|
-
end
|
120
|
-
|
121
|
-
def prettyprint
|
122
|
-
chunks = []
|
123
|
-
chunks << [@name, @address1, @address2, @address3].reject(&:blank?).join("\n")
|
124
|
-
chunks << [@city, @province, @postal_code].reject(&:blank?).join(', ')
|
125
|
-
chunks << @country
|
126
|
-
chunks.reject(&:blank?).join("\n")
|
127
|
-
end
|
128
|
-
|
129
|
-
def inspect
|
130
|
-
string = prettyprint
|
131
|
-
string << "\nPhone: #{@phone}" unless @phone.blank?
|
132
|
-
string << "\nFax: #{@fax}" unless @fax.blank?
|
133
|
-
string
|
134
|
-
end
|
135
|
-
|
136
|
-
# Returns the postal code as a properly formatted Zip+4 code, e.g. "77095-2233"
|
137
|
-
def zip_plus_4
|
138
|
-
if /(\d{5})(\d{4})/ =~ @postal_code
|
139
|
-
return "#{$1}-#{$2}"
|
140
|
-
elsif /\d{5}-\d{4}/ =~ @postal_code
|
141
|
-
return @postal_code
|
142
|
-
else
|
143
|
-
nil
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
def address2_and_3
|
148
|
-
[address2, address3].reject(&:blank?).join(", ")
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
@@ -1,243 +0,0 @@
|
|
1
|
-
module ActiveMerchant #:nodoc:
|
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
|
5
|
-
# for shipping methods (label creation) right now.
|
6
|
-
class PackageItem
|
7
|
-
include Quantified
|
8
|
-
|
9
|
-
attr_reader :sku, :hs_code, :value, :name, :weight, :quantity, :options
|
10
|
-
|
11
|
-
def initialize(name, grams_or_ounces, value, quantity, options = {})
|
12
|
-
@name = name
|
13
|
-
|
14
|
-
imperial = (options[:units] == :imperial) ||
|
15
|
-
(grams_or_ounces.respond_to?(:unit) && m.unit.to_sym == :imperial)
|
16
|
-
|
17
|
-
@unit_system = imperial ? :imperial : :metric
|
18
|
-
|
19
|
-
@weight = attribute_from_metric_or_imperial(grams_or_ounces, Mass, :grams, :ounces)
|
20
|
-
|
21
|
-
@value = Package.cents_from(value)
|
22
|
-
@quantity = quantity > 0 ? quantity : 1
|
23
|
-
|
24
|
-
@sku = options[:sku]
|
25
|
-
@hs_code = options[:hs_code]
|
26
|
-
@options = options
|
27
|
-
end
|
28
|
-
|
29
|
-
def weight(options = {})
|
30
|
-
case options[:type]
|
31
|
-
when nil, :actual
|
32
|
-
@weight
|
33
|
-
when :volumetric, :dimensional
|
34
|
-
@volumetric_weight ||= begin
|
35
|
-
m = Mass.new((centimetres(:box_volume) / 6.0), :grams)
|
36
|
-
@unit_system == :imperial ? m.in_ounces : m
|
37
|
-
end
|
38
|
-
when :billable
|
39
|
-
[weight, weight(:type => :volumetric)].max
|
40
|
-
end
|
41
|
-
end
|
42
|
-
alias_method :mass, :weight
|
43
|
-
|
44
|
-
def ounces(options = {})
|
45
|
-
weight(options).in_ounces.amount
|
46
|
-
end
|
47
|
-
alias_method :oz, :ounces
|
48
|
-
|
49
|
-
def grams(options = {})
|
50
|
-
weight(options).in_grams.amount
|
51
|
-
end
|
52
|
-
alias_method :g, :grams
|
53
|
-
|
54
|
-
def pounds(options = {})
|
55
|
-
weight(options).in_pounds.amount
|
56
|
-
end
|
57
|
-
alias_method :lb, :pounds
|
58
|
-
alias_method :lbs, :pounds
|
59
|
-
|
60
|
-
def kilograms(options = {})
|
61
|
-
weight(options).in_kilograms.amount
|
62
|
-
end
|
63
|
-
alias_method :kg, :kilograms
|
64
|
-
alias_method :kgs, :kilograms
|
65
|
-
|
66
|
-
private
|
67
|
-
|
68
|
-
def attribute_from_metric_or_imperial(obj, klass, metric_unit, imperial_unit)
|
69
|
-
if obj.is_a?(klass)
|
70
|
-
return value
|
71
|
-
else
|
72
|
-
return klass.new(obj, (@unit_system == :imperial ? imperial_unit : metric_unit))
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
class Package
|
78
|
-
include Quantified
|
79
|
-
|
80
|
-
cattr_accessor :default_options
|
81
|
-
attr_reader :options, :value, :currency
|
82
|
-
|
83
|
-
# Package.new(100, [10, 20, 30], :units => :metric)
|
84
|
-
# Package.new(Mass.new(100, :grams), [10, 20, 30].map {|m| Length.new(m, :centimetres)})
|
85
|
-
# Package.new(100.grams, [10, 20, 30].map(&:centimetres))
|
86
|
-
def initialize(grams_or_ounces, dimensions, options = {})
|
87
|
-
options = @@default_options.update(options) if @@default_options
|
88
|
-
options.symbolize_keys!
|
89
|
-
@options = options
|
90
|
-
|
91
|
-
@dimensions = [dimensions].flatten.reject(&:nil?)
|
92
|
-
|
93
|
-
imperial = (options[:units] == :imperial) ||
|
94
|
-
([grams_or_ounces, *dimensions].all? { |m| m.respond_to?(:unit) && m.unit.to_sym == :imperial })
|
95
|
-
|
96
|
-
weight_imperial = dimensions_imperial = imperial if options.include?(:units)
|
97
|
-
|
98
|
-
if options.include?(:weight_units)
|
99
|
-
weight_imperial = (options[:weight_units] == :imperial) ||
|
100
|
-
(grams_or_ounces.respond_to?(:unit) && m.unit.to_sym == :imperial)
|
101
|
-
end
|
102
|
-
|
103
|
-
if options.include?(:dim_units)
|
104
|
-
dimensions_imperial = (options[:dim_units] == :imperial) ||
|
105
|
-
(dimensions && dimensions.all? { |m| m.respond_to?(:unit) && m.unit.to_sym == :imperial })
|
106
|
-
end
|
107
|
-
|
108
|
-
@weight_unit_system = weight_imperial ? :imperial : :metric
|
109
|
-
@dimensions_unit_system = dimensions_imperial ? :imperial : :metric
|
110
|
-
|
111
|
-
@weight = attribute_from_metric_or_imperial(grams_or_ounces, Mass, @weight_unit_system, :grams, :ounces)
|
112
|
-
|
113
|
-
if @dimensions.blank?
|
114
|
-
@dimensions = [Length.new(0, (dimensions_imperial ? :inches : :centimetres))] * 3
|
115
|
-
else
|
116
|
-
process_dimensions
|
117
|
-
end
|
118
|
-
|
119
|
-
@value = Package.cents_from(options[:value])
|
120
|
-
@currency = options[:currency] || (options[:value].currency if options[:value].respond_to?(:currency))
|
121
|
-
@cylinder = (options[:cylinder] || options[:tube]) ? true : false
|
122
|
-
@gift = options[:gift] ? true : false
|
123
|
-
@oversized = options[:oversized] ? true : false
|
124
|
-
@unpackaged = options[:unpackaged] ? true : false
|
125
|
-
end
|
126
|
-
|
127
|
-
def unpackaged?
|
128
|
-
@unpackaged
|
129
|
-
end
|
130
|
-
|
131
|
-
def oversized?
|
132
|
-
@oversized
|
133
|
-
end
|
134
|
-
|
135
|
-
def cylinder?
|
136
|
-
@cylinder
|
137
|
-
end
|
138
|
-
alias_method :tube?, :cylinder?
|
139
|
-
|
140
|
-
def gift?; @gift end
|
141
|
-
|
142
|
-
def ounces(options = {})
|
143
|
-
weight(options).in_ounces.amount
|
144
|
-
end
|
145
|
-
alias_method :oz, :ounces
|
146
|
-
|
147
|
-
def grams(options = {})
|
148
|
-
weight(options).in_grams.amount
|
149
|
-
end
|
150
|
-
alias_method :g, :grams
|
151
|
-
|
152
|
-
def pounds(options = {})
|
153
|
-
weight(options).in_pounds.amount
|
154
|
-
end
|
155
|
-
alias_method :lb, :pounds
|
156
|
-
alias_method :lbs, :pounds
|
157
|
-
|
158
|
-
def kilograms(options = {})
|
159
|
-
weight(options).in_kilograms.amount
|
160
|
-
end
|
161
|
-
alias_method :kg, :kilograms
|
162
|
-
alias_method :kgs, :kilograms
|
163
|
-
|
164
|
-
def inches(measurement = nil)
|
165
|
-
@inches ||= @dimensions.map { |m| m.in_inches.amount }
|
166
|
-
measurement.nil? ? @inches : measure(measurement, @inches)
|
167
|
-
end
|
168
|
-
alias_method :in, :inches
|
169
|
-
|
170
|
-
def centimetres(measurement = nil)
|
171
|
-
@centimetres ||= @dimensions.map { |m| m.in_centimetres.amount }
|
172
|
-
measurement.nil? ? @centimetres : measure(measurement, @centimetres)
|
173
|
-
end
|
174
|
-
alias_method :cm, :centimetres
|
175
|
-
|
176
|
-
def weight(options = {})
|
177
|
-
case options[:type]
|
178
|
-
when nil, :actual
|
179
|
-
@weight
|
180
|
-
when :volumetric, :dimensional
|
181
|
-
@volumetric_weight ||= begin
|
182
|
-
m = Mass.new((centimetres(:box_volume) / 6.0), :grams)
|
183
|
-
@weight_unit_system == :imperial ? m.in_ounces : m
|
184
|
-
end
|
185
|
-
when :billable
|
186
|
-
[weight, weight(:type => :volumetric)].max
|
187
|
-
end
|
188
|
-
end
|
189
|
-
alias_method :mass, :weight
|
190
|
-
|
191
|
-
def self.cents_from(money)
|
192
|
-
return nil if money.nil?
|
193
|
-
if money.respond_to?(:cents)
|
194
|
-
return money.cents
|
195
|
-
else
|
196
|
-
case money
|
197
|
-
when Float
|
198
|
-
(money * 100).round
|
199
|
-
when String
|
200
|
-
money =~ /\./ ? (money.to_f * 100).round : money.to_i
|
201
|
-
else
|
202
|
-
money.to_i
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
private
|
208
|
-
|
209
|
-
def attribute_from_metric_or_imperial(obj, klass, unit_system, metric_unit, imperial_unit)
|
210
|
-
if obj.is_a?(klass)
|
211
|
-
return obj
|
212
|
-
else
|
213
|
-
return klass.new(obj, (unit_system == :imperial ? imperial_unit : metric_unit))
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def measure(measurement, ary)
|
218
|
-
case measurement
|
219
|
-
when Fixnum then ary[measurement]
|
220
|
-
when :x, :max, :length, :long then ary[2]
|
221
|
-
when :y, :mid, :width, :wide then ary[1]
|
222
|
-
when :z, :min, :height, :depth, :high, :deep then ary[0]
|
223
|
-
when :girth, :around, :circumference
|
224
|
-
self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 2) : (2 * ary[0]) + (2 * ary[1])
|
225
|
-
when :volume then self.cylinder? ? (Math::PI * (ary[0] + ary[1]) / 4)**2 * ary[2] : measure(:box_volume, ary)
|
226
|
-
when :box_volume then ary[0] * ary[1] * ary[2]
|
227
|
-
end
|
228
|
-
end
|
229
|
-
|
230
|
-
def process_dimensions
|
231
|
-
@dimensions = @dimensions.map do |l|
|
232
|
-
attribute_from_metric_or_imperial(l, Length, @dimensions_unit_system, :centimetres, :inches)
|
233
|
-
end.sort
|
234
|
-
# [1,2] => [1,1,2]
|
235
|
-
# [5] => [5,5,5]
|
236
|
-
# etc..
|
237
|
-
2.downto(@dimensions.length) do |_n|
|
238
|
-
@dimensions.unshift(@dimensions[0])
|
239
|
-
end
|
240
|
-
end
|
241
|
-
end
|
242
|
-
end
|
243
|
-
end
|
@@ -1,66 +0,0 @@
|
|
1
|
-
module ActiveMerchant #:nodoc:
|
2
|
-
module Shipping #:nodoc:
|
3
|
-
class RateEstimate
|
4
|
-
attr_reader :origin # Location objects
|
5
|
-
attr_reader :destination
|
6
|
-
attr_reader :package_rates # array of hashes in the form of {:package => <Package>, :rate => 500}
|
7
|
-
attr_reader :carrier # Carrier.name ('USPS', 'FedEx', etc.)
|
8
|
-
attr_reader :service_name # name of service ("First Class Ground", etc.)
|
9
|
-
attr_reader :service_code
|
10
|
-
attr_reader :currency # 'USD', 'CAD', etc.
|
11
|
-
# http://en.wikipedia.org/wiki/ISO_4217
|
12
|
-
attr_reader :shipping_date
|
13
|
-
attr_reader :delivery_date # Usually only available for express shipments
|
14
|
-
attr_reader :delivery_range # Min and max delivery estimate in days
|
15
|
-
attr_reader :negotiated_rate
|
16
|
-
attr_reader :insurance_price
|
17
|
-
|
18
|
-
def initialize(origin, destination, carrier, service_name, options = {})
|
19
|
-
@origin, @destination, @carrier, @service_name = origin, destination, carrier, service_name
|
20
|
-
@service_code = options[:service_code]
|
21
|
-
if options[:package_rates]
|
22
|
-
@package_rates = options[:package_rates].map { |p| p.update(:rate => Package.cents_from(p[:rate])) }
|
23
|
-
else
|
24
|
-
@package_rates = Array(options[:packages]).map { |p| {:package => p} }
|
25
|
-
end
|
26
|
-
@total_price = Package.cents_from(options[:total_price])
|
27
|
-
@negotiated_rate = options[:negotiated_rate] ? Package.cents_from(options[:negotiated_rate]) : nil
|
28
|
-
@currency = ActiveMerchant::CurrencyCode.standardize(options[:currency])
|
29
|
-
@delivery_range = options[:delivery_range] ? options[:delivery_range].map { |date| date_for(date) }.compact : []
|
30
|
-
@shipping_date = date_for(options[:shipping_date])
|
31
|
-
@delivery_date = @delivery_range.last
|
32
|
-
@insurance_price = Package.cents_from(options[:insurance_price])
|
33
|
-
end
|
34
|
-
|
35
|
-
def total_price
|
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.")
|
39
|
-
end
|
40
|
-
alias_method :price, :total_price
|
41
|
-
|
42
|
-
def add(package, rate = nil)
|
43
|
-
cents = Package.cents_from(rate)
|
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?
|
45
|
-
@package_rates << {:package => package, :rate => cents}
|
46
|
-
self
|
47
|
-
end
|
48
|
-
|
49
|
-
def packages
|
50
|
-
package_rates.map { |p| p[:package] }
|
51
|
-
end
|
52
|
-
|
53
|
-
def package_count
|
54
|
-
package_rates.length
|
55
|
-
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def date_for(date)
|
60
|
-
date && DateTime.strptime(date.to_s, "%Y-%m-%d")
|
61
|
-
rescue ArgumentError
|
62
|
-
nil
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|