active_shipping 0.9.13 → 0.9.14

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.
@@ -37,7 +37,7 @@ module ActiveMerchant
37
37
  :items => [ { :sku => '', :quantity => 1 } ]
38
38
  )
39
39
  rescue ActiveMerchant::Shipping::ResponseError => e
40
- e.message != "Could not verify e-mail/password combination"
40
+ e.message != "Could not verify Username/EmailAddress and Password combination"
41
41
  end
42
42
 
43
43
  private
@@ -113,9 +113,11 @@ module ActiveMerchant
113
113
  def build_rate_estimates(response, origin, destination)
114
114
  response["rates"].collect do |quote|
115
115
  RateEstimate.new(origin, destination, carrier_for(quote["service"]), quote["service"],
116
- :service_code => quote["method"],
117
- :total_price => quote["cost"],
118
- :currency => quote["currency"]
116
+ :service_code => quote["method"],
117
+ :total_price => quote["cost"],
118
+ :currency => quote["currency"],
119
+ :delivery_range => [ timestamp_from_business_day(quote["delivery_min"]),
120
+ timestamp_from_business_day(quote["delivery_max"]) ]
119
121
  )
120
122
  end
121
123
  end
@@ -139,6 +141,10 @@ module ActiveMerchant
139
141
  rate["service"] = parse_child_text(e, "Service")
140
142
  rate["cost"] = parse_child_text(e, "Cost")
141
143
  rate["currency"] = parse_child_attribute(e, "Cost", "currency")
144
+ if delivery_estimate = e.elements["DeliveryEstimate"]
145
+ rate["delivery_min"] = parse_child_text(delivery_estimate, "Minimum").to_i
146
+ rate["delivery_max"] = parse_child_text(delivery_estimate, "Maximum").to_i
147
+ end
142
148
  response["rates"] << rate
143
149
  end
144
150
 
@@ -166,7 +172,18 @@ module ActiveMerchant
166
172
  if element = parent.elements[name]
167
173
  element.attributes[attribute]
168
174
  end
169
- end
175
+ end
176
+
177
+ def timestamp_from_business_day(days)
178
+ return unless days
179
+ date = DateTime.now
180
+ days.times do
181
+ begin
182
+ date = date + 1
183
+ end until ![0,6].include?(date.wday)
184
+ end
185
+ date
186
+ end
170
187
  end
171
188
  end
172
- end
189
+ end
@@ -10,7 +10,7 @@ module ActiveMerchant
10
10
  @@name = "UPS"
11
11
 
12
12
  TEST_URL = 'https://wwwcie.ups.com'
13
- LIVE_URL = 'https://www.ups.com'
13
+ LIVE_URL = 'https://onlinetools.ups.com'
14
14
 
15
15
  RESOURCES = {
16
16
  :rates => 'ups.app/xml/Rate',
@@ -275,12 +275,16 @@ module ActiveMerchant
275
275
 
276
276
  xml.elements.each('/*/RatedShipment') do |rated_shipment|
277
277
  service_code = rated_shipment.get_text('Service/Code').to_s
278
+ days_to_delivery = rated_shipment.get_text('GuaranteedDaysToDelivery').to_s.to_i
279
+ delivery_date = days_to_delivery >= 1 ? days_to_delivery.days.from_now.strftime("%Y-%m-%d") : nil
280
+
278
281
  rate_estimates << RateEstimate.new(origin, destination, @@name,
279
282
  service_name_for(origin, service_code),
280
283
  :total_price => rated_shipment.get_text('TotalCharges/MonetaryValue').to_s.to_f,
281
284
  :currency => rated_shipment.get_text('TotalCharges/CurrencyCode').to_s,
282
285
  :service_code => service_code,
283
- :packages => packages)
286
+ :packages => packages,
287
+ :delivery_range => [delivery_date])
284
288
  end
285
289
  end
286
290
  RateResponse.new(success, message, Hash.from_xml(response).values.first, :rates => rate_estimates, :xml => response, :request => last_request)
@@ -387,4 +391,4 @@ module ActiveMerchant
387
391
 
388
392
  end
389
393
  end
390
- end
394
+ end
@@ -14,13 +14,15 @@ module ActiveMerchant #:nodoc:
14
14
  :address3,
15
15
  :phone,
16
16
  :fax,
17
- :address_type
17
+ :address_type,
18
+ :company_name
18
19
 
19
20
  alias_method :zip, :postal_code
20
21
  alias_method :postal, :postal_code
21
22
  alias_method :state, :province
22
23
  alias_method :territory, :province
23
24
  alias_method :region, :province
25
+ alias_method :company, :company_name
24
26
 
25
27
  def initialize(options = {})
26
28
  @country = (options[:country].nil? or options[:country].is_a?(ActiveMerchant::Country)) ?
@@ -35,12 +37,9 @@ module ActiveMerchant #:nodoc:
35
37
  @address3 = options[:address3]
36
38
  @phone = options[:phone]
37
39
  @fax = options[:fax]
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
40
+ @company_name = options[:company_name] || options[:company]
41
+
42
+ self.address_type = options[:address_type]
44
43
  end
45
44
 
46
45
  def self.from(object, options={})
@@ -56,7 +55,8 @@ module ActiveMerchant #:nodoc:
56
55
  :address3 => [:address3],
57
56
  :phone => [:phone, :phone_number],
58
57
  :fax => [:fax, :fax_number],
59
- :address_type => [:address_type]
58
+ :address_type => [:address_type],
59
+ :company_name => [:company, :company_name]
60
60
  }
61
61
  attributes = {}
62
62
  hash_access = begin
@@ -84,7 +84,35 @@ module ActiveMerchant #:nodoc:
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
87
-
87
+
88
+ def address_type=(value)
89
+ return unless value.present?
90
+ raise ArgumentError.new("address_type must be one of #{ADDRESS_TYPES.join(', ')}") unless ADDRESS_TYPES.include?(value.to_s)
91
+ @address_type = value.to_s
92
+ end
93
+
94
+ def to_hash
95
+ {
96
+ :country => country_code,
97
+ :postal_code => postal_code,
98
+ :province => province,
99
+ :city => city,
100
+ :name => name,
101
+ :address1 => address1,
102
+ :address2 => address2,
103
+ :address3 => address3,
104
+ :phone => phone,
105
+ :fax => fax,
106
+ :address_type => address_type,
107
+ :company_name => company_name
108
+ }
109
+ end
110
+
111
+ def to_xml(options={})
112
+ options[:root] ||= "location"
113
+ to_hash.to_xml(options)
114
+ end
115
+
88
116
  def to_s
89
117
  prettyprint.gsub(/\n/, ' ')
90
118
  end
@@ -106,4 +134,4 @@ module ActiveMerchant #:nodoc:
106
134
  end
107
135
 
108
136
  end
109
- end
137
+ end
@@ -98,9 +98,9 @@ module ActiveMerchant #:nodoc:
98
98
  else
99
99
  case money
100
100
  when Float
101
- (money * 100).to_i
101
+ (money * 100).round
102
102
  when String
103
- money =~ /\./ ? (money.to_f * 100).to_i : money.to_i
103
+ money =~ /\./ ? (money.to_f * 100).round : money.to_i
104
104
  else
105
105
  money.to_i
106
106
  end
@@ -144,4 +144,4 @@ module ActiveMerchant #:nodoc:
144
144
 
145
145
  end
146
146
  end
147
- end
147
+ end
@@ -11,6 +11,7 @@ module ActiveMerchant #:nodoc:
11
11
  attr_reader :currency # 'USD', 'CAD', etc.
12
12
  # http://en.wikipedia.org/wiki/ISO_4217
13
13
  attr_reader :delivery_date # Usually only available for express shipments
14
+ attr_reader :delivery_range # Min and max delivery estimate in days
14
15
 
15
16
  def initialize(origin, destination, carrier, service_name, options={})
16
17
  @origin, @destination, @carrier, @service_name = origin, destination, carrier, service_name
@@ -22,9 +23,10 @@ module ActiveMerchant #:nodoc:
22
23
  end
23
24
  @total_price = Package.cents_from(options[:total_price])
24
25
  @currency = options[:currency]
25
- @delivery_date = options[:delivery_date]
26
+ @delivery_range = options[:delivery_range] ? options[:delivery_range].map { |date| date_for(date) }.compact : []
27
+ @delivery_date = @delivery_range.last
26
28
  end
27
-
29
+
28
30
  def total_price
29
31
  begin
30
32
  @total_price || @package_rates.sum {|p| p[:rate]}
@@ -48,7 +50,13 @@ module ActiveMerchant #:nodoc:
48
50
  def package_count
49
51
  package_rates.length
50
52
  end
51
-
53
+
54
+ private
55
+ def date_for(date)
56
+ date && DateTime.strptime(date.to_s, "%Y-%m-%d")
57
+ rescue ArgumentError
58
+ nil
59
+ end
52
60
  end
53
61
  end
54
62
  end
@@ -0,0 +1,48 @@
1
+ module ActiveMerchant
2
+ module Shipping
3
+ class ShipmentPacker
4
+ class OverweightItem < StandardError
5
+ end
6
+
7
+ # items - array of hashes containing quantity, grams and price.
8
+ # ex. [{:quantity => 2, :price => 1.0, :grams => 50}]
9
+ # dimensions - [5.0, 15.0, 30.0]
10
+ # maximum_weight - maximum weight in grams
11
+ # currency - ISO currency code
12
+ def self.pack(items, dimensions, maximum_weight, currency)
13
+ items = items.map(&:symbolize_keys).map { |item| [item] * item[:quantity].to_i }.flatten
14
+ packages = []
15
+ state = :package_empty
16
+
17
+ while state != :packing_finished
18
+ case state
19
+ when :package_empty
20
+ package_weight, package_value = 0, 0
21
+ state = :filling_package
22
+ when :filling_package
23
+ item = items.shift
24
+ item_weight, item_price = item[:grams].to_i, Package.cents_from(item[:price])
25
+
26
+ if item_weight > maximum_weight
27
+ raise OverweightItem, "The item with weight of #{item_weight}g is heavier than the allowable package weight of #{maximum_weight}g"
28
+ end
29
+
30
+ if (package_weight + item_weight) <= maximum_weight
31
+ package_weight += item_weight
32
+ package_value += item_price
33
+ state = :package_full if items.empty?
34
+ else
35
+ items.unshift(item)
36
+ state = :package_full
37
+ end
38
+ when :package_full
39
+ packages << ActiveMerchant::Shipping::Package.new(package_weight, dimensions, :value => package_value, :currency => currency)
40
+ state = items.any? ? :package_empty : :packing_finished
41
+ end
42
+ end
43
+
44
+ packages
45
+ end
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,3 @@
1
1
  module ActiveShipping
2
- VERSION = "0.9.13"
3
- end
2
+ VERSION = "0.9.14"
3
+ end
@@ -1,8 +1,6 @@
1
1
  $: << File.dirname(__FILE__)
2
-
3
- require 'active_support/all'
4
2
  require 'bigdecimal'
5
3
 
6
4
  require 'quantified/attribute'
7
5
  require 'quantified/mass'
8
- require 'quantified/length'
6
+ require 'quantified/length'
@@ -76,14 +76,10 @@ module Quantified
76
76
  if system
77
77
  self.systems_to_units[system.to_sym].dup
78
78
  else
79
- read_inheritable_attribute(:primitives) | self.conversions.keys
79
+ self.primitives | self.conversions.keys
80
80
  end
81
81
  end
82
82
 
83
- def self.primitives
84
- read_inheritable_attribute(:primitives).dup
85
- end
86
-
87
83
  def self.non_primitives
88
84
  self.conversions.keys
89
85
  end
@@ -103,14 +99,18 @@ module Quantified
103
99
  end
104
100
 
105
101
  protected
106
-
107
- class_inheritable_accessor :add_numeric_methods, :primitives, :conversions, :current_system, :systems_to_units, :units_to_systems
108
- self.add_numeric_methods = false
109
- self.primitives = []
110
- self.conversions = {}
111
- self.current_system = nil
112
- self.systems_to_units = {}
113
- self.units_to_systems = {}
102
+
103
+ class << self
104
+ def primitives; @primitives ||= []; end
105
+ def add_numeric_methods; @add_numeric_methods ||= false; end
106
+ def add_numeric_methods=(v); @add_numeric_methods = v; end
107
+ def conversions; @conversions ||= {}; end
108
+ def current_system; @current_system; end
109
+ def current_system=(v); @current_system = v; end
110
+ def systems_to_units; @systems_to_units ||= {}; end
111
+ def units_to_systems; @units_to_systems ||= {}; end
112
+ end
113
+
114
114
 
115
115
  def self.system(system_name, &block)
116
116
  old_system = self.current_system
@@ -205,4 +205,4 @@ module Quantified
205
205
  end
206
206
  end
207
207
  end
208
- end
208
+ end
@@ -1,2 +1,10 @@
1
1
  require 'test/unit'
2
- require File.dirname(__FILE__) + '/../lib/quantified'
2
+ begin
3
+ require 'active_support/inflector'
4
+ rescue LoadError => e
5
+ require 'rubygems'
6
+ gem "activesupport", ">= 2.3.5"
7
+ require 'active_support/inflector'
8
+ end
9
+
10
+ require File.dirname(__FILE__) + '/../lib/quantified'
@@ -4,10 +4,4 @@ $:.unshift(File.dirname(__FILE__) + '/../lib')
4
4
 
5
5
  require 'test/unit'
6
6
  require 'active_shipping'
7
-
8
- begin
9
- require 'mocha'
10
- rescue LoadError
11
- require 'rubygems'
12
- require 'mocha'
13
- end
7
+ require 'mocha'
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: 33
4
+ hash: 39
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 9
9
- - 13
10
- version: 0.9.13
9
+ - 14
10
+ version: 0.9.14
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-04-27 00:00:00 -04:00
21
+ date: 2012-05-02 00:00:00 -04:00
22
22
  default_executable:
23
23
  dependencies:
24
24
  - !ruby/object:Gem::Dependency
@@ -38,7 +38,7 @@ dependencies:
38
38
  type: :runtime
39
39
  version_requirements: *id001
40
40
  - !ruby/object:Gem::Dependency
41
- name: mocha
41
+ name: i18n
42
42
  prerelease: false
43
43
  requirement: &id002 !ruby/object:Gem::Requirement
44
44
  none: false
@@ -49,8 +49,82 @@ dependencies:
49
49
  segments:
50
50
  - 0
51
51
  version: "0"
52
- type: :development
52
+ type: :runtime
53
53
  version_requirements: *id002
54
+ - !ruby/object:Gem::Dependency
55
+ name: active_utils
56
+ prerelease: false
57
+ requirement: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 21
63
+ segments:
64
+ - 1
65
+ - 0
66
+ - 1
67
+ version: 1.0.1
68
+ type: :runtime
69
+ version_requirements: *id003
70
+ - !ruby/object:Gem::Dependency
71
+ name: builder
72
+ prerelease: false
73
+ requirement: &id004 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ hash: 3
79
+ segments:
80
+ - 0
81
+ version: "0"
82
+ type: :runtime
83
+ version_requirements: *id004
84
+ - !ruby/object:Gem::Dependency
85
+ name: json
86
+ prerelease: false
87
+ requirement: &id005 !ruby/object:Gem::Requirement
88
+ none: false
89
+ requirements:
90
+ - - ">="
91
+ - !ruby/object:Gem::Version
92
+ hash: 1
93
+ segments:
94
+ - 1
95
+ - 5
96
+ - 1
97
+ version: 1.5.1
98
+ type: :runtime
99
+ version_requirements: *id005
100
+ - !ruby/object:Gem::Dependency
101
+ name: rake
102
+ prerelease: false
103
+ requirement: &id006 !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ hash: 3
109
+ segments:
110
+ - 0
111
+ version: "0"
112
+ type: :development
113
+ version_requirements: *id006
114
+ - !ruby/object:Gem::Dependency
115
+ name: mocha
116
+ prerelease: false
117
+ requirement: &id007 !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ hash: 3
123
+ segments:
124
+ - 0
125
+ version: "0"
126
+ type: :development
127
+ version_requirements: *id007
54
128
  description: Get rates and tracking info from various shipping carriers.
55
129
  email:
56
130
  - james@shopify.com
@@ -61,15 +135,6 @@ extensions: []
61
135
  extra_rdoc_files: []
62
136
 
63
137
  files:
64
- - lib/active_merchant/common/connection.rb
65
- - lib/active_merchant/common/country.rb
66
- - lib/active_merchant/common/error.rb
67
- - lib/active_merchant/common/post_data.rb
68
- - lib/active_merchant/common/posts_data.rb
69
- - lib/active_merchant/common/requires_parameters.rb
70
- - lib/active_merchant/common/utils.rb
71
- - lib/active_merchant/common/validateable.rb
72
- - lib/active_merchant/common.rb
73
138
  - lib/active_shipping/shipping/base.rb
74
139
  - lib/active_shipping/shipping/carrier.rb
75
140
  - lib/active_shipping/shipping/carriers/bogus_carrier.rb
@@ -87,10 +152,10 @@ files:
87
152
  - lib/active_shipping/shipping/rate_response.rb
88
153
  - lib/active_shipping/shipping/response.rb
89
154
  - lib/active_shipping/shipping/shipment_event.rb
155
+ - lib/active_shipping/shipping/shipment_packer.rb
90
156
  - lib/active_shipping/shipping/tracking_response.rb
91
157
  - lib/active_shipping/version.rb
92
158
  - lib/active_shipping.rb
93
- - lib/certs/cacert.pem
94
159
  - lib/certs/eParcel.dtd
95
160
  - lib/vendor/quantified/init.rb
96
161
  - lib/vendor/quantified/lib/quantified/attribute.rb