suitcase 1.4.1 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/examples/redis_adapter.rb +4 -4
- data/lib/suitcase.rb +21 -21
- data/lib/suitcase/car_rental.rb +8 -2
- data/lib/suitcase/codes.rb +5 -0
- data/lib/suitcase/configuration.rb +12 -59
- data/lib/suitcase/hotel/amenity.rb +38 -35
- data/lib/suitcase/hotel/cache.rb +52 -0
- data/lib/suitcase/hotel/helpers.rb +115 -111
- data/lib/suitcase/hotel/hotel.rb +1 -1
- data/lib/suitcase/hotel/location.rb +25 -5
- data/lib/suitcase/hotel/nightly_rate.rb +6 -3
- data/lib/suitcase/hotel/payment_option.rb +33 -22
- data/lib/suitcase/hotel/reservation.rb +9 -4
- data/lib/suitcase/hotel/room.rb +84 -67
- data/lib/suitcase/hotel/session.rb +7 -0
- data/lib/suitcase/version.rb +1 -1
- data/test/hotels/amenity_test.rb +5 -5
- data/test/hotels/caching_test.rb +4 -4
- data/test/hotels/helpers_test.rb +3 -3
- data/test/hotels/payment_option_test.rb +3 -3
- data/test/hotels/reservation_test.rb +3 -3
- data/test/hotels/room_test.rb +3 -3
- data/test/hotels/session_test.rb +3 -3
- data/test/keys.rb +4 -4
- metadata +4 -7
- data/.rbenv-gemsets +0 -2
- data/.rspec +0 -1
- data/lib/suitcase/airport_codes.rb +0 -3
- data/lib/suitcase/cache.rb +0 -49
- data/lib/suitcase/country_codes.rb +0 -3
- data/lib/suitcase/session.rb +0 -5
data/lib/suitcase/hotel/hotel.rb
CHANGED
@@ -52,7 +52,7 @@
|
|
52
52
|
# Public: A Class representing a single Hotel. It provides methods for
|
53
53
|
# all Hotel EAN-related queries in the gem.
|
54
54
|
class Hotel
|
55
|
-
extend
|
55
|
+
extend Helpers
|
56
56
|
|
57
57
|
# Public: The Amenities that can be passed in to searches, and are returned
|
58
58
|
# from many queries.
|
@@ -1,9 +1,8 @@
|
|
1
1
|
module Suitcase
|
2
2
|
class Hotel
|
3
3
|
class Location
|
4
|
-
|
5
|
-
|
6
|
-
attr_accessor :destination_id, :type, :active, :city, :province, :country, :country_code
|
4
|
+
attr_accessor :destination_id, :type, :active, :city, :province,
|
5
|
+
:country, :country_code
|
7
6
|
|
8
7
|
def initialize(info)
|
9
8
|
info.each do |k, v|
|
@@ -12,12 +11,22 @@ module Suitcase
|
|
12
11
|
end
|
13
12
|
|
14
13
|
class << self
|
14
|
+
include Helpers
|
15
|
+
|
16
|
+
# Public: Find a Location.
|
17
|
+
#
|
18
|
+
# info - A Hash of information to search by, including city & address.
|
19
|
+
#
|
20
|
+
# Returns an Array of Location's.
|
15
21
|
def find(info)
|
16
22
|
params = {}
|
17
23
|
[:city, :address].each do |dup|
|
18
24
|
params[dup] = info[dup] if info[dup]
|
19
25
|
end
|
20
|
-
|
26
|
+
if info[:destination_string]
|
27
|
+
params[:destinationString] = info[:destination_string]
|
28
|
+
end
|
29
|
+
|
21
30
|
if Configuration.cache? and Configuration.cache.cached?(:geoSearch, params)
|
22
31
|
raw = Configuration.cache.get_query(:geoSearch, params)
|
23
32
|
else
|
@@ -25,12 +34,22 @@ module Suitcase
|
|
25
34
|
raw = parse_response(url)
|
26
35
|
handle_errors(raw)
|
27
36
|
end
|
37
|
+
|
28
38
|
parse(raw)
|
29
39
|
end
|
30
40
|
|
31
41
|
def parse(raw)
|
32
42
|
[raw["LocationInfoResponse"]["LocationInfos"]["LocationInfo"]].flatten.map do |raw|
|
33
|
-
Location.new(
|
43
|
+
Location.new(
|
44
|
+
province: raw["stateProvinceCode"],
|
45
|
+
destination_id: raw["destinationId"],
|
46
|
+
type: raw["type"],
|
47
|
+
city: raw["city"],
|
48
|
+
active: raw["active"],
|
49
|
+
code: raw["code"],
|
50
|
+
country: raw["country"],
|
51
|
+
country_code: raw["countryCode"]
|
52
|
+
)
|
34
53
|
end
|
35
54
|
end
|
36
55
|
|
@@ -39,6 +58,7 @@ module Suitcase
|
|
39
58
|
if info[key] && info[key]["EanWsError"]
|
40
59
|
message = info[key]["EanWsError"]["presentationMessage"]
|
41
60
|
end
|
61
|
+
|
42
62
|
raise EANException.new(message) if message
|
43
63
|
end
|
44
64
|
end
|
@@ -2,10 +2,13 @@ module Suitcase
|
|
2
2
|
class NightlyRate
|
3
3
|
attr_accessor :promo, :rate, :base_rate
|
4
4
|
|
5
|
+
# Internal: Create a NightlyRate from the API response.
|
6
|
+
#
|
7
|
+
# info - A Hash from the API response containing nightly rate information.
|
5
8
|
def initialize(info)
|
6
|
-
promo = info["@promo"]
|
7
|
-
|
8
|
-
|
9
|
+
@promo = info["@promo"]
|
10
|
+
@rate = info["@rate"]
|
11
|
+
@base_rate = info["@baseRate"]
|
9
12
|
end
|
10
13
|
end
|
11
14
|
end
|
@@ -1,30 +1,41 @@
|
|
1
1
|
module Suitcase
|
2
|
-
class
|
3
|
-
|
4
|
-
|
2
|
+
class Hotel
|
3
|
+
class PaymentOption
|
4
|
+
attr_accessor :code, :name
|
5
5
|
|
6
|
-
|
7
|
-
@code = code
|
8
|
-
@name = name
|
9
|
-
end
|
6
|
+
extend Helpers
|
10
7
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
Configuration.cache.save_query(:paymentInfo, params, types_raw) if Configuration.cache?
|
8
|
+
# Internal: Create a PaymentOption.
|
9
|
+
#
|
10
|
+
# code - The String code from the API response (e.g. "VI").
|
11
|
+
# name - The String name of the PaymentOption.
|
12
|
+
def initialize(code, name)
|
13
|
+
@code, @name = code, name
|
18
14
|
end
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
15
|
+
|
16
|
+
# Public: Find PaymentOptions for a specific currency.
|
17
|
+
#
|
18
|
+
# info - A Hash of information with one key: :currency_code.
|
19
|
+
#
|
20
|
+
# Returns an Array of PaymentOption's.
|
21
|
+
def self.find(info)
|
22
|
+
params = { "currencyCode" => info[:currency_code] }
|
23
|
+
|
24
|
+
if Configuration.cache? and Configuration.cache.cached?(:paymentInfo, params)
|
25
|
+
types_raw = Configuration.cache.get_query(:paymentInfo, params)
|
26
|
+
else
|
27
|
+
types_raw = parse_response(url(:method => "paymentInfo", :params => params, :session => info[:session]))
|
28
|
+
Configuration.cache.save_query(:paymentInfo, params, types_raw) if Configuration.cache?
|
24
29
|
end
|
30
|
+
update_session(types_raw, info[:session])
|
31
|
+
|
32
|
+
types_raw["HotelPaymentResponse"].map do |raw|
|
33
|
+
types = raw[0] != "PaymentType" ? [] : raw[1]
|
34
|
+
types.map do |type|
|
35
|
+
PaymentOption.new(type["code"], type["name"])
|
36
|
+
end
|
37
|
+
end.flatten
|
25
38
|
end
|
26
|
-
update_session(types_raw, info[:session])
|
27
|
-
options
|
28
39
|
end
|
29
40
|
end
|
30
|
-
end
|
41
|
+
end
|
@@ -1,9 +1,14 @@
|
|
1
1
|
module Suitcase
|
2
|
-
class
|
3
|
-
|
2
|
+
class Hotel
|
3
|
+
class Reservation
|
4
|
+
attr_accessor :itinerary_id, :confirmation_numbers
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
# Internal: Create a new Reservation from the API response.
|
7
|
+
#
|
8
|
+
# info - The Hash of information returned from the API.
|
9
|
+
def initialize(info)
|
10
|
+
@itinerary_id, @confirmation_numbers = info[:itinerary_id], [info[:confirmation_numbers]].flatten
|
11
|
+
end
|
7
12
|
end
|
8
13
|
end
|
9
14
|
end
|
data/lib/suitcase/hotel/room.rb
CHANGED
@@ -1,77 +1,94 @@
|
|
1
1
|
module Suitcase
|
2
|
-
class
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
class Hotel
|
3
|
+
class Room
|
4
|
+
attr_accessor :rate_key, :hotel_id, :supplier_type, :rate_code,
|
5
|
+
:room_type_code, :supplier_type, :tax_rate, :non_refundable,
|
6
|
+
:occupancy, :quoted_occupancy, :min_guest_age, :total,
|
7
|
+
:surcharge_total, :nightly_rate_total, :average_base_rate,
|
8
|
+
:average_rate, :max_nightly_rate, :currency_code, :value_adds,
|
9
|
+
:room_type_description, :price_breakdown, :total_price,
|
10
|
+
:average_nightly_rate, :promo, :arrival, :departure, :rooms,
|
11
|
+
:bed_types
|
11
12
|
|
12
|
-
|
13
|
+
extend Helpers
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
# Internal: Create a new Room from within a Room search query.
|
16
|
+
#
|
17
|
+
# info - A Hash of parsed information from the API, with any of the keys
|
18
|
+
# from the attr_accessor's list.
|
19
|
+
def initialize(info)
|
20
|
+
info.each do |k, v|
|
21
|
+
instance_variable_set("@" + k.to_s, v)
|
22
|
+
end
|
17
23
|
end
|
18
|
-
end
|
19
24
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
params["
|
53
|
-
params["
|
54
|
-
params["
|
55
|
-
params["
|
56
|
-
|
25
|
+
# Public: Reserve a room.
|
26
|
+
#
|
27
|
+
# info - A Hash of the information described on the Suitcase
|
28
|
+
# [wiki](http://github.com/thoughtfusion/suitcase/wiki/User-flow).
|
29
|
+
#
|
30
|
+
# Returns a Suitcase::Reservation.
|
31
|
+
def reserve!(info)
|
32
|
+
params = {}
|
33
|
+
params["hotelId"] = @hotel_id
|
34
|
+
params["arrivalDate"] = @arrival
|
35
|
+
params["departureDate"] = @departure
|
36
|
+
params["supplierType"] = @supplier_type
|
37
|
+
params["rateKey"] = @rate_key
|
38
|
+
params["rateTypeCode"] = @room_type_code
|
39
|
+
params["rateCode"] = @rate_code
|
40
|
+
params["roomTypeCode"] = @room_type_code
|
41
|
+
params["chargeableRate"] = chargeable_rate
|
42
|
+
params["email"] = info[:email]
|
43
|
+
params["firstName"] = info[:first_name]
|
44
|
+
params["lastName"] = info[:last_name]
|
45
|
+
params["homePhone"] = info[:home_phone]
|
46
|
+
params["workPhone"] = info[:work_phone] if info[:work_phone]
|
47
|
+
params["extension"] = info[:work_phone_extension] if info[:work_phone_extension]
|
48
|
+
params["faxPhone"] = info[:fax_phone] if info[:fax_phone]
|
49
|
+
params["companyName"] = info[:company_name] if info[:company_name]
|
50
|
+
params["emailIntineraryList"] = info[:additional_emails].join(",") if info[:additional_emails]
|
51
|
+
params["creditCardType"] = info[:payment_option].code
|
52
|
+
params["creditCardNumber"] = info[:credit_card_number]
|
53
|
+
params["creditCardIdentifier"] = info[:credit_card_verification_code]
|
54
|
+
expiration_date = Date._parse(info[:credit_card_expiration_date])
|
55
|
+
params["creditCardExpirationMonth"] = (expiration_date[:mon].to_s.length == 1 ? "0" + expiration_date[:mon].to_s : expiration_date[:mon].to_s)
|
56
|
+
params["creditCardExpirationYear"] = expiration_date[:year].to_s
|
57
|
+
params["address1"] = info[:address1]
|
58
|
+
params["address2"] = info[:address2] if info[:address2]
|
59
|
+
params["address3"] = info[:address3] if info[:address3]
|
60
|
+
params["city"] = info[:city]
|
61
|
+
@rooms.each_with_index do |room, index|
|
62
|
+
index += 1
|
63
|
+
params["room#{index}"] = "#{room[:adults].to_s},#{room[:children_ages].join(",")}"
|
64
|
+
params["room#{index}FirstName"] = room[:first_name] || params["firstName"] # defaults to the billing
|
65
|
+
params["room#{index}LastName"] = room[:last_name] || params["lastName"] # person's name
|
66
|
+
params["room#{index}BedTypeId"] = room[:bed_type].id
|
67
|
+
params["room#{index}SmokingPreference"] = room[:smoking_preference] or "E"
|
68
|
+
end
|
69
|
+
params["stateProvinceCode"] = info[:province]
|
70
|
+
params["countryCode"] = info[:country]
|
71
|
+
params["postalCode"] = info[:postal_code]
|
72
|
+
|
73
|
+
uri = Room.url :method => "res", :params => params, :include_key => true, :include_cid => true, :secure => true
|
74
|
+
session = Patron::Session.new
|
75
|
+
session.timeout = 30000
|
76
|
+
session.base_url = "https://" + uri.host
|
77
|
+
res = session.post uri.request_uri, {}
|
78
|
+
parsed = JSON.parse res.body
|
79
|
+
|
80
|
+
Reservation.new(itinerary_id: parsed["HotelRoomReservationResponse"]["itineraryId"], confirmation_numbers: parsed["HotelRoomReservationResponse"]["confirmationNumbers"])
|
57
81
|
end
|
58
|
-
params["stateProvinceCode"] = info[:province]
|
59
|
-
params["countryCode"] = info[:country]
|
60
|
-
params["postalCode"] = info[:postal_code]
|
61
|
-
uri = Room.url :method => "res", :params => params, :include_key => true, :include_cid => true, :secure => true
|
62
|
-
session = Patron::Session.new
|
63
|
-
session.timeout = 30000
|
64
|
-
session.base_url = "https://" + uri.host
|
65
|
-
res = session.post uri.request_uri, {}
|
66
|
-
parsed = JSON.parse res.body
|
67
|
-
Reservation.new(itinerary_id: parsed["HotelRoomReservationResponse"]["itineraryId"], confirmation_numbers: parsed["HotelRoomReservationResponse"]["confirmationNumbers"])
|
68
|
-
end
|
69
82
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
@
|
83
|
+
# Public: The chargeable rate for the Hotel room.
|
84
|
+
#
|
85
|
+
# Returns the chargeable rate for the Room.
|
86
|
+
def chargeable_rate
|
87
|
+
if @supplier_type == "E"
|
88
|
+
@total_price
|
89
|
+
else
|
90
|
+
@max_nightly_rate
|
91
|
+
end
|
75
92
|
end
|
76
93
|
end
|
77
94
|
end
|
data/lib/suitcase/version.rb
CHANGED
data/test/hotels/amenity_test.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
require "minitest_helper"
|
2
2
|
|
3
|
-
describe Suitcase::Amenity do
|
3
|
+
describe Suitcase::Hotel::Amenity do
|
4
4
|
describe ".parse_mask" do
|
5
5
|
describe "when provided bitmask is not nil or 0" do
|
6
6
|
it "returns an Array of Symbols representing given Amenities" do
|
7
|
-
Suitcase::Amenity.parse_mask(5).must_equal [:business_services, :hot_tub]
|
7
|
+
Suitcase::Hotel::Amenity.parse_mask(5).must_equal [:business_services, :hot_tub]
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
describe "when bitmask is 0" do
|
12
12
|
it "returns an empty Array" do
|
13
|
-
Suitcase::Amenity.parse_mask(0).must_equal []
|
13
|
+
Suitcase::Hotel::Amenity.parse_mask(0).must_equal []
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
17
|
describe "when provided bitmask is nil" do
|
18
18
|
it "returns nil" do
|
19
|
-
Suitcase::Amenity.parse_mask(nil).must_equal nil
|
19
|
+
Suitcase::Hotel::Amenity.parse_mask(nil).must_equal nil
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
|
-
end
|
23
|
+
end
|
data/test/hotels/caching_test.rb
CHANGED
@@ -16,7 +16,7 @@ describe Suitcase do
|
|
16
16
|
room = hotel.rooms(arrival: "6/23/2012", departure: "6/30/2012").first
|
17
17
|
|
18
18
|
# Query 4
|
19
|
-
Suitcase::PaymentOption.find currency_code: "USD"
|
19
|
+
Suitcase::Hotel::PaymentOption.find currency_code: "USD"
|
20
20
|
|
21
21
|
# Query 5, don't cache though
|
22
22
|
room.rooms[0][:bed_type] = room.bed_types[0]
|
@@ -30,13 +30,13 @@ describe Suitcase do
|
|
30
30
|
hotel = Suitcase::Hotel.find(id: 123904)
|
31
31
|
Suitcase::Hotel.find(location: "Boston, US")
|
32
32
|
hotel.rooms(arrival: "6/23/2012", departure: "6/30/2012")
|
33
|
-
Suitcase::PaymentOption.find currency_code: "USD"
|
33
|
+
Suitcase::Hotel::PaymentOption.find currency_code: "USD"
|
34
34
|
|
35
35
|
# Disable API access
|
36
36
|
Net::HTTP.expects(:get_response).never
|
37
37
|
hotel = Suitcase::Hotel.find(id: 123904)
|
38
38
|
Suitcase::Hotel.find(location: "Boston, US")
|
39
39
|
hotel.rooms(arrival: "6/23/2012", departure: "6/30/2012")
|
40
|
-
Suitcase::PaymentOption.find currency_code: "USD"
|
40
|
+
Suitcase::Hotel::PaymentOption.find currency_code: "USD"
|
41
41
|
end
|
42
|
-
end
|
42
|
+
end
|
data/test/hotels/helpers_test.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require "minitest_helper"
|
2
2
|
|
3
|
-
describe Suitcase::Helpers do
|
3
|
+
describe Suitcase::Hotel::Helpers do
|
4
4
|
before :each do
|
5
|
-
class Dummy; extend Suitcase::Helpers; end
|
5
|
+
class Dummy; extend Suitcase::Hotel::Helpers; end
|
6
6
|
end
|
7
7
|
|
8
8
|
describe "#url" do
|
@@ -41,4 +41,4 @@ describe Suitcase::Helpers do
|
|
41
41
|
signature.must_equal(Digest::MD5.hexdigest("abc12310"))
|
42
42
|
end
|
43
43
|
end
|
44
|
-
end
|
44
|
+
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
require "minitest_helper"
|
2
2
|
|
3
|
-
describe Suitcase::PaymentOption do
|
3
|
+
describe Suitcase::Hotel::PaymentOption do
|
4
4
|
before :each do
|
5
5
|
@info = { currency_code: "USD" }
|
6
6
|
end
|
7
7
|
|
8
8
|
describe ".find" do
|
9
9
|
it "returns an Array of PaymentOption's" do
|
10
|
-
options = Suitcase::PaymentOption.find(@info)
|
10
|
+
options = Suitcase::Hotel::PaymentOption.find(@info)
|
11
11
|
options.must_be_kind_of(Array)
|
12
|
-
options.first.must_be_kind_of(Suitcase::PaymentOption)
|
12
|
+
options.first.must_be_kind_of(Suitcase::Hotel::PaymentOption)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
end
|