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 +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +213 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/prioticket/api.rb +94 -0
- data/lib/prioticket/availabilities.rb +89 -0
- data/lib/prioticket/booking.rb +197 -0
- data/lib/prioticket/config.rb +36 -0
- data/lib/prioticket/engine.rb +13 -0
- data/lib/prioticket/prioticket_error.rb +28 -0
- data/lib/prioticket/reservation.rb +122 -0
- data/lib/prioticket/ticket.rb +34 -0
- data/lib/prioticket/ticket_details.rb +97 -0
- data/lib/prioticket/ticket_list.rb +54 -0
- data/lib/prioticket/version.rb +3 -0
- data/lib/prioticket.rb +109 -0
- data/prioticket.gemspec +40 -0
- metadata +150 -0
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
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
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
|
+
[](https://badge.fury.io/rb/prioticket)
|
3
|
+
[](https://gemnasium.com/henkm/prioticket)
|
4
|
+
[](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
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,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
|