264 lines
14 KiB
Markdown
264 lines
14 KiB
Markdown
# 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`).
|