seatlayer 0.8.0 → 0.9.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 +4 -4
- data/CHANGELOG.md +109 -0
- data/README.md +167 -42
- data/lib/seatlayer/event_series.rb +78 -0
- data/lib/seatlayer/holders.rb +109 -0
- data/lib/seatlayer/http_client.rb +29 -14
- data/lib/seatlayer/inventory.rb +19 -2
- data/lib/seatlayer/orders.rb +75 -0
- data/lib/seatlayer/resources.rb +103 -2
- data/lib/seatlayer/seasons.rb +432 -11
- data/lib/seatlayer/version.rb +1 -1
- data/lib/seatlayer.rb +7 -1
- metadata +6 -2
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SeatLayer
|
|
4
|
+
# Season holders and customers: contact details, sessions, tickets, ticket
|
|
5
|
+
# transfers between holders, returns, and renewals.
|
|
6
|
+
class Holders < Resource
|
|
7
|
+
# One page of customers, or the one matching +email+ or +holder_ref+.
|
|
8
|
+
def list_customers(email: nil, holder_ref: nil, cursor: nil, limit: nil)
|
|
9
|
+
@client.get("/v1/customers", compact({ "email" => email, "holderRef" => holder_ref,
|
|
10
|
+
"cursor" => cursor, "limit" => limit }))
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Read one holder.
|
|
14
|
+
def retrieve_holder(holder_ref)
|
|
15
|
+
@client.get(path(holder_ref))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Set a holder's email, name or phone. Pass +nil+ for +name+ or +phone+ to
|
|
19
|
+
# send an explicit JSON null.
|
|
20
|
+
def update_holder(holder_ref, email: nil, name: UNSET, phone: UNSET, idempotency_key: nil)
|
|
21
|
+
body = compact({ "email" => email })
|
|
22
|
+
body.merge!(supplied({ "name" => name, "phone" => phone }))
|
|
23
|
+
@client.mutation_with_header_replay(
|
|
24
|
+
"PATCH", path(holder_ref), body, idempotency_key: idempotency_key
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Sign a holder out of every session, or only out of +session_id+.
|
|
29
|
+
# Single-attempt.
|
|
30
|
+
def revoke_holder_sessions(holder_ref, session_id: nil)
|
|
31
|
+
@client.post(path(holder_ref, "/sessions/revoke"), compact({ "sessionId" => session_id }))
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# List the Seasons a holder belongs to.
|
|
35
|
+
def list_holder_seasons(holder_ref)
|
|
36
|
+
@client.get(path(holder_ref, "/seasons"))
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# One page of a holder's tickets. +from+ and +to+ are epoch milliseconds.
|
|
40
|
+
def list_holder_tickets(holder_ref, season_key: nil, from: nil, to: nil, cursor: nil,
|
|
41
|
+
limit: nil)
|
|
42
|
+
@client.get(path(holder_ref, "/tickets"),
|
|
43
|
+
compact({ "seasonKey" => season_key, "from" => from, "to" => to,
|
|
44
|
+
"cursor" => cursor, "limit" => limit }))
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Read one of a holder's tickets.
|
|
48
|
+
def retrieve_holder_ticket(holder_ref, ticket_id)
|
|
49
|
+
@client.get(path(holder_ref, "/tickets/#{encode(ticket_id)}"))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Offer tickets to another person by email. Turning customer sends off in
|
|
53
|
+
# Settings › Ticket site doesn't stop your server; cut-offs still apply.
|
|
54
|
+
def create_holder_transfer(holder_ref, ticket_ids:, to_email:, idempotency_key: nil)
|
|
55
|
+
@client.post(path(holder_ref, "/transfers"),
|
|
56
|
+
{ "ticketIds" => ticket_ids, "toEmail" => to_email },
|
|
57
|
+
idempotency_key: idempotency_key, retry_policy: :header_replay)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# List a holder's ticket transfers.
|
|
61
|
+
def list_holder_transfers(holder_ref)
|
|
62
|
+
@client.get(path(holder_ref, "/transfers"))
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# Cancel a transfer that has not been accepted yet. Single-attempt.
|
|
66
|
+
def cancel_holder_transfer(holder_ref, transfer_id)
|
|
67
|
+
@client.post(path(holder_ref, "/transfers/#{encode(transfer_id)}/cancel"))
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Accept a transfer for its recipient. Single-attempt.
|
|
71
|
+
def accept_holder_transfer(holder_ref, transfer_id)
|
|
72
|
+
@client.post(path(holder_ref, "/transfers/#{encode(transfer_id)}/accept"))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Give back a holder's seat on one date, one per ticket: 1 to 20 tickets,
|
|
76
|
+
# all of one Season. A repeat with the same key answers with the same return.
|
|
77
|
+
# Turning give-backs off in Settings › Ticket site doesn't stop your server;
|
|
78
|
+
# cut-offs still apply.
|
|
79
|
+
def create_holder_return(holder_ref, ticket_ids:, idempotency_key: nil)
|
|
80
|
+
@client.post(path(holder_ref, "/returns"), { "ticketIds" => ticket_ids },
|
|
81
|
+
idempotency_key: idempotency_key, retry_policy: :header_replay)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Start a SeatLayer checkout that renews one of a holder's offers (+renewalOffer+
|
|
85
|
+
# on +list_holder_seasons+). Send the buyer to +payment.url+. Retried with one
|
|
86
|
+
# Idempotency-Key, which answers the same order.
|
|
87
|
+
def create_holder_renewal_checkout(holder_ref, offer_id, return_url:, buyer_email: nil,
|
|
88
|
+
buyer_name: nil, provider: nil, idempotency_key: nil)
|
|
89
|
+
@client.post(path(holder_ref, "/renewal-offers/#{encode(offer_id)}/checkout"),
|
|
90
|
+
compact({ "returnUrl" => return_url, "buyerEmail" => buyer_email,
|
|
91
|
+
"buyerName" => buyer_name, "provider" => provider }),
|
|
92
|
+
idempotency_key: idempotency_key, retry_policy: :header_replay)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Decline one of a holder's renewal offers and release its seats. +reason+
|
|
96
|
+
# (1 to 200 characters) is kept on the offer as +declineReason+; declining
|
|
97
|
+
# again answers the same offer, with the first reason. Single-attempt.
|
|
98
|
+
def decline_holder_renewal_offer(holder_ref, offer_id, reason: nil)
|
|
99
|
+
@client.post(path(holder_ref, "/renewal-offers/#{encode(offer_id)}/decline"),
|
|
100
|
+
compact({ "reason" => reason }))
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
private
|
|
104
|
+
|
|
105
|
+
def path(holder_ref, suffix = "")
|
|
106
|
+
"/v1/holders/#{encode(holder_ref)}#{suffix}"
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
@@ -64,17 +64,8 @@ module SeatLayer
|
|
|
64
64
|
|
|
65
65
|
def request(method, path, query: nil, body: nil, raw_body: nil, content_type: nil,
|
|
66
66
|
idempotency_key: nil, retry_policy: :none)
|
|
67
|
-
url =
|
|
68
|
-
|
|
69
|
-
pairs = query.compact
|
|
70
|
-
url += "?#{URI.encode_www_form(pairs)}" unless pairs.empty?
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
headers = {
|
|
74
|
-
"Authorization" => "Bearer #{@secret_key}",
|
|
75
|
-
"Accept" => "application/json",
|
|
76
|
-
"User-Agent" => "seatlayer-ruby"
|
|
77
|
-
}
|
|
67
|
+
url = build_url(path, query)
|
|
68
|
+
headers = default_headers
|
|
78
69
|
payload = build_payload(body, raw_body, content_type, headers)
|
|
79
70
|
|
|
80
71
|
# Only operations with exact server-side response replay get an automatic
|
|
@@ -97,6 +88,13 @@ module SeatLayer
|
|
|
97
88
|
request("GET", path, query: query)
|
|
98
89
|
end
|
|
99
90
|
|
|
91
|
+
# Internal path for CSV exports. Same auth, retries and error mapping as
|
|
92
|
+
# #get, but a success body comes back as the raw String, never parsed.
|
|
93
|
+
def get_text(path, query = nil)
|
|
94
|
+
headers = default_headers.merge("Accept" => "text/csv")
|
|
95
|
+
execute("GET", build_url(path, query), headers, nil, retry_allowed: true, text: true)
|
|
96
|
+
end
|
|
97
|
+
|
|
100
98
|
def post(path, body = nil, idempotency_key: nil, retry_policy: :none)
|
|
101
99
|
request("POST", path, body: body, idempotency_key: idempotency_key, retry_policy: retry_policy)
|
|
102
100
|
end
|
|
@@ -125,6 +123,22 @@ module SeatLayer
|
|
|
125
123
|
|
|
126
124
|
private
|
|
127
125
|
|
|
126
|
+
def build_url(path, query)
|
|
127
|
+
url = @base_url + path
|
|
128
|
+
return url unless query
|
|
129
|
+
|
|
130
|
+
pairs = query.compact
|
|
131
|
+
pairs.empty? ? url : "#{url}?#{URI.encode_www_form(pairs)}"
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def default_headers
|
|
135
|
+
{
|
|
136
|
+
"Authorization" => "Bearer #{@secret_key}",
|
|
137
|
+
"Accept" => "application/json",
|
|
138
|
+
"User-Agent" => "seatlayer-ruby"
|
|
139
|
+
}
|
|
140
|
+
end
|
|
141
|
+
|
|
128
142
|
def build_payload(body, raw_body, content_type, headers)
|
|
129
143
|
raise ArgumentError, "body and raw_body are mutually exclusive" if !body.nil? && !raw_body.nil?
|
|
130
144
|
|
|
@@ -140,7 +154,7 @@ module SeatLayer
|
|
|
140
154
|
|
|
141
155
|
# The retry loop, extracted from #request so each piece stays readable: the
|
|
142
156
|
# public method builds the call, this one decides how many times to make it.
|
|
143
|
-
def execute(method, url, headers, payload, retry_allowed:)
|
|
157
|
+
def execute(method, url, headers, payload, retry_allowed:, text: false)
|
|
144
158
|
last_error = nil
|
|
145
159
|
|
|
146
160
|
@max_retries.times do |attempt|
|
|
@@ -155,7 +169,7 @@ module SeatLayer
|
|
|
155
169
|
end
|
|
156
170
|
|
|
157
171
|
status = response[:status]
|
|
158
|
-
return parse_success(status, response[:body]) if status >= 200 && status < 300
|
|
172
|
+
return parse_success(status, response[:body], text) if status >= 200 && status < 300
|
|
159
173
|
|
|
160
174
|
error_body = decode_error_body(response[:body])
|
|
161
175
|
retry_after = parse_retry_after(response[:headers], error_body)
|
|
@@ -183,7 +197,8 @@ module SeatLayer
|
|
|
183
197
|
{}
|
|
184
198
|
end
|
|
185
199
|
|
|
186
|
-
def parse_success(status, body)
|
|
200
|
+
def parse_success(status, body, text)
|
|
201
|
+
return body.to_s if text
|
|
187
202
|
return {} if status == 204 || body.nil? || body.empty?
|
|
188
203
|
|
|
189
204
|
JSON.parse(body)
|
data/lib/seatlayer/inventory.rb
CHANGED
|
@@ -205,9 +205,26 @@ module SeatLayer
|
|
|
205
205
|
|
|
206
206
|
# Manage webhook subscriptions. To VERIFY a delivery, see SeatLayer::Webhook.
|
|
207
207
|
class Webhooks < Resource
|
|
208
|
+
# All 58 public event names, in the order the API lists them.
|
|
208
209
|
EVENT_NAMES = [
|
|
209
|
-
"seat.booked", "seat.released", "seat.blocked", "hold.expired",
|
|
210
|
-
"hold.
|
|
210
|
+
"seat.booked", "seat.released", "seat.blocked", "hold.expired", "hold.created",
|
|
211
|
+
"hold.extended", "event.created", "event.soldout", "object.resale.listed",
|
|
212
|
+
"object.resale.unlisted", "object.resale.sold", "customer.created", "customer.email_changed",
|
|
213
|
+
"order.paid", "order.refunded", "order.cancelled", "season.ticket.transfer_sent",
|
|
214
|
+
"season.ticket.transferred", "season.ticket.transfer_cancelled", "season.ticket.issued",
|
|
215
|
+
"season.ticket.voided", "season.structure.activated", "season.structure.closed",
|
|
216
|
+
"season.structure.archived", "season.plan.published", "season.plan.superseded",
|
|
217
|
+
"season.sales.opened", "season.sales.paused", "season.sales.ended", "season.hold.committed",
|
|
218
|
+
"season.hold.released", "season.hold.expired", "season.booking.confirmed",
|
|
219
|
+
"season.booking.cancelled", "season.booking.emergency_requested",
|
|
220
|
+
"season.occurrence.returned", "season.occurrence.reclaimed", "season.renewal.offered",
|
|
221
|
+
"season.renewal.intent_received", "season.renewal.renewed", "season.renewal.declined",
|
|
222
|
+
"season.renewal.lapsed", "season.renewal.released", "season.operation.partial_terminal",
|
|
223
|
+
"season.amendment.applied", "season.performance.added", "season.performance.removed",
|
|
224
|
+
"season.performance.past", "season.performance.postponed", "season.performance.cancelled",
|
|
225
|
+
"season.performance.rescheduled", "season.bulk_action.completed", "season.block.ready",
|
|
226
|
+
"season.block.released", "season.order.paid", "season.order.refunded", "series.created",
|
|
227
|
+
"series.dates_added"
|
|
211
228
|
].freeze
|
|
212
229
|
|
|
213
230
|
def list
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module SeatLayer
|
|
4
|
+
# Orders SeatLayer took through its own checkout: reads, CSV export,
|
|
5
|
+
# refunds, cancellations and ticket resends.
|
|
6
|
+
class Orders < Resource
|
|
7
|
+
# One page of orders. +from+ and +to+ are epoch milliseconds. +holder_ref+ lists
|
|
8
|
+
# one holder's orders: the Season order with that id and renewals offered to that
|
|
9
|
+
# reference. Each order carries "holderRef" and "customerId"; "buyer"/"email" is
|
|
10
|
+
# nil for a box office sale taken without one.
|
|
11
|
+
def list_orders(event_key: nil, season_key: nil, status: nil, from: nil, to: nil,
|
|
12
|
+
cursor: nil, limit: nil, holder_ref: nil)
|
|
13
|
+
@client.get("/v1/orders", compact({ "eventKey" => event_key, "seasonKey" => season_key,
|
|
14
|
+
"holderRef" => holder_ref,
|
|
15
|
+
"status" => status, "from" => from, "to" => to,
|
|
16
|
+
"cursor" => cursor, "limit" => limit }))
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Read one order.
|
|
20
|
+
def retrieve_order(order_id)
|
|
21
|
+
@client.get("/v1/orders/#{encode(order_id)}")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# List one order's tickets.
|
|
25
|
+
def list_order_tickets(order_id)
|
|
26
|
+
@client.get("/v1/orders/#{encode(order_id)}/tickets")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# One page of an event's orders. +search+ is sent as the API's +q+
|
|
30
|
+
# parameter; +from+ and +to+ are epoch milliseconds.
|
|
31
|
+
def list_event_orders(event_key, search: nil, status: nil, paid_by: nil, from: nil, to: nil,
|
|
32
|
+
cursor: nil, limit: nil)
|
|
33
|
+
@client.get("/v1/events/#{encode(event_key)}/orders",
|
|
34
|
+
compact({ "q" => search, "status" => status, "paidBy" => paid_by,
|
|
35
|
+
"from" => from, "to" => to, "cursor" => cursor, "limit" => limit }))
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Read one of an event's orders.
|
|
39
|
+
def retrieve_event_order(event_key, order_id)
|
|
40
|
+
@client.get("/v1/events/#{encode(event_key)}/orders/#{encode(order_id)}")
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Download an event's orders as CSV, with the same filters as
|
|
44
|
+
# +list_event_orders+. Returns the raw CSV text.
|
|
45
|
+
def export_event_orders_csv(event_key, search: nil, status: nil, paid_by: nil, from: nil,
|
|
46
|
+
to: nil)
|
|
47
|
+
@client.get_text("/v1/events/#{encode(event_key)}/orders.csv",
|
|
48
|
+
compact({ "q" => search, "status" => status, "paidBy" => paid_by,
|
|
49
|
+
"from" => from, "to" => to }))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Refund an event order, in full or by +amount_minor+.
|
|
53
|
+
def refund_event_order(event_key, order_id, amount_minor: nil, idempotency_key: nil)
|
|
54
|
+
@client.post("/v1/events/#{encode(event_key)}/orders/#{encode(order_id)}/refund",
|
|
55
|
+
compact({ "amountMinor" => amount_minor }),
|
|
56
|
+
idempotency_key: idempotency_key, retry_policy: :header_replay)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Cancel an event order.
|
|
60
|
+
def cancel_event_order(event_key, order_id, reason:, note: nil, refund_confirmed: nil,
|
|
61
|
+
used_tickets_acknowledged: nil, notify_buyer: nil, idempotency_key: nil)
|
|
62
|
+
body = compact({ "reason" => reason, "note" => note, "refundConfirmed" => refund_confirmed,
|
|
63
|
+
"usedTicketsAcknowledged" => used_tickets_acknowledged,
|
|
64
|
+
"notifyBuyer" => notify_buyer })
|
|
65
|
+
@client.post("/v1/events/#{encode(event_key)}/orders/#{encode(order_id)}/cancel", body,
|
|
66
|
+
idempotency_key: idempotency_key, retry_policy: :header_replay)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Send an event order's tickets again. Single-attempt: never retried automatically.
|
|
70
|
+
def resend_event_order_tickets(event_key, order_id, email: nil)
|
|
71
|
+
@client.post("/v1/events/#{encode(event_key)}/orders/#{encode(order_id)}/resend",
|
|
72
|
+
compact({ "email" => email }))
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
data/lib/seatlayer/resources.rb
CHANGED
|
@@ -157,11 +157,14 @@ module SeatLayer
|
|
|
157
157
|
#
|
|
158
158
|
# Live availability counts cost one round-trip per event server-side. They
|
|
159
159
|
# are on by default because most callers of a single page want them; pass
|
|
160
|
-
# <tt>counts: false</tt> when paging a whole catalogue.
|
|
161
|
-
|
|
160
|
+
# <tt>counts: false</tt> when paging a whole catalogue. +series_key+ lists only
|
|
161
|
+
# the dates of one event series.
|
|
162
|
+
def list(workspace_id: nil, external_ref: nil, limit: nil, cursor: nil, counts: true,
|
|
163
|
+
series_key: nil)
|
|
162
164
|
query = compact({ "workspaceId" => workspace_id, "externalRef" => external_ref,
|
|
163
165
|
"limit" => limit, "cursor" => cursor })
|
|
164
166
|
query["counts"] = "0" unless counts
|
|
167
|
+
query["seriesKey"] = series_key unless series_key.nil?
|
|
165
168
|
@client.get("/v1/events", query)
|
|
166
169
|
end
|
|
167
170
|
|
|
@@ -249,6 +252,8 @@ module SeatLayer
|
|
|
249
252
|
@client.post("/v1/events/#{encode(event_key)}/close")
|
|
250
253
|
end
|
|
251
254
|
|
|
255
|
+
# Open a paused event's sales again. A date its season cancelled never opens
|
|
256
|
+
# again: 409 season_date_cancelled.
|
|
252
257
|
def reopen(event_key)
|
|
253
258
|
@client.post("/v1/events/#{encode(event_key)}/reopen")
|
|
254
259
|
end
|
|
@@ -289,5 +294,101 @@ module SeatLayer
|
|
|
289
294
|
@client.get("/v1/events/#{encode(event_key)}/log",
|
|
290
295
|
compact({ "limit" => limit, "before" => before }))
|
|
291
296
|
end
|
|
297
|
+
|
|
298
|
+
# Read who takes payment for the event, and what blocks a change.
|
|
299
|
+
def retrieve_event_buyer_checkout(event_key)
|
|
300
|
+
@client.get("/v1/events/#{encode(event_key)}/buyer-checkout")
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
# Choose who takes payment: "seatlayer" or "integrator". Single-attempt;
|
|
304
|
+
# +expected_revision+ stops two writers overwriting each other.
|
|
305
|
+
def replace_event_buyer_checkout(event_key, buyer_checkout:, expected_revision:)
|
|
306
|
+
@client.put("/v1/events/#{encode(event_key)}/buyer-checkout",
|
|
307
|
+
{ "buyerCheckout" => buyer_checkout, "expectedRevision" => expected_revision })
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Read the payment gateway the event uses, optionally for one +currency+.
|
|
311
|
+
def retrieve_event_payment_gateway(event_key, currency: nil)
|
|
312
|
+
@client.get("/v1/events/#{encode(event_key)}/payment-gateway",
|
|
313
|
+
compact({ "currency" => currency }))
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
# Assign a payment gateway connection to the event. Pass +nil+ to send an
|
|
317
|
+
# explicit JSON null. Single-attempt: never retried automatically.
|
|
318
|
+
def replace_event_payment_gateway(event_key, connection_id: UNSET, provider: UNSET)
|
|
319
|
+
@client.put("/v1/events/#{encode(event_key)}/payment-gateway",
|
|
320
|
+
supplied({ "connectionId" => connection_id, "provider" => provider }))
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# Read what the event still needs before it can sell.
|
|
324
|
+
def retrieve_event_sales_readiness(event_key)
|
|
325
|
+
@client.get("/v1/events/#{encode(event_key)}/sales/readiness")
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Check one order against the event's sales setup. Single-attempt.
|
|
329
|
+
def preflight_event_sales(event_key, order_id:)
|
|
330
|
+
@client.post("/v1/events/#{encode(event_key)}/sales/preflight", { "orderId" => order_id })
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
# Move the event's sales to another state (setup, testable, live, paused or ended).
|
|
334
|
+
# A date its season cancelled never opens again: moving it to testable or live
|
|
335
|
+
# answers 409 season_date_cancelled.
|
|
336
|
+
def transition_event_sales(event_key, to:, expected_revision:, reason: nil)
|
|
337
|
+
@client.post("/v1/events/#{encode(event_key)}/sales/transition",
|
|
338
|
+
compact({ "to" => to, "expectedRevision" => expected_revision,
|
|
339
|
+
"reason" => reason }))
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
# Read the event's booking fee.
|
|
343
|
+
def retrieve_event_booking_fee(event_key)
|
|
344
|
+
@client.get("/v1/events/#{encode(event_key)}/booking-fee")
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# Set the booking fee in minor units; +nil+ clears it and stays an explicit
|
|
348
|
+
# JSON null. Single-attempt: never retried automatically.
|
|
349
|
+
def replace_event_booking_fee(event_key, booking_fee_minor:)
|
|
350
|
+
@client.put("/v1/events/#{encode(event_key)}/booking-fee",
|
|
351
|
+
{ "bookingFeeMinor" => booking_fee_minor })
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# List the event's discount codes.
|
|
355
|
+
def list_event_discount_codes(event_key)
|
|
356
|
+
@client.get("/v1/events/#{encode(event_key)}/discount-codes")
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# Create a discount code. +kind+ is "percent" or "amount". Pass +nil+ for
|
|
360
|
+
# +starts_at+, +ends_at+ or +max_uses+ to send an explicit JSON null.
|
|
361
|
+
# Single-attempt: never retried automatically.
|
|
362
|
+
# rubocop:disable-next Metrics/ParameterLists
|
|
363
|
+
def create_event_discount_code(event_key, code:, kind:, percent: nil, amount_minor: nil,
|
|
364
|
+
starts_at: UNSET, ends_at: UNSET, max_uses: UNSET, active: nil)
|
|
365
|
+
body = compact({ "code" => code, "kind" => kind, "percent" => percent,
|
|
366
|
+
"amountMinor" => amount_minor, "active" => active })
|
|
367
|
+
body.merge!(supplied({ "startsAt" => starts_at, "endsAt" => ends_at, "maxUses" => max_uses }))
|
|
368
|
+
@client.post("/v1/events/#{encode(event_key)}/discount-codes", body)
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
# Change a discount code. Only the fields you pass are sent; pass +nil+ for
|
|
372
|
+
# +starts_at+, +ends_at+ or +max_uses+ to send an explicit JSON null.
|
|
373
|
+
# Single-attempt: never retried automatically.
|
|
374
|
+
# rubocop:disable-next Metrics/ParameterLists
|
|
375
|
+
def update_event_discount_code(event_key, code_id, code: nil, kind: nil, percent: nil,
|
|
376
|
+
amount_minor: nil, starts_at: UNSET, ends_at: UNSET,
|
|
377
|
+
max_uses: UNSET, active: nil, state: nil)
|
|
378
|
+
body = compact({ "code" => code, "kind" => kind, "percent" => percent,
|
|
379
|
+
"amountMinor" => amount_minor, "active" => active, "state" => state })
|
|
380
|
+
body.merge!(supplied({ "startsAt" => starts_at, "endsAt" => ends_at, "maxUses" => max_uses }))
|
|
381
|
+
@client.patch("/v1/events/#{encode(event_key)}/discount-codes/#{encode(code_id)}", body)
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
# End a discount code now, keeping its history.
|
|
385
|
+
def end_event_discount_code(event_key, code_id)
|
|
386
|
+
@client.post("/v1/events/#{encode(event_key)}/discount-codes/#{encode(code_id)}/end")
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
# Delete a discount code. The API answers 204, so this returns an empty Hash.
|
|
390
|
+
def delete_event_discount_code(event_key, code_id)
|
|
391
|
+
@client.delete("/v1/events/#{encode(event_key)}/discount-codes/#{encode(code_id)}")
|
|
392
|
+
end
|
|
292
393
|
end
|
|
293
394
|
end
|