Browse Source
MEETING_2026-04-23.md — product roadmap proposal: gentleman's set (Phase 1 transactional base + Phase 1.5 communication overlay), 10 business segments matrix (primary/returning lens), four segment groups A/C/B/D. build_deck.py — python-pptx builder generating 18-slide 16:9 deck styled to the clinic's design system (teal, PT Sans). Also expands README with design system tokens and screens overview. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>main
4 changed files with 1224 additions and 0 deletions
@ -0,0 +1,285 @@ |
|||||||
|
# Приоритеты развития мобильного приложения — встреча 23 апр 2026 |
||||||
|
|
||||||
|
Клиника УГН (ЛОР, сурдология, аллергология, хирургия). Цель встречи — определить порядок развития функций: что закрываем как базу для всех пациентов, какие сегменты углубляем и в каком порядке. |
||||||
|
|
||||||
|
## 1. Контекст и критерии приоритизации |
||||||
|
|
||||||
|
**Текущие функции:** список врачей, запись на приём, ближайший приём, чат с оператором, профиль, семейный профиль, контакты. |
||||||
|
|
||||||
|
### Ключевые факты о потоке |
||||||
|
|
||||||
|
- **2 из 3 пациентов клиники — повторные.** Значительная доля — **повторные внутри одного лечения**: после первого визита (острое заболевание или обострение хронического) ещё 1–3+ приёма, процедуры, контроль. |
||||||
|
- **Бизнес-сегментация (из аналитики клиники)** — 10 сегментов, лидеры по выручке: амбулаторный поток (~120 млн), взрослая хирургия «заблокированный нос» (~30 млн), детская аденоидная хирургия (~20–30 млн), сурдология (~20 млн). |
||||||
|
|
||||||
|
### Продуктовая логика: что делает приложение |
||||||
|
|
||||||
|
**Приложение — инструмент удержания и углубления, а не привлечения.** Первичного пациента клиника получает через сайт, SEO, рекламу, сарафан. Приложение устанавливают уже пришедшие — в момент записи или на первом визите. Поэтому приоритет развития — **повторные во всех сегментах**. |
||||||
|
|
||||||
|
Это совпадает с фактом «2 из 3 — повторные» и означает, что: |
||||||
|
- **Первичные сценарии в приложении** закрываются универсальным минимумом (запись + контакты + цены + AI-помощник, который знает услуги). Нет смысла строить специализированные первичные потоки для каждого из 10 сегментов. |
||||||
|
- **Повторные сценарии** — специфичны по сегменту и требуют отдельных модулей (бегунок, аудиограмма, АСИТ-дневник и т.п.). |
||||||
|
- **Исключения** — сегменты, где «первичный в приложении» ≠ «первый визит»: после первого визита пациент уходит, и вернуть его в клинику может только приложение. |
||||||
|
- **Сурдология** — после визита и демо пациент уходит думать 2–3 месяца о покупке аппарата. |
||||||
|
- **Хирургия (FESS, детские аденоиды, вазотомия)** — после пред-операционного приёма у хирурга пациент часто уходит **думать, решаться ли на операцию вообще**. Эти «сомневающиеся» — отдельная работа по возврату. Вторая часть — те, кто решился, уходят в 6-недельную подготовку (бегунок). |
||||||
|
- **АСИТ** — после назначения впереди 3–5-летний курс, есть сценарии «не начал» и «бросил в первые месяцы». |
||||||
|
|
||||||
|
### Три слоя работы |
||||||
|
|
||||||
|
1. **Фаза 1 · Транзакционная база** — детерминированные функции для любого пациента: запись, ближайший приём, чат с оператором, **план лечения, результаты/медкарта, заказ справок**. Без LLM и прямого чата с врачом. Минимум рисков, быстрый запуск. |
||||||
|
2. **Фаза 1.5 · Коммуникационная надстройка** — чат с медицинским консьержем (дежурным врачом/фельдшером) и AI-помощник в shadow-mode. Отделено от Фазы 1, чтобы регламенты и безопасность не задерживали релиз базы. |
||||||
|
3. **Фаза 2 · Сегментные модули** — углубление по приоритетным группам сегментов (A → C → B → D). |
||||||
|
|
||||||
|
### Критерии приоритета |
||||||
|
|
||||||
|
| Критерий | Что меряем | |
||||||
|
|---|---| |
||||||
|
| **Охват** | Сколько пациентов клиники затронуто (в абсолюте) | |
||||||
|
| **Глубина пользы** | Насколько закрывает реальную боль (есть ли альтернатива без нас) | |
||||||
|
| **Частота касаний** | Как часто функция возвращает пользователя в приложение | |
||||||
|
| **Бизнес-эффект** | Влияние на возвратность, средний чек, удержание, вклад в выручку | |
||||||
|
| **Сложность** | Вторичная ось: усилия (вкл. зависимости от МИС и контента) | |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
## 2. Текущие функции — утилита и приоритет |
||||||
|
|
||||||
|
### 🟢 Высокий приоритет (ядро ценности) |
||||||
|
|
||||||
|
**Запись на приём** — главный транзакционный поток. Экономит 3–8 минут разговора, 24/7, ближайшие окна. Единственная функция, которая приводит новых пациентов через приложение. Усилить: запись из плана лечения в 1 клик (§3), запись из маршрутной карты пред-опа (§4). |
||||||
|
|
||||||
|
**Ближайший приём** — «что со мной сейчас». Снимает тревогу «когда, куда, к кому». Перед визитом открывается 3–10 раз. Усилить: чек-лист подготовки, маршрут до кабинета, тригеры 24ч/2ч/15мин. |
||||||
|
|
||||||
|
### 🟡 Средний приоритет (поддержка) |
||||||
|
|
||||||
|
**Список врачей / карточка врача** — инструмент выбора при первом визите. Повторный пациент почти не открывает. Усилить: соцдоказательства, фильтр «по моему диагнозу». |
||||||
|
|
||||||
|
**Чат с оператором** — замена звонка в регистратуру. Ограничен одним собеседником. Основное развитие — в §3. |
||||||
|
|
||||||
|
**Профиль** — точка идентификации. Редко открывается, но критичен для персонализации. |
||||||
|
|
||||||
|
### 🔴 Низкий приоритет (ниша) |
||||||
|
|
||||||
|
**Семейный профиль** — высокая польза для 20–30% (родители с детьми, взрослые с пожилыми), становится критичным для сегмента «дети с аденоидами» и «сложные хроники — ЧБД». |
||||||
|
|
||||||
|
**Контакты** — функция «галочка», 1–2 открытия за всё время. |
||||||
|
|
||||||
|
### Вывод |
||||||
|
|
||||||
|
Ядро «Запись + Ближайший приём» работает. Слабое место — **нет причины открывать приложение между визитами**. Это и закрывает джентльменский набор. |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
## 3. Джентльменский набор — базовые функции для всех пациентов |
||||||
|
|
||||||
|
Минимум, который должен быть у любого пациента клиники, вне зависимости от диагноза и сегмента. **Приоритет до любых сегментных модулей.** |
||||||
|
|
||||||
|
Набор сознательно разделён на две подфазы по риску и зависимостям: **транзакционная база** (детерминированные функции с понятным MVP) и **коммуникационная надстройка** (LLM и асинхронные каналы, требующие регламентов и безопасности). Это позволяет выпустить базу быстро и безопасно, а надстройку строить поверх уже стабильного фундамента. |
||||||
|
|
||||||
|
### Фаза 1 · Транзакционная база |
||||||
|
|
||||||
|
Функции, где пациент **что-то получает или делает** — без LLM и без диалога. Минимизируют риски, быстрее в запуск, дают те самые «не удалю это приложение»-причины. |
||||||
|
|
||||||
|
| Функция | Статус | Что в ней | |
||||||
|
|---|---|---| |
||||||
|
| Запись на приём | ✅ есть | Запись 24/7, ближайшие окна. | |
||||||
|
| Ближайший приём | ✅ есть | Что, где, когда — снимает тревогу перед визитом. | |
||||||
|
| Чат с оператором | ✅ есть | Справки, переносы, счета, расписание (человеческий канал). | |
||||||
|
| Статьи / база знаний | ✅ есть (Спринт 1) | Уже есть. Источник правды для будущего RAG. | |
||||||
|
| **План лечения с приёма** | ❌ нет — фундамент | После каждого приёма структурированный чеклист: диагноз, назначения (препарат + доза + курс + календарь), ссылки на процедуры самопомощи (Группа A), контрольный приём, запись на следующий визит в 1 клик. Живой объект с напоминаниями. Источник правды для всех следующих надстроек. | |
||||||
|
| **Результаты обследований и медкарта** | ❌ нет | Пациент видит свои анализы, аудиограммы, снимки, заключения **без звонка в клинику**. Статус каждого результата: готов / в работе / годен до [дата]. Критично для Группы C (пред-оп): срок годности анализов виден в одном месте. | |
||||||
|
| **Заказ справок и финансовых документов** | ❌ нет | Справка для налогового вычета (13%), справки работодателю, копии заключений, счета. Заказ в 1 клик, готовая в приложении или с самовывозом. Снимает нагрузку с администраторов и даёт сильный retention-якорь даже у разовых пациентов. | |
||||||
|
|
||||||
|
### Фаза 1.5 · Коммуникационная надстройка |
||||||
|
|
||||||
|
Функции, где идёт **живой или AI-диалог** по поводу лечения. Строятся поверх уже работающей базы (плана лечения, медкарты, статей) и требуют отдельных регламентов — по ответственности, SLA, проверке качества. |
||||||
|
|
||||||
|
| Функция | Статус | Что в ней | Ключевой риск | |
||||||
|
|---|---|---|---| |
||||||
|
| **Чат с медицинским консьержем** | ❌ нет | **Не прямой чат с лечащим врачом.** Дежурный врач / фельдшер / медсестра отвечает по протоколам на 80% рутины («можно ли совмещать с X», «нормально ли, что третий день болит», «когда повторно сдать анализ»), эскалирует клинически значимое лечащему. Асинхронно, SLA — X часов в рабочее время. | Перегрузка врачей и SLA-хаос, если пустить пациентов напрямую к хирургу. Консьерж-слой — основной буфер. Нужен регламент тарификации/компенсации врачам за эскалированные вопросы. | |
||||||
|
| **AI-помощник (RAG 24/7)** | ❌ нет | Знает базу знаний клиники, статьи, план лечения пациента, историю приёмов. Объясняет назначение, ищет ответ в статьях, оценивает «норма или срочно» и эскалирует к консьержу/врачу при тревожных признаках. | Галлюцинация LLM в медицинском контексте = юридический и репутационный риск. **Запускаем в shadow-mode**: ответы сначала идут через консьержа для валидации, метрики точности собираются, и только после набора статистики — переход в прямой режим для безопасных категорий вопросов. | |
||||||
|
|
||||||
|
### Почему это ядро, а не сегмент |
||||||
|
|
||||||
|
- **Работает на 100% пациентов** — без разделения по сегменту. |
||||||
|
- **Усиливает любое сегментное направление**: бегунок, слухопротезирование, АСИТ — всё опирается на план лечения, медкарту и тот же чат-канал. |
||||||
|
- **Закрывает главный пробел транзакционной модели** — «что делать между визитами». |
||||||
|
- **Частично закрывает самый массовый сегмент** (амбулаторный + хроники). Полностью закрыть их может только отдельный модуль «Процедуры самопомощи» (Группа A, §4.3) — это первый сегментный модуль после Фазы 1.5. |
||||||
|
|
||||||
|
### Порядок работ внутри набора |
||||||
|
|
||||||
|
**Фаза 1:** |
||||||
|
1. **План лечения с приёма** — фундамент. Без структурированных назначений не работает ничего поверх (ни AI, ни напоминания, ни процедуры самопомощи). |
||||||
|
2. **Результаты / медкарта** — следующий retention-якорь. |
||||||
|
3. **Заказ справок** — быстрый win для большой части пациентов, снимает нагрузку с администраторов. |
||||||
|
|
||||||
|
**Фаза 1.5** (после стабилизации Фазы 1): |
||||||
|
4. **Чат с медицинским консьержем** — инфраструктура канала + регламент ответов. |
||||||
|
5. **AI-помощник на RAG (shadow-mode)** — сначала ответы валидируются консьержем, потом постепенный переход в прямой режим для безопасных категорий. |
||||||
|
|
||||||
|
### Критическая зависимость от МИС |
||||||
|
|
||||||
|
«План лечения» — это структурированные данные (препарат, доза, частота, курс, процедура). Два сценария: |
||||||
|
- **МИС отдаёт назначения по API структурированно** — план лечения собирается автоматически из данных приёма. Предпочтительно. |
||||||
|
- **МИС отдаёт только PDF-заключение** — план лечения MVP стартует с **ручного ввода врачом в виджет** (шаблоны по нозологиям + чеклисты + автоподстановка из предыдущего приёма). Интеграция с МИС — отдельной задачей позже. |
||||||
|
|
||||||
|
Ответ на этот вопрос определяет сроки и стоимость Фазы 1. Добавлен в §6 как первоочередной. |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
## 4. Сегменты пациентов через призму приложения |
||||||
|
|
||||||
|
### 4.1. Фундаментальное деление: первичный vs повторный |
||||||
|
|
||||||
|
| Линза | Первичный в приложении | Повторный в приложении | |
||||||
|
|---|---|---| |
||||||
|
| **Главный job** | «Куда мне обратиться и как записаться» | «Что мне делать сейчас по моему лечению» | |
||||||
|
| **Источник** | Попадает через сайт/рекламу/сарафан | Приложение уже установлено, уведомление/сам открывает | |
||||||
|
| **Частота открытия** | 1–3 раза до визита | Ежедневно в активном эпизоде | |
||||||
|
| **Что нужно в приложении** | Базовый минимум (запись, цены, контакты, врачи) | Специализированный модуль сегмента | |
||||||
|
| **Приоритет развития** | Низкий (веб и реклама работают лучше) | ● Высокий (2/3 потока) | |
||||||
|
|
||||||
|
**Ключевое следствие.** Специализированных «первичных» модулей под каждый сегмент строить не нужно. Исключения — сегменты, где «после первого визита» начинается длинный путь: сурдология, хирургия, АСИТ. Там «первичный» в терминах клиники ≠ «первичный» в терминах приложения. |
||||||
|
|
||||||
|
### 4.2. Матрица 10 сегментов × первичный / повторный |
||||||
|
|
||||||
|
Из 10 сегментов бизнес-аналитики выделяем: объём × чек × что нужно в приложении для первичного × что нужно для повторного × итоговый приоритет приложения. |
||||||
|
|
||||||
|
| # | Сегмент (из аналитики) | Объём / Вклад | Первичный в приложении | Повторный в приложении (главная работа) | Приоритет в App | |
||||||
|
|---|---|---|---|---|:-:| |
||||||
|
| 1 | **Взрослые «заблокированный нос»** (полипы, перегородка, FESS) | 300 оп/год · 100т · 30 млн | Джентльменский + материалы о методах (FESS/лазер), кейсы пациентов, калькулятор, **возвратные push для сомневающихся после пред-оп приёма** | Пред-оп бегунок (6 нед) → восстановление → контроль 3/6/12 мес | ● **Высокий** (Группа C) | |
||||||
|
| 2 | **Амбулаторный поток** (острые и хроники ЛОР) | Тысячи/мес · 120 млн | Джентльменский | План лечения + эпизод лечения + дневник симптомов (§3) **+ модуль процедур самопомощи: библиотека техник (промывание носа физраствором, полоскание горла, ингаляции), напоминания, трекер комплаенса** | ● **Высший** (Группа A — отдельный модуль) | |
||||||
|
| 3 | **Родители детей с аденоидами** | 400–500 оп/год · 60т · 20–30 млн | Джентльменский + семейный профиль + подготовка ребёнка + **материалы «нужна ли операция» и возврат сомневающихся родителей** | Пред-оп бегунок (детская версия) → восстановление. Далее — редко. | ● **Высокий** (Группа C) | |
||||||
|
| 4 | **Потеря слуха (сурдология)** | 20 млн/год | **Нестандартный первичный:** аудиограмма в профиле, аудио-демо, каталог моделей, калькулятор, шеринг близкому, возвратные push | Паспорт аппарата, сервисный календарь, расходники, калибровка раз в год, дневник адаптации | ● **Высокий** (Группа B — уникальный модуль) | |
||||||
|
| 5 | **Сложные хроники** (иммунология/аллергология, ЧБД) | Высокий, часть 120 млн · длинный LTV | Джентльменский + семейный (ЧБД) + запись на консилиум | Модуль процедур самопомощи (Группа A): промывания, полоскания, ингаляции у ЧБД. Плюс специализация: **АСИТ-трекер** (дневник симптомов + пыльцевой календарь + навигатор побочки) | ● **Высокий** (Группа A + Группа D) | |
||||||
|
| 6 | **Зависимость от капель (вазотомия)** | Высокий объём · входной в хирургию | Джентльменский + материалы «как слезть с капель» + **возврат сомневающихся после пред-оп приёма** | Пред-оп бегунок (компактная версия) → восстановление | ● **Высокий** (Группа C) | |
||||||
|
| 7 | **Пульмонология** (кашель/астма) | Средний · сезонный | Джентльменский | Дневник астмы, напоминания об ингаляторах, контроль триггеров (пересекается с АСИТ) | ◐ **Средний** (частично Группа D) | |
||||||
|
| 8 | **Социально активные храпуны** | Низкий · высокая платёжеспособность | Джентльменский + образовательный контент о сомнологии | Сомнологический чек-up, СИПАП-трекер (если назначен) | ○ **Низкий** | |
||||||
|
| 9 | **Фониатрия** (голос) | Очень низкий · срочный | Джентльменский + срочная запись | Короткое окно, низкая повторность | ○ **Низкий** | |
||||||
|
| 10 | **Check-up и Второе мнение** | Единичный · высокая маржа | Джентльменский + позиционирование бренда Оленевой | Разовая услуга, минимальная повторность | ○ **Низкий** | |
||||||
|
|
||||||
|
### 4.3. Четыре группы сегментов для повторных |
||||||
|
|
||||||
|
**Группа A. Амбулаторный поток + хроники — процедуры самопомощи** — сегменты 2 + 5 (повторная часть). Самый массовый сегмент × ежедневная повторность. |
||||||
|
|
||||||
|
Джентльменский набор (план лечения + чат с врачом + AI) закрывает коммуникацию и напоминания, **но не закрывает саму регулярную работу пациента между приёмами**: |
||||||
|
- Промывание носа физраствором (при хр. рините, синусите, после операций) |
||||||
|
- Полоскание горла (при хр. тонзиллите) |
||||||
|
- Ингаляции |
||||||
|
- Гимнастика слуховой трубы (при евстахиите) |
||||||
|
- Голосовые упражнения (фониатрия) |
||||||
|
- Туалет уха (при хр. отите) |
||||||
|
|
||||||
|
**Что нужно в модуле:** |
||||||
|
- **Библиотека техник** — короткие видео и пошаговые инструкции «как правильно». Ошибки в технике (сильный напор при промывании, не тот раствор) — частая причина, почему «не помогает». |
||||||
|
- **Напоминания** — утро/вечер по схеме, привязаны к плану лечения. |
||||||
|
- **Трекер комплаенса** — ежедневные отметки, стрики, сводка «сколько дней подряд». |
||||||
|
- **Дневник симптомов в связке** — «промываю 5 дней, насморк уменьшился с 4 до 2» — главный мотиватор продолжать. |
||||||
|
- **Сводка для врача** — перед контрольным приёмом врач видит, что пациент делал, как часто, с какой динамикой симптомов. |
||||||
|
|
||||||
|
**Это отдельный модуль, не продолжение Фазы 1.** Он опирается на план лечения как на источник назначений, но требует собственного контента (библиотека техник) и UX (трекер). |
||||||
|
|
||||||
|
**Группа B. Сурдология** — сегмент 4. Уникальный набор функций (аудиограмма, аудио-демо, каталог, паспорт аппарата). Пожизненная повторность. Высокий чек. **Отдельный модуль, не пересекается с другими.** |
||||||
|
|
||||||
|
**Группа C. Пред-операционная подготовка + восстановление** — сегменты 1 + 3 + 6 (одна механика для трёх сегментов). **Две фазы, как у Группы B:** |
||||||
|
- **Кандидаты на операцию** — после пред-оп приёма ушли «думать». Возврат через материалы, кейсы пациентов, чат с хирургом, возвратные push-триггеры (3/7/21 день), прозрачность по цене/рассрочке. |
||||||
|
- **Решившиеся** — бегунок → чек-лист дня операции → операция → восстановление. Окно 6–12 недель. |
||||||
|
|
||||||
|
**Один модуль закрывает три сегмента бизнес-аналитики** (FESS, детские аденоиды, вазотомия). |
||||||
|
|
||||||
|
**Группа D. АСИТ + контроль астмы** — часть сегмента 5 + сегмент 7. Ежедневный трекер, дневник симптомов, навигатор побочки. **Самый сложный, требует верификации врачом.** |
||||||
|
|
||||||
|
### 4.4. Что остаётся за кадром |
||||||
|
|
||||||
|
Сегменты 8 (храпуны), 9 (фониатрия), 10 (check-up) — низкая повторность и/или низкий охват. Закрываются базовым джентльменским набором, специализированных модулей в ближайшем горизонте не требуют. |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
## 5. Порядок внедрения |
||||||
|
|
||||||
|
### Фаза 1. Транзакционная база (§3) |
||||||
|
|
||||||
|
План лечения → Результаты / медкарта → Заказ справок. |
||||||
|
|
||||||
|
**Эффект:** пациент видит свои назначения, результаты и может получить документы без звонка в клинику. Это и есть базовые retention-якоря: «не удалю это приложение». Массовый амбулаторный + хроники покрыты в части информирования и документов. |
||||||
|
|
||||||
|
**Критический параметр сроков** — структурированность назначений в МИС (см. §6 вопрос 1). От этого зависит, собирается ли план лечения автоматически или врач заполняет его вручную в виджете. |
||||||
|
|
||||||
|
### Фаза 1.5. Коммуникационная надстройка (§3) |
||||||
|
|
||||||
|
Чат с медицинским консьержем → AI-помощник (shadow-mode). |
||||||
|
|
||||||
|
**Зачем отдельная подфаза:** эти функции несут организационные и юридические риски (SLA, выгорание врачей, галлюцинации LLM) и могут надолго задержать релиз, если класть в Фазу 1. Выделение в 1.5 позволяет: собрать транзакционную базу быстро и безопасно, отработать регламент консьержа отдельно, запустить AI сначала под валидацией человека. |
||||||
|
|
||||||
|
### Фаза 2. Сегментные модули — порядок |
||||||
|
|
||||||
|
Рекомендуемая последовательность: |
||||||
|
|
||||||
|
**1. Группа A (Процедуры самопомощи хроников) — первым** |
||||||
|
- **Самый массовый охват** — тысячи пациентов в месяц (сегмент 2 + 5). |
||||||
|
- Напрямую опирается на план лечения из Фазы 1 — продолжение той же инфраструктуры. |
||||||
|
- Средняя сложность: контент (видео-инструкции, 10–15 техник) + простой трекер + дневник симптомов. |
||||||
|
- Бизнес-эффект: рост комплаенса → меньше обострений → меньше экстренных приёмов и операций, на которые хроники срываются, когда дома не помогает. |
||||||
|
- Эффект заметен пациенту сразу — ежедневная польза. |
||||||
|
|
||||||
|
**2. Группа C (Пред-операционная подготовка) — вторым** |
||||||
|
- Закрывает 3 сегмента (1, 3, 6) одним модулем. |
||||||
|
- Быстрый MVP — маршрутная карта с чекбоксами, сроки годности, автозапись. Восстановление уже есть в прототипе. |
||||||
|
- Прямой измеримый бизнес-эффект: снижение переносов операций из-за просроченных анализов + возврат сомневающихся кандидатов на операцию. |
||||||
|
- Вклад сегментов в выручку: ~50–60 млн (хирургия), плюс косвенно вазотомия как конвертер в большую хирургию. |
||||||
|
|
||||||
|
**3. Группа B (Сурдология) — третьим** |
||||||
|
- Изолированный сегмент с уникальными функциями. |
||||||
|
- Пожизненное удержание × высокий чек × растущий рынок (старение). |
||||||
|
- Две половины: возврат кандидатов после демо (высокая конверсия в деньги) + обслуживание после покупки (лояльность и LTV). |
||||||
|
- Можно запускать параллельно с C после Фазы 1, если есть ресурс. |
||||||
|
|
||||||
|
**4. Группа D (АСИТ + астма) — четвёртым** |
||||||
|
- Самая высокая глубина пользы (влияет на медисход), но самая высокая ответственность. |
||||||
|
- Требует верификации контента аллергологом/пульмонологом клиники. |
||||||
|
- Можно начать готовить контент и интеграции параллельно с A/C/B, выпустить позже. |
||||||
|
|
||||||
|
### Что не берём в план сейчас |
||||||
|
|
||||||
|
- Храпуны (8), фониатрия (9), check-up (10) — специализированных модулей в горизонте планирования не делаем. |
||||||
|
- Отдельные «первичные» модули под сегменты — не делаем. Первичный путь = джентльменский набор + базовые функции (запись, врачи, цены, контакты), которые уже есть. |
||||||
|
|
||||||
|
### Что нужно сделать вне Фаз, уже сейчас |
||||||
|
|
||||||
|
- **Добавить аллерголога-иммунолога в список врачей** (есть специализация, нет конкретного врача в данных). Предусловие для Группы D. |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
## 6. Вопросы к обсуждению на встрече |
||||||
|
|
||||||
|
**Первоочередной (определяет сроки Фазы 1):** |
||||||
|
|
||||||
|
1. **МИС и структурированные назначения.** Отдаёт ли МИС по API назначения структурированно (препарат, доза, частота, курс) или только PDF-заключением? От этого зависит: план лечения собирается автоматически или врач заполняет вручную в виджете. Там же: API для результатов анализов, сроков годности, расписания. |
||||||
|
|
||||||
|
**По процессам клиники:** |
||||||
|
|
||||||
|
2. **Медицинский консьерж — кто в роли?** Дежурный врач / фельдшер / медсестра? Кто держит SLA? Как компенсируется эскалация вопроса лечащему врачу? |
||||||
|
3. **SLA чата** — целевое время ответа в рабочее время (1ч / 4ч / день)? |
||||||
|
4. **Справки и финдокументы** — текущий процесс заказа через администратора; что готовы автоматизировать в первую очередь (ФНС-справка, выписки, счета)? |
||||||
|
|
||||||
|
**По метрикам (для оценки эффекта):** |
||||||
|
|
||||||
|
5. Подтвердить **«2 из 3 — повторные»** — уникальные пациенты в год или визиты? Меняет оценку охвата Группы A. |
||||||
|
6. **Процент повторных, не доходящих до контроля** — метрика успеха Фазы 1. |
||||||
|
7. **Сурдология** — кандидатов/мес, % возврата за аппаратом. От этого зависит приоритет Группы B. |
||||||
|
8. **Переносы операций** — частая причина просроченные анализы? Усиливает Группу C. |
||||||
|
|
||||||
|
**По ресурсам Фазы 1.5 и 2:** |
||||||
|
|
||||||
|
9. Готов ли **аллерголог** верифицировать контент для АСИТ-трекера? Без этого D не запускаем. |
||||||
|
10. База знаний / статьи — достаточно ли материала для RAG или формировать отдельно? |
||||||
|
11. Политика по **AI shadow-mode**: кто утверждает категории вопросов для постепенного перевода в прямой режим? |
||||||
|
|
||||||
|
--- |
||||||
|
|
||||||
|
## Приложение. Короткая сводка для слайда |
||||||
|
|
||||||
|
**Что предлагаем:** |
||||||
|
1. **Фаза 1** — транзакционная база для всех: план лечения, результаты/медкарта, заказ справок + уже существующие запись, ближайший приём, чат с оператором, статьи. Быстрый MVP, минимум рисков. |
||||||
|
2. **Фаза 1.5** — коммуникационная надстройка: чат с медицинским консьержем (не прямой с врачом) и AI-помощник в shadow-mode. Запускается после стабилизации базы. |
||||||
|
3. **Фаза 2** — четыре сегментных модуля в порядке: A (процедуры самопомощи хроников — массовый) → C (пред-оп подготовка — 3 сегмента разом) → B (сурдология — высокий чек) → D (АСИТ + астма — с верификацией врачом). |
||||||
|
4. **Первичные в приложении** = базовый минимум, который уже есть. Новых первичных модулей не строим — они приходят через веб. Исключения — сегменты, где после первого визита пациент «уходит думать»: сурдология, хирургия, АСИТ. |
||||||
Binary file not shown.
@ -0,0 +1,913 @@ |
|||||||
|
"""Собирает MEETING_2026-04-23.pptx из содержания MEETING_2026-04-23.md. |
||||||
|
|
||||||
|
Запуск: python3 build_deck.py |
||||||
|
Выход: MEETING_2026-04-23.pptx в корне проекта |
||||||
|
""" |
||||||
|
|
||||||
|
from pptx import Presentation |
||||||
|
from pptx.util import Inches, Pt, Emu |
||||||
|
from pptx.dml.color import RGBColor |
||||||
|
from pptx.enum.shapes import MSO_SHAPE |
||||||
|
from pptx.enum.text import PP_ALIGN, MSO_ANCHOR |
||||||
|
from pptx.oxml.ns import qn |
||||||
|
from copy import deepcopy |
||||||
|
|
||||||
|
# ---------- Бренд клиники ---------- |
||||||
|
PRIMARY = RGBColor(0x2B, 0xB4, 0xA8) |
||||||
|
PRIMARY_DARK = RGBColor(0x1C, 0x8A, 0x80) |
||||||
|
PRIMARY_50 = RGBColor(0xE8, 0xF7, 0xF5) |
||||||
|
ACCENT = RGBColor(0xE0, 0x4E, 0x44) |
||||||
|
WARM = RGBColor(0xF5, 0xED, 0xDF) |
||||||
|
SUCCESS = RGBColor(0x2E, 0x9B, 0x6B) |
||||||
|
WARNING = RGBColor(0xE8, 0xA1, 0x3C) |
||||||
|
DANGER = RGBColor(0xD9, 0x41, 0x41) |
||||||
|
FG = RGBColor(0x1F, 0x29, 0x37) |
||||||
|
FG2 = RGBColor(0x4B, 0x55, 0x63) |
||||||
|
FG3 = RGBColor(0x9C, 0xA3, 0xAF) |
||||||
|
BG = RGBColor(0xFF, 0xFF, 0xFF) |
||||||
|
SOFT = RGBColor(0xF3, 0xF4, 0xF6) |
||||||
|
|
||||||
|
FONT_SANS = "PT Sans" |
||||||
|
FONT_DISPLAY = "PT Sans Narrow" |
||||||
|
|
||||||
|
# ---------- Геометрия 16:9 ---------- |
||||||
|
prs = Presentation() |
||||||
|
prs.slide_width = Inches(13.333) |
||||||
|
prs.slide_height = Inches(7.5) |
||||||
|
SW = prs.slide_width |
||||||
|
SH = prs.slide_height |
||||||
|
|
||||||
|
BLANK_LAYOUT = prs.slide_layouts[6] # Blank |
||||||
|
|
||||||
|
MARGIN_L = Inches(0.6) |
||||||
|
MARGIN_R = Inches(0.6) |
||||||
|
MARGIN_T = Inches(0.45) |
||||||
|
CONTENT_W = SW - MARGIN_L - MARGIN_R |
||||||
|
|
||||||
|
FOOTER_TXT = "Клиника УГН · Приложение · 23 апр 2026" |
||||||
|
|
||||||
|
# ---------- Примитивы ---------- |
||||||
|
def add_rect(slide, x, y, w, h, fill=None, line=None, line_w=None): |
||||||
|
shp = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, x, y, w, h) |
||||||
|
shp.shadow.inherit = False |
||||||
|
if fill is None: |
||||||
|
shp.fill.background() |
||||||
|
else: |
||||||
|
shp.fill.solid() |
||||||
|
shp.fill.fore_color.rgb = fill |
||||||
|
if line is None: |
||||||
|
shp.line.fill.background() |
||||||
|
else: |
||||||
|
shp.line.color.rgb = line |
||||||
|
if line_w is not None: |
||||||
|
shp.line.width = line_w |
||||||
|
return shp |
||||||
|
|
||||||
|
def add_text(slide, x, y, w, h, text, *, size=16, bold=False, color=FG, |
||||||
|
font=FONT_SANS, align=PP_ALIGN.LEFT, anchor=MSO_ANCHOR.TOP, |
||||||
|
line_spacing=None): |
||||||
|
tb = slide.shapes.add_textbox(x, y, w, h) |
||||||
|
tf = tb.text_frame |
||||||
|
tf.word_wrap = True |
||||||
|
tf.margin_left = tf.margin_right = Emu(0) |
||||||
|
tf.margin_top = tf.margin_bottom = Emu(0) |
||||||
|
tf.vertical_anchor = anchor |
||||||
|
lines = text.split("\n") |
||||||
|
for i, ln in enumerate(lines): |
||||||
|
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph() |
||||||
|
p.alignment = align |
||||||
|
if line_spacing is not None: |
||||||
|
p.line_spacing = line_spacing |
||||||
|
r = p.add_run() |
||||||
|
r.text = ln |
||||||
|
r.font.name = font |
||||||
|
r.font.size = Pt(size) |
||||||
|
r.font.bold = bold |
||||||
|
r.font.color.rgb = color |
||||||
|
return tb |
||||||
|
|
||||||
|
def add_rich(slide, x, y, w, h, runs, *, align=PP_ALIGN.LEFT, |
||||||
|
anchor=MSO_ANCHOR.TOP, size=14, line_spacing=1.15): |
||||||
|
"""runs = [(text, {'bold':bool,'color':RGB,'size':int,'font':str}), ...]""" |
||||||
|
tb = slide.shapes.add_textbox(x, y, w, h) |
||||||
|
tf = tb.text_frame |
||||||
|
tf.word_wrap = True |
||||||
|
tf.margin_left = tf.margin_right = Emu(0) |
||||||
|
tf.margin_top = tf.margin_bottom = Emu(0) |
||||||
|
tf.vertical_anchor = anchor |
||||||
|
paragraphs = [[]] |
||||||
|
for text, style in runs: |
||||||
|
if text == "\n": |
||||||
|
paragraphs.append([]) |
||||||
|
else: |
||||||
|
paragraphs[-1].append((text, style)) |
||||||
|
for i, para in enumerate(paragraphs): |
||||||
|
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph() |
||||||
|
p.alignment = align |
||||||
|
p.line_spacing = line_spacing |
||||||
|
for text, style in para: |
||||||
|
r = p.add_run() |
||||||
|
r.text = text |
||||||
|
r.font.name = style.get("font", FONT_SANS) |
||||||
|
r.font.size = Pt(style.get("size", size)) |
||||||
|
r.font.bold = style.get("bold", False) |
||||||
|
r.font.color.rgb = style.get("color", FG) |
||||||
|
return tb |
||||||
|
|
||||||
|
def footer(slide, idx, total): |
||||||
|
add_rect(slide, 0, SH - Inches(0.32), SW, Inches(0.32), fill=PRIMARY_50) |
||||||
|
add_text(slide, MARGIN_L, SH - Inches(0.3), Inches(8), Inches(0.25), |
||||||
|
FOOTER_TXT, size=10, color=FG2) |
||||||
|
add_text(slide, SW - Inches(1.2), SH - Inches(0.3), Inches(0.6), Inches(0.25), |
||||||
|
f"{idx} / {total}", size=10, color=FG2, align=PP_ALIGN.RIGHT) |
||||||
|
|
||||||
|
def title_bar(slide, title, eyebrow=None): |
||||||
|
"""Верхняя полоска: маленькая подпись категории + крупный заголовок.""" |
||||||
|
y = MARGIN_T |
||||||
|
if eyebrow: |
||||||
|
add_text(slide, MARGIN_L, y, CONTENT_W, Inches(0.3), |
||||||
|
eyebrow.upper(), size=11, bold=True, color=PRIMARY, |
||||||
|
font=FONT_SANS) |
||||||
|
y += Inches(0.34) |
||||||
|
add_text(slide, MARGIN_L, y, CONTENT_W, Inches(0.6), |
||||||
|
title, size=28, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
y += Inches(0.7) |
||||||
|
# Тонкая линия |
||||||
|
add_rect(slide, MARGIN_L, y, Inches(1.2), Inches(0.04), fill=PRIMARY) |
||||||
|
return y + Inches(0.25) |
||||||
|
|
||||||
|
def new_slide(): |
||||||
|
return prs.slides.add_slide(BLANK_LAYOUT) |
||||||
|
|
||||||
|
# ---------- Стилизованная таблица ---------- |
||||||
|
def add_table(slide, x, y, w, h, data, *, |
||||||
|
header=True, col_widths=None, row_heights=None, |
||||||
|
header_fill=PRIMARY, header_fg=BG, body_fg=FG, |
||||||
|
alt_fill=PRIMARY_50, size=11, header_size=11): |
||||||
|
rows, cols = len(data), len(data[0]) |
||||||
|
tbl_shp = slide.shapes.add_table(rows, cols, x, y, w, h).table |
||||||
|
if col_widths: |
||||||
|
for i, cw in enumerate(col_widths): |
||||||
|
tbl_shp.columns[i].width = cw |
||||||
|
if row_heights: |
||||||
|
for i, rh in enumerate(row_heights): |
||||||
|
tbl_shp.rows[i].height = rh |
||||||
|
for ri, row in enumerate(data): |
||||||
|
for ci, cell_val in enumerate(row): |
||||||
|
cell = tbl_shp.cell(ri, ci) |
||||||
|
cell.margin_left = cell.margin_right = Inches(0.08) |
||||||
|
cell.margin_top = cell.margin_bottom = Inches(0.05) |
||||||
|
# Fill |
||||||
|
if header and ri == 0: |
||||||
|
cell.fill.solid(); cell.fill.fore_color.rgb = header_fill |
||||||
|
elif alt_fill and ri % 2 == 0 and not (header and ri == 0): |
||||||
|
cell.fill.solid(); cell.fill.fore_color.rgb = alt_fill |
||||||
|
else: |
||||||
|
cell.fill.solid(); cell.fill.fore_color.rgb = BG |
||||||
|
# Text |
||||||
|
tf = cell.text_frame |
||||||
|
tf.word_wrap = True |
||||||
|
tf.clear() |
||||||
|
lines = str(cell_val).split("\n") |
||||||
|
for i, ln in enumerate(lines): |
||||||
|
p = tf.paragraphs[0] if i == 0 else tf.add_paragraph() |
||||||
|
p.alignment = PP_ALIGN.LEFT |
||||||
|
r = p.add_run() |
||||||
|
r.text = ln |
||||||
|
r.font.name = FONT_SANS |
||||||
|
if header and ri == 0: |
||||||
|
r.font.size = Pt(header_size) |
||||||
|
r.font.bold = True |
||||||
|
r.font.color.rgb = header_fg |
||||||
|
else: |
||||||
|
r.font.size = Pt(size) |
||||||
|
r.font.color.rgb = body_fg |
||||||
|
return tbl_shp |
||||||
|
|
||||||
|
# ============================================================ |
||||||
|
# СЛАЙДЫ |
||||||
|
# ============================================================ |
||||||
|
|
||||||
|
def slide_title(): |
||||||
|
s = new_slide() |
||||||
|
# Фоновая тёплая полоса слева |
||||||
|
add_rect(s, 0, 0, Inches(4.5), SH, fill=WARM) |
||||||
|
# Teal-акцент |
||||||
|
add_rect(s, Inches(4.5), 0, Inches(0.12), SH, fill=PRIMARY) |
||||||
|
# Левый блок — мета |
||||||
|
add_text(s, Inches(0.7), Inches(0.7), Inches(3.5), Inches(0.3), |
||||||
|
"КЛИНИКА УГН", size=12, bold=True, color=PRIMARY_DARK) |
||||||
|
add_text(s, Inches(0.7), Inches(1.1), Inches(3.5), Inches(0.3), |
||||||
|
"Мобильное приложение", size=13, color=FG2) |
||||||
|
add_text(s, Inches(0.7), SH - Inches(1.2), Inches(3.5), Inches(0.3), |
||||||
|
"Встреча", size=12, color=FG3) |
||||||
|
add_text(s, Inches(0.7), SH - Inches(0.9), Inches(3.5), Inches(0.4), |
||||||
|
"23 апреля 2026", size=18, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
# Правый блок — заголовок |
||||||
|
add_text(s, Inches(5.1), Inches(2.2), Inches(7.6), Inches(1.0), |
||||||
|
"Приоритеты развития", size=48, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, Inches(5.1), Inches(3.2), Inches(7.6), Inches(0.8), |
||||||
|
"мобильного приложения", size=36, color=FG2, font=FONT_DISPLAY) |
||||||
|
# Подзаголовок |
||||||
|
add_rect(s, Inches(5.1), Inches(4.5), Inches(0.8), Inches(0.04), fill=PRIMARY) |
||||||
|
add_text(s, Inches(5.1), Inches(4.7), Inches(7.6), Inches(1.5), |
||||||
|
"Джентльменский набор для всех\nи четыре группы сегментов повторных", |
||||||
|
size=20, color=FG2, font=FONT_DISPLAY) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_agenda(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Повестка", "Что обсуждаем") |
||||||
|
items = [ |
||||||
|
("1", "Контекст и критерии приоритизации", |
||||||
|
"Факты о потоке пациентов, 10 бизнес-сегментов, рамка оценки"), |
||||||
|
("2", "Текущие функции — что есть", |
||||||
|
"Приоритеты использования и точки усиления"), |
||||||
|
("3", "Джентльменский набор для всех пациентов", |
||||||
|
"Транзакционная база (Фаза 1) + коммуникационная надстройка (Фаза 1.5)"), |
||||||
|
("4", "10 сегментов × первичный/повторный в приложении", |
||||||
|
"Матрица и 4 группы сегментных модулей"), |
||||||
|
("5", "Порядок внедрения и решение", |
||||||
|
"Фаза 1 → Фаза 1.5 → Фаза 2 (A → C → B → D). Что выбираем сегодня"), |
||||||
|
] |
||||||
|
row_h = Inches(0.95) |
||||||
|
for i, (num, title, sub) in enumerate(items): |
||||||
|
yy = y + row_h * i |
||||||
|
# кружок-номер |
||||||
|
circle = s.shapes.add_shape(MSO_SHAPE.OVAL, MARGIN_L, yy, |
||||||
|
Inches(0.6), Inches(0.6)) |
||||||
|
circle.shadow.inherit = False |
||||||
|
circle.fill.solid(); circle.fill.fore_color.rgb = PRIMARY |
||||||
|
circle.line.fill.background() |
||||||
|
tf = circle.text_frame |
||||||
|
tf.margin_left = tf.margin_right = Emu(0) |
||||||
|
tf.margin_top = tf.margin_bottom = Emu(0) |
||||||
|
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER |
||||||
|
r = p.add_run(); r.text = num |
||||||
|
r.font.name = FONT_DISPLAY; r.font.size = Pt(20); r.font.bold = True |
||||||
|
r.font.color.rgb = BG |
||||||
|
add_text(s, MARGIN_L + Inches(0.9), yy + Inches(0.02), |
||||||
|
Inches(11), Inches(0.4), title, size=18, bold=True, |
||||||
|
color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, MARGIN_L + Inches(0.9), yy + Inches(0.45), |
||||||
|
Inches(11), Inches(0.4), sub, size=13, color=FG2) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_facts(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Ключевые факты о потоке", "Контекст") |
||||||
|
# Большая статистика слева |
||||||
|
add_text(s, MARGIN_L, y + Inches(0.2), Inches(5), Inches(1.6), |
||||||
|
"2 из 3", size=88, bold=True, color=PRIMARY, font=FONT_DISPLAY) |
||||||
|
add_text(s, MARGIN_L, y + Inches(1.8), Inches(5.5), Inches(0.7), |
||||||
|
"пациентов клиники — повторные", |
||||||
|
size=18, color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, MARGIN_L, y + Inches(2.4), Inches(5.5), Inches(1.4), |
||||||
|
"Значительная доля — повторные внутри одного эпизода лечения: " |
||||||
|
"после первого визита ещё 1–3+ приёма, процедуры, контроль.", |
||||||
|
size=13, color=FG2) |
||||||
|
# Правый блок — выручка |
||||||
|
bx = Inches(7.0); bw = Inches(5.7) |
||||||
|
add_rect(s, bx, y + Inches(0.1), bw, Inches(4.8), |
||||||
|
fill=PRIMARY_50, line=PRIMARY, line_w=Pt(0.5)) |
||||||
|
add_text(s, bx + Inches(0.3), y + Inches(0.3), bw - Inches(0.6), Inches(0.4), |
||||||
|
"ВЫРУЧКА ~200 МЛН / ГОД · 10 СЕГМЕНТОВ", size=11, bold=True, |
||||||
|
color=PRIMARY_DARK) |
||||||
|
lead_rows = [ |
||||||
|
("Амбулаторный поток", "тысячи/мес", "~120 млн"), |
||||||
|
("Взрослая хирургия (FESS, полипы, перегородка)", "300 оп/год", "~30 млн"), |
||||||
|
("Детская аденоидная хирургия", "400–500 оп/год", "~20–30 млн"), |
||||||
|
("Сурдология (слуховые аппараты)", "высокая конверсия", "~20 млн"), |
||||||
|
("Хроники, ЧБД, вазотомия, пульмо, храпуны, фониатрия, check-up", "6 сегментов", "остальное"), |
||||||
|
] |
||||||
|
ty = y + Inches(0.8) |
||||||
|
for name, vol, rev in lead_rows: |
||||||
|
add_text(s, bx + Inches(0.3), ty, Inches(3.5), Inches(0.3), |
||||||
|
name, size=12, bold=True, color=FG) |
||||||
|
add_text(s, bx + Inches(0.3), ty + Inches(0.28), Inches(3.5), Inches(0.24), |
||||||
|
vol, size=10, color=FG3) |
||||||
|
add_text(s, bx + bw - Inches(1.8), ty, Inches(1.5), Inches(0.4), |
||||||
|
rev, size=14, bold=True, color=ACCENT, align=PP_ALIGN.RIGHT, |
||||||
|
font=FONT_DISPLAY) |
||||||
|
ty += Inches(0.76) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_frame(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Приложение = удержание, не привлечение", "Продуктовая рамка") |
||||||
|
# Две колонки |
||||||
|
colw = Inches(6.15) |
||||||
|
gap = Inches(0.23) |
||||||
|
# Левая |
||||||
|
lx = MARGIN_L |
||||||
|
add_rect(s, lx, y + Inches(0.1), colw, Inches(4.7), |
||||||
|
fill=SOFT, line=None) |
||||||
|
add_text(s, lx + Inches(0.3), y + Inches(0.25), colw - Inches(0.6), Inches(0.4), |
||||||
|
"ПЕРВИЧНЫЕ", size=12, bold=True, color=FG3) |
||||||
|
add_text(s, lx + Inches(0.3), y + Inches(0.6), colw - Inches(0.6), Inches(0.6), |
||||||
|
"Приходят через веб", size=22, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_rich(s, lx + Inches(0.3), y + Inches(1.3), colw - Inches(0.6), Inches(3.4), [ |
||||||
|
("Главный job: ", {"bold": True, "color": FG}), |
||||||
|
("«куда мне обратиться, как записаться»", {}), |
||||||
|
("\n", {}), |
||||||
|
("Источник: ", {"bold": True, "color": FG}), |
||||||
|
("сайт, SEO, реклама, сарафан", {}), |
||||||
|
("\n", {}), |
||||||
|
("В приложении: ", {"bold": True, "color": FG}), |
||||||
|
("базовый минимум, который уже есть", {}), |
||||||
|
("\n", {}), |
||||||
|
("Приоритет развития: ", {"bold": True, "color": FG}), |
||||||
|
("низкий — веб работает лучше", {}), |
||||||
|
], size=13, line_spacing=1.3) |
||||||
|
# Правая (основная) |
||||||
|
rx = lx + colw + gap |
||||||
|
add_rect(s, rx, y + Inches(0.1), colw, Inches(4.7), |
||||||
|
fill=PRIMARY_50, line=PRIMARY, line_w=Pt(1)) |
||||||
|
add_text(s, rx + Inches(0.3), y + Inches(0.25), colw - Inches(0.6), Inches(0.4), |
||||||
|
"ПОВТОРНЫЕ · 2 ИЗ 3", size=12, bold=True, color=PRIMARY_DARK) |
||||||
|
add_text(s, rx + Inches(0.3), y + Inches(0.6), colw - Inches(0.6), Inches(0.6), |
||||||
|
"Приоритет приложения", size=22, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_rich(s, rx + Inches(0.3), y + Inches(1.3), colw - Inches(0.6), Inches(3.4), [ |
||||||
|
("Главный job: ", {"bold": True, "color": FG}), |
||||||
|
("«что делать сейчас по моему лечению»", {}), |
||||||
|
("\n", {}), |
||||||
|
("Источник: ", {"bold": True, "color": FG}), |
||||||
|
("приложение уже установлено, push / сам открывает", {}), |
||||||
|
("\n", {}), |
||||||
|
("В приложении: ", {"bold": True, "color": FG}), |
||||||
|
("специализированный модуль сегмента", {}), |
||||||
|
("\n", {}), |
||||||
|
("Приоритет развития: ", {"bold": True, "color": FG}), |
||||||
|
("высокий — закрывает 2/3 потока", {}), |
||||||
|
], size=13, line_spacing=1.3) |
||||||
|
# Сноска-исключения |
||||||
|
add_text(s, MARGIN_L, y + Inches(5.1), CONTENT_W, Inches(0.4), |
||||||
|
"Исключения: сурдология, хирургия, АСИТ — после первого визита пациент «уходит думать», и вернуть его может только приложение.", |
||||||
|
size=11, color=FG2) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_current_functions(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Текущие функции — утилита и приоритет", "Что есть сегодня") |
||||||
|
# Три колонки: зелёная, жёлтая, красная |
||||||
|
groups = [ |
||||||
|
("ЯДРО ЦЕННОСТИ", SUCCESS, [ |
||||||
|
("Запись на приём", "Единственная функция, приводящая новых."), |
||||||
|
("Ближайший приём", "3–10 открытий перед визитом. Самый частый экран."), |
||||||
|
]), |
||||||
|
("ПОДДЕРЖКА", WARNING, [ |
||||||
|
("Список врачей", "Помогает при первом визите, повторный не открывает."), |
||||||
|
("Чат с оператором", "Ограничен одним собеседником — основное развитие в §3."), |
||||||
|
("Профиль", "Редко открывается, но критичен для персонализации."), |
||||||
|
]), |
||||||
|
("НИША", DANGER, [ |
||||||
|
("Семейный профиль", "Критичен для 20–30% (дети, пожилые)."), |
||||||
|
("Контакты", "1–2 открытия за всё время. Функция «галочка»."), |
||||||
|
]), |
||||||
|
] |
||||||
|
cw = (CONTENT_W - Inches(0.5)) / 3 |
||||||
|
for i, (label, col, items) in enumerate(groups): |
||||||
|
cx = MARGIN_L + (cw + Inches(0.25)) * i |
||||||
|
add_rect(s, cx, y, cw, Inches(0.5), fill=col) |
||||||
|
add_text(s, cx + Inches(0.3), y + Inches(0.1), cw - Inches(0.6), Inches(0.3), |
||||||
|
label, size=12, bold=True, color=BG) |
||||||
|
yy = y + Inches(0.7) |
||||||
|
for title, desc in items: |
||||||
|
add_text(s, cx, yy, cw, Inches(0.35), title, |
||||||
|
size=15, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, cx, yy + Inches(0.38), cw, Inches(0.9), desc, |
||||||
|
size=11, color=FG2) |
||||||
|
yy += Inches(1.15) |
||||||
|
# Подвал — вывод |
||||||
|
add_rect(s, MARGIN_L, Inches(6.55), CONTENT_W, Inches(0.55), |
||||||
|
fill=WARM) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), Inches(6.66), CONTENT_W - Inches(0.6), Inches(0.4), |
||||||
|
"Слабое место: нет причины открывать приложение между визитами. Это и закрывает джентльменский набор.", |
||||||
|
size=13, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_three_layers(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Три слоя работы", "План") |
||||||
|
box_h = Inches(1.75) |
||||||
|
gap = Inches(0.15) |
||||||
|
# Слой 1 |
||||||
|
y1 = y + Inches(0.1) |
||||||
|
add_rect(s, MARGIN_L, y1, CONTENT_W, box_h, |
||||||
|
fill=PRIMARY_50, line=PRIMARY, line_w=Pt(1)) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y1 + Inches(0.2), Inches(3), Inches(0.3), |
||||||
|
"ФАЗА 1 · ТРАНЗАКЦИОННАЯ БАЗА", size=11, bold=True, color=PRIMARY_DARK) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y1 + Inches(0.5), Inches(11), Inches(0.5), |
||||||
|
"Всем пациентам · быстрый MVP · минимум рисков", |
||||||
|
size=18, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y1 + Inches(1.0), CONTENT_W - Inches(0.6), Inches(0.7), |
||||||
|
"План лечения · Результаты и медкарта · Заказ справок · " |
||||||
|
"(+ уже есть: запись, ближайший приём, чат с оператором, статьи)", |
||||||
|
size=13, color=FG2) |
||||||
|
# Слой 1.5 |
||||||
|
y15 = y1 + box_h + gap |
||||||
|
add_rect(s, MARGIN_L, y15, CONTENT_W, box_h, |
||||||
|
fill=WARM, line=WARNING, line_w=Pt(1)) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y15 + Inches(0.2), Inches(4), Inches(0.3), |
||||||
|
"ФАЗА 1.5 · КОММУНИКАЦИОННАЯ НАДСТРОЙКА", size=11, bold=True, color=WARNING) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y15 + Inches(0.5), Inches(11), Inches(0.5), |
||||||
|
"Поверх стабильной базы · отдельный регламент и безопасность", |
||||||
|
size=18, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y15 + Inches(1.0), CONTENT_W - Inches(0.6), Inches(0.7), |
||||||
|
"Чат с медицинским консьержем (не прямой с лечащим) · AI-помощник на RAG в shadow-mode", |
||||||
|
size=13, color=FG2) |
||||||
|
# Слой 2 |
||||||
|
y2 = y15 + box_h + gap |
||||||
|
add_rect(s, MARGIN_L, y2, CONTENT_W, box_h, |
||||||
|
fill=SOFT, line=FG3, line_w=Pt(0.5)) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y2 + Inches(0.2), Inches(3), Inches(0.3), |
||||||
|
"ФАЗА 2 · СЕГМЕНТНЫЕ МОДУЛИ", size=11, bold=True, color=FG3) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y2 + Inches(0.5), Inches(11), Inches(0.5), |
||||||
|
"Углубление по группам сегментов", |
||||||
|
size=18, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
# 4 мини-плитки |
||||||
|
tiles = [("A", "Самопомощь"), ("C", "Пред-оп"), ("B", "Сурдология"), ("D", "АСИТ + астма")] |
||||||
|
tw = (CONTENT_W - Inches(0.6) - Inches(0.15) * 3) / 4 |
||||||
|
for i, (code, name) in enumerate(tiles): |
||||||
|
tx = MARGIN_L + Inches(0.3) + (tw + Inches(0.15)) * i |
||||||
|
ty = y2 + Inches(1.05) |
||||||
|
add_rect(s, tx, ty, tw, Inches(0.55), fill=BG, line=PRIMARY, line_w=Pt(0.75)) |
||||||
|
add_text(s, tx + Inches(0.15), ty + Inches(0.08), Inches(0.4), Inches(0.4), |
||||||
|
code, size=18, bold=True, color=PRIMARY, font=FONT_DISPLAY) |
||||||
|
add_text(s, tx + Inches(0.55), ty + Inches(0.13), tw - Inches(0.6), Inches(0.4), |
||||||
|
name, size=11, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_phase1_base(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Фаза 1 · Транзакционная база", "Джентльменский набор, часть 1") |
||||||
|
add_text(s, MARGIN_L, y + Inches(0.0), CONTENT_W, Inches(0.4), |
||||||
|
"Детерминированные функции без LLM и прямого врачебного диалога. Быстрый MVP, минимум рисков.", |
||||||
|
size=13, color=FG2) |
||||||
|
data = [ |
||||||
|
["Функция", "Статус", "Суть"], |
||||||
|
["Запись на приём", "Есть", "Запись 24/7, ближайшие окна."], |
||||||
|
["Ближайший приём", "Есть", "Что, где, когда — снимает тревогу перед визитом."], |
||||||
|
["Чат с оператором", "Есть", "Справки, переносы, счета, расписание (человеческий канал)."], |
||||||
|
["Статьи / база знаний", "Есть", "Источник правды для будущего RAG."], |
||||||
|
["План лечения с приёма", "Нет — фундамент", "Структурированные назначения, календарь, напоминания, ссылки на процедуры."], |
||||||
|
["Результаты и медкарта", "Нет — новое", "Анализы, аудиограммы, снимки, заключения. Срок годности виден — критично для пред-опа."], |
||||||
|
["Заказ справок и финдокументов", "Нет — новое", "ФНС-вычет 13%, справки работодателю, счета. Снимает нагрузку с администраторов."], |
||||||
|
] |
||||||
|
add_table(s, MARGIN_L, y + Inches(0.55), |
||||||
|
CONTENT_W, Inches(4.6), |
||||||
|
data, |
||||||
|
col_widths=[Inches(3.3), Inches(2.3), CONTENT_W - Inches(5.6)], |
||||||
|
size=12, header_size=12) |
||||||
|
# Порядок работ |
||||||
|
add_rect(s, MARGIN_L, Inches(6.25), CONTENT_W, Inches(0.85), |
||||||
|
fill=PRIMARY_50, line=PRIMARY, line_w=Pt(0.5)) |
||||||
|
add_rich(s, MARGIN_L + Inches(0.3), Inches(6.35), CONTENT_W - Inches(0.6), Inches(0.7), [ |
||||||
|
("Порядок внутри Фазы 1: ", {"bold": True, "color": PRIMARY_DARK}), |
||||||
|
("1) План лечения — фундамент · ", {}), |
||||||
|
("2) Результаты / медкарта · ", {}), |
||||||
|
("3) Заказ справок. ", {}), |
||||||
|
("Критическая зависимость — МИС: ", {"bold": True, "color": FG}), |
||||||
|
("отдаёт ли API структурированные назначения или план заполняет врач в виджете (см. вопрос №1).", {}), |
||||||
|
], size=12, line_spacing=1.3) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_phase1_5_overlay(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Фаза 1.5 · Коммуникационная надстройка", "Джентльменский набор, часть 2") |
||||||
|
add_text(s, MARGIN_L, y + Inches(0.0), CONTENT_W, Inches(0.6), |
||||||
|
"Живой диалог по поводу лечения. Строится поверх стабильной Фазы 1, требует отдельных регламентов.", |
||||||
|
size=13, color=FG2) |
||||||
|
# Две большие карточки |
||||||
|
cw = (CONTENT_W - Inches(0.3)) / 2 |
||||||
|
cy = y + Inches(0.7) |
||||||
|
ch = Inches(4.5) |
||||||
|
# Консьерж |
||||||
|
lx = MARGIN_L |
||||||
|
add_rect(s, lx, cy, cw, ch, fill=BG, line=PRIMARY, line_w=Pt(1)) |
||||||
|
add_rect(s, lx, cy, cw, Inches(0.55), fill=PRIMARY) |
||||||
|
add_text(s, lx + Inches(0.3), cy + Inches(0.12), cw - Inches(0.6), Inches(0.4), |
||||||
|
"ЧАТ С МЕДИЦИНСКИМ КОНСЬЕРЖЕМ", size=12, bold=True, color=BG) |
||||||
|
add_text(s, lx + Inches(0.3), cy + Inches(0.75), cw - Inches(0.6), Inches(0.5), |
||||||
|
"Не прямой с лечащим врачом", |
||||||
|
size=18, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, lx + Inches(0.3), cy + Inches(1.3), cw - Inches(0.6), Inches(2.4), |
||||||
|
"Дежурный врач / фельдшер / медсестра отвечает по протоколам " |
||||||
|
"на 80% рутины: «можно ли совмещать с X», «нормально ли, что третий день болит», " |
||||||
|
"«когда повторно сдать анализ».\n\n" |
||||||
|
"Эскалация лечащему — только клинически значимое.\n\n" |
||||||
|
"Буфер SLA и защита от выгорания врачей.", |
||||||
|
size=12, color=FG2) |
||||||
|
add_rect(s, lx + Inches(0.3), cy + ch - Inches(0.85), cw - Inches(0.6), Inches(0.7), |
||||||
|
fill=WARM) |
||||||
|
add_rich(s, lx + Inches(0.45), cy + ch - Inches(0.75), cw - Inches(0.9), Inches(0.55), [ |
||||||
|
("Риск: ", {"bold": True, "color": DANGER}), |
||||||
|
("перегрузка врачей. ", {}), |
||||||
|
("Митигация: ", {"bold": True, "color": SUCCESS}), |
||||||
|
("консьерж-слой + тарификация эскалаций.", {}), |
||||||
|
], size=11, line_spacing=1.3) |
||||||
|
# AI |
||||||
|
rx = lx + cw + Inches(0.3) |
||||||
|
add_rect(s, rx, cy, cw, ch, fill=BG, line=WARNING, line_w=Pt(1)) |
||||||
|
add_rect(s, rx, cy, cw, Inches(0.55), fill=WARNING) |
||||||
|
add_text(s, rx + Inches(0.3), cy + Inches(0.12), cw - Inches(0.6), Inches(0.4), |
||||||
|
"AI-ПОМОЩНИК (RAG, 24/7)", size=12, bold=True, color=BG) |
||||||
|
add_text(s, rx + Inches(0.3), cy + Inches(0.75), cw - Inches(0.6), Inches(0.5), |
||||||
|
"Запуск в shadow-mode", |
||||||
|
size=18, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, rx + Inches(0.3), cy + Inches(1.3), cw - Inches(0.6), Inches(2.4), |
||||||
|
"Знает: базу знаний клиники, статьи, план лечения пациента, медкарту, историю приёмов.\n\n" |
||||||
|
"Объясняет назначения, ищет ответ в статьях, оценивает «норма или срочно», " |
||||||
|
"эскалирует консьержу/врачу.\n\n" |
||||||
|
"Отвечает ночью, когда человеческие каналы недоступны.", |
||||||
|
size=12, color=FG2) |
||||||
|
add_rect(s, rx + Inches(0.3), cy + ch - Inches(0.85), cw - Inches(0.6), Inches(0.7), |
||||||
|
fill=WARM) |
||||||
|
add_rich(s, rx + Inches(0.45), cy + ch - Inches(0.75), cw - Inches(0.9), Inches(0.55), [ |
||||||
|
("Риск: ", {"bold": True, "color": DANGER}), |
||||||
|
("галлюцинация LLM = юр./репутация. ", {}), |
||||||
|
("Митигация: ", {"bold": True, "color": SUCCESS}), |
||||||
|
("shadow-mode, валидация через консьержа, метрики точности перед прямым режимом.", {}), |
||||||
|
], size=11, line_spacing=1.3) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_primary_vs_returning(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Первичный vs повторный в приложении", "Фундаментальное деление") |
||||||
|
data = [ |
||||||
|
["Линза", "Первичный в приложении", "Повторный в приложении"], |
||||||
|
["Главный job", |
||||||
|
"«Куда обратиться и как записаться»", |
||||||
|
"«Что делать сейчас по моему лечению»"], |
||||||
|
["Источник", |
||||||
|
"Сайт, SEO, реклама, сарафан", |
||||||
|
"Уведомление, пациент сам открывает"], |
||||||
|
["Частота открытия", |
||||||
|
"1–3 раза до визита", |
||||||
|
"Ежедневно в активном эпизоде"], |
||||||
|
["Что нужно в приложении", |
||||||
|
"Базовый минимум (есть)", |
||||||
|
"Специализированный модуль сегмента"], |
||||||
|
["Приоритет развития", |
||||||
|
"Низкий — веб работает лучше", |
||||||
|
"Высокий — 2/3 потока"], |
||||||
|
] |
||||||
|
add_table(s, MARGIN_L, y + Inches(0.2), |
||||||
|
CONTENT_W, Inches(4.4), |
||||||
|
data, |
||||||
|
col_widths=[Inches(3.0), Inches(4.55), Inches(4.55)], |
||||||
|
size=13, header_size=12, |
||||||
|
header_fill=FG) |
||||||
|
add_rect(s, MARGIN_L, Inches(6.1), CONTENT_W, Inches(1.0), |
||||||
|
fill=PRIMARY_50, line=PRIMARY, line_w=Pt(0.5)) |
||||||
|
add_rich(s, MARGIN_L + Inches(0.3), Inches(6.2), CONTENT_W - Inches(0.6), Inches(0.85), [ |
||||||
|
("Исключения: ", {"bold": True, "color": PRIMARY_DARK}), |
||||||
|
("сегменты, где «первичный в приложении» ≠ «первый визит» — сурдология, хирургия, АСИТ. " |
||||||
|
"После первого визита пациент уходит, и вернуть его может только приложение. " |
||||||
|
"Эти сегменты требуют отдельных «первичных» сценариев удержания.", {}), |
||||||
|
], size=13, line_spacing=1.3) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_segment_matrix(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "10 сегментов × первичный / повторный", "Матрица") |
||||||
|
header = ["#", "Сегмент", "Объём · вклад", "Повторный — что нужно", "Группа"] |
||||||
|
rows = [ |
||||||
|
["1", "Заблокированный нос (FESS, полипы)", "300 оп · 30 млн", |
||||||
|
"Пред-оп бегунок → восстановление → контроль 3/6/12 мес", "C"], |
||||||
|
["2", "Амбулаторный поток (острые + хроники)", "тысячи/мес · 120 млн", |
||||||
|
"План лечения + эпизод + процедуры самопомощи", "A"], |
||||||
|
["3", "Дети с аденоидами", "400–500 оп · 20–30 млн", |
||||||
|
"Детский бегунок → восстановление (семейный профиль)", "C"], |
||||||
|
["4", "Потеря слуха (сурдология)", "20 млн", |
||||||
|
"Паспорт аппарата, сервисный календарь, расходники, калибровка", "B"], |
||||||
|
["5", "Сложные хроники, ЧБД, аллергия", "часть 120 млн · LTV", |
||||||
|
"Процедуры самопомощи + АСИТ-трекер + пыльцевой календарь", "A+D"], |
||||||
|
["6", "Зависимость от капель (вазотомия)", "высокий объём", |
||||||
|
"Пред-оп бегунок (компактный) → восстановление", "C"], |
||||||
|
["7", "Пульмонология (кашель/астма)", "средний · сезонный", |
||||||
|
"Дневник астмы, напоминания об ингаляторах", "D"], |
||||||
|
["8", "Социально активные храпуны", "низкий · высокий чек", |
||||||
|
"Сомнологический чек-up, СИПАП-трекер", "—"], |
||||||
|
["9", "Фониатрия (голос)", "очень низкий", |
||||||
|
"Короткое окно, низкая повторность", "—"], |
||||||
|
["10", "Check-up и второе мнение", "единичный", |
||||||
|
"Разовая услуга, минимальная повторность", "—"], |
||||||
|
] |
||||||
|
data = [header] + rows |
||||||
|
# раскраска групп через цвет текста в последней колонке делается потом |
||||||
|
tbl = add_table(s, MARGIN_L, y + Inches(0.1), |
||||||
|
CONTENT_W, Inches(5.6), |
||||||
|
data, |
||||||
|
col_widths=[Inches(0.4), Inches(3.4), Inches(2.2), Inches(5.5), Inches(0.8)], |
||||||
|
size=10, header_size=11) |
||||||
|
# Подкрасить колонку «Группа» |
||||||
|
group_colors = {"A": PRIMARY_DARK, "B": PRIMARY_DARK, "C": PRIMARY_DARK, |
||||||
|
"D": PRIMARY_DARK, "A+D": PRIMARY_DARK, "—": FG3} |
||||||
|
for ri, row in enumerate(rows, start=1): |
||||||
|
cell = tbl.cell(ri, 4) |
||||||
|
tf = cell.text_frame |
||||||
|
for p in tf.paragraphs: |
||||||
|
for r in p.runs: |
||||||
|
r.font.bold = True |
||||||
|
r.font.color.rgb = group_colors.get(row[4], FG) |
||||||
|
r.font.size = Pt(12) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_groups_overview(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Четыре группы сегментов для повторных", "Укрупнение") |
||||||
|
# 4 плитки 2×2 |
||||||
|
tiles = [ |
||||||
|
("A", "Процедуры самопомощи", |
||||||
|
"Амбулаторный + хроники (2, 5ч)", |
||||||
|
"Библиотека техник, напоминания, трекер, дневник.\nСамый массовый охват."), |
||||||
|
("C", "Пред-оп подготовка", |
||||||
|
"FESS + аденоиды + вазотомия (1, 3, 6)", |
||||||
|
"Две фазы: возврат сомневающихся; бегунок → восстановление.\nОдин модуль — три сегмента."), |
||||||
|
("B", "Сурдология", |
||||||
|
"Потеря слуха (4)", |
||||||
|
"Две фазы: возврат после демо-аппарата; обслуживание аппарата.\nИзолированный модуль, высокий чек."), |
||||||
|
("D", "АСИТ + астма", |
||||||
|
"Часть аллергии + пульмо (5ч, 7)", |
||||||
|
"Ежедневный трекер, пыльцевой календарь, навигатор побочки.\nВысокая ответственность."), |
||||||
|
] |
||||||
|
tw = (CONTENT_W - Inches(0.3)) / 2 |
||||||
|
th = (Inches(5.0) - Inches(0.3)) / 2 |
||||||
|
for i, (code, name, segments, desc) in enumerate(tiles): |
||||||
|
col = i % 2 |
||||||
|
row = i // 2 |
||||||
|
tx = MARGIN_L + (tw + Inches(0.3)) * col |
||||||
|
ty = y + Inches(0.1) + (th + Inches(0.3)) * row |
||||||
|
add_rect(s, tx, ty, tw, th, fill=BG, line=PRIMARY, line_w=Pt(1)) |
||||||
|
# Круг с буквой |
||||||
|
circ = s.shapes.add_shape(MSO_SHAPE.OVAL, tx + Inches(0.3), ty + Inches(0.3), |
||||||
|
Inches(0.8), Inches(0.8)) |
||||||
|
circ.shadow.inherit = False |
||||||
|
circ.fill.solid(); circ.fill.fore_color.rgb = PRIMARY |
||||||
|
circ.line.fill.background() |
||||||
|
tf = circ.text_frame |
||||||
|
tf.margin_left = tf.margin_right = Emu(0); tf.margin_top = tf.margin_bottom = Emu(0) |
||||||
|
p = tf.paragraphs[0]; p.alignment = PP_ALIGN.CENTER |
||||||
|
r = p.add_run(); r.text = code |
||||||
|
r.font.name = FONT_DISPLAY; r.font.size = Pt(28); r.font.bold = True |
||||||
|
r.font.color.rgb = BG |
||||||
|
# Название |
||||||
|
add_text(s, tx + Inches(1.3), ty + Inches(0.3), tw - Inches(1.5), Inches(0.5), |
||||||
|
name, size=20, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, tx + Inches(1.3), ty + Inches(0.8), tw - Inches(1.5), Inches(0.3), |
||||||
|
segments, size=11, color=FG3) |
||||||
|
# Описание |
||||||
|
add_text(s, tx + Inches(0.3), ty + Inches(1.5), tw - Inches(0.6), |
||||||
|
th - Inches(1.7), desc, size=12, color=FG2) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_group_detail(code, color, title, caption, what_it_does, why_priority): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, title, f"Группа {code}") |
||||||
|
# Крупный код слева |
||||||
|
add_rect(s, MARGIN_L, y, Inches(1.4), Inches(5.0), fill=PRIMARY_50) |
||||||
|
add_text(s, MARGIN_L, y + Inches(1.5), Inches(1.4), Inches(2.0), |
||||||
|
code, size=120, bold=True, color=PRIMARY, font=FONT_DISPLAY, |
||||||
|
align=PP_ALIGN.CENTER) |
||||||
|
# Правый контент |
||||||
|
rx = MARGIN_L + Inches(1.6) |
||||||
|
rw = CONTENT_W - Inches(1.6) |
||||||
|
add_text(s, rx, y + Inches(0.0), rw, Inches(0.4), |
||||||
|
caption, size=13, color=FG3) |
||||||
|
# Что делает |
||||||
|
add_text(s, rx, y + Inches(0.45), rw, Inches(0.35), |
||||||
|
"ЧТО В МОДУЛЕ", size=11, bold=True, color=PRIMARY_DARK) |
||||||
|
add_text(s, rx, y + Inches(0.8), rw, Inches(2.8), |
||||||
|
what_it_does, size=13, color=FG) |
||||||
|
# Почему приоритет |
||||||
|
add_rect(s, rx, y + Inches(3.7), rw, Inches(1.3), |
||||||
|
fill=WARM) |
||||||
|
add_text(s, rx + Inches(0.3), y + Inches(3.8), Inches(5), Inches(0.3), |
||||||
|
"ПОЧЕМУ В ЭТОМ ПОРЯДКЕ", size=11, bold=True, color=FG2) |
||||||
|
add_text(s, rx + Inches(0.3), y + Inches(4.1), rw - Inches(0.6), Inches(1.1), |
||||||
|
why_priority, size=13, color=FG) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_group_A(): |
||||||
|
return slide_group_detail( |
||||||
|
"A", PRIMARY, |
||||||
|
"Процедуры самопомощи для хроников", |
||||||
|
"Амбулаторный поток + сложные хроники · сегменты 2 и 5", |
||||||
|
"• Библиотека техник (видео + шаги): промывание носа физраствором, полоскание горла, " |
||||||
|
"ингаляции, гимнастика слуховой трубы, голосовые упражнения, туалет уха.\n" |
||||||
|
"• Напоминания утром/вечером, привязка к плану лечения.\n" |
||||||
|
"• Трекер комплаенса: ежедневные отметки, стрики, сводка.\n" |
||||||
|
"• Дневник симптомов в связке: «промываю 5 дней, насморк 4 → 2».\n" |
||||||
|
"• Сводка для врача перед контрольным приёмом.", |
||||||
|
"Самый массовый охват (тысячи/мес) × ежедневная повторность. " |
||||||
|
"Напрямую опирается на план лечения из Фазы 1. " |
||||||
|
"Контент-ориентированный MVP (видео + простой трекер). " |
||||||
|
"Эффект заметен пациенту сразу." |
||||||
|
) |
||||||
|
|
||||||
|
def slide_group_C(): |
||||||
|
return slide_group_detail( |
||||||
|
"C", PRIMARY, |
||||||
|
"Пред-операционная подготовка + восстановление", |
||||||
|
"FESS + дети-аденоиды + вазотомия · сегменты 1, 3, 6", |
||||||
|
"Две фазы:\n" |
||||||
|
"1) Кандидаты на операцию — ушли «думать» после пред-оп приёма. Возврат через материалы, " |
||||||
|
"кейсы пациентов, чат с хирургом, возвратные push (3/7/21 день), прозрачность цены/рассрочки.\n" |
||||||
|
"2) Решившиеся — маршрутная карта («бегунок») с чекбоксами, сроки годности анализов, " |
||||||
|
"автозапись из пункта, загрузка сторонних результатов, чек-лист дня операции, " |
||||||
|
"договор и оплата в приложении → передача в «Восстановление».", |
||||||
|
"Один модуль закрывает 3 сегмента. Быстрый MVP (маршрутная карта — простой список с состояниями). " |
||||||
|
"Прямой бизнес-эффект: меньше переносов операций + возврат сомневающихся кандидатов. " |
||||||
|
"Вклад сегментов: ~50–60 млн." |
||||||
|
) |
||||||
|
|
||||||
|
def slide_group_B(): |
||||||
|
return slide_group_detail( |
||||||
|
"B", PRIMARY, |
||||||
|
"Сурдология — слухопротезирование", |
||||||
|
"Потеря слуха · сегмент 4", |
||||||
|
"Две фазы, зеркально Группе C:\n" |
||||||
|
"1) Кандидаты — после первого визита и демо уходят думать 2–3 месяца. " |
||||||
|
"Аудиограмма в профиле, аудио-демо «до/после» в любых наушниках, каталог моделей с фильтром " |
||||||
|
"по аудиограмме, калькулятор стоимости (ФСС, рассрочка, трейд-ин), шеринг близкому, " |
||||||
|
"истории пациентов, возвратные push 3/7/21 день.\n" |
||||||
|
"2) Пользователи аппарата — паспорт аппарата, календарь обслуживания, расходники, " |
||||||
|
"навигатор неполадок, ежегодная калибровка.", |
||||||
|
"Пожизненный LTV × высокий чек (60–180 тыс.) × растущий рынок (старение). " |
||||||
|
"Изолированный модуль — не пересекается с другими. " |
||||||
|
"Можно запускать параллельно с C после Фазы 1." |
||||||
|
) |
||||||
|
|
||||||
|
def slide_group_D(): |
||||||
|
return slide_group_detail( |
||||||
|
"D", PRIMARY, |
||||||
|
"АСИТ + контроль астмы", |
||||||
|
"Часть аллергии + пульмонология · сегменты 5ч и 7", |
||||||
|
"• Календарь курса (3–5 лет) с маркером «вы здесь».\n" |
||||||
|
"• Ежедневный приём СЛИТ с push, стрики.\n" |
||||||
|
"• Журнал инъекций ПКИТ.\n" |
||||||
|
"• Дневник симптомов + пыльцевой календарь региона.\n" |
||||||
|
"• Навигатор побочки с эскалацией к врачу / скорой.\n" |
||||||
|
"• Экстренная связь, аптечка дома.\n" |
||||||
|
"• Автошеринг дневника врачу перед плановым визитом.", |
||||||
|
"Самая высокая глубина пользы — прямое влияние на медицинский исход (удержание = успех лечения). " |
||||||
|
"Но самая высокая ответственность: требует верификации контента аллергологом/пульмонологом. " |
||||||
|
"Запускаем последним; контент можно готовить параллельно." |
||||||
|
) |
||||||
|
|
||||||
|
def slide_roadmap(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Порядок внедрения", "Дорожная карта") |
||||||
|
# Фаза 1 бокс |
||||||
|
p1_h = Inches(0.9) |
||||||
|
add_rect(s, MARGIN_L, y + Inches(0.05), CONTENT_W, p1_h, |
||||||
|
fill=PRIMARY_50, line=PRIMARY, line_w=Pt(1)) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y + Inches(0.15), Inches(3), Inches(0.3), |
||||||
|
"ФАЗА 1 · ТРАНЗАКЦИОННАЯ БАЗА", size=11, bold=True, color=PRIMARY_DARK) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y + Inches(0.48), CONTENT_W - Inches(0.6), Inches(0.4), |
||||||
|
"План лечения → Результаты и медкарта → Заказ справок", |
||||||
|
size=14, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
# Фаза 1.5 бокс |
||||||
|
y15 = y + Inches(0.05) + p1_h + Inches(0.15) |
||||||
|
add_rect(s, MARGIN_L, y15, CONTENT_W, p1_h, |
||||||
|
fill=WARM, line=WARNING, line_w=Pt(1)) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y15 + Inches(0.1), Inches(4), Inches(0.3), |
||||||
|
"ФАЗА 1.5 · КОММУНИКАЦИОННАЯ НАДСТРОЙКА", size=11, bold=True, color=WARNING) |
||||||
|
add_text(s, MARGIN_L + Inches(0.3), y15 + Inches(0.43), CONTENT_W - Inches(0.6), Inches(0.4), |
||||||
|
"Чат с медицинским консьержем → AI-помощник (shadow-mode)", |
||||||
|
size=14, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
# Фаза 2 — 4 шага |
||||||
|
y2 = y15 + p1_h + Inches(0.25) |
||||||
|
add_text(s, MARGIN_L, y2, Inches(6), Inches(0.3), |
||||||
|
"ФАЗА 2 · СЕГМЕНТНЫЕ МОДУЛИ", size=11, bold=True, color=FG2) |
||||||
|
# 4 карточки горизонтально со стрелками |
||||||
|
steps = [ |
||||||
|
("1", "A", "Процедуры самопомощи", "Массовый охват · продолжение плана лечения"), |
||||||
|
("2", "C", "Пред-оп подготовка", "3 сегмента одним модулем · быстрый эффект"), |
||||||
|
("3", "B", "Сурдология", "Высокий чек · пожизненное удержание"), |
||||||
|
("4", "D", "АСИТ + астма", "Верификация врачом · высокая польза"), |
||||||
|
] |
||||||
|
step_y = y2 + Inches(0.35) |
||||||
|
step_h = Inches(2.0) |
||||||
|
step_w = (CONTENT_W - Inches(0.4) * 3) / 4 |
||||||
|
for i, (num, code, name, sub) in enumerate(steps): |
||||||
|
sx = MARGIN_L + (step_w + Inches(0.4)) * i |
||||||
|
add_rect(s, sx, step_y, step_w, step_h, fill=BG, line=PRIMARY, line_w=Pt(1)) |
||||||
|
# Номер и код группы |
||||||
|
add_text(s, sx + Inches(0.2), step_y + Inches(0.2), Inches(0.8), Inches(0.4), |
||||||
|
f"Шаг {num}", size=11, color=FG3) |
||||||
|
add_text(s, sx + Inches(0.2), step_y + Inches(0.45), step_w - Inches(0.4), Inches(0.6), |
||||||
|
code, size=36, bold=True, color=PRIMARY, font=FONT_DISPLAY) |
||||||
|
add_text(s, sx + Inches(0.2), step_y + Inches(1.0), step_w - Inches(0.4), Inches(0.4), |
||||||
|
name, size=13, bold=True, color=FG, font=FONT_DISPLAY) |
||||||
|
add_text(s, sx + Inches(0.2), step_y + Inches(1.4), step_w - Inches(0.4), Inches(0.55), |
||||||
|
sub, size=10, color=FG2) |
||||||
|
# Стрелка |
||||||
|
if i < 3: |
||||||
|
arr_x = sx + step_w + Inches(0.05) |
||||||
|
arr = s.shapes.add_shape(MSO_SHAPE.RIGHT_ARROW, arr_x, |
||||||
|
step_y + step_h / 2 - Inches(0.15), |
||||||
|
Inches(0.3), Inches(0.3)) |
||||||
|
arr.shadow.inherit = False |
||||||
|
arr.fill.solid(); arr.fill.fore_color.rgb = PRIMARY |
||||||
|
arr.line.fill.background() |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_questions(): |
||||||
|
s = new_slide() |
||||||
|
y = title_bar(s, "Вопросы к обсуждению", "Что уточнить у клиники") |
||||||
|
questions = [ |
||||||
|
("Поток", "«2 из 3 повторных» — уникальные пациенты в год или визиты?"), |
||||||
|
("Метрики", "Процент повторных, не доходящих до контрольного приёма?"), |
||||||
|
("Врачи", "Готовность врачей к SLA по асинхронному чату и в каком окне?"), |
||||||
|
("МИС", "API: структурированные назначения, сроки годности анализов, расписание?"), |
||||||
|
("Сурдо", "Сколько кандидатов/мес, % возврата за аппаратом?"), |
||||||
|
("Хирургия", "Частая причина переноса операций — просроченные анализы?"), |
||||||
|
("Аллерго", "Готов ли аллерголог верифицировать контент АСИТ-трекера?"), |
||||||
|
("Контент", "Достаточно ли материалов для RAG-базы?"), |
||||||
|
] |
||||||
|
col_h = Inches(0.6) |
||||||
|
for i, (tag, q) in enumerate(questions): |
||||||
|
col = i % 2 |
||||||
|
row = i // 2 |
||||||
|
qx = MARGIN_L + (CONTENT_W / 2 + Inches(0.15)) * col |
||||||
|
qy = y + Inches(0.2) + (col_h + Inches(0.4)) * row |
||||||
|
qw = CONTENT_W / 2 - Inches(0.15) |
||||||
|
add_rect(s, qx, qy, Inches(1.0), col_h, fill=PRIMARY) |
||||||
|
add_text(s, qx, qy, Inches(1.0), col_h, tag, |
||||||
|
size=12, bold=True, color=BG, font=FONT_DISPLAY, |
||||||
|
align=PP_ALIGN.CENTER, anchor=MSO_ANCHOR.MIDDLE) |
||||||
|
add_rect(s, qx + Inches(1.0), qy, qw - Inches(1.0), col_h, |
||||||
|
fill=PRIMARY_50) |
||||||
|
add_text(s, qx + Inches(1.2), qy, qw - Inches(1.2), col_h, q, |
||||||
|
size=12, color=FG, anchor=MSO_ANCHOR.MIDDLE) |
||||||
|
return s |
||||||
|
|
||||||
|
def slide_final(): |
||||||
|
s = new_slide() |
||||||
|
# Большой финал: что решить сегодня |
||||||
|
add_rect(s, 0, 0, SW, SH, fill=PRIMARY) |
||||||
|
add_text(s, MARGIN_L, Inches(0.8), CONTENT_W, Inches(0.5), |
||||||
|
"ЧТО РЕШАЕМ СЕГОДНЯ", size=14, bold=True, color=PRIMARY_50) |
||||||
|
add_text(s, MARGIN_L, Inches(1.4), CONTENT_W, Inches(1.2), |
||||||
|
"Подтвердить порядок:", size=36, bold=True, color=BG, font=FONT_DISPLAY) |
||||||
|
add_text(s, MARGIN_L, Inches(2.4), CONTENT_W, Inches(1.8), |
||||||
|
"Фаза 1 · транзакционная база\n→ Фаза 1.5 · консьерж + AI\n→ Фаза 2: A → C → B → D", |
||||||
|
size=26, bold=True, color=BG, font=FONT_DISPLAY, line_spacing=1.3) |
||||||
|
# Три пункта |
||||||
|
items = [ |
||||||
|
("1", "С чего начинаем Фазу 1?", "План лечения — фундамент. Зависит от МИС-API."), |
||||||
|
("2", "Когда стартует Фаза 1.5?", "После стабилизации базы. AI в shadow-mode."), |
||||||
|
("3", "Параллельно", "Контент для D, добавить аллерголога в справочники."), |
||||||
|
] |
||||||
|
y = Inches(4.8) |
||||||
|
for i, (num, q, a) in enumerate(items): |
||||||
|
ix = MARGIN_L + (CONTENT_W / 3) * i |
||||||
|
iw = CONTENT_W / 3 - Inches(0.3) |
||||||
|
add_text(s, ix, y, Inches(0.5), Inches(0.5), |
||||||
|
num, size=36, bold=True, color=WARM, font=FONT_DISPLAY) |
||||||
|
add_text(s, ix + Inches(0.6), y + Inches(0.05), iw - Inches(0.6), Inches(0.5), |
||||||
|
q, size=14, bold=True, color=BG, font=FONT_DISPLAY) |
||||||
|
add_text(s, ix + Inches(0.6), y + Inches(0.6), iw - Inches(0.6), Inches(1.2), |
||||||
|
a, size=12, color=PRIMARY_50) |
||||||
|
# Подпись |
||||||
|
add_text(s, MARGIN_L, SH - Inches(0.7), CONTENT_W, Inches(0.4), |
||||||
|
"Клиника УГН · мобильное приложение · 23 апр 2026", |
||||||
|
size=11, color=PRIMARY_50) |
||||||
|
return s |
||||||
|
|
||||||
|
# ============================================================ |
||||||
|
# СБОРКА |
||||||
|
# ============================================================ |
||||||
|
slides = [ |
||||||
|
slide_title(), |
||||||
|
slide_agenda(), |
||||||
|
slide_facts(), |
||||||
|
slide_frame(), |
||||||
|
slide_current_functions(), |
||||||
|
slide_three_layers(), |
||||||
|
slide_phase1_base(), |
||||||
|
slide_phase1_5_overlay(), |
||||||
|
slide_primary_vs_returning(), |
||||||
|
slide_segment_matrix(), |
||||||
|
slide_groups_overview(), |
||||||
|
slide_group_A(), |
||||||
|
slide_group_C(), |
||||||
|
slide_group_B(), |
||||||
|
slide_group_D(), |
||||||
|
slide_roadmap(), |
||||||
|
slide_questions(), |
||||||
|
slide_final(), |
||||||
|
] |
||||||
|
|
||||||
|
# Футер на всех слайдах, кроме титульного и финального (у них свой фон) |
||||||
|
total = len(slides) |
||||||
|
for idx, s in enumerate(slides, start=1): |
||||||
|
if idx == 1 or idx == total: |
||||||
|
continue |
||||||
|
footer(s, idx, total) |
||||||
|
|
||||||
|
out = "MEETING_2026-04-23.pptx" |
||||||
|
prs.save(out) |
||||||
|
print(f"OK {out} ({total} slides)") |
||||||
Loading…
Reference in new issue