suitcase 1.4.1 → 1.5.0
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.
- 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
|