prioticket 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a8270ce77d4f2db94fbdd7ba0393af31199f9863
4
+ data.tar.gz: 496fdc625a0d8006ed9734bed00e055d108e5028
5
+ SHA512:
6
+ metadata.gz: 55f87f2ad13a09ed5ad7f9e08636f7f7b5a7f26b4dcea6b078e4758eb16b17a0e74342a6be42670b2a2f2ea988a71d8ac6c7a004c490f5a5f35a15ec8ccd3a10
7
+ data.tar.gz: 11d934e649cb210de50288c330f7a73355400579760f1f0b2626c2592b5bab68e31a254a04175904139e41c3ffce129a0187a726bbb8ddd6e913894564acbf52
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.2.3
5
+ before_install: gem install bundler -v 1.13.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in prioticket.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2018 Henk Meijer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,213 @@
1
+ # PrioTicket
2
+ [![Gem Version](https://badge.fury.io/rb/prioticket.svg)](https://badge.fury.io/rb/prioticket)
3
+ [![Dependency Status](https://gemnasium.com/henkm/prioticket.svg)](https://gemnasium.com/henkm/prioticket)
4
+ [![Code Climate](https://codeclimate.com/github/henkm/prioticket/badges/gpa.svg)](https://codeclimate.com/github/henkm/prioticket)
5
+
6
+ This gem works as a simple Ruby wrapper for the PrioTicket API. All the API functions are implemented.
7
+
8
+ Instead of working with JSON, you work with Ruby Classes and intuitive methods.
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'prioticket'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ $ bundle
21
+
22
+ Or install it yourself as:
23
+
24
+ $ gem install prioticket
25
+
26
+ ## Configuration
27
+
28
+ First, obtain an API key from PrioTicket. Set it up like this:
29
+ ```ruby
30
+ PrioTicket::Config.api_key = "MY-API-KEY"
31
+ PrioTicket::Config.environment = "test"
32
+ ```
33
+
34
+ To use this gem in a Rails project:
35
+ ```ruby
36
+ # config/development.rb
37
+ config.prioticcket.api_key = "MY-API-KEY"
38
+ config.prioticcket.environment = "test"
39
+ ```
40
+
41
+ ## Usage
42
+ The available classes and methods are listed below. General rule of thumb: all the naming is 100% consistant with the official API Documentation. So use `PrioTicket::Booking.new(booking_name: 'John Doe', booking_email: 'john@example.net')` instead of using the more intuitive `PrioTicket::Booking.new(name: 'John Doe', email: 'john@example.com')`
43
+
44
+ **Important**: the `Reservation` and `Booking` classes will only create a new reservation/booking in memory, when initialized (e.g. `Reservation.new(...)`). To submit it to the server, call `save`.
45
+
46
+ ### TicketList
47
+ To list the available tickets, call:
48
+ ```ruby
49
+ @ticket_list = PrioTicket::TicketList.find(distributor_id: 1234, identifier: "my-unique-order-abc-123")
50
+ # Returns an object with a method `tickets`, which returns an array of tickets:
51
+ # => <PrioTicket::TicketList @tickets=[##<PrioTicket::Ticket @ticket_id=362, @ticket_title="100 Highlights Cruise", @venue_name="Stromma Nederland", @txt_language="zh,ru,pt,nl,it,fr,de,es,en">, etc...]>
52
+ ```
53
+
54
+ ### TicketDetails
55
+ There are two ways to collect detailed information about a Ticket from the TicketList:
56
+
57
+ #### Find them using the `find` method
58
+
59
+ ```ruby
60
+ @ticket_details = PrioTicket::TicketDetails.find(distributor_id: 1234, ticket_id: 123, identifier: "my-unique-order-abc-123")
61
+ # => <PrioTicket::TicketDetails @ticket_id=1234, @ticket_title="100 Highlights Cruise", @short_description="The No.1 Amsterdam canal cruise", etc...>
62
+ ```
63
+
64
+ #### Collect them via the parent object
65
+ ```ruby
66
+ @ticket_list = PrioTicket::TicketList.find(distributor_id: 1234, identifier: "my-unique-order-abc-123")
67
+ @ticket_details = @ticket_list.first.ticket_details
68
+ # => <PrioTicket::TicketDetails @ticket_id=1234, @ticket_title="100 Highlights Cruise", @short_description="The No.1 Amsterdam canal cruise", etc...>
69
+ ```
70
+
71
+ So to get the tags from a certain TicketDetails, you can call:
72
+ ```ruby
73
+ @ticket_list.first.ticket_details.tags
74
+ # => ["Students", "Wheelchair accessible"]
75
+ ```
76
+ or:
77
+ ```ruby
78
+ @ticket_list.first.ticket_details.company_opening_times.first.start_from
79
+ # => "09:00:00"
80
+
81
+ ```
82
+
83
+ ### Availabilities
84
+ The same goes for fetching availabilities:
85
+ ```ruby
86
+ @availabilities = PrioTicket::Availabilities.find(distributor_id: 1234, ticket_id: 123, identifier: "my-unique-order-abc-123", from_date: Time.now, until_date: Time.now+(60*60*24*7))
87
+ # or:
88
+ @availabilities = @ticket_details.availabilities(from_date: Time.now, until_date: Time.now+(60*60*24*7))
89
+ ```
90
+
91
+ ### Reservation
92
+ To reserve a date, use the `PrioTicket::Reservation` class:
93
+ ```ruby
94
+ @reservation = PrioTicket::Reservation.new(
95
+ identifier: "my-unique-order-abc-123",
96
+ distributor_id: 1234,
97
+ ticket_id: 123,
98
+ from_date_time: @availabilities.first.from_date_time,
99
+ to_date_time: @availabilities.first.to_date_time,
100
+ booking_details: [{ticket_type: "ADULT", count: 1}],
101
+ distributor_reference: "TEST_RESERVATION"
102
+ )
103
+ # at this point, the reservation is only made in memory, but not yet
104
+ # send to the PrioTicket server. To make in final, call `save`.
105
+
106
+ @reservation.save
107
+ # => #<PrioTicket::Reservation @identifier="test-1522067114", @distributor_id=1234, @ticket_id=123, @from_date_time="2018-03-26T23:00:00+02:00", @to_date_time="2018-03-26T23:59:00+02:00", @booking_details=[#<OpenStruct ticket_type="ADULT", count=1>], @distributor_reference="TEST_RESERVATION", @booking_status="Reserved", @reservation_reference="YYY2067115376XXX">
108
+
109
+ # Cancel this reservation:
110
+ @reservation.cancel
111
+ @reservation.booking_status #=> "Cancelled"
112
+ ```
113
+
114
+ ### Booking
115
+ To make a booking, please take note of the official API Documentation: for tickets of type_2 and type_3, a `from_date_time` and `to_date_time` must be present.
116
+
117
+ Example code in section below.
118
+
119
+ ## Full example
120
+ All the steps are combined in the example below:
121
+ 1. Setup the API credentials
122
+ 2. Get a list of all the tickets/products
123
+ 3. Find out details of a specific ticket
124
+ 4. Get availability
125
+ 5. Make a booking
126
+ 6. Get status / cancel booking
127
+
128
+ ```ruby
129
+
130
+ # step 1
131
+ # config/development.rb (in case of Ruby on Rails App)
132
+ config.prioticcket.api_key = "MY-API-KEY"
133
+ config.prioticcket.environment = "test"
134
+
135
+ # Code below goes in a controller or model, handling the application logic
136
+
137
+ # step 2
138
+ @ticket_list = PrioTicket::TicketList.find(distributor_id: 1234, identifier: "test-123")
139
+
140
+ # step 3
141
+ @ticket = @ticket_list.tickets.first.details
142
+ #=> <PrioTicket::TicketDetails> includes name, prices, etc.
143
+
144
+ # step 4
145
+ # method defaults to 3 weeks ahead, you can provice from_date_time and to_date_time
146
+ @available_times = @ticket.availabilities
147
+
148
+ # step 5 - book first available time
149
+ @booking = PrioTicket::Booking.new(
150
+ identifier: "test-123",
151
+ distributor_id: 1234,
152
+ booking_type: {
153
+ ticket_id: @ticket.ticket_id,
154
+ booking_details: [{
155
+ ticket_type: "ADULT",
156
+ count: 2,
157
+ extra_options: []
158
+ }]
159
+ },
160
+ booking_name: "John Doe",
161
+ booking_email: "john@example.com",
162
+ contact: {
163
+ address: {
164
+ street: "Amstel 1",
165
+ postal_code: "1011 PN",
166
+ city: "Amsterdam"
167
+ },
168
+ phonenumber: "0643210123"
169
+ },
170
+ notes: ["This is a test booking"],
171
+ product_language: "en",
172
+ distributor_reference: "ABC123456"
173
+ )
174
+
175
+ # the booking is now made in memory, but not yet final
176
+ @booking.confirmed?
177
+ # => false
178
+
179
+ @booking.save
180
+ # => <PrioTicket::Booking> object, with status and barcodes
181
+
182
+ @booking.confirmed?
183
+ # => true
184
+
185
+ @booking.cancel
186
+ @booking.confirmed?
187
+ # => false
188
+ @booking.canceled?
189
+ # => true
190
+
191
+ @booking.booking_reference # => 123ABC456XYZ
192
+
193
+ # another way to ask for the status of a booking:
194
+ @booking = PrioTicket::Booking.get_status(
195
+ identifier: @booking.identifier,
196
+ distributor_id: DIST_ID,
197
+ booking_reference: "123ABC456XYZ",
198
+ distributor_reference: "ABC123456
199
+ )
200
+ @booking.status # => "Cancelled"
201
+ ```
202
+
203
+ ## Contributing
204
+
205
+ Bug reports and pull requests are welcome on GitHub at https://github.com/henkm/prioticket.
206
+
207
+
208
+ ## License
209
+
210
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT). No rights can be derrived from using this library.
211
+
212
+ This gem is made with love by the smart people at [Eskes Media B.V.](https://www.eskesmedia.nl) and [DagjeWeg.NL Tickets](https://www.dagjewegtickets.nl)
213
+ PrioTicket is not involved with this project and has no affiliation with Eskes Media B.V.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "prioticket"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,94 @@
1
+ module PrioTicket
2
+
3
+ # The communication layer implements all the methods available in the PrioTicket API
4
+ # NOTE: You need to request access to view the documentation.
5
+ # https://support.prioticket.com/docs/
6
+ class API
7
+
8
+ #
9
+ # Returns the API endpoint to use
10
+ #
11
+ # @return [type] [description]
12
+ def self.endpoint
13
+ if PrioTicket::Config.environment.to_s == "test"
14
+ "https://test-api.prioticket.com/v2.4/booking_service"
15
+ else
16
+ "https://api.prioticket.com/v2.4/booking_service"
17
+ end
18
+ end
19
+
20
+ # The request authentication key will contain the following items:
21
+ # (a) API Key Token
22
+ # (b) Request Identifier
23
+ #
24
+ # The API Key Token information for the TEST and LIVE environment will be sent in a separate mail.
25
+ # The Request Identifier should be an unique string generated by the initiator. Common examples are
26
+ # a timestamp, booking reference or UUID.The request authentication key will be computed per request
27
+ # as follows:
28
+ #
29
+ def self.request_authentication_key(request_identifier="")
30
+ # 1. Create a string with format <x-request-identifier>:<apikeytoken> where x-request-identifier
31
+ # and apikeytoken are respective strings.
32
+ step_1_string = "#{request_identifier}:#{Config.api_key}"
33
+
34
+ # 2. Convert the string from step 1 to byte array using UTF-8 encoding.
35
+ step_2_string = step_1_string.encode('utf-8')
36
+
37
+ # 3. Compute the SHA-256 hash for the byte array from step 2. The result will be a byte array.
38
+ step_3_string = Digest::SHA256.digest(step_2_string).strip
39
+
40
+ # 4. Base64 encode the byte array as computed in step 3.
41
+ # This string will be the x-request-authentication key for this request.
42
+ step_4_string = Base64.encode64(step_3_string).strip
43
+
44
+ return step_4_string
45
+ end
46
+
47
+ #
48
+ # Computes the request header
49
+ # @param request_identifier="" [type] A unique request identifier,
50
+ # e.g. timestamp order_id, booking_reference or UUID.
51
+ #
52
+ # @return [Hash] the header details for API calls
53
+ def self.request_header(request_identifier="")
54
+ {
55
+ content_type: "application/json",
56
+ x_request_authentication: request_authentication_key(request_identifier),
57
+ x_request_identifier: request_identifier
58
+ }
59
+ end
60
+
61
+
62
+ #
63
+ # Makes a HTTP POST call to the endpoint en returns the response
64
+ #
65
+ # @param request_body [type] [description]
66
+ # @param request_identifier [type] [description]
67
+ #
68
+ # @return OpenStruct object with nested methods.
69
+ def self.call(request_body, request_identifier, verbose=false)
70
+ values = request_body.to_json
71
+ headers = request_header(request_identifier)
72
+ if verbose || PrioTicket::Config.verbose == true
73
+ puts "Calling with:"
74
+ puts "Identifier: #{request_identifier}"
75
+ puts "Header: #{headers.to_json}"
76
+ puts "Body: #{values}"
77
+ puts "Endpoint: #{endpoint}"
78
+ end
79
+ raise PrioTicketError.new "Request Identifier is not present, please provide an @identifier" if request_identifier.nil? || request_identifier == ''
80
+ begin
81
+ response = RestClient.post endpoint, values, headers
82
+ rescue RestClient::ExceptionWithResponse => e
83
+ if verbose || PrioTicket::Config.verbose == true
84
+ puts "Error: #{e.response}"
85
+ end
86
+ error_json = JSON.parse(e.response)
87
+ message = "#{error_json["error_message"]} (#{error_json["error_code"]}) - #{e}"
88
+ raise PrioTicketError.new message
89
+ end
90
+ object = JSON.parse(response.body)
91
+ return object
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,89 @@
1
+ module PrioTicket
2
+
3
+ # This endpoint should be called in order to get up-to-date availability
4
+ # information for a product with managed capacity. The response will contain
5
+ # the availability for each time slot of the requested product that lies within
6
+ # the specified date range. Time slots will not be omitted in case of no availability.
7
+ # Neither will a NO_AVAILABILITY error be returned in that case.
8
+ # Instead, an explicit vacancy of zero should be expected.
9
+ #
10
+ class Availabilities
11
+ attr_accessor :from_date_time
12
+ attr_accessor :to_date_time
13
+ attr_accessor :vacancies
14
+
15
+
16
+ def initialize(args=nil)
17
+ return if args.nil?
18
+ args.each do |k,v|
19
+ PrioTicket.parse_json_value(self, k,v)
20
+ end
21
+ end
22
+
23
+ #
24
+ # Calls the request type 'availabilities' with given
25
+ # details and retruns an array of Availabilities objects
26
+ #
27
+ # @param distributor_id Integer
28
+ # @return Array
29
+ def self.find(distributor_id: nil, ticket_id: nil, from_date: nil, until_date: nil, identifier: nil)
30
+ result = PrioTicket::API.call(request_body(ticket_id: ticket_id, distributor_id: distributor_id, from_date: from_date, until_date: until_date), identifier, false)
31
+ list = []
32
+ for a in result["data"]["availabilities"]
33
+ list << Availabilities.new(a)
34
+ end
35
+ return list
36
+ end
37
+
38
+ #
39
+ # Computes the request body to send to the API endpoint
40
+ # @param distributor_id Integer
41
+ # @param ticket_id Integer
42
+ # @param from_date String
43
+ # @param until_date String
44
+ #
45
+ # @return Hash
46
+ def self.request_body(distributor_id: nil, ticket_id: nil, from_date: nil, until_date: nil)
47
+ {
48
+ request_type: "availabilities",
49
+ data: {
50
+ distributor_id: distributor_id,
51
+ ticket_id: ticket_id,
52
+ from_date: PrioTicket.parsed_date(from_date),
53
+ until_date: PrioTicket.parsed_date(until_date)
54
+ }
55
+ }
56
+ end
57
+
58
+
59
+ def reserve
60
+ # {
61
+ # "request_type": "reserve",
62
+ # "data": {
63
+ # "distributor_id": "501",
64
+ # "ticket_id": "509",
65
+ # "pickup_point_id": "Wyndham_Apollo_hotel",
66
+ # "from_date_time": "2017-11-22T09:00:00+01:00",
67
+ # "to_date_time": "2017-11-23T09:00:00+01:00",
68
+ # "booking_details": [
69
+ # {
70
+ # "ticket_type": "ADULT",
71
+ # "count": 1
72
+ # }
73
+ # ],
74
+ # "distributor_reference": "ABC123456"
75
+ # }
76
+ # }
77
+
78
+ # {
79
+ # "response_type": "reserve",
80
+ # "data": {
81
+ # "reservation_reference": "123456789",
82
+ # "distributor_reference": "ABC123456",
83
+ # "booking_status": "Reserved"
84
+ # }
85
+ # }
86
+ end
87
+
88
+ end
89
+ end
@@ -0,0 +1,197 @@
1
+ module PrioTicket
2
+
3
+ # Describes a Booking
4
+ # This API is called to get a ticket booked and get a barcode/QR-code in response.
5
+ # The booking API provides a booking reference in response.
6
+ # There are 5 different booking options:
7
+ # - Booking of ticket without timeslot (ticket_class 1).
8
+ # - Booking of ticket with timeslot (ticket_class 2/ticket_class 3),
9
+ # without reservation_reference.
10
+ # - Booking of ticket with timeslot (ticket_class 2/ticket_class 3),
11
+ # with reservation_reference.
12
+ #
13
+ class Booking
14
+
15
+ attr_accessor :identifier
16
+ attr_accessor :distributor_id
17
+ # attr_accessor :booking_type
18
+ attr_accessor :booking_type
19
+ attr_accessor :booking_name
20
+ attr_accessor :booking_email
21
+ attr_accessor :notes
22
+ attr_accessor :contact
23
+ attr_accessor :product_language
24
+ attr_accessor :distributor_reference
25
+ attr_accessor :reservation_reference
26
+
27
+
28
+ # contact details
29
+ attr_accessor :phone_number
30
+ attr_accessor :street
31
+ attr_accessor :postal_code
32
+ attr_accessor :city
33
+
34
+ # completed booking attrs
35
+ attr_accessor :booking_reference
36
+ attr_accessor :booking_status
37
+ attr_accessor :booking_details
38
+
39
+ def initialize(args)
40
+ return if args.nil?
41
+ args.each do |k,v|
42
+ PrioTicket.parse_json_value(self, k,v)
43
+ end
44
+ end
45
+
46
+ #
47
+ # Sends the reservation request tot the API
48
+ #
49
+ def save
50
+ request_booking
51
+ end
52
+
53
+
54
+ def canceled
55
+ booking_status == "Cancelled"
56
+ end
57
+ alias_method :canceled?, :canceled
58
+
59
+
60
+ def success
61
+ booking_status == "Confirmed"
62
+ end
63
+ for meth in [:success?, :confirmed, :confirmed?]
64
+ alias_method meth, :success
65
+ end
66
+
67
+
68
+ # Fetches information from ticket_details,
69
+ # to validate the input for this booking.
70
+ # e.g. if ticket_type == 2, from/to date are required.
71
+ #
72
+ # @return [type] [description]
73
+ def ticket
74
+ begin
75
+ @ticket ||= PrioTicket::TicketDetails.find(distributor_id: distributor_id, ticket_id: booking_type['ticket_id'], identifier: identifier)
76
+ rescue
77
+ false
78
+ end
79
+ end
80
+
81
+
82
+ #
83
+ # Cancels a Booking
84
+ #
85
+ # @return Booking
86
+ def self.cancel(distributor_id: nil, booking_reference: nil, distributor_reference: nil, identifier: nil)
87
+ body = {
88
+ request_type: "cancel_booking",
89
+ data: {
90
+ distributor_id: distributor_id,
91
+ booking_reference: booking_reference,
92
+ distributor_reference: booking_reference
93
+ }
94
+ }
95
+ result = PrioTicket::API.call(body, identifier)
96
+ booking = PrioTicket::Booking.new(result["data"])
97
+ return booking
98
+ end
99
+
100
+ #
101
+ # Gets the status from a Booking
102
+ #
103
+ # @return Booking
104
+ def self.get_status(distributor_id: nil, booking_reference: nil, distributor_reference: nil, identifier: nil)
105
+ body = {
106
+ request_type: "booking_status",
107
+ data: {
108
+ distributor_id: distributor_id,
109
+ booking_reference: booking_reference,
110
+ distributor_reference: booking_reference
111
+ }
112
+ }
113
+ result = PrioTicket::API.call(body, identifier)
114
+ booking = PrioTicket::Booking.new(result["data"])
115
+ return booking
116
+ end
117
+
118
+ private
119
+
120
+ #
121
+ # Sends the reservation request to the API endpoint
122
+ # and enriches current object with status and reference.
123
+ #
124
+ def request_booking
125
+ result = PrioTicket::API.call(request_body, identifier)
126
+ parse_result(result)
127
+ end
128
+
129
+
130
+ #
131
+ # Computes the details to send to the API
132
+ #
133
+ # @return Hash
134
+ def request_body
135
+ for att in [:distributor_id, :booking_type, :booking_name, :booking_email, :contact, :notes, :product_language, :distributor_reference]
136
+ raise PrioTicketError.new("Booking is missing attribute `#{att}` (Hash)") unless send(att)
137
+ end
138
+ body = {
139
+ request_type: "booking",
140
+ data: {
141
+ distributor_id: distributor_id,
142
+ booking_type: validated_booking_type_hash,
143
+ booking_name: booking_name,
144
+ booking_email: booking_email,
145
+ contact: PrioTicket.openstruct_to_hash(contact).to_h,
146
+ notes: notes.to_a,
147
+ product_language: product_language,
148
+ distributor_reference: distributor_reference
149
+ }
150
+ }
151
+
152
+ # add pickuppoint to body, if present
153
+ # body[:data][:pickup_point_id] = pickup_point_id if pickup_point_id
154
+ return body
155
+ end
156
+
157
+ #
158
+ # Calculates and validates the information for 'booking_type'
159
+ #
160
+ # @return Hash
161
+ def validated_booking_type_hash
162
+
163
+ # loops through all the booking details and raises error
164
+ # if from/to date_time are not present.
165
+ if ticket
166
+ if [2,3].include?(ticket.ticket_class)
167
+ unless booking_type.from_date_time && booking_type.to_date_time
168
+ err_msg = "The `booking_type` attribute requires a from_date_time and to_date_time for a ticket of ticket_class #{ticket.ticket_class}."
169
+ raise PrioTicketError.new(err_msg)
170
+ end
171
+ end
172
+ end
173
+ data = {}
174
+
175
+ data[:ticket_id] = booking_type.ticket_id unless booking_type.reservation_reference
176
+ data[:booking_details] = booking_type.booking_details.map{|bd| PrioTicket.openstruct_to_hash(bd)} unless booking_type.reservation_reference
177
+ data[:reservation_reference] = booking_type.reservation_reference if booking_type.reservation_reference
178
+
179
+ if booking_type.from_date_time && booking_type.to_date_time
180
+ data[:from_date_time] = booking_type.from_date_time
181
+ data[:to_date_time] = booking_type.to_date_time
182
+ end
183
+ return data
184
+ end
185
+
186
+ #
187
+ # Parses the return value from the API
188
+ #
189
+ def parse_result(result)
190
+ self.booking_status = result["data"]["booking_status"]
191
+ self.booking_reference = result["data"]["booking_reference"]
192
+ PrioTicket.parse_json_value(self, :booking_details, result["data"]["booking_details"])
193
+ end
194
+
195
+
196
+ end
197
+ end