shipping-calc 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +13 -0
- data/Manifest.txt +2 -1
- data/README.markdown +88 -0
- data/examples/fq_example.rb +1 -0
- data/lib/shipping_calc.rb +1 -1
- data/lib/shipping_calc/freight_quote.rb +112 -33
- data/test/freight_quote/freight_quote_test.rb +48 -1
- metadata +5 -4
data/History.txt
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
=== 0.1.3 / 2008-03-17
|
2
|
+
|
3
|
+
* FreightQuote support improved
|
4
|
+
|
5
|
+
Now you can query FQ's API with information for:
|
6
|
+
|
7
|
+
* Liftgates
|
8
|
+
* Loading docks
|
9
|
+
* Different types of shipping and receiving locations
|
10
|
+
* Inside deliveries
|
11
|
+
|
12
|
+
* Minor bugfixes
|
13
|
+
|
1
14
|
=== 0.1.2
|
2
15
|
|
3
16
|
* Freight quote now supports FQ's classes. With this the shipment's
|
data/Manifest.txt
CHANGED
data/README.markdown
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
ShippingCalc
|
2
|
+
============
|
3
|
+
|
4
|
+
* http://github.com/febuiles/shipping_calc/
|
5
|
+
* mailto:federico.builes@gmail.com
|
6
|
+
|
7
|
+
DESCRIPTION:
|
8
|
+
-----------
|
9
|
+
|
10
|
+
Shipping Calculator written in Ruby to get quick quotes from the major
|
11
|
+
carriers (UPS, DHL, FedEX, FreightQuote).
|
12
|
+
|
13
|
+
FEATURES/PROBLEMS:
|
14
|
+
-----------------
|
15
|
+
- Current version only supports DHL and FreightQuote
|
16
|
+
|
17
|
+
SYNOPSIS:
|
18
|
+
--------
|
19
|
+
You can find an example of each carrier's API under the /examples directory.
|
20
|
+
|
21
|
+
A simple DHL example:
|
22
|
+
|
23
|
+
require 'rubygems'
|
24
|
+
require 'shipping_calc'
|
25
|
+
|
26
|
+
include ShippingCalc
|
27
|
+
|
28
|
+
opts = {
|
29
|
+
:api_user => "your_user",
|
30
|
+
:api_password => "your_pwd",
|
31
|
+
:shipping_key => "your_key",
|
32
|
+
:account_num => "your_accnt",
|
33
|
+
:date => Time.now, # or something...
|
34
|
+
:service_code => "E", # check the docs to find out what this means
|
35
|
+
:shipment_code => "P", # check the docs to find out what this means
|
36
|
+
:weight => 34, # weight in lbs
|
37
|
+
:to_zip => 10001,
|
38
|
+
:to_state => "NY"
|
39
|
+
}
|
40
|
+
|
41
|
+
d = DHL.new
|
42
|
+
a = d.quote(opts)
|
43
|
+
p a
|
44
|
+
|
45
|
+
REQUIREMENTS:
|
46
|
+
---------------
|
47
|
+
* You must obtain all the DHL ShipIt data (user, password, key and account) from http://www.dhl-usa.com/TechTools/detail/TTDetail.asp?nav=TechnologyTools/Shipping/OwnSoln
|
48
|
+
* REXML
|
49
|
+
|
50
|
+
INSTALL:
|
51
|
+
-------
|
52
|
+
* sudo gem install shipping-calc
|
53
|
+
|
54
|
+
TEST:
|
55
|
+
-----
|
56
|
+
To run the DHL tests you'll need to have a .dhl_info.yml file in your home directory with your auth info like this:
|
57
|
+
~/.dhl_info.yml
|
58
|
+
|
59
|
+
api_user: your_user
|
60
|
+
api_password: your_password
|
61
|
+
shipping_key: your_key
|
62
|
+
account_num: your_accnt_num
|
63
|
+
|
64
|
+
This is necessary only for the tests and it'll be ignored for the actual
|
65
|
+
usage of the the library.
|
66
|
+
|
67
|
+
LICENSE:
|
68
|
+
-------
|
69
|
+
Copyright (c) 2008 Federico Builes
|
70
|
+
|
71
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
72
|
+
a copy of this software and associated documentation files (the
|
73
|
+
'Software'), to deal in the Software without restriction, including
|
74
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
75
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
76
|
+
permit persons to whom the Software is furnished to do so, subject to
|
77
|
+
the following conditions:
|
78
|
+
|
79
|
+
The above copyright notice and this permission notice shall be
|
80
|
+
included in all copies or substantial portions of the Software.
|
81
|
+
|
82
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
83
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
84
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
85
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
86
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
87
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
88
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/examples/fq_example.rb
CHANGED
data/lib/shipping_calc.rb
CHANGED
@@ -32,7 +32,7 @@ require 'shipping_calc/freight_quote'
|
|
32
32
|
module ShippingCalc
|
33
33
|
class ShippingCalcError < StandardError
|
34
34
|
end
|
35
|
-
VERSION = "0.1.
|
35
|
+
VERSION = "0.1.3"
|
36
36
|
|
37
37
|
US_STATES = ['AK', 'AL', 'AR', 'AZ', 'CA', 'CO', 'CT', 'DC',
|
38
38
|
'DE', 'FL', 'GA', 'HI', 'IA', 'ID', 'IL', 'IN',
|
@@ -49,28 +49,19 @@ module ShippingCalc
|
|
49
49
|
# :*from_zip*:: Sender's zip code.
|
50
50
|
# :*to_zip*:: Recipient's zip code.
|
51
51
|
# :*weight*:: Total weight of the order in lbs.
|
52
|
-
# :*dimensions*::
|
53
|
-
# :*description*::
|
54
|
-
# :*class*::
|
55
|
-
#
|
56
|
-
#
|
52
|
+
# :*dimensions*:: _Optional_ - Length, width and height of the shipment, described as a string: "[Length]x[Width]x[Height]" (e.g. "23x32x15").
|
53
|
+
# :*description*:: _Optional_ - Description of the stuff that's being shipped. Defaults to "NODESC".
|
54
|
+
# :*class*:: _Optional_ - Freightquote's shipping class. Defaults to nil.
|
55
|
+
# :*from_conditions*:: _Optional_ - String that indicates if the sending location is a residence ("RES"), a business with a forklift or dock ("BIZ_WITH") or a business without a forklift or dock ("BIZ_WITHOUT"). Defaults to "RES".
|
56
|
+
# :*to_conditions*:: _Optional_ - String that indicates if the receiving location is a residence ("RES"), a business with a forklift or dock ("BIZ_WITH") or a business without a forklift or dock ("BIZ_WITHOUT"). Defaults to "RES".
|
57
|
+
# :*liftgate*:: _Optional_ - A boolean indicating if a liftgate's required at the receiving location (API page 10). Defaults to false.
|
58
|
+
# :*inside_delivery*:: _Optional_ - A boolean indicating if inside delivery's required at the receiving location (API page 10). Defaults to false.
|
59
|
+
# *Note* Both dimensions or class are optional but one of them has to be there. If both parameters are filled then priority will be given to class.
|
57
60
|
def quote(params)
|
58
|
-
|
59
|
-
:weight]
|
60
|
-
|
61
|
-
raise ShippingCalcError.new("Nil parameters for FreightQuote quote.") if params.nil?
|
62
|
-
raise ShippingCalcError.new("Invalid shipment dimensions") unless
|
63
|
-
((params[:dimensions] =~ /\d+x\d+x\d+/) || (!params[:class].nil?))
|
64
|
-
|
65
|
-
required_fields.each do |f|
|
66
|
-
if params.has_key?(f) && !params[f].nil? # Cover all the mandatory fields
|
67
|
-
next
|
68
|
-
else
|
69
|
-
raise ShippingCalcError.new("Required field \"#{f}\" not found.")
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
61
|
+
validate params
|
73
62
|
params[:description] ||= "NODESC"
|
63
|
+
params[:from_conditions] ||= "RES"
|
64
|
+
params[:to_conditions] ||= "RES"
|
74
65
|
|
75
66
|
@xml = xml = Document.new
|
76
67
|
xml << XMLDecl.new("1.0' encoding='UTF-8")
|
@@ -89,19 +80,9 @@ module ShippingCalc
|
|
89
80
|
# We're only getting a quote, let's pretend the shipper's paying.
|
90
81
|
root.attributes["BILLTO"] = "SHIPPER"
|
91
82
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
origin << orig_zip
|
97
|
-
root << origin
|
98
|
-
|
99
|
-
dest = Element.new("DESTINATION")
|
100
|
-
dest_zip = Element.new("ZIPCODE")
|
101
|
-
dest_zip.text = params[:from_zip]
|
102
|
-
|
103
|
-
dest << dest_zip
|
104
|
-
root << dest
|
83
|
+
root << destination(params[:from_zip], params[:from_conditions],
|
84
|
+
params[:liftgate], params[:inside_delivery])
|
85
|
+
root << origin(params[:from_zip], params[:from_conditions])
|
105
86
|
|
106
87
|
root << shipment_item(params[:weight], params[:dimensions],
|
107
88
|
params[:description], params[:class])
|
@@ -131,6 +112,67 @@ module ShippingCalc
|
|
131
112
|
quotes
|
132
113
|
end
|
133
114
|
|
115
|
+
# TODO Merge this method with destination's.
|
116
|
+
def origin (zip, conditions)
|
117
|
+
origin = Element.new("ORIGIN")
|
118
|
+
orig_zip = Element.new("ZIPCODE")
|
119
|
+
orig_zip.text = zip
|
120
|
+
origin << orig_zip
|
121
|
+
|
122
|
+
case conditions
|
123
|
+
when "RES"
|
124
|
+
residence = Element.new("RESIDENCE")
|
125
|
+
residence.text = "TRUE"
|
126
|
+
origin << residence
|
127
|
+
when "BIZ_WITH"
|
128
|
+
dock = Element.new("LOADINGDOCK")
|
129
|
+
dock.text = "TRUE"
|
130
|
+
origin << dock
|
131
|
+
when "BIZ_WITHOUT"
|
132
|
+
dock = Element.new("LOADINGDOCK")
|
133
|
+
dock.text = "FALSE"
|
134
|
+
origin << dock
|
135
|
+
end
|
136
|
+
|
137
|
+
origin
|
138
|
+
end
|
139
|
+
|
140
|
+
def destination(zip, conditions, liftgate, inside)
|
141
|
+
dest = Element.new("DESTINATION")
|
142
|
+
dest_zip = Element.new("ZIPCODE")
|
143
|
+
dest_zip.text = zip
|
144
|
+
dest << dest_zip
|
145
|
+
|
146
|
+
case conditions
|
147
|
+
when "RES"
|
148
|
+
residence = Element.new("RESIDENCE")
|
149
|
+
residence.text = "TRUE"
|
150
|
+
dest << residence
|
151
|
+
when "BIZ_WITH"
|
152
|
+
dock = Element.new("LOADINGDOCK")
|
153
|
+
dock.text = "TRUE"
|
154
|
+
dest << dock
|
155
|
+
when "BIZ_WITHOUT"
|
156
|
+
dock = Element.new("LOADINGDOCK")
|
157
|
+
dock.text = "FALSE"
|
158
|
+
dest << dock
|
159
|
+
end
|
160
|
+
|
161
|
+
if !liftgate.nil? && liftgate
|
162
|
+
liftgate = Element.new("LIFTGATEDELIVERY")
|
163
|
+
liftgate.text = "TRUE"
|
164
|
+
dest << liftgate
|
165
|
+
end
|
166
|
+
|
167
|
+
if !inside.nil? && inside
|
168
|
+
inside = Element.new("INSIDEDELIVERY")
|
169
|
+
inside.text = "TRUE"
|
170
|
+
dest << inside
|
171
|
+
end
|
172
|
+
|
173
|
+
dest
|
174
|
+
end
|
175
|
+
|
134
176
|
# Create a shipment item based on the weight, dimension and description.
|
135
177
|
def shipment_item(weight_, dim, desc, s_class = nil)
|
136
178
|
raise ShippingCalcError.new("Invalid weight") if !(weight_ > 0)
|
@@ -169,5 +211,42 @@ module ShippingCalc
|
|
169
211
|
|
170
212
|
shipment
|
171
213
|
end
|
214
|
+
|
215
|
+
def validate(params)
|
216
|
+
required_fields = [:api_email, :api_password, :to_zip, :from_zip,
|
217
|
+
:weight]
|
218
|
+
|
219
|
+
raise ShippingCalcError.new("Nil parameters for FreightQuote quote.") if params.nil?
|
220
|
+
raise ShippingCalcError.new("Invalid shipment dimensions") unless
|
221
|
+
((params[:dimensions] =~ /\d+x\d+x\d+/) || (!params[:class].nil?))
|
222
|
+
|
223
|
+
raise ShippingCalcError.new("Invalid receiving conditions") unless
|
224
|
+
valid_conditions(params[:to_conditions])
|
225
|
+
raise ShippingCalcError.new("Invalid shipping conditions") unless
|
226
|
+
valid_conditions(params[:from_conditions])
|
227
|
+
|
228
|
+
if !(params[:liftgate].nil?)
|
229
|
+
raise ShippingCalcError.new("Invalid liftgate option, only boolean values.") unless
|
230
|
+
(params[:liftgate].class == TrueClass || params[:liftgate].class == FalseClass)
|
231
|
+
end
|
232
|
+
|
233
|
+
if !(params[:inside_delivery].nil?)
|
234
|
+
raise ShippingCalcError.new("Invalid inside delivery option, only boolean values.") unless
|
235
|
+
(params[:inside_delivery].class == TrueClass || params[:inside_delivery].class == FalseClass)
|
236
|
+
end
|
237
|
+
|
238
|
+
required_fields.each do |f|
|
239
|
+
if params.has_key?(f) && !params[f].nil? # Cover all the mandatory fields
|
240
|
+
next
|
241
|
+
else
|
242
|
+
raise ShippingCalcError.new("Required field \"#{f}\" not found.")
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
end
|
247
|
+
|
248
|
+
def valid_conditions(cond)
|
249
|
+
cond.nil? || ((cond =~ /^(BIZ_WITH|RES|BIZ_WITHOUT)$/) == 0)
|
250
|
+
end
|
172
251
|
end
|
173
252
|
end
|
@@ -14,7 +14,6 @@ class FreightQuoteTest < Test::Unit::TestCase
|
|
14
14
|
:weight => 150,
|
15
15
|
:dimensions => "12x23x12"
|
16
16
|
}
|
17
|
-
|
18
17
|
end
|
19
18
|
|
20
19
|
def test_invalid_params
|
@@ -32,6 +31,54 @@ class FreightQuoteTest < Test::Unit::TestCase
|
|
32
31
|
assert q.size > 0
|
33
32
|
end
|
34
33
|
|
34
|
+
def test_quote_with_conditions
|
35
|
+
@opts[:to_conditions] = "BIZ_WITH"
|
36
|
+
@opts[:from_conditions] = "BIZ_WITHOUT"
|
37
|
+
f = FreightQuote.new
|
38
|
+
q = f.quote(@opts)
|
39
|
+
assert q.size > 0
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_invalid_conditions
|
43
|
+
@opts[:to_conditions] = "BIZ_WITH"
|
44
|
+
@opts[:from_conditions] = "something weird goes here"
|
45
|
+
f = FreightQuote.new
|
46
|
+
assert_raise ShippingCalcError do
|
47
|
+
f.quote(@opts)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_with_liftgate_and_inside_delivery
|
52
|
+
@opts[:inside_delivery] = false
|
53
|
+
@opts[:liftgate] = true
|
54
|
+
f = FreightQuote.new
|
55
|
+
q = f.quote(@opts)
|
56
|
+
assert q.size > 0
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_invalid_liftgate
|
60
|
+
@opts[:liftgate] = "something"
|
61
|
+
f = FreightQuote.new
|
62
|
+
assert_raise ShippingCalcError do
|
63
|
+
f.quote(@opts)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_invalid_inside_delivery
|
68
|
+
@opts[:inside_delivery] = 3
|
69
|
+
f = FreightQuote.new
|
70
|
+
assert_raise ShippingCalcError do
|
71
|
+
f.quote(@opts)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_quote_with_class_and_dimensions
|
76
|
+
@opts[:class] = 92.5
|
77
|
+
f = FreightQuote.new
|
78
|
+
q = f.quote(@opts)
|
79
|
+
assert q.size > 0
|
80
|
+
end
|
81
|
+
|
35
82
|
def test_invalid_dimension
|
36
83
|
@opts[:dimensions] = "12x3"
|
37
84
|
f = FreightQuote.new
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: shipping-calc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Federico Builes
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-03-
|
12
|
+
date: 2008-03-17 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -29,13 +29,14 @@ executables: []
|
|
29
29
|
extensions: []
|
30
30
|
|
31
31
|
extra_rdoc_files:
|
32
|
+
- README.txt
|
32
33
|
- History.txt
|
33
34
|
- Manifest.txt
|
34
|
-
- README.txt
|
35
35
|
files:
|
36
|
+
- README.txt
|
36
37
|
- History.txt
|
37
38
|
- Manifest.txt
|
38
|
-
- README.
|
39
|
+
- README.markdown
|
39
40
|
- Rakefile
|
40
41
|
- lib/shipping_calc.rb
|
41
42
|
- lib/shipping_calc/dhl.rb
|