Записи (Booking)
Управление записями клиентов. Нативная запись включена (NATIVE_BOOKING_ENABLED=true).
Модель в коде:
booking.Appointment
Лог изменений статуса:booking.AppointmentStatusLog
Жизненный цикл записи
Каждая запись проходит через статусы:
┌─────────┐
создание │ booked │
─────────────────>│ забронир│
└────┬────┘
│ администратор подтверждает
▼
┌─────────────┐
│ confirmed │
│ подтверждена│
└─────┬───────┘
│ клиент пришёл
▼
┌─────────────┐
│ in_progress │
│ идёт приём │
└─────┬───────┘
│ услуга завершена
▼
┌─────────────┐
│ done │
│ завершена │
└─────────────┘
(из booked / confirmed)
│
│ отмена
▼
┌──────────────┐ ┌──────────┐
│ cancelled │ │ no_show │
│ отменена │ │ не пришёл│
└──────────────┘ └──────────┘
| Статус | Описание | Переход назад |
|---|---|---|
booked | Запись создана, ожидает подтверждения | — |
confirmed | Подтверждена администратором | → cancelled |
in_progress | Клиент пришёл, услуга оказывается | нет |
done | Визит завершён | нет |
cancelled | Отменена клиентом или администратором | нет |
no_show | Клиент не пришёл без предупреждения | нет |
примечание
Каждое изменение статуса фиксируется в AppointmentStatusLog с полями old_status, new_status, user_id, note, created_at.
Источники записи
source | Откуда пришла запись |
|---|---|
journal | Создана вручную администратором через журнал |
online | Онлайн-запись клиентом через форму |
import_yclients | Импортирована из YClients |
import_dikidi | Импортирована из Dikidi |
Логика проверки свободных слотов
При запросе /api/records/available-slots/ сервер:
- Берёт расписание мастера (
StaffSchedule/StaffScheduleDay) - Исключает выходные и отгулы (
StaffTimeOff) - Загружает все активные записи на эту дату (статусы
booked,confirmed,in_progress) - Вычитает занятые интервалы с учётом длительности услуги (
MasterService.duration_minutes) - Возвращает только окна, в которые влезает вся длительность до конца рабочего дня
Запрос: date=2026-08-05, service_id=12 (длительность 60 мин)
Рабочий день мастера: 10:00 – 18:00
Занятые слоты: 11:00–12:00, 14:00–15:30
Свободные окна: 10:00, 12:00, 15:30, 16:30, 17:00
(17:30 не попадает — до конца дня остаётся < 60 мин)
Список записей
GET /api/records/
Authorization: Bearer <token>
Параметры фильтрации:
| Параметр | Тип | Описание |
|---|---|---|
date | date | Дата записи (YYYY-MM-DD) |
date_from | date | С даты |
date_to | date | По дату |
status | string | booked, confirmed, in_progress, done, cancelled, no_show |
client_id | integer | ID клиента |
master_id | integer | ID мастера |
service_id | integer | ID услуги |
Ответ:
{
"count": 25,
"next": null,
"previous": null,
"results": [
{
"id": 1001,
"client": {
"id": 42,
"name": "Иван Иванов",
"phone": "+79991234567"
},
"master": {
"id": 5,
"name": "Анна Мастерова"
},
"service": {
"id": 12,
"name": "Стрижка женская",
"duration_minutes": 60,
"price": "1500.00"
},
"date": "2026-08-05",
"time": "14:00:00",
"status": "confirmed",
"source": "online",
"yclients_id": 987654,
"created_at": "2026-07-30T10:15:00Z"
}
]
}
Создать запись
POST /api/records/
Authorization: Bearer <token>
{
"master_id": 5,
"service_id": 12,
"date": "2026-08-05",
"time": "14:00",
"comment": "Первый визит"
}
Логика при создании:
- Проверяется, что слот свободен (конкурентная проверка через транзакцию БД)
- Создаётся
Appointmentсо статусомbooked - Если YClients подключён — запись синхронизируется туда и создаётся
YclientsBookingLog - Клиенту отправляется уведомление (Telegram / WhatsApp)
- Статус может сразу стать
confirmedв зависимости отSalonBookingSettings
Возможные ошибки:
| Код | Причина |
|---|---|
409 Conflict | Слот уже занят в момент создания |
400 Bad Request | Мастер недоступен в это время |
400 Bad Request | Дата в прошлом |
Получить запись
GET /api/records/{id}/
Authorization: Bearer <token>
Отменить запись
POST /api/records/{id}/cancel/
Authorization: Bearer <token>
{
"reason": "Не смогу прийти"
}
Логика при отмене:
- Проверяется текущий статус — отмена доступна только для
bookedиconfirmed - Статус меняется на
cancelled, фиксируется вAppointmentStatusLog - Если запись была в YClients — отменяется через
yclients-connector - Клиенту и мастеру отправляется уведомление
Свободные слоты
GET /api/records/available-slots/
Authorization: Bearer <token>
Параметры:
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
date | date | ✅ | Дата |
service_id | integer | ✅ | Услуга |
master_id | integer | ❌ | Конкретный мастер (если не указан — слоты всех доступных мастеров) |
Ответ:
{
"date": "2026-08-05",
"slots": [
{ "time": "10:00", "master_id": 3, "master_name": "Мария С." },
{ "time": "10:00", "master_id": 5, "master_name": "Анна М." },
{ "time": "11:30", "master_id": 5, "master_name": "Анна М." }
]
}