feat: migrate to VitePress from monorepo docs, add test-contour section

This commit is contained in:
sova-bootstrap
2026-05-28 12:29:31 +03:00
parent e90dfe1bd4
commit e3e438df68
76 changed files with 11998 additions and 60 deletions
+108
View File
@@ -0,0 +1,108 @@
---
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).