prioticket 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![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
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
|