Зафиксировать факт оплаты. Записывает payment_method, paid_amount, rrn, card_last4. Не меняет статус заказа (изменено в BR 2.5 — раньше переводил в ready).
Допустимо из статусов ready, delivered (оплата может идти до выдачи, или курьер принимает наличку после доставки). Из других статусов — 409 INVALID_TRANSITION.
Параметр
Значение
Auth
Bearer JWT (Cashier, Manager)
Content-Type
application/json
Path Parameters
Param
Type
Description
id
uuid
ID заказа
Request Body
{ "method": "cash", // required: cash | card | qr | mixed "amount": 630.00, // required "rrn": "string", // optional — для card/qr "card_last4": "1234" // optional — для card}
Завершить заказ (выдан клиенту). Допустимо из ready (для внутренних заказов) или delivered (для доставки после курьера). Проставляет completed_at, переводит в closed.
Инвариант(добавлено в BR 2.5): paid_at IS NOT NULL обязательно, иначе 409 ORDER_NOT_PAID. Legacy-записи без paid_at (до BR 2.5) этому правилу не подчиняются — проверяется только для новых переходов.
Прикрепить клиента к заказу. Вызывается с POS (кассир после поиска/создания клиента) или из админки. Только для незакрытых заказов.
Параметр
Значение
Auth
Bearer JWT + permission customers.create_quick (для кассира на POS) или orders.edit (для менеджера в админке)
Content-Type
application/json
Path Parameters
Param
Type
Description
id
uuid
ID заказа
Request Body
{ "customer_id": "uuid" }
Если текущий заказ уже имеет customer_id — он заменяется.
Response 200
Заказ с обновлённым customer_id (полный объект как в GET /orders/{id}).
Errors
Code
HTTP
Описание
ORDER_NOT_FOUND
404
CUSTOMER_NOT_FOUND
404
Клиент не существует (Order Service валидирует через GET /internal/customers/{id} Customer Service) или другая франшиза
ORDER_FINALIZED
422
Заказ в статусе closed или cancelled — клиента менять нельзя
UNAUTHORIZED
401
FORBIDDEN
403
DELETE /orders/{id}/customer
(BR 3.1)
Открепить клиента от заказа (обнулить customer_id). Только для незакрытых заказов.
Параметр
Значение
Auth
Bearer JWT + permission customers.create_quick или orders.edit
Response 204
Errors
Code
HTTP
Описание
ORDER_NOT_FOUND
404
ORDER_FINALIZED
422
Заказ в статусе closed или cancelled
Жизненный цикл — переходы статусов (BR 2.5)
Секция добавлена в BR 2.5. Каждый endpoint = явный переход одного направления между статусами. Ошибка 409 INVALID_TRANSITION если текущий статус не допускает перехода.
POST /orders/{id}/start-cooking
«Начать готовку» — переход new → accepted. Триггерит кухню / повара начать обработку заказа. Проставляет accepted_at, accepted_by.
Shortcut для быстрой продажи: new → closed за один вызов. Разрешён только если order_type = takeawayиrequires_kitchen = false (в заказе нет позиций, требующих приготовления). Внутренне выполняет pay + close атомарно.
Параметр
Значение
Auth
Bearer JWT (Cashier / Manager с orders.edit)
Content-Type
application/json
Path Parameters
Param
Type
Description
id
uuid
ID заказа
Request Body
Тот же что и у POST /orders/{id}/pay — { method, amount, rrn, card_last4 }.
Response 200
Заказ в статусе closed со всеми полями paid_at и completed_at.
Errors
Code
HTTP
Описание
UNAUTHORIZED
401
FORBIDDEN
403
ORDER_NOT_FOUND
404
INVALID_TRANSITION
409
Заказ не в статусе new
ORDER_FLOW_MISMATCH
409
Тип не takeaway или requires_kitchen=true — нужен полный flow
VALIDATION_ERROR
400
Invalid payment body
POST /orders/{id}/hand-over-to-courier
Передать заказ курьеру — переход ready → handed_over. Проставляет handed_over_at, courier_id.
Параметр
Значение
Auth
Bearer JWT (Cashier / Manager с orders.edit)
Content-Type
application/json
Path Parameters
Param
Type
Description
id
uuid
ID заказа
Request Body
{ "courier_id": "uuid"}
Field
Type
Required
Description
courier_id
uuid
yes
ID сотрудника-курьера (должен иметь permission orders.delivery)
Активные заказы для выбранных кухонных станций, для подгрузки списка на KDS-устройстве. Возвращает заказы в статусе accepted (или указанном) с позициями указанных станций. Позиции других станций тоже возвращаются (для контекста), но KDS-приложение их рендерит серым без управления.
Позиции возвращаются все — фильтрация по station_ids делается на клиенте/в pos-bff (для отображения серых позиций в карточке).
Errors
Code
HTTP
Описание
UNAUTHORIZED
401
Невалидный X-Service-Token
INVALID_PARAMS
400
Неправильный формат station_ids или отсутствуют обязательные query
PATCH /orders/{id}/items/{itemId}/kitchen-status
(BR 5.1 — KDS)
Изменение kitchen_status одной позиции через KDS-устройство (тап «В работе» или «Готово»). Откат ready → preparing запрещён.
Параметр
Значение
Auth
Bearer JWT с permission kds.access
Content-Type
application/json
Path Parameters
Param
Type
Description
id
uuid
ID заказа
itemId
uuid
ID позиции
Request Body
{ "kitchen_status": "preparing" }
Допустимые значения: preparing, ready. (pending через KDS не выставляется — это default.)
Response 200
Обновлённый item (формат как в GET /orders/{id} → items[]).
Errors
Code
HTTP
Описание
UNAUTHORIZED
401
FORBIDDEN
403
Нет permission kds.access
INVALID_FRANCHISE
403
Multi-tenancy violation
ORDER_NOT_FOUND
404
ITEM_NOT_FOUND
404
ORDER_NOT_IN_KITCHEN_FLOW
422
Заказ не в accepted
KITCHEN_STATUS_BACKWARD
422
Попытка ready → preparing (откат запрещён)
VALIDATION_ERROR
400
Невалидное значение kitchen_status
Side-effects
preparing → kitchen_started_at = NOW() (если ещё не было)
ready → kitchen_ready_at = NOW()
Публикуется order.item.kitchen_status_changed (см. Events)
Если все items заказа в ready → orders.status = ready, ready_at = NOW(), событие order.ready с trigger=kds_auto
PATCH /orders/{id}/kitchen-status
(BR 5.1 — KDS)
Atomic batch — закрыть все позиции одной кухонной станции одним вызовом. Используется кнопкой «Готово» по станции на KDS.
Параметр
Значение
Auth
Bearer JWT с permission kds.access
Content-Type
application/json
Path Parameters
Param
Type
Description
id
uuid
ID заказа
Query Parameters
Param
Type
Required
Description
station_id
uuid
yes
Станция, чьи позиции массово закрываются
Request Body
{ "kitchen_status": "ready" }
В P0 поддерживается только ready (массовое закрытие). preparing для batch — не имеет смысла.
Response 200
Обновлённый заказ со всеми позициями (формат как GET /orders/{id}).
Errors
Code
HTTP
Описание
UNAUTHORIZED
401
FORBIDDEN
403
Нет permission kds.access
INVALID_FRANCHISE
403
ORDER_NOT_FOUND
404
STATION_NOT_FOUND
404
На станции нет позиций в этом заказе
ORDER_NOT_IN_KITCHEN_FLOW
422
Заказ не в accepted
STATION_NOT_READY
422
Не все позиции этой станции готовы (был pending/preparing без принудительного «Готово») — kdc сам должен вызвать PATCH /items/{itemId}/kitchen-status сначала
VALIDATION_ERROR
400
Side-effects
Для каждой позиции с kitchen_station_id = station_id И kitchen_status != 'ready' ставится kitchen_status = 'ready', kitchen_ready_at = NOW()
Публикуется одно событие order.item.kitchen_status_changed per item
Триггерится автопереход accepted → ready если все позиции готовы
Альтернативная семантика (P1+)
В P0 endpoint требует чтобы все позиции станции были предварительно в ready. Это даёт более явный пользовательский поток: повар сначала тапает «Готово» на каждой позиции, потом «Готово на станцию» — sanity check. В P1+ может быть relaxed.
GET /internal/orders/customer-summary
(BR 3.1)
Агрегированная статистика заказов клиента. Используется Customer Service для пересчёта dynamic групп (правила total_spent_all_time, days_inactive и т.п.).
Учитываются только заказы со статусом closed (завершённые с оплатой). Возвраты (refund_records) уменьшают total_spent_*.
Errors
Code
HTTP
Описание
UNAUTHORIZED
401
Нет или невалидный X-Service-Token
POST /internal/orders/{orderId}/refund
Создать запись возврата для существующего оплаченного заказа. Вызывается из POS BFF (кассир на терминале) или Admin BFF (менеджер в админке). Идемпотентен по client_refund_id: повторный вызов с тем же id возвращает 200 OK и существующую запись вместо 201.
Публикует Kafka-событие order.refunded (при новом создании). Не публикует при идемпотентном повторе.
Errors
Code
HTTP
Описание
VALIDATION_ERROR
400
Невалидное тело (amount ≤ 0, нет client_refund_id)
ORDER_NOT_FOUND
404
Заказ не найден
ORDER_NOT_PAID
422
Нельзя возвращать неоплаченный заказ
REFUND_EXCEEDS_ORDER_TOTAL
422
Суммарный возврат превысил бы сумму заказа
POST /internal/shifts/open
Зафиксировать факт открытия кассовой смены на POS-терминале. Order Service не хранит shift persistence — только публикует Kafka pos.shift.opened для консьюмеров (админка). Вызывается POS BFF при явном открытии смены кассиром через ServiceMenu.