feat: migrate to VitePress from monorepo docs, add test-contour section
This commit is contained in:
@@ -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).
|
||||
Reference in New Issue
Block a user