--- 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).