Class: SeatLayer::Inventory
- Defined in:
- lib/seatlayer/inventory.rb
Overview
Holds, booking, blocking and availability.
Two complete flows, both first-class:
browser holds → retrieve_hold for authoritative pricing → charge → book(hold_id:)
backend books labels directly — box office, phone sales, comps
Never price from what the browser tells you. retrieve_hold is the
authoritative answer, which is why it is a separate call.
Constant Summary
Constants inherited from Resource
Instance Method Summary collapse
-
#block(event_key, labels:, release_at: nil) ⇒ Object
Hold inventory back from sale (house seats, production holds).
- #book(event_key, hold_id: nil, labels: nil, booking_ref: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) ⇒ Object
-
#book_best_available(event_key, qty:, booking_ref:, category_key: nil, zone_id: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) ⇒ Object
Pick and book in one call — the box-office shape.
- #box_office_book(event_key, labels:, booking_ref:, idempotency_key: nil) ⇒ Object
-
#extend_hold(event_key, hold_id, ttl_ms: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil) ⇒ Object
Push an active hold's expiry out by a fresh window before it lapses.
-
#hold(event_key, labels: nil, selections: nil, ttl_ms: nil, replace_hold_id: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) ⇒ Object
Explicit keywords keep allocation authority visible at every sale call.
-
#hold_best_available(event_key, qty:, category_key: nil, zone_id: nil, ttl_ms: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) ⇒ Object
Ask us to pick the best free objects and hold them.
-
#list_bookings(event_key, query: nil, state: nil, limit: nil, cursor: nil) ⇒ Object
One page of inventory booking lifecycles, newest first.
- #release(event_key, labels:, hold_id:) ⇒ Object
- #retrieve_availability(event_key) ⇒ Object
- #retrieve_booking(event_key, booking_ref) ⇒ Object
-
#retrieve_hold(event_key, hold_id) ⇒ Object
Authoritative items and prices.
- #unblock(event_key, labels:) ⇒ Object
- #unblock_all(event_key) ⇒ Object
-
#unbook(event_key, labels:, booking_ref:) ⇒ Object
Reverse a booking.
- #update_availability(event_key, fields) ⇒ Object
Methods inherited from Resource
Constructor Details
This class inherits a constructor from SeatLayer::Resource
Instance Method Details
#block(event_key, labels:, release_at: nil) ⇒ Object
Hold inventory back from sale (house seats, production holds).
106 107 108 109 |
# File 'lib/seatlayer/inventory.rb', line 106 def block(event_key, labels:, release_at: nil) @client.post(path(event_key, "/block"), compact({ "labels" => labels, "releaseAt" => release_at })) end |
#book(event_key, hold_id: nil, labels: nil, booking_ref: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) ⇒ Object
83 84 85 86 87 88 89 90 91 |
# File 'lib/seatlayer/inventory.rb', line 83 def book(event_key, hold_id: nil, labels: nil, booking_ref: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) body = compact({ "holdId" => hold_id, "labels" => labels, "bookingRef" => normalise_booking_ref(booking_ref), "channelIds" => channel_ids, "ignoreChannelRestrictions" => ignore_channel_restrictions, "reason" => reason }) @client.post(path(event_key, "/book"), body, idempotency_key: idempotency_key) end |
#book_best_available(event_key, qty:, booking_ref:, category_key: nil, zone_id: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) ⇒ Object
Pick and book in one call — the box-office shape.
Prefer this over hold-then-book when payment is already taken: a failure between two calls would strand inventory until the TTL expired.
47 48 49 50 51 52 53 54 55 56 |
# File 'lib/seatlayer/inventory.rb', line 47 def book_best_available(event_key, qty:, booking_ref:, category_key: nil, zone_id: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) body = compact({ "qty" => qty, "bookingRef" => normalise_booking_ref(booking_ref), "categoryKey" => category_key, "zoneId" => zone_id, "channelIds" => channel_ids, "ignoreChannelRestrictions" => ignore_channel_restrictions, "reason" => reason }) @client.post(path(event_key, "/best-available-book"), body, idempotency_key: idempotency_key) end |
#box_office_book(event_key, labels:, booking_ref:, idempotency_key: nil) ⇒ Object
93 94 95 96 97 |
# File 'lib/seatlayer/inventory.rb', line 93 def box_office_book(event_key, labels:, booking_ref:, idempotency_key: nil) @client.post(path(event_key, "/box-book"), { "labels" => labels, "bookingRef" => normalise_booking_ref(booking_ref) }, idempotency_key: idempotency_key) end |
#extend_hold(event_key, hold_id, ttl_ms: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil) ⇒ Object
Push an active hold's expiry out by a fresh window before it lapses.
Use this rather than release-and-re-hold when an order takes longer than
the checkout window — invoiced sales, a phone order on hold. Releasing
first hands the seats to whoever is racing for them in between. A hold that
is gone, expired, or at its renewal cap answers 409 cannot_extend.
65 66 67 68 69 70 71 72 |
# File 'lib/seatlayer/inventory.rb', line 65 def extend_hold(event_key, hold_id, ttl_ms: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil) body = compact({ "holdId" => hold_id, "ttlMs" => ttl_ms, "channelIds" => channel_ids, "ignoreChannelRestrictions" => ignore_channel_restrictions, "reason" => reason }) @client.post(path(event_key, "/extend"), body) end |
#hold(event_key, labels: nil, selections: nil, ttl_ms: nil, replace_hold_id: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) ⇒ Object
Explicit keywords keep allocation authority visible at every sale call. rubocop:disable Metrics/ParameterLists
16 17 18 19 20 21 22 23 24 25 |
# File 'lib/seatlayer/inventory.rb', line 16 def hold(event_key, labels: nil, selections: nil, ttl_ms: nil, replace_hold_id: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) body = compact({ "labels" => labels, "selections" => selections, "ttlMs" => ttl_ms, "replaceHoldId" => replace_hold_id, "channelIds" => channel_ids, "ignoreChannelRestrictions" => ignore_channel_restrictions, "reason" => reason }) @client.post(path(event_key, "/hold"), body, idempotency_key: idempotency_key) end |
#hold_best_available(event_key, qty:, category_key: nil, zone_id: nil, ttl_ms: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) ⇒ Object
Ask us to pick the best free objects and hold them.
The picker is the one the buyer widget uses, so a phone order and a web
order get the same answer for the same inventory. A qty above the server
cap is clamped, not rejected.
32 33 34 35 36 37 38 39 40 41 |
# File 'lib/seatlayer/inventory.rb', line 32 def hold_best_available(event_key, qty:, category_key: nil, zone_id: nil, ttl_ms: nil, channel_ids: nil, ignore_channel_restrictions: nil, reason: nil, idempotency_key: nil) body = compact({ "qty" => qty, "categoryKey" => category_key, "zoneId" => zone_id, "ttlMs" => ttl_ms, "channelIds" => channel_ids, "ignoreChannelRestrictions" => ignore_channel_restrictions, "reason" => reason }) @client.post(path(event_key, "/best-available"), body, idempotency_key: idempotency_key) end |
#list_bookings(event_key, query: nil, state: nil, limit: nil, cursor: nil) ⇒ Object
One page of inventory booking lifecycles, newest first.
128 129 130 131 |
# File 'lib/seatlayer/inventory.rb', line 128 def list_bookings(event_key, query: nil, state: nil, limit: nil, cursor: nil) @client.get(path(event_key, "/bookings"), compact({ "q" => query, "state" => state, "limit" => limit, "cursor" => cursor })) end |
#release(event_key, labels:, hold_id:) ⇒ Object
79 80 81 |
# File 'lib/seatlayer/inventory.rb', line 79 def release(event_key, labels:, hold_id:) @client.post(path(event_key, "/release"), { "labels" => labels, "holdId" => hold_id }) end |
#retrieve_availability(event_key) ⇒ Object
119 120 121 |
# File 'lib/seatlayer/inventory.rb', line 119 def retrieve_availability(event_key) @client.get(path(event_key, "/availability")) end |
#retrieve_booking(event_key, booking_ref) ⇒ Object
133 134 135 |
# File 'lib/seatlayer/inventory.rb', line 133 def retrieve_booking(event_key, booking_ref) @client.get(path(event_key, "/bookings/#{encode(normalise_booking_ref(booking_ref))}")) end |
#retrieve_hold(event_key, hold_id) ⇒ Object
Authoritative items and prices. Charge from this, not the browser.
75 76 77 |
# File 'lib/seatlayer/inventory.rb', line 75 def retrieve_hold(event_key, hold_id) @client.get(path(event_key, "/holds/#{encode(hold_id)}")) end |
#unblock(event_key, labels:) ⇒ Object
111 112 113 |
# File 'lib/seatlayer/inventory.rb', line 111 def unblock(event_key, labels:) @client.post(path(event_key, "/unblock"), { "labels" => labels }) end |
#unblock_all(event_key) ⇒ Object
115 116 117 |
# File 'lib/seatlayer/inventory.rb', line 115 def unblock_all(event_key) @client.post(path(event_key, "/unblock-all")) end |
#unbook(event_key, labels:, booking_ref:) ⇒ Object
Reverse a booking. Requires a key with cancel authority.
100 101 102 103 |
# File 'lib/seatlayer/inventory.rb', line 100 def unbook(event_key, labels:, booking_ref:) @client.post(path(event_key, "/unbook"), { "labels" => labels, "bookingRef" => normalise_booking_ref(booking_ref) }) end |
#update_availability(event_key, fields) ⇒ Object
123 124 125 |
# File 'lib/seatlayer/inventory.rb', line 123 def update_availability(event_key, fields) @client.post(path(event_key, "/availability"), fields) end |