Files
docs/apps/backend-scenarios/sync-doctors-reviews.md
T

116 lines
6.3 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.
---
title: Синхронизация врачей и отзывов (Backend)
---
# Сценарий 4.1: Синхронизация врачей и отзывов (Infoclinica + Bitrix)
## Бизнес-цель
Актуализировать справочники backend из внешних систем:
- **Список врачей из Инфоклиники** загружается и складывается в PostgreSQL (сущность **`Idoctor`** — staging/интеграционная модель).
- **Нормализация признаков `Specialist`** из Bitrix-related данных (команда **`bitrix-update-doctors`** — очистка `dcodes`).
- **Отзывы** подтягиваются **из MySQL Bitrix** через `BitrixService` и сохраняются как `Review`, связанные с `Specialist`.
## Точки входа
| Тип | Имя команды Symfony | Класс |
| --- | --- | --- |
| CLI | `upload:doctors` | `UploadDoctorsCommand` |
| CLI | `bitrix-update-doctors` | `BitrixUpdateDoctorsCommand` |
| CLI | `bitrix-update-reviews` | `BitrixUpdateReviewsCommand` |
Все три предназначены для **cron** или ручного запуска в контейнере `php84`.
## Сценарий A — `upload:doctors` (Инфоклиника → `Idoctor`)
### Алгоритм
1. Читает активные отделения из PostgreSQL (`Department`, опция `--department` для одного `did`).
2. Для каждого отделения в цикле вызывает HTTP **через клиент Инфоклиники**: `GET /specialists/doctors?departments={did}&onlineMode={0|1}&firstrow=&lastrow=` чанками (`CHUNK_SIZE` 300).
3. Для каждого врача определяется ключ `"{dcode}_{departmentId}_{onlineMode}"`, подгружаются существующие `Idoctor` тем же ключом.
4. `updateDoctorEntity` обновляет поля (`dcode`, `name`, `department`, `filial`, `nearestDate`, `onlineMode`), `persist`, пакетный `flush` каждые `BATCH_SIZE` (150).
5. Между отделениями — `sleep(1)`; между чанками — `usleep(200000)`.
### «Конфликты»
Явного SQL `ON CONFLICT` нет: используется **ORM upsert-паттерн** — найти сущность по составному ключу в PHP или создать `new Idoctor()`, затем `persist`.
## Сценарий B — `bitrix-update-doctors` (PostgreSQL `Specialist`)
### Алгоритм
1. Загружает **все** `Specialist` из БД.
2. Нормализует строку `dcodes`: для каждого врача фильтрует коды длиной ≥ 7, отбрасывает `'0'`, пустые наборы превращает в `null`.
3. `flush` один раз в конце.
4. Обращение к `BitrixService` для `kodoper` **закомментировано** в текущей версии файла.
**Это не загрузка врачей из Bitrix**, а офлайн-очистка данных в уже существующей таблице `specialist`.
## Сценарий C — `bitrix-update-reviews` (MySQL Bitrix → PostgreSQL `Review`)
### Алгоритм
1. Постранично обходит `Specialist` батчами по 5 записей.
2. Для каждого врача `BitrixService::getReviews($specialist->getId())`:
- читает связанные элементы инфоблоков в **MySQL** (`doctrine.dbal.mysql_connection`);
- для каждого отзыва известен `REVIEW_ID`.
3. В PostgreSQL ищется `Review` с тем же `externalId`; если нет — `new Review()` + `setExternalId`.
4. Поля текста, рейтинга, автора, даты, активности заполняются из структуры Bitrix (включая «распаковку» сериализованных полей в `getReviews`).
5. Неактивные или без текста — пропуск.
6. `$specialist->addReview($review)`, `flush`; при ошибке драйвера — логирование проблемных UTF-8 последовательностей.
### «Конфликты»
Снова **без `ON CONFLICT`**: идемпотентность за счёт поиска по `externalId` перед вставкой.
## Mermaid
```mermaid
flowchart LR
subgraph MIS["Инфоклиника"]
API["GET /specialists/doctors"]
end
subgraph PG["PostgreSQL"]
ID["Idoctor"]
SP["Specialist"]
RV["Review"]
end
subgraph BX["Bitrix MySQL"]
IB["Инфоблоки отзывов"]
end
UC["upload:doctors"] --> API
API --> ID
BD["bitrix-update-doctors"] --> SP
BR["bitrix-update-reviews"] --> IB
BR --> RV
RV --> SP
```
Узлы `UC` / `BD` / `BR` — это команды `upload:doctors`, `bitrix-update-doctors`, `bitrix-update-reviews`.
## Внешние зависимости
| Система | Сценарий |
| --- | --- |
| Инфоклиника HTTP | `upload:doctors` |
| PostgreSQL | все три команды |
| Bitrix MySQL | `bitrix-update-reviews` (и потенциально расширения `BitrixService`) |
## Обработка ошибок и edge cases
- **Сетевые ошибки загрузки врачей** — warning в консоли, переход к следующему чанку/отделению.
- **Проблемные отзывы** — `DriverException` логируется с дампом полей.
- **`BitrixService` зависит от `regionId` в некоторых методах** — убедитесь, что выставление региона покрыто в вашем окружении при расширении команды.
## Ссылки на классы
- `apps/backend/src/Command/UploadDoctorsCommand.php`
- `apps/backend/src/Command/BitrixUpdateDoctorsCommand.php`
- `apps/backend/src/Command/BitrixUpdateReviewsCommand.php`
- `apps/backend/src/Service/Bitrix/BitrixService.php`
- `apps/backend/src/Entity/Idoctor.php`, `Specialist.php`, `Review.php`
См. [backend-ddd.md](../backend-ddd.md) и [data-model.md](../../data-model.md).