Files
docs/apps/backend-ddd.md
T

264 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`).