87 lines
4.1 KiB
Markdown
87 lines
4.1 KiB
Markdown
---
|
||
title: Карточка врача и локации приёма (Backend)
|
||
---
|
||
|
||
# Сценарий 2.1: Карточка врача и локации (`Specialist` + `Location`)
|
||
|
||
## Бизнес-цель
|
||
|
||
Пользователю нужна **карточка врача** (ФИО, медиа, признаки активности, регион и т.д.) вместе с **локациями приёма**: привязка к отделению, филиалу, режиму online и пр., чтобы выбрать место и сценарий записи.
|
||
|
||
## Точки входа
|
||
|
||
| Тип | Метод + URL | Класс |
|
||
| --- | --- | --- |
|
||
| HTTP | `GET /specialist/{id}` | `SpecialistController::show` (`id` — целое) |
|
||
| HTTP | `GET /specialist/by/{identifier}?regionId=` | `SpecialistController::showBy` |
|
||
|
||
Список врачей: `GET /specialist/list` — отдельный сценарий фильтрации, тот же репозиторий.
|
||
|
||
CLI / Messenger для **чтения карточки** не используются.
|
||
|
||
## Как собирается «агрегат» в рамках Symfony / ORM
|
||
|
||
Doctrine-сущность `App\Entity\Specialist` содержит `OneToMany` на `App\Entity\Location` (`mappedBy: 'specialist'`, каскады `persist`/`remove`). Для API **отдельного сервиса-сборщика нет**: при `GET /specialist/{id}` используется param converter и сериализация.
|
||
|
||
Группы Serializer **`specialist:detail`** и **`from.specialist:read`** включают в ответ связанные локации (см. атрибуты `Groups` на поле коллекции локаций в `Specialist`).
|
||
|
||
Маршрут **`showBy`**:
|
||
|
||
1. `SpecialistService::getSpecialist($identifier, $regionId)`;
|
||
2. если `identifier` числовой — выборка по `id`;
|
||
3. иначе — по `alias` и опциональному `regionId` через `SpecialistRepository::createFilteredQueryBuilder`;
|
||
4. при `null` — **404** `{"error":"not found"}`.
|
||
|
||
## Пошаговый алгоритм — `GET /specialist/{id}`
|
||
|
||
1. Загрузка `Specialist` из БД по `id` (или 404 на уровне фреймворка, если не найден).
|
||
2. `JsonResponse` с группами `specialist:detail`, `from.specialist:read`.
|
||
3. При обходе графа сериализатором Doctrine догружает `locations`.
|
||
|
||
## Mermaid
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant C as Клиент
|
||
participant SC as SpecialistController
|
||
participant SS as SpecialistService
|
||
participant SR as SpecialistRepository
|
||
participant SER as Serializer / ORM
|
||
|
||
alt По числовому id
|
||
C->>SC: GET /specialist/{id}
|
||
SC->>SER: serialize(Specialist)
|
||
SER->>SER: подтягивание Location
|
||
SC-->>C: JSON
|
||
else По alias
|
||
C->>SC: GET /specialist/by/{identifier}
|
||
SC->>SS: getSpecialist
|
||
SS->>SR: QueryBuilder
|
||
SR-->>SS: Specialist | null
|
||
SS-->>SC: entity
|
||
SC->>SER: serialize
|
||
SC-->>C: 200 или 404
|
||
end
|
||
```
|
||
|
||
## Внешние зависимости
|
||
|
||
| Система | Участие |
|
||
| --- | --- |
|
||
| PostgreSQL | данные `specialist` и `location` |
|
||
| Инфоклиника / Bitrix | **не вызываются** при чтении карточки |
|
||
|
||
## Обработка ошибок и edge cases
|
||
|
||
- **Не найден по alias** — `404` с простым телом.
|
||
- **Фото врача**: отдельные эндпоинты загрузки картинки (`specialistPicture`, upload) — не часть сценария «только чтение».
|
||
|
||
## Ссылки на классы
|
||
|
||
- `apps/backend/src/Controller/SpecialistController.php`
|
||
- `apps/backend/src/Service/Specialist/SpecialistService.php`
|
||
- `apps/backend/src/Entity/Specialist.php`, `Entity/Location.php`
|
||
- `apps/backend/src/Repository/SpecialistRepository.php`
|
||
|
||
Админские CRUD по локациям: `LocationController`. Карта домена: [backend-ddd.md](../backend-ddd.md).
|