Изменения брони
Что можно сделать с бронью после оформления: изменить данные, отменить, восстановить, перенести на
другую смену, поселить детей вместе, получить путёвку. Для всех изменений нужно право bookings,
для чтения — read.
| Нужно | Запрос |
|---|---|
| Изменить данные | PATCH /bookings/{id} |
| Отменить | POST /bookings/{id}/cancel |
| Восстановить отменённую | POST /bookings/{id}/restore |
| Перенести на другую смену | POST /bookings/{id}/move |
| Поселить вместе | POST /bookings/{id}/together |
| История изменений | GET /bookings/{id}/history |
| Путёвка и её PDF | GET /bookings/{id}/voucher, GET /bookings/{id}/voucher.pdf |
| Найти по номеру вашей CRM | GET /bookings/by-external-id/{external_id} |
Изменить бронь
PATCH /bookings/{id} — передайте только то, что меняется. Чего нет в теле — не меняется.
Idempotency-Key для PATCH не нужен: повтор той же правки даёт тот же результат.
Code
Ответ 200 — бронь целиком, уже с изменениями и новой version.
Что можно менять:
| Поле | Как |
|---|---|
child.full_name, child.birth_date, child.city_id | ФИО, дата рождения, город ребёнка |
parent.full_name, parent.phone | ФИО и телефон родителя |
payer_phone | Телефон плательщика. Пустая строка "" — платит родитель |
needs_transfer, transfer_point_id | Трансфер и точка посадки |
discount | Скидка (amount, note) — в пределах max_discount смены |
comment | Комментарий |
external_id | Не передано — не менять; строка — заменить; null — стереть |
metadata | Заменяет ваши метки целиком (передайте все пары, которые должны остаться) |
partner_manager | Кто продал. Пустая строка — снять |
Что важно:
- Деньги пересчитываются сами. Изменили трансфер или скидку — меняются
totalиdebt, а живой счёт Kaspi на старую сумму лагерь гасит и выставляет новый (см. Счета Kaspi). - ФИО или телефон у брони без даты рождения. Если у брони (старой, оформленной ещё в CRM
лагеря) нет даты рождения ребёнка, сменить ФИО ребёнка, ФИО или телефон родителя можно только
вместе с датой рождения — иначе
400 birth_date_required. - Ребёнок перешёл в другой отдел (
contacts_hidden: true) — телефоны родителя и плательщика менять нельзя (403 contacts_hidden): контакты меняет отдел, который ведёт ребёнка сейчас. - Неизвестное поле в теле —
422 invalid_input.
If-Match: не затереть чужую правку
Бронь может одновременно править ваш менеджер, другой менеджер отдела и сотрудник лагеря. Чтобы
ваша правка не легла поверх чужой, передайте в If-Match значение version брони, которую вы
показывали менеджеру. Если бронь с тех пор изменили — ответ 412 version_mismatch: перечитайте
бронь, покажите менеджеру новые данные и повторите. Без If-Match правка применяется к текущей
версии.
Отменить бронь
POST /bookings/{id}/cancel с Idempotency-Key. Причина обязательна. Можно передать If-Match.
Code
Ответ 200 — бронь с status: cancelled и cancelled_reason. Придёт событие booking.cancelled.
Что происходит при отмене:
- место возвращается в квоту вашего отдела;
- неоплаченный счёт Kaspi гасится;
- внесённые деньги автоматически не возвращаются. Вернуть их родителю можно заявкой на возврат (возможность в подготовке, см. Возвраты) или через лагерь.
Отказы: 400 reason_required — нет причины; 409 already_cancelled — уже отменена;
409 already_checked_in — ребёнок уже заехал в лагерь, такую бронь не отменить (обратитесь в
лагерь); 412 version_mismatch — бронь изменили после вашего чтения.
Восстановить отменённую бронь
POST /bookings/{id}/restore с Idempotency-Key, без тела. Подходит и для брони, снятой по
неоплате (booking.hold_expired), когда семья всё-таки решила ехать.
Code
Бронь снова занимает место в квоте (если оно ещё есть), снова держит его 24 часа до
минимального платежа, и плательщику уходит счёт Kaspi. Ответ 200 — бронь, событие
booking.restored.
Отказы: 409 not_cancelled — бронь не отменена; 409 quota_exhausted — места закончились;
409 sales_closed — продажи закрыты; 409 duplicate_child — ребёнка уже записали на эту смену
другой бронью.
Перенести на другую смену
POST /bookings/{id}/move с Idempotency-Key. Работает как кнопка лагеря «Остаётся на следующую
смену»:
Code
Ответ 201 — новая бронь на смену 13 (событие booking.created).
Перенос — это новая бронь, а не перемещение старой
- Новая бронь оформляется по цене новой смены, без прежней скидки, с удержанием места на 24 часа и счётом Kaspi на минимальный платёж.
- Прежняя бронь остаётся как есть — со своим местом, счетами и платежами. Деньги на новую бронь не переезжают.
- Если прежнее место больше не нужно, отмените прежнюю бронь отдельно. Что делать с уже внесёнными по ней деньгами — решите с лагерем.
Отказы: 409 same_shift — бронь уже на этой смене; 409 shift_started — смена уже началась;
409 quota_exhausted, sales_closed, duplicate_child — как при оформлении; 403 contacts_hidden
— ребёнка ведёт другой отдел, переносит он.
Поселить вместе
Просьба лагерю поселить детей в один отряд (друзья, братья и сёстры). Все брони — ваши, действующие и на одной смене, не больше 50.
Code
Ответ 201:
Code
Можно сразу при оформлении — поле together_with в POST /bookings, или together: true в
POST /bookings/batch для детей одной семьи. Номер чужой брони — отказ 400 unknown_booking.
Путёвка
GET /bookings/{id}/voucher— статус путёвки:none— не сформирована,generated— сформирована,sent— отправлена семье.- Скачать PDF — проще всего по ссылке
pdf_urlизGET /bookings/{id}/voucher: ключ к ней не нужен, её можно сразу отдать браузеру или мессенджеру, файл придёт с именем ребёнка. Ссылка живёт 10 минут (pdf_url_expires_at) — не храните её, за новой снова вызовитеGET /bookings/{id}/voucher. - Если
pdf_urlравенnull(путёвка не выпущена или файл для вашего отдела собирается заново), скачайтеGET /bookings/{id}/voucher.pdfс ключом — тяжёлый запрос, не чаще раза в секунду.
Code
- События
voucher.readyиvoucher.sent.
Выпустить путёвку и отметить её отправленной через ключ API нельзя (403 voucher_head_only) — это
делает руководитель вашего отдела или лагерь.
История брони
GET /bookings/{id}/history — кто и когда что менял в брони, порциями. Удобно, когда менеджер
спрашивает «почему изменилась сумма».
Заезд и отъезд
Когда ребёнок приехал в лагерь и уехал, видно в брони — поле checkin (checked_in_at,
checked_out_at) — и приходит событиями child.checked_in, child.checked_out. Через API отметить
заезд нельзя: это делает лагерь на месте.