---
title: Анонимная запись на приём через MIS (Backend)
---

# Сценарий 3.1: Анонимная запись (**Anonymous Reserve**)

## Бизнес-цель

Посетитель сайта может **записаться на приём**, указав контактные данные и выбранный слот, **без обязательной регистрации** в Laravel/Next-сенсах личного кабинета: запись фиксируется в **МИС (Инфоклиника)**.

## Точки входа

| Тип | Метод + URL | Класс |
| --- | --- | --- |
| HTTP | `POST /reservation/anonymous-reserve` | `InfoclinicaController::bookingAnonymous` |

Внутренне вызывается Messenger-сообщение **`GetAnonymousReserveRequestMessage`** (транспорт `sync` по `messenger.yaml`).

## Входной контракт (DTO)

`App\Dto\AnonymousReserveRequestDto` валидирует:

- ФИО, email, телефон в формате `+7(999)999-99-99`;
- `workDate` — 8 цифр `YYYYMMDD`;
- `time` — интервал `HH:MM-HH:MM`;
- `filial`, `schedident`, `rnum`, `specialist` (dcode), `accept`, `captcha` и т.д.

Метод `toArray()` формирует тело для MIS:

- поле `reserve` — **JSON-строка** с деталями слота (`date`, `st`, `en`, `services`, `filial`, `timezone`, `schedident`, `rnum`, `dcode`).

Пример упрощённой структуры тела:

```json
{
  "accept": true,
  "fio": "Иванов Иван",
  "captcha": "...",
  "email": "user@example.com",
  "phone": "+7(903)123-45-67",
  "reserve": "{\"date\":\"20260520\",\"st\":\"10:00\",\"en\":\"10:30\", ... }"
}
```

## Пошаговый алгоритм

1. `InfoclinicaController::bookingAnonymous` десериализует JSON в `AnonymousReserveRequestDto`, валидирует.
2. `SpecialistService::createAnonymousReserve($dto)` создаёт `GetAnonymousReserveRequestMessage` и диспатчит через `MessageBusInterface` (sync).
3. `GetAnonymousReserveRequestMessageHandler::__invoke`:
   - логирует старт;
   - вызывает `InfoclinicaClientService::anonymousReserve($dto)`;
   - выполняет `POST` на путь **`/api/reservation/anonymous-reserve`** MIS с `json_encode($dto->toArray())`;
   - возвращает массив ответа `toArray()` HTTP-клиента Symfony;
   - при `HttpExceptionInterface` — лог и массив с `status_code`, телом ответа MIS.

4. Контроллер делает `$this->json($reserve, $reserve['status_code'] ?? 200)` — **если в ответе есть числовой `status_code`, он подставляется как HTTP-код ответа API**.

## Создание строки `Record` в PostgreSQL

В текущем дереве `apps/backend/src` **не найдено** кода `persist(new Record(...))` или использования `RecordRepository` в связке с этим эндпоинтом. Сущность `Record` и таблица описаны в модели данных, но **локальное сохранение факта записи вместе с анонимным reserve в этом HTTP-сценарии не реализовано** (или перенесено в другой сервис).

## Mermaid

```mermaid
sequenceDiagram
    participant C as Клиент
    participant IC as InfoclinicaController
    participant SS as SpecialistService
    participant BUS as MessageBus
    participant H as GetAnonymousReserveRequestMessageHandler
    participant CL as InfoclinicaClientService
    participant MIS as Инфоклиника API

    C->>IC: POST /reservation/anonymous-reserve
    IC->>SS: createAnonymousReserve(dto)
    SS->>BUS: dispatch(GetAnonymousReserveRequestMessage)
    BUS->>H: __invoke
    H->>CL: anonymousReserve(dto)
    CL->>MIS: POST /api/reservation/anonymous-reserve
    MIS-->>CL: JSON
    CL-->>H: массив
    H-->>IC: результат
    IC-->>C: HTTP код из status_code или 200
```

## Внешние зависимости

| Система | Роль |
| --- | --- |
| Инфоклиника | создание записи |
| PostgreSQL | **не задействуется** для `Record` в этом сценарии (по текущему коду) |

## Обработка ошибок и edge cases

- **`InvalidArgumentException` в контроллере** — `400` с текстом валидации.
- **Ошибки десериализации JSON в DTO** — должны обрабатываться обработчиком исключений приложения (в контроллере явного try/catch на `ExceptionInterface` нет).
- **Ответ MIS с ошибкой**: может прийти как `200` с полем `status_code` внутри JSON — клиентский код фронта должен учитывать оба уровня (HTTP и вложенный).

## Ссылки на классы

- `apps/backend/src/Controller/InfoclinicaController.php`
- `apps/backend/src/Service/Specialist/SpecialistService.php`
- `apps/backend/src/Message/GetAnonymousReserveRequestMessage.php`
- `apps/backend/src/MessageHandler/GetAnonymousReserveRequestMessageHandler.php`
- `apps/backend/src/Service/Client/InfoclinicaClientService.php`
- `apps/backend/src/Dto/AnonymousReserveRequestDto.php`

См. [sms-record.md](./sms-record.md), [backend-ddd.md](../backend-ddd.md).
