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
+263
View File
@@ -0,0 +1,263 @@
# Backend: бизнес-сущности и границы (DDD-обзор)
Страница описывает `apps/backend` с точки зрения **предметной области**: какие сущности относятся к одному смысловому блоку, какие HTTP-контроллеры и сервисы их обслуживают, и как устроены фоновые задачи. Это не «каноничное» DDD-приложение с явными bounded context в коде, а **карта домена поверх существующей Symfony-структуры** (`Entity`, `Repository`, `Controller`, `Service`, `Command`, `Message`).
См. также: [архитектура модулей](./backend-architecture.md), [бизнес-сценарии по потокам](./backend-scenarios/index.md), [CRUD контента](./backend-content-crud.md), [модели данных](../data-model.md), [потоки данных](../flows.md).
## Карта контекстов
```mermaid
flowchart TB
subgraph identity[Идентичность и доступ]
User[User]
end
subgraph org[Организация клиники]
Filial[Filial]
Department[Department]
MedicalCenter[MedicalCenter]
end
subgraph staff[Врач, локации, расписание]
Specialist[Specialist]
Location[Location]
Schedule[Schedule]
Docs[SpecialistDocs]
DcodeDesc[SpecialistDcodeDescription]
Docinfo[WebGetDocinfo]
Idoctor[Idoctor]
end
subgraph booking[Запись и уведомления]
Record[Record]
AlertSms[AlertSms]
MarkKiosk[MarkKiosk]
end
subgraph pricing[Прайс]
PriceList[PriceList]
PriceDepartment[PriceDepartment]
end
subgraph content[Контент сайта]
Article[Article]
News[News]
Promo[Promo]
Disease[Disease]
SiteService[SiteService]
Stock[Stock]
end
subgraph reputation[Отзывы]
Review[Review]
end
subgraph integrations[Интеграции и утилиты]
Calltouch[Calltouch API]
XmlFeed[XML фиды]
MailCaptcha[Почта / SmartCaptcha]
end
Specialist --> Location
Specialist --> Review
Specialist --> Docs
Specialist --> DcodeDesc
Record --> AlertSms
PriceList --> PriceDepartment
```
---
## 1. Идентичность и доступ
**Смысл:** учётная запись пользователя API, вход по паролю, JWT, регистрация, смена региона, сценарии с UID/pcode.
| Роль в DDD | Артефакт | Путь / класс |
| --- | --- | --- |
| Агрегат / сущность | `User` | `src/Entity/User.php` |
| Репозиторий | `UserRepository` | `src/Repository/UserRepository.php` |
| Входная точка API | `UserController` | префикс маршрута `/user` |
| Доменные сервисы | `AuthenticationService`, `RegistrationService`, `UserProfileService` | `src/Service/User/` |
| Инфраструктура | `JWTDecoderService`, Lexik JWT | `src/Service/DecoderJWT/` |
| DTO | `UserLoginDto`, `RegistrationDto`, `UserAuthDto`, `UserUidAuthDto`, `RegionDto` | `src/Dto/` |
Консольных команд импорта для `User` в текущем дереве нет: пользователи создаются через API и админские сценарии.
---
## 2. Организация клиники (филиалы, отделения, медцентры)
**Смысл:** где оказываются услуги, структура сети, справочники для сайта и записи.
| Сущность | Репозиторий | Контроллер (префикс) | Сервисы | Команды синхронизации |
| --- | --- | --- | --- | --- |
| `Filial` | `FilialRepository` | `FilialController``/filial` | `FilialService` | `UploadFilialsCommand` |
| `Department` | `DepartmentRepository` | `DepartmentController``/department` | `DepartmentService` | `UploadDepartmentsCommand` |
| `MedicalCenter` | `MedicalCenterRepository` | `MedicalCenterController``/medical-center` | `MedicalCenterCrudService` | `UploadMedicalCentersCommand` |
---
## 3. Врач, локации приёма, расписание и материалы
**Смысл:** центральный домен — **врач** (`Specialist`), его **локации** (`Location`: отделение, филиал, online, ближайшая дата), **слоты расписания** (`Schedule`), справочные тексты и медиа.
| Сущность | Репозиторий | Где в API | Основная логика |
| --- | --- | --- | --- |
| `Specialist` | `SpecialistRepository` | `SpecialistController``/specialist` | `SpecialistService` (список, карточка, расписание, фото, запись, интеграция с MIS) |
| `Location` | `LocationRepository` | `LocationController` (admin) — пути вида `/specialist/{id}/location/...`, `/locations/empty` | `LocationService`, `EntityManager` в контроллере |
| `Schedule` | `ScheduleRepository` | косвенно через `SpecialistService`, кеш | `ScheduleCacheService`, `ScheduleErrorHandlerService` |
| `SpecialistDocs` | `SpecialistDocsRepository` | `SpecialistDocsController``/specialist-docs/...` | загрузка файлов, `ImageService`, `FileUploaderService` |
| `SpecialistDcodeDescription` | `SpecialistDcodeDescriptionRepository` | `SpecialistDcodeDescriptionController``/specialist-dcode-description/...` | пагинация, CRUD |
| `WebGetDocinfo` | `WebGetDocinfoRepository` | `WebGetDocinfoController``/docinfo` | чтение внешнего/legacy-представления врача |
| `Idoctor` | `IdoctorRepository` | `InfoclinicaController``/idoctor/list` | фильтрация, пагинация |
**Асинхронные сообщения (Messenger):**
- `GetScheduleMessage``GetScheduleMessageHandler`
- `GetSpecialistPictureMessage``GetSpecialistPictureMessageHandler`
- `GetAnonymousReserveRequestMessage``GetAnonymousReserveRequestMessageHandler`
**Команды:** `UploadDoctorsCommand`, `BitrixUpdateDoctorsCommand`, `ClearScheduleCacheCommand`.
**Внешние системы в этом контексте:** Infoclinica/MIS (`InfoclinicaClientService`), Bitrix (`BitrixClientService`, `BitrixService`) для врачей и медиа.
---
## 4. Запись пациента, отметки киоска, SMS
**Смысл:** факт записи, уведомление по SMS, отметка прохождения для киоска.
| Сущность | Репозиторий / доступ | Где используется |
| --- | --- | --- |
| `Record` | `RecordRepository` | создание/учёт записи через `SpecialistService` и сценарии записи |
| `AlertSms` | `AlertSmsRepository` | связь записи с ответом SMS-провайдера (`Record``AlertSms`) |
| `MarkKiosk` | `EntityManager::getRepository(MarkKiosk::class)` | `InfoclinicaController::clvisitsovacheckpass` — отметка по `pcode` и филиалу |
HTTP: `POST /reservation/anonymous-reserve` (`InfoclinicaController`) — анонимная запись; проверка киоска — `GET /infoclinica/clvisitsovacheckpass/{filial}` (требуется `ROLE_USER`).
SMS-клиенты: `Sms4bClientService`, `SmsruClientService`.
---
## 5. Прейскурант
| Сущность | Репозиторий | Контроллер | Сервис | Команды |
| --- | --- | --- | --- | --- |
| `PriceList` | `PriceListRepository` | `PriceListController` — префикс `/pricelist`, список `/list` | `PriceListService` | `UploadPriceCommand` |
| `PriceDepartment` | `PriceDepartmentRepository` | `PriceDepartmentController` — тот же префикс `/pricelist`, эндпоинт `/department` | через репозиторий и сервисы фидов | `UploadPriceDepCommand` |
`XmlFeedController` использует `PriceListService` и филиал для генерации фидов — см. контекст интеграций.
---
## 6. Контент сайта (статьи, новости, акции, услуги, заболевания, акции у врачей)
| Сущность | Репозиторий | Контроллер | Паттерн |
| --- | --- | --- | --- |
| `Article` | `ArticleRepository` | `ArticleController``/article` | `CrudResponder` + `Paginator` + `ContentFilterDto` ([описание CRUD](./backend-content-crud.md)) |
| `News` | `NewsRepository` | `NewsController``/news` | `NewsCrudService` + типовой CRUD |
| `Promo` | `PromoRepository` | `PromoController``/promo` | `PromoCrudService` |
| `Disease` | `DiseaseRepository` | `DiseaseController``/disease` | `DiseaseCrudService` |
| `SiteService` | `SiteServiceRepository` | `SiteServiceController``/site-services` | `SiteServiceCrudService` |
| `Stock` | `StockRepository` | `StockController``/stock/...` | CRUD, изображения, связь Many-to-Many с `Specialist` |
**Команды:** `UploadNewsCommand`, `UploadPromoCommand`, `UploadDiseasesCommand`, `UploadSiteServicesCommand` (остальные сущности этого блока подтягиваются согласно фактическим именам команд в `src/Command`).
---
## 7. Отзывы
| Сущность | Репозиторий | Контроллер | Прочее |
| --- | --- | --- | --- |
| `Review` | `ReviewRepository` | `ReviewController``/review` | список с фильтрами, создание от авторизованного пользователя, CRUD для админа |
**Команда:** `BitrixUpdateReviewsCommand` — синхронизация с Bitrix.
---
## 8. Интеграции и публичные утилиты
| Назначение | Контроллер / вход | Сервисы |
| --- | --- | --- |
| Лиды Calltouch | `CalltouchController``/calltouch/create-lead` | `CalltouchClientService` |
| XML для Яндекса | `XmlFeedController``/xml/feed` | `XmlFeedGeneratorService`, `XmlFeedGeneratorV1Service`, данные врачей/цен/филиалов |
| Отправка почты + captcha | `ServiceController``/service/sendmail` | `SendMailService`, `SmartCaptchaClientService` |
| Мелкие helper | `HelperController``/helper/text-year` | `HelperService` |
| Заглушка | `DefaultController` | `GET /` |
---
## 9. Аудит: логи пользователей (legacy БД)
| Назначение | Контроллер | Реализация |
| --- | --- | --- |
| Список записей `usrlog` | `UsrlogController``/usrlog/list` | DBAL-подключение `doctrine.dbal.cabinet_connection`, роль `ROLE_LOGS` |
Это **интеграционный контекст**: сущность в `apps/backend/src/Entity` не выделяется, данные читаются из базы cabinet.
---
## 10. Сущности без выделенного HTTP-слоя в текущем API
Их таблицы и Doctrine-модели есть, репозитории сгенерированы, но **отдельного REST-контроллера в `src/Controller` нет** (на момент описания документа):
| Сущность | Репозиторий | Зачем полезно знать |
| --- | --- | --- |
| `Banner` | `BannerRepository` | баннеры; возможна выдача через другие сервисы или будущие эндпоинты |
| `WidgetForm`, `WidgetFormInput` | `WidgetFormRepository`, `WidgetFormInputRepository` | Symfony Forms `WidgetFormType`, `WidgetFormInputType` — конструктор полей, данные в БД |
При появлении новых маршрутов их логично отнести к контексту **«виджеты и формы»** или **«маркетинг»**.
---
## Сводная таблица: контроллер → базовый префикс
| Контроллер | Префикс или примечание |
| --- | --- |
| `ArticleController` | `/article` |
| `CalltouchController` | `/calltouch` |
| `DefaultController` | `/` |
| `DepartmentController` | `/department` |
| `DiseaseController` | `/disease` |
| `FilialController` | `/filial` |
| `HelperController` | `/helper` |
| `InfoclinicaController` | без классового префикса: `/infoclinica/...`, `/idoctor/...`, `/reservation/...` |
| `LocationController` | без префикса: `/locations/...`, `/specialist/{id}/location/...` |
| `MedicalCenterController` | `/medical-center` |
| `NewsController` | `/news` |
| `PriceDepartmentController` | `/pricelist` |
| `PriceListController` | `/pricelist` |
| `PromoController` | `/promo` |
| `ReviewController` | `/review` |
| `ServiceController` | `/service/...` |
| `SiteServiceController` | `/site-services` |
| `SpecialistController` | `/specialist` |
| `SpecialistDcodeDescriptionController` | `/specialist-dcode-description/...` |
| `SpecialistDocsController` | `/specialist-docs/...` |
| `StockController` | `/stock/...` |
| `UserController` | `/user` |
| `UsrlogController` | `/usrlog/...` |
| `WebGetDocinfoController` | `/docinfo` |
| `XmlFeedController` | `/xml/feed` |
---
## Консольные команды по доменам
| Команда (класс) | Домен |
| --- | --- |
| `UploadDoctorsCommand` | Врачи |
| `BitrixUpdateDoctorsCommand` | Врачи (Bitrix) |
| `BitrixUpdateReviewsCommand` | Отзывы |
| `UploadDepartmentsCommand` | Отделения |
| `UploadDiseasesCommand` | Заболевания |
| `UploadFilialsCommand` | Филиалы |
| `UploadMedicalCentersCommand` | Медцентры |
| `UploadNewsCommand` | Новости |
| `UploadPriceCommand` | Цены |
| `UploadPriceDepCommand` | Группы цен |
| `UploadPromoCommand` | Акции |
| `UploadSiteServicesCommand` | Услуги сайта |
| `ClearScheduleCacheCommand` | Расписание (кеш) |
Точные имена команд Symfony: `docker exec -it php84 php bin/console list app` (или локальный `php bin/console` из `apps/backend`).