hotel_beds 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -44
  3. data/lib/hotel_beds/basket_remove/envelope.rb +16 -0
  4. data/lib/hotel_beds/basket_remove/operation.rb +36 -0
  5. data/lib/hotel_beds/basket_remove/request.rb +19 -0
  6. data/lib/hotel_beds/basket_remove/response.rb +31 -0
  7. data/lib/hotel_beds/client.rb +21 -0
  8. data/lib/hotel_beds/hotel_basket_add/request.rb +1 -1
  9. data/lib/hotel_beds/hotel_basket_add/response.rb +4 -35
  10. data/lib/hotel_beds/hotel_search/envelope.rb +10 -9
  11. data/lib/hotel_beds/hotel_search/request.rb +6 -4
  12. data/lib/hotel_beds/hotel_search/response.rb +4 -9
  13. data/lib/hotel_beds/model/available_room.rb +22 -1
  14. data/lib/hotel_beds/model/cancellation_policy.rb +0 -1
  15. data/lib/hotel_beds/model/comment.rb +13 -0
  16. data/lib/hotel_beds/model/contract.rb +15 -0
  17. data/lib/hotel_beds/model/customer.rb +21 -0
  18. data/lib/hotel_beds/model/destination.rb +13 -0
  19. data/lib/hotel_beds/model/hotel.rb +12 -7
  20. data/lib/hotel_beds/model/price.rb +18 -0
  21. data/lib/hotel_beds/model/purchase.rb +7 -2
  22. data/lib/hotel_beds/model/room.rb +0 -1
  23. data/lib/hotel_beds/model/service.rb +6 -4
  24. data/lib/hotel_beds/parser.rb +94 -0
  25. data/lib/hotel_beds/parser/available_room.rb +37 -0
  26. data/lib/hotel_beds/parser/cancellation_policy.rb +13 -0
  27. data/lib/hotel_beds/parser/comment.rb +13 -0
  28. data/lib/hotel_beds/parser/contract.rb +17 -0
  29. data/lib/hotel_beds/parser/customer.rb +18 -0
  30. data/lib/hotel_beds/parser/destination.rb +13 -0
  31. data/lib/hotel_beds/parser/errors.rb +39 -0
  32. data/lib/hotel_beds/parser/hotel.rb +27 -0
  33. data/lib/hotel_beds/parser/price.rb +14 -0
  34. data/lib/hotel_beds/parser/purchase.rb +24 -0
  35. data/lib/hotel_beds/parser/room_grouper.rb +104 -0
  36. data/lib/hotel_beds/parser/service.rb +21 -0
  37. data/lib/hotel_beds/purchase_confirm/envelope.rb +42 -0
  38. data/lib/hotel_beds/purchase_confirm/operation.rb +36 -0
  39. data/lib/hotel_beds/purchase_confirm/request.rb +72 -0
  40. data/lib/hotel_beds/purchase_confirm/response.rb +31 -0
  41. data/lib/hotel_beds/purchase_flush/envelope.rb +15 -0
  42. data/lib/hotel_beds/purchase_flush/operation.rb +36 -0
  43. data/lib/hotel_beds/purchase_flush/request.rb +17 -0
  44. data/lib/hotel_beds/purchase_flush/response.rb +26 -0
  45. data/lib/hotel_beds/version.rb +1 -1
  46. data/spec/features/flushing_the_basket_spec.rb +63 -0
  47. data/spec/features/ordering_a_hotel_room_spec.rb +96 -0
  48. data/spec/features/removing_a_basket_item_spec.rb +74 -0
  49. data/spec/lib/hotel_beds/hotel_search/request_spec.rb +4 -4
  50. data/spec/lib/hotel_beds/{hotel_search/parser → parser}/room_grouper_spec.rb +3 -3
  51. data/spec/lib/hotel_beds/parser/service_spec.rb +44 -0
  52. metadata +42 -15
  53. data/lib/hotel_beds/hotel_search/parser/errors.rb +0 -49
  54. data/lib/hotel_beds/hotel_search/parser/hotel.rb +0 -71
  55. data/lib/hotel_beds/hotel_search/parser/price.rb +0 -38
  56. data/lib/hotel_beds/hotel_search/parser/room.rb +0 -61
  57. data/lib/hotel_beds/hotel_search/parser/room_grouper.rb +0 -101
  58. data/spec/features/adding_a_hotel_to_basket_spec.rb +0 -58
  59. data/spec/features/grouped_hotel_search_spec.rb +0 -67
  60. data/spec/features/hotel_search_spec.rb +0 -113
@@ -0,0 +1,15 @@
1
+ require "hotel_beds/model"
2
+ require "hotel_beds/model/comment"
3
+
4
+ module HotelBeds
5
+ module Model
6
+ class Contract
7
+ include HotelBeds::Model
8
+
9
+ # attributes
10
+ attribute :name, String
11
+ attribute :incoming_office_code, String
12
+ attribute :comments, Array[HotelBeds::Model::Comment]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ require "hotel_beds/model"
2
+
3
+ module HotelBeds
4
+ module Model
5
+ class Customer
6
+ include HotelBeds::Model
7
+
8
+ # attributes
9
+ attribute :id, Integer
10
+ attribute :type, Symbol
11
+ attribute :age, Integer
12
+ attribute :name, Integer
13
+ attribute :last_name, Integer
14
+
15
+ # validation
16
+ validates :id, :name, :last_name, presence: true
17
+ validates :age, numericality: { greater_than_or_equal_to: 0 }
18
+ validates :type, inclusion: { in: %i(adult child) }
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ require "hotel_beds/model"
2
+
3
+ module HotelBeds
4
+ module Model
5
+ class Destination
6
+ include HotelBeds::Model
7
+
8
+ # attributes
9
+ attribute :code, String
10
+ attribute :name, String
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,8 @@
1
1
  require "hotel_beds/model"
2
- require_relative "search_result"
2
+ require "hotel_beds/model/available_room"
3
+ require "hotel_beds/model/contract"
4
+ require "hotel_beds/model/destination"
5
+ require "hotel_beds/parser/room_grouper"
3
6
 
4
7
  module HotelBeds
5
8
  module Model
@@ -7,17 +10,19 @@ module HotelBeds
7
10
  include HotelBeds::Model
8
11
 
9
12
  # attributes
10
- attribute :id, Integer
13
+ attribute :code, String
11
14
  attribute :availability_token, String
12
15
  attribute :name, String
13
16
  attribute :images, Array[String]
14
- attribute :stars, Integer
15
17
  attribute :longitude, BigDecimal
16
18
  attribute :latitude, BigDecimal
17
- attribute :results, Array[SearchResult]
18
- attribute :destination_code, String
19
- attribute :contract_name, String
20
- attribute :contract_incoming_office_code, String
19
+ attribute :available_rooms, Array[HotelBeds::Model::AvailableRoom]
20
+ attribute :contract, HotelBeds::Model::Contract
21
+ attribute :destination, HotelBeds::Model::Destination
22
+
23
+ def grouped_rooms(requested_rooms)
24
+ HotelBeds::Parser::RoomGrouper.new(requested_rooms, available_rooms).groups
25
+ end
21
26
  end
22
27
  end
23
28
  end
@@ -0,0 +1,18 @@
1
+ require "hotel_beds/model"
2
+
3
+ module HotelBeds
4
+ module Model
5
+ class Price
6
+ include HotelBeds::Model
7
+
8
+ # attributes
9
+ attribute :from, Date
10
+ attribute :to, Date
11
+ attribute :amount, BigDecimal
12
+
13
+ def dates
14
+ (from..to).to_a
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,5 +1,6 @@
1
1
  require "hotel_beds/model"
2
2
  require "hotel_beds/model/service"
3
+ require "hotel_beds/model/customer"
3
4
 
4
5
  module HotelBeds
5
6
  module Model
@@ -7,10 +8,14 @@ module HotelBeds
7
8
  include HotelBeds::Model
8
9
 
9
10
  # attributes
10
- attribute :id, String
11
- attribute :services, Array[Service]
11
+ attribute :token, String
12
+ attribute :time_to_expiration, Integer
13
+ attribute :agency_reference, String
14
+ attribute :status, String
12
15
  attribute :currency, String
13
16
  attribute :amount, BigDecimal
17
+ attribute :services, Array[HotelBeds::Model::Service]
18
+ attribute :holder, HotelBeds::Model::Customer
14
19
  end
15
20
  end
16
21
  end
@@ -1,5 +1,4 @@
1
1
  require "hotel_beds/model"
2
- require_relative "room"
3
2
 
4
3
  module HotelBeds
5
4
  module Model
@@ -1,4 +1,5 @@
1
1
  require "hotel_beds/model"
2
+ require "hotel_beds/model/contract"
2
3
 
3
4
  module HotelBeds
4
5
  module Model
@@ -7,10 +8,11 @@ module HotelBeds
7
8
 
8
9
  # attributes
9
10
  attribute :id, String
10
- attribute :contract_name, String
11
- attribute :contract_incoming_office_code, String
12
- attribute :check_in_date, Date
13
- attribute :check_out_date, Date
11
+ attribute :type, String
12
+ attribute :status, String
13
+ attribute :contract, HotelBeds::Model::Contract
14
+ attribute :date_from, Date
15
+ attribute :date_to, Date
14
16
  attribute :currency, String
15
17
  attribute :amount, BigDecimal
16
18
  end
@@ -0,0 +1,94 @@
1
+ module HotelBeds
2
+ module Parser
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ base.send(:include, InstanceMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ class Attribute
10
+ attr_accessor :name, :parser, :selector, :attr, :multiple, :custom
11
+ private :name=, :parser=, :selector=, :attr=, :multiple=, :custom=
12
+
13
+ def initialize(name, parser: nil, selector: nil, attr: :content, multiple: false, &block)
14
+ self.name = name.to_sym
15
+ self.parser = parser
16
+ self.selector = selector
17
+ self.attr = attr
18
+ self.multiple = !!multiple
19
+ self.custom = block
20
+ freeze
21
+ end
22
+
23
+ def retrieve(doc)
24
+ if custom
25
+ custom.yield(doc)
26
+ elsif multiple
27
+ doc.css(selector).map(&method(:read_element))
28
+ elsif selector
29
+ (element = doc.at_css(selector)) && read_element(element) or nil
30
+ else
31
+ read_element(doc)
32
+ end
33
+ end
34
+
35
+ private
36
+ def read_element(element)
37
+ if parser
38
+ parser.new(element).to_h
39
+ elsif attr == :content
40
+ element.content
41
+ else
42
+ element.attr(attr)
43
+ end
44
+ end
45
+ end
46
+
47
+ def attributes
48
+ @attributes ||= Array.new
49
+ end
50
+
51
+ protected def attribute(*args, &block)
52
+ (@attributes ||= Array.new).push(Attribute.new(*args, &block))
53
+ end
54
+
55
+ def default_model_class(klass = nil)
56
+ # set the class, if given
57
+ @default_model_class = klass if klass
58
+ # return the class, defaulting to HotelBeds::Model::ClassName
59
+ @default_model_class ||= begin
60
+ klass_name = name.gsub(/^.*\:\:(.*?)$/, '\1')
61
+ file_name = klass_name.gsub(/(?<=.)([A-Z]+)/, '_\1').downcase
62
+ require "hotel_beds/model/#{file_name}"
63
+ ::HotelBeds.const_get("Model").const_get(klass_name)
64
+ end
65
+ end
66
+ end
67
+
68
+ module InstanceMethods
69
+ def self.included(base)
70
+ base.class_eval do
71
+ attr_accessor :doc
72
+ private :doc=
73
+ end
74
+ end
75
+
76
+ def initialize(doc)
77
+ self.doc = doc
78
+ freeze
79
+ end
80
+
81
+ # parses the document into a hash of attributes
82
+ def to_h
83
+ self.class.attributes.inject(Hash.new) do |result, attribute|
84
+ result.merge(attribute.name => attribute.retrieve(doc))
85
+ end
86
+ end
87
+
88
+ # parses the document into a HotelBeds::Model instance
89
+ def to_model(klass = self.class.default_model_class)
90
+ klass.new(to_h)
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,37 @@
1
+ require "hotel_beds/parser"
2
+ require "hotel_beds/parser/cancellation_policy"
3
+ require "hotel_beds/parser/price"
4
+ require "hotel_beds/parser/customer"
5
+
6
+ module HotelBeds
7
+ module Parser
8
+ class AvailableRoom
9
+ include HotelBeds::Parser
10
+
11
+ # attributes
12
+ attribute :id, selector: "HotelRoom", attr: "SHRUI"
13
+ attribute :room_count, selector: "HotelOccupancy RoomCount"
14
+ attribute :adult_count, selector: "HotelOccupancy AdultCount"
15
+ attribute :child_count, selector: "HotelOccupancy ChildCount"
16
+ attribute :number_available, selector: "HotelRoom", attr: "availCount"
17
+ attribute :description, selector: "HotelRoom RoomType"
18
+ attribute :board, selector: "HotelRoom Board"
19
+ attribute :board_code, selector: "HotelRoom Board", attr: "code"
20
+ attribute :room_type_code, selector: "HotelRoom RoomType", attr: "code"
21
+ attribute :room_type_characteristic,
22
+ selector: "HotelRoom RoomType", attr: "characteristic"
23
+ attribute :price do |element|
24
+ ((element.at_css("HotelRoom") > "Price") > "Amount").first.content
25
+ end
26
+ attribute :cancellation_policies,
27
+ selector: "HotelRoom CancellationPolicy", multiple: true,
28
+ parser: HotelBeds::Parser::CancellationPolicy
29
+ attribute :rates,
30
+ selector: "Price PriceList Price", multiple: true,
31
+ parser: HotelBeds::Parser::Price
32
+ attribute :customers,
33
+ selector: "HotelOccupancy GuestList Customer", multiple: true,
34
+ parser: HotelBeds::Parser::Customer
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ require "hotel_beds/parser"
2
+
3
+ module HotelBeds
4
+ module Parser
5
+ class CancellationPolicy
6
+ include HotelBeds::Parser
7
+
8
+ # attributes
9
+ attribute :amount, attr: "amount"
10
+ attribute :from, attr: "dateFrom"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require "hotel_beds/parser"
2
+
3
+ module HotelBeds
4
+ module Parser
5
+ class Comment
6
+ include HotelBeds::Parser
7
+
8
+ # attributes
9
+ attribute :type, attr: "type"
10
+ attribute :content
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ require "hotel_beds/parser"
2
+ require "hotel_beds/parser/comment"
3
+
4
+ module HotelBeds
5
+ module Parser
6
+ class Contract
7
+ include HotelBeds::Parser
8
+
9
+ # attributes
10
+ attribute :name, selector: "Name"
11
+ attribute :incoming_office_code, selector: "IncomingOffice", attr: "code"
12
+ attribute :comments,
13
+ selector: "CommentList Comment", multiple: true,
14
+ parser: HotelBeds::Parser::Comment
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ require "hotel_beds/parser"
2
+
3
+ module HotelBeds
4
+ module Parser
5
+ class Customer
6
+ include HotelBeds::Parser
7
+
8
+ # attributes
9
+ attribute :id, selector: "CustomerId"
10
+ attribute :type do |element|
11
+ element.attr("type") == "CH" ? :child : :adult
12
+ end
13
+ attribute :name, selector: "Name"
14
+ attribute :last_name, selector: "LastName"
15
+ attribute :age, selector: "Age"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ require "hotel_beds/parser"
2
+
3
+ module HotelBeds
4
+ module Parser
5
+ class Destination
6
+ include HotelBeds::Parser
7
+
8
+ # attributes
9
+ attribute :code, attr: "code"
10
+ attribute :name, selector: "Name"
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ require "active_model/errors"
2
+
3
+ module HotelBeds
4
+ module Parser
5
+ class Errors
6
+ attr_accessor :response
7
+ private :response=
8
+
9
+ def initialize(response)
10
+ self.response = response
11
+ freeze
12
+ end
13
+
14
+ def to_model(object)
15
+ ActiveModel::Errors.new(object).tap do |errors|
16
+ if response.http_error?
17
+ errors.add(:base, "HTTP error")
18
+ elsif response.soap_fault?
19
+ errors.add(:base, "SOAP error")
20
+ elsif !response.success?
21
+ errors.add(:base, "Request failed")
22
+ end
23
+
24
+ body.css("ErrorList Error").each do |error|
25
+ errors.add(:base, [
26
+ (sm = error.at_css("Message")) && sm.content,
27
+ (dm = error.at_css("DetailedMessage")) && dm.content
28
+ ].compact.join("\n"))
29
+ end
30
+ end
31
+ end
32
+
33
+ private
34
+ def body
35
+ Nokogiri::XML(response.body.values.first)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ require "hotel_beds/parser"
2
+ require "hotel_beds/parser/contract"
3
+ require "hotel_beds/parser/destination"
4
+ require "hotel_beds/parser/available_room"
5
+
6
+ module HotelBeds
7
+ module Parser
8
+ class Hotel
9
+ include HotelBeds::Parser
10
+
11
+ # attributes
12
+ attribute :code, selector: "HotelInfo > Code"
13
+ attribute :availability_token, attr: "availToken"
14
+ attribute :name, selector: "HotelInfo > Name"
15
+ attribute :images, selector: "HotelInfo > ImageList > Image > Url",
16
+ multiple: true
17
+ attribute :longitude, selector: "Position", attr: "longitude"
18
+ attribute :latitude, selector: "Position", attr: "latitude"
19
+ attribute :contract, selector: "ContractList > Contract",
20
+ parser: HotelBeds::Parser::Contract
21
+ attribute :destination, selector: "HotelInfo > Destination",
22
+ parser: HotelBeds::Parser::Destination
23
+ attribute :available_rooms, selector: "AvailableRoom", multiple: true,
24
+ parser: HotelBeds::Parser::AvailableRoom
25
+ end
26
+ end
27
+ end