Жизненный цикл заказа
Заказ несёт два независимых поля состояния, которые легко перепутать:
state— состояние создания заказа внутри AploDelivery (от «принят» до «создан в ресторане» или «отклонён»). Управляется плагином на кассе через claim/ACK-протокол.deliveryStatus— статус уже созданной в iiko доставки (от «новый» до «доставлен»). Появляется только после того, какstateдошёл доcreated_verified.
Плюс отдельное поле cancelState, которое описывает попытку отмены и не является частью основной цепочки state — см. Отмену заказа.
Диаграмма состояний state
stateDiagram-v2
[*] --> queued: POST /v1/orders (201)
queued --> claimed: плагин на кассе забирает заказ (claim)
queued --> cancelled: партнёр отменяет ДО claim (POST .../cancel)
claimed --> prepared
claimed --> rejected_final: плагин не смог подготовить заказ
prepared --> create_sending
prepared --> rejected_final: плагин не смог отправить заказ
create_sending --> created_verified: iiko подтвердил создание
create_sending --> reconciliation_required: ответ iiko не получен однозначно
reconciliation_required --> created_verified: сверка подтвердила создание
reconciliation_required --> manual_review: сверка не смогла подтвердить
created_verified --> [*]
rejected_final --> [*]
manual_review --> [*]
cancelled --> [*]
Важные свойства, которых нет на схеме, но которые нужно знать:
iikoOrderIdиiikoDeliveryIdвыданы AploDelivery сразу при создании (ещё в состоянииqueued) — это стабильные UUID самого AploDelivery, они присутствуют в ответе с первой секунды, до того как плагин вообще увидел заказ. Не путайте их с моментом фактического создания заказа в iiko (это происходит на переходе вcreated_verified).- Из
claimedзаказ может быть перезабран (re-claim) только если предыдущий claim истёк по лease —prepared,create_sendingиreconciliation_requiredникогда не переставляются в очередь автоматически. - После
create_sendingрезультат только один из двух:created_verifiedилиreconciliation_required. Изreconciliation_requiredесть ровно один способ дальше — эндпоинт сверки (внутренний, плагинский), результат —created_verifiedлибоmanual_review. rejected_finalдостижим только до начала отправки в iiko (claimed/prepared) — если заказ уже дошёл доcreate_sending, «отклонён» в этом смысле уже невозможен: дальше толькоcreated_verified/reconciliation_required/manual_review.cancelled(терминальное состояние создания) достижимо только изqueued, и только через партнёрский запрос отмены до того, как плагин забрал заказ. Отмена уже подхваченного заказа — это другой механизм,cancelState, см. Отмену заказа;stateпри этом остаётсяcreated_verified, вcancelledне переходит.
Значения state и подписи для пользователя
state | Подпись в UI (RU) | Смысл |
|---|---|---|
queued | «Принят» | заказ создан в AploDelivery, ждёт, пока плагин на кассе его заберёт |
claimed | «Взято в обработку» | плагин забрал заказ, готовит к отправке |
prepared | «Подготовлен к отправке» | заказ прошёл маппинг товаров/адреса, готов уйти в iiko |
create_sending | «Передаётся в ресторан» | запрос создания уже отправлен в iiko, ответ ещё не подтверждён |
created_verified | «Создан в ресторане» | заказ подтверждённо существует в iiko, дальше действует deliveryStatus |
reconciliation_required | «Требует сверки» | ответ iiko неоднозначен, идёт автоматическая сверка |
manual_review | «На ручной проверке» | сверка не смогла подтвердить создание автоматически, нужен человек |
rejected_final | «Отклонён» | заказ не был создан, дальнейших действий по нему нет |
cancelled | «Отменён» | заказ отменён партнёром до того, как его забрал плагин |
Диаграмма deliveryStatus
deliveryStatus начинает заполняться только после state = created_verified и обновляется плагином при каждом опросе кассы:
stateDiagram-v2
[*] --> Unconfirmed
Unconfirmed --> New
New --> Waiting
Waiting --> OnWay
OnWay --> Delivered
Delivered --> Closed
New --> Cancelled
Unconfirmed --> Cancelled
Closed --> [*]
Cancelled --> [*]
deliveryStatus | Подпись в UI (RU) |
|---|---|
Unconfirmed | «Статус не подтверждён» |
New | «Новый» |
CookingStarted | «Готовится» |
CookingCompleted | «Приготовлен» |
Waiting | «Ожидает» |
OnWay | «В пути» |
Delivered | «Доставлен» |
Closed | «Закрыт» |
Cancelled | «Отменён» |
Диаграмма выше показывает типичный порядок на практике. Сервер не проверяет, что переход между конкретными значениями допустим — он принимает любое валидное значение enum и применяет его как текущее, если его occurredAt не старше уже сохранённого (см. «Порядок и идемпотентность» ниже). Единственное жёсткое правило — Delivered, Closed и Cancelled терминальны (domain.DeliveryStatus.Terminal()): именно на них плагин прекращает опрашивать заказ. Не пишите на своей стороне строгий валидатор переходов между статусами доставки — он будет ломаться на реальных данных из iiko.
Важно: CookingStarted/CookingCompleted на текущих кассах не приходят
Кассы ВиЛ сейчас работают на iiko Front API V8 8.7, где у DeliveryStatus только семь значений: Unconfirmed, New, Waiting, OnWay, Delivered, Closed, Cancelled. Сервер AploDelivery технически принимает и CookingStarted, и CookingCompleted — они есть в контракте на будущее (более новая версия iiko Front API их поддерживает), — но установленный сейчас плагин их не отправляет. Между «Новый» и «Ожидает» заказ фактически готовится, но отдельного события об этом партнёр не получит.
Практическое следствие: не проектируйте UI-шаг, который блокируется ожиданием CookingStarted/CookingCompleted. Переход New → Waiting — это и есть сигнал «кухня закончила и заказ ждёт курьера/самовывоза» на текущей версии касс.
Порядок и идемпотентность обновлений
- Обновления
deliveryStatusидемпотентны поeventIdплагина. - Более старое по
occurredAtсобытие, чем уже сохранённый статус, записывается в историю, но не перезаписывает текущийdeliveryStatus— не удивляйтесь, если вебхук пришёл, а видимый статус заказа не изменился: значит событие оказалось «из прошлого» относительно уже применённого. deliveryStatus,deliveryStatusAtиcancelReasonв JSON присутствуют всегда (могут бытьnull), а не отсутствуют как ключи — не полагайтесь наhasOwnProperty/in, проверяйте значение.
Плагин перестаёт опрашивать статус доставки конкретного заказа через 48 часов после создания, даже если тот так и не дошёл до терминального статуса — на практике это касается только аномально зависших заказов, но если вы видите заказ без обновлений deliveryStatus больше двух суток, дальнейших автоматических обновлений уже не будет.
Как узнать текущее состояние
- Вебхуки
order.state_changedиorder.delivery_status_changed— основной канал, см. Вебхуки. - Резервный поллинг:
GET /v1/orders/{id}?source=...по UUID заказа илиGET /v1/orders?externalOrderId=...по вашему собственному ID — см. Быстрый старт.