116 lines
6.3 KiB
Markdown
116 lines
6.3 KiB
Markdown
---
|
||
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).
|