Состояния мест и типы удержания

Seatmap.pro отслеживает каждое место на каждом событии через двухслойную модель состояний. Первый слой – небольшой закрытый набор состояний жизненного цикла, которые движок бронирования использует для управления конкурентным доступом и доступностью. Второй слой – открытый holdType, задаваемый для каждой организации, который несёт бизнес-контекст: почему это место удерживается, кто может его освободить и как оно должно выглядеть на схеме.

Два слоя

Слой Поле Значения Что определяет
Жизненный цикл state закрытый enum конкурентный доступ, доступность
Тип удержания holdType открытая строка политика освобождения, оплата, отображение

Движок бронирования проверяет лишь, находится ли место в состоянии ACTIVE, чтобы определить, можно ли его заблокировать. holdType – это метаданные, управляющие бизнес-процессом вокруг этого места.

Состояния жизненного цикла

Три состояния, фиксированные платформой.

Состояние Значение Доступно для брони
ACTIVE Доступно для выбора Да
LOCKED Недоступно; причину задаёт holdType Нет
SOLD Подтверждено и оформлено Нет

Типичный поток корзины переводит место ACTIVE → LOCKED → SOLD. Брошенная корзина возвращает его LOCKED → ACTIVE. Место, выведенное из эксплуатации – повреждённое, с ограниченным обзором или иначе снятое с продажи, – это просто LOCKED с типом удержания, который фиксирует причину: сегодня для этого подходит RESERVED, а отдельное значение по умолчанию OUT_OF_SERVICE запланировано.

NOTE Перечисление state в API также содержит значение BLOCKED. Платформа никогда его не устанавливает – ни одно место не возвращается в этом состоянии – и оно выводится из использования. Если вы делаете switch по state, считайте его недоступным.

Состояние каждого места события доступно через GET /api/private/v2.0/events/{id}/seats/ вместе с рядом, секцией и ценой места. Этот эндпоинт также поддерживает инкрементальное чтение: передайте наибольшее увиденное значение updatedAt обратно как lastUpdated, чтобы получить только изменившееся с тех пор.

Типы удержания

holdType – это строка, которую вы прикрепляете к месту при его переходе из ACTIVE. Она существует рядом с состоянием жизненного цикла и описывает причину удержания места.

Значения платформы по умолчанию

Два типа удержания поставляются из коробки:

Тип удержания Допустимое состояние Освобождается Оплата Отображение
CART LOCKED клиент, админ, система требуется In Cart
RESERVED LOCKED админ не требуется Reserved

CART – значение по умолчанию для эндпоинта /lock бронирования v2: отсутствие holdType в теле запроса разрешается в CART.

RESERVED – тип удержания для всего, что оператор удерживает вне продажи: место, отложенное для конкретного клиента, или выведенное из эксплуатации. Освобождается только явным вызовом /unlock.

WARNING Поле ttlSeconds ниже принимается и сохраняется как часть определения типа удержания, но автоматическое освобождение по истечении срока пока не применяется. Удержания сохраняются до явного вызова /unlock, /sale или /revertsale. Не рассчитывайте на то, что удержание освободится само.

Определение собственных типов удержания

Помимо двух значений по умолчанию, типы удержания настраиваются для вашей организации силами Seatmap.pro. Пришлите нам нужные определения, и мы применим их к вашей организации или к вашему арендатору, чтобы их унаследовала каждая организация под ним.

NOTE Самостоятельного эндпоинта для определения типов удержания сегодня нет – напишите в поддержку с нужными вам определениями.

Определение имеет такой вид:

{
  "holdTypes": {
    "PARTNER_HOLD": {
      "validStates": ["LOCKED"],
      "ttlSeconds": 3600,
      "releaseApi": "ADMIN,API",
      "paymentRequired": true,
      "displayName": "Partner Hold",
      "displayColor": "#8B008B"
    },
    "COMP": {
      "validStates": ["LOCKED", "SOLD"],
      "ttlSeconds": null,
      "releaseApi": "ADMIN",
      "paymentRequired": false,
      "displayName": "Complimentary",
      "displayColor": "#FFD700"
    }
  }
}

Справочник полей:

Поле Тип Описание
validStates массив строк Для каких состояний жизненного цикла допустим этот тип удержания. Запросы с недопустимым сочетанием отклоняются.
ttlSeconds целое число или null Предполагаемое окно автоосвобождения в секундах. Хранится как конфигурационные метаданные; автоосвобождение пока не применяется (см. примечание выше). null означает, что удержание сохраняется до явного освобождения.
releaseApi строка Список акторов через запятую, которым разрешено освобождать: CUSTOMER, ADMIN, SYSTEM, API.
paymentRequired boolean Должна ли за этим удержанием следовать оплата для перехода в SOLD.
skipLockedState boolean При true переход выполняется напрямую ACTIVE → SOLD (используется для процессов кассы).
displayName строка Человекочитаемая подпись, отображаемая в админ-интерфейсах.
displayColor строка Hex-цвет для оформления в рендерере.
displayIcon строка Необязательная ссылка на изображение или иконку для рендерера.

Наследование на уровне арендатора

Если ваша организация принадлежит арендатору, типы удержания можно определить на уровне арендатора один раз, и они применятся к каждой организации в нём. Переопределения на уровне организации имеют приоритет поле за полем, поэтому организация может, например, переопределить displayColor у CART, не переписывая полное определение.

Порядок разрешения при любом поиске типа удержания:

  1. Определение на уровне организации
  2. Определение на уровне арендатора
  3. Значения платформы по умолчанию

Эти три слоя объединяются. Если вы переопределяете только displayColor на уровне организации, остальная часть определения наследуется от арендатора или значения платформы по умолчанию.

Использование типов удержания в booking API

Payload блокировки бронирования v2 принимает необязательное поле holdType:

POST /api/private/v2.0/booking/lock?eventId=123e4567-e89b-12d3-a456-426614174000
Content-Type: application/json

{
  "sessionId": "abc123",
  "seats": [{ "id": 42 }],
  "holdType": "PARTNER_HOLD"
}

Когда место выходит из состояния ACTIVE, тип удержания проверяется:

  • Он должен быть определён для вызывающей организации – как значение платформы по умолчанию, запись на уровне арендатора или на уровне организации.
  • Его validStates должен включать целевое состояние жизненного цикла.

Неизвестные или несовпадающие типы удержания возвращают 400 Bad Request. Эндпоинты /unlock и /revertsale не принимают holdType – возврат места в ACTIVE очищает любое прикреплённое удержание.

Конкурентный доступ

Каждый переход состояния утверждает ожидаемое текущее состояние места как часть изменения. Два конкурентных запроса, блокирующих одно и то же место, не могут оба завершиться успешно: второй обнаруживает, что место уже не в ожидаемом состоянии, и это место возвращается в списке неуспешных попыток. Двойное бронирование тем самым исключено независимо от того, как пересекаются во времени потоки корзины, и без какой-либо синхронизации на стороне вызывающего.

Журнал аудита

Каждый успешный переход состояния записывается неизменяемо и фиксирует:

  • Прежнее и новое состояние жизненного цикла
  • Тип удержания на момент перехода
  • Идентификатор сессии (когда доступен)
  • Затронутое место или группу мест
  • Временную метку

Эта запись обеспечивает отчётность по конверсии – например, какая доля удержаний CART перешла в SOLD за неделю. Как API она сегодня не публикуется. Если история переходов по месту была бы полезна в вашем админ-инструментарии, напишите в поддержку, и мы её проработаем.

Интеграция с рендерером

Booking Renderer стилизует места по их состоянию жизненного цикла (ACTIVE, LOCKED, SOLD) из коробки.

Чтобы визуализировать значения holdType – или любое другое различие, нужное вашим сотрудникам – собственными цветами, анимациями или иконками, SDK рендерера предоставляет setSeatsState(seats, stateKey) и clearSeatsState(seats), управляемые декларативной конфигурацией theme.seatStyles.

IMPORTANT Эндпоинт мест возвращает состояние жизненного цикла state, но пока не возвращает holdType по каждому месту. Отслеживайте применённые вами типы удержания на своей стороне и сопоставляйте их с ключами состояний рендерера при отрисовке схемы. Возврат holdType в payload места запланирован.

См. Пользовательские состояния мест (Renderer SDK) для полного API, справочника типов и проработанных примеров.

Связанное

Введите название функции, настройки, эндпоинта или метода SDK.