--- title: Онлайн-консультация в личном кабинете --- # Онлайн-консультация (cabinet) > Как устроена запись на **онлайн-приём** в `apps/cabinet`: маршруты, MIS/Widget API, оплата и видеоконференция. Связано с [расписанием врачей](./doctor-schedule-sync.md). --- ## TL;DR | Этап | Где | Внешний ресурс | |------|-----|----------------| | Список онлайн-врачей | `GET /online-specialists` (нужен login) | PostgreSQL `location_view` (`online_mode=true`) | | Слоты | `GET /api/interval?onlineMode=1` | `MIS` → `widget.sovamed.ru` | | Запись | `webSDK.scheduleRecReserve({ onlineType: 1 })` | Infoclinica SDK в браузере | | Оплата / видео | `/case-history` | `webSDK.loadPaymentView`, `openConference` | Cron `upload:doctors 1` (backend) обновляет **ближайшие даты** для онлайн-локаций, не сами слоты. --- ## 1. Маршруты | URL | Auth | Назначение | |-----|------|------------| | `/online-specialists` | `ROLE_USER` | Список врачей с онлайн-локациями | | `/specialists` | публичный | Очный приём (`onlineMode=0`) | | `/api/interval` | публичный | Прокси расписания в MIS | | `/case-history` | `ROLE_USER` | Записи, оплата, «Онлайн приём», возврат | | `/refund` | `ROLE_USER` | Форма возврата | Код: [`SpecialistController.php`](../../apps/cabinet/src/Controller/SpecialistController.php), [`PublicAPIController.php`](../../apps/cabinet/src/Controller/PublicAPIController.php), [`SecurityController.php`](../../apps/cabinet/src/Controller/SecurityController.php). --- ## 2. Поток данных ```mermaid sequenceDiagram participant User as Пользователь ЛК participant Cab as cabinet participant MIS as widget.sovamed.ru participant SDK as webSDK браузер User->>Cab: GET /online-specialists Cab->>Cab: location_view online_mode=1 User->>Cab: GET /api/interval onlineMode=1 Cab->>MIS: /api/reservation/schedule + /intervals MIS-->>Cab: intervalsData User->>SDK: scheduleRecReserve onlineType=1 User->>Cab: GET /case-history Cab->>SDK: records, payment, conference ``` --- ## 3. Отличия online vs offline | | Offline | Online | |---|---------|--------| | Список | `/specialists` | `/online-specialists` + login | | `onlineMode` в API | `0` | `1` | | Анонимная запись | да (`/api/anonymous-reserve`) | **нет** | | Согласия | PD | PD + оферта + ИДС | | После записи | `#doctor-success` | `#online` + предупреждение об оплате 5 мин | | Оплата / видео | — | `/case-history` | --- ## 4. Типичные причины поломки ### 4.1. Пустой список `/online-specialists` - Нет строк в `location_view` с `online_mode = true` (cron `upload:doctors 1` + `update_location()`). - Врач не привязан к MIS (`dcode`, `department`, `filial`). **Проверка:** SQL `SELECT * FROM location_view WHERE online_mode = true;` ### 4.2. Нет слотов на карточке - MIS недоступен (`MIS` env, `widget.sovamed.ru`). - Неверный `filial`/`department` для онлайн-режима. - `GET /api/interval?onlineMode=1` возвращает 5xx. **Проверка:** `curl "https://widget.sovamed.ru/specialists/departments"` и `/api/interval` с prod. ### 4.3. Запись создаётся как очная - Баг нормализации `onlineMode` в JS/PHP (исправлено: `OnlineMode`, `onlineMode.js`). - В `scheduleRecReserve` уходит `onlineType: 0` вместо `1`. ### 4.4. Фильтр на онлайн-странице уводит на `/specialists` - Форма поиска post'ила на `specialist_index` (исправлено → `specialist_online_index`). ### 4.5. Оплата / видео не работает - Не загружен SDK (`loader.js` → `widget.sovamed.ru/.../sdk.build.min.js`). - Запись не оплачена в течение 5 мин (MIS отменяет). - `webSDK.openConference` — вне окна времени приёма. ### 4.6. Авторизация внутри iframe (`#iframeProtocol`) — не должна появляться **Симптом:** пользователь уже в ЛК, но в модальном окне «Онлайн приём» или «Оплата» внутри iframe просят войти снова. **Причина:** две независимые сессии: | Сессия | Где хранится | За что отвечает | |--------|--------------|-----------------| | Symfony (`ROLE_USER`) | cookie `cabinet.sovamed.ru` | `/case-history`, `/online-specialists` | | MIS / webSDK | cookie `widget.sovamed.ru` + скрытый iframe `/sdk` | `openConference`, `loadPaymentView`, `scheduleRecReserve` | Symfony может быть активна, а MIS — нет (истёк timeout, другой браузер, блокировка third-party cookies). **Где iframe:** | Действие | Метод SDK | Элемент | |----------|-----------|---------| | «Онлайн приём» | `openConference()` | `#iframeProtocol` — URL видеоконференции | | Вход через Госуслуги | `loadLoginView()` | `#iframeProtocol` — **ожидаемо** показывает login | | Оплата | `loadPaymentView()` | виджет ЮKassa в `#popup-body` (не login-iframe) | **Исправление в коде (cabinet):** - `assets/components/misSession.js` — проверка `webSDK.data.user.authenticated` / `isLoggedIn()` перед оплатой и конференцией. - `caseHistory_controller.js` — `openConference` **без** `container` (DOM-элемент ломал SDK `eval(container)` и пропускал Guest URL); iframe переносится в popup через `mountConferenceInPopup()`. - При протухшей MIS-сессии — popup «Войти снова» → `/logout`, а не форма login внутри iframe. **Проверка в браузере (prod):** ```javascript // на /case-history, до клика «Онлайн приём» window.webSDK?.data?.user?.authenticated // должно быть true ``` ```bash # Symfony-сессия (smoke-скрипт) curl -b cookies.txt https://cabinet.sovamed.ru/api/userInfo # → {"data":""} — это НЕ гарантия MIS-сессии ``` **Smoke:** ```bash make local-online-smoke # шаги 9–10: UI-маркеры case-history, /api/userInfo, доступность MIS SDK ``` ### 4.7. MIS / Infoclinica Env: `MIS=https://widget.sovamed.ru` в [`apps/cabinet/.env`](../../apps/cabinet/.env). Публичный DNS: CNAME `production.infoclinica.ru` → `217.74.42.159` (не путать с внутренними IP вроде `10.34.23.239`). --- ## 5. Тесты ### Shell smoke (Docker local) ```bash make local-up make local-online-smoke ``` Скрипт: [`scripts/online-consultation-smoke.sh`](../../scripts/online-consultation-smoke.sh) ### Pytest e2e ```bash ./scripts/run-online-consultation-pytest.sh ``` Каталог: [`tests/e2e/online_consultation/`](../../tests/e2e/online_consultation/) ### PHPUnit (cabinet) ```bash make cabinet-test # или docker exec php82-local php bin/phpunit tests/Unit tests/Controller ``` - `tests/Unit/Support/OnlineModeTest.php` — нормализация `0/1/true/false` - `tests/Controller/OnlineSpecialistsControllerTest.php` — auth на `/online-specialists` --- ## 6. Чеклист диагностики на prod 1. Пользователь залогинен? `/online-specialists` без login → redirect. 2. Есть онлайн-локации в БД? `location_view.online_mode = true`. 3. `docker exec php84 php bin/console upload:doctors 1` — без ошибок? 4. `/api/interval?...&onlineMode=1` — HTTP 200 и `intervalsData`? 5. В браузере загружен `webSDK`? Console → нет 404 на `sdk.build.min.js`. 6. `/case-history` — запись с `onlineType`, статус оплаты? 7. **До «Онлайн приём»:** `window.webSDK.data.user.authenticated === true`? Если `false` — MIS-сессия протухла (см. §4.6). 8. Iframe `#iframeProtocol`: `src` — URL конференции, а не `/login`? --- ## 7. Ключевые файлы | Файл | Роль | |------|------| | `src/Controller/SpecialistController.php` | `/online-specialists` | | `src/Controller/PublicAPIController.php` | `/api/interval` | | `src/Repository/SpecialistViewRepository.php` | фильтр `onlineMode` | | `src/Support/OnlineMode.php` | нормализация флага | | `assets/components/record.js` | запись, `onlineType` | | `assets/components/misSession.js` | проверка MIS-сессии, mount iframe конференции | | `assets/controllers/caseHistory_controller.js` | оплата, конференция | | `assets/components/loader.js` | загрузка SDK | | `templates/specialist/_item.html.twig` | карточка врача |