Медтех · Мобильное
Anamna
Приложение для пациентов клиники: запись, результаты анализов и напоминания в одном экране. Работа под этим экраном — доказать, что пациент тот самый, и решить, что можно писать в уведомлении.
- Роль
- Продуктовый дизайн, мобильная разработка, бэкенд
- Срок
- 6 месяцев
- Стек
- React Native · Expo · Node.js
Что изменилось
- 1 аккаунт
- вместо трёх. Запись, результаты и напоминания были тремя входами с тремя логинами, и один из них выдавали на бумажке в регистратуре.
- 44%
- записей пациенты делают сами в приложении к концу первого года. Через сайт до запуска — 17%, остальное шло звонком.
- 12 минут
- в худшем случае от подписи результата в лаборатории до уведомления на телефоне. Раньше о готовности пациент узнавал, позвонив сам.
- 800 → 510
- звонков в неделю про статус: «готов ли анализ» и «во сколько я записан». Приложением пользуется каждый третий пациент, но звонили чаще как раз те, кто ходит часто.
Что не изменилось — доля несостоявшихся приёмов: 11,8% до запуска и 11,2% через год. Разница внутри годовых колебаний, и записывать её на приложение мы не будем. Изменилось другое: о том, что пациент не придёт, теперь узнают заранее — за год около 1 400 записей отменили в приложении больше чем за сутки, раньше для этого нужно было дозвониться в рабочие часы. Занять успели примерно половину освободившихся слотов: за сутки перезаписать получается не по каждой специальности.
Что было до
Пациент заводил три аккаунта — на запись, на результаты и на напоминания — и всё равно пропускал приёмы. Запись жила в системе клиники, результаты — на портале лаборатории с логином, выданным на бумажке, а напоминания приходили по СМС — ответить на них было некуда: чтобы отменить приём, надо было дозвониться в рабочие часы.
- Три входа с тремя логинами на одного человека. Для системы клиники он был картой с фамилией и датой рождения, для лаборатории — номером заказа на бланке, для рассылки — телефоном.
- Из 2 600 звонков в неделю около 800 были не про запись, а про статус: «готов ли анализ» и «во сколько я записан».
- Отменить приём можно было только звонком в рабочие часы. О том, что пациент не придёт, клиника узнавала в момент приёма, и слот сгорал.
Что сделали
Одно приложение поверх трёх систем: запись из системы клиники, результаты из внешней лаборатории, напоминания — и привязка пациента к медкарте, без которой ничего из этого показывать нельзя.
Уведомления, которые ничего не выдают: текст собирается на сервере из закрытого списка шаблонов, а исследования, которые объясняет врач, в приложение не уходят вовсе.
Выпуск в App Store и Google Play от лица клиники: приложение с медицинскими данными сторы не публикуют под аккаунтом подрядчика.
Результат
За первый год приложением пользовались 18 000 пациентов — примерно каждый третий из тех, кто был в клинике за этот год. Запись и результаты оказались там же, где приходит напоминание, а что и кому показать, решает сервер по согласиям, а не экран.
Кто заказчик
Частная многопрофильная клиника: четыре филиала в одном городе, сто тридцать врачей, приём взрослых и детей. За год — около девяноста тысяч приёмов примерно на пятьдесят пять тысяч разных пациентов.
Примерно на каждом втором приёме назначают анализы: пробы берут в клинике, исследует внешняя лаборатория — около девятисот заказов в неделю. Картотека — двести десять тысяч карт, из них за последний год открывали пятьдесят пять тысяч. Девять операторов колл-центра принимают около двух тысяч шестисот звонков в неделю.
Задача
- Как ставил заказчик
- «Личный кабинет в телефоне». На сайте он есть, но им почти не пользуются; нужно приложение, где пациент видит запись, результаты и напоминания. Срок — к открытию четвёртого филиала.
- Как задача выглядела после разбора
- Экран оказался следствием, а не задачей. Три системы знали одного человека по-разному: карта с фамилией и датой рождения, номер заказа на бланке, телефон в рассылке — и ничто не доказывало, что это один и тот же человек. Пока это не решено, «показать результаты» значит «показать чьи-то результаты». Поэтому первые два месяца ушли не на экраны, а на два вопроса: кто такой пациент и что именно он разрешил показывать.
Почему нельзя было в лоб
С медицинскими данными не работает порядок «сначала сделаем, потом закроем». Каждое ограничение здесь либо стоит в чужой системе, либо написано в законе — и каждое видно в архитектуре.
- Система клиники
- Расписание и медкарта живут в коробочной системе, которую обслуживает вендор. Наружу она смотрит одним шлюзом и отдаёт ограниченный набор методов: свободный слот можно занять, занятый — освободить, а создать слот, перенести врача или удлинить приём нельзя. Приложение наследует это ограничение: «перенести на другое время» в нём означает освободить один слот и занять другой.
- Лаборатория снаружи
- Пробы берут в клинике, исследует внешняя лаборатория со своей системой. Готовое она отдаёт пачкой раз в десять минут, а не событием на каждый результат. Значит, мгновенно не бывает: между подписью в лаборатории и уведомлением проходит до двенадцати минут, и обещать меньше было бы неправдой.
- Экран блокировки
- Push виден на заблокированном экране, а телефон не всегда в одних руках. Поэтому текст уведомления сам по себе медицинские данные: «результат анализа на гормоны готов» на заблокированном экране рассказывает о человеке больше, чем он соглашался рассказать. То же с напоминанием о приёме — специальность врача в нём такая же лишняя строка.
- Согласие и представитель
- Согласие — не галочка при регистрации, а состояние: его дают, переподтверждают при новой редакции текста и отзывают. За ребёнка его даёт родитель, и в возрасте, с которого пациент распоряжается данными самостоятельно, доступ родителя обязан закрыться сам — не по чьей-то памяти. Отзыв выключает приложение, но медкарту не удаляет: сроки её хранения задаёт не клиника, и в приложении об этом сказано прямо.
- Данные не выходят за контур
- Ни в аналитику, ни в отчёты о падениях, ни в чужой ретранслятор пуш-уведомлений. Ограничение убрало из проекта половину привычных инструментов и определило место бэкенда: он стоит в контуре клиники, рядом с её системой, а не там, где нам удобнее.
Как шла работа
- 01
Разбор
4 неделиДве недели операторы колл-центра помечали каждый звонок темой: 2 600 звонков в неделю, из них около 800 — «готов ли анализ» и «во сколько я записан». Параллельно с юристом клиники и заведующей лабораторией разбирали, что можно показать в приложении, а что пациенту объясняет врач. Итог этапа — не макеты, а список того, чего приложение делать не будет.
- 02
Личность и согласия
5 недельВход по коду, привязка медкарты по совпадению полей, ветка «в регистратуру с документом», версии согласий, журнал доступа. Экранов почти нет: пока нет ответа, кто такой пациент, любой экран показывает чужое.
- 03
Запись
4 неделиРасписание, свободные слоты, отмена и перенос, напоминание за сутки и за два часа. Здесь выяснилось, что отмена нужнее записи: записаться можно и по телефону, а отменить в девять вечера — нельзя.
- 04
Результаты и уведомления
6 недельПриём выгрузки из лаборатории, флаг «отдаёт врач», шаблоны уведомлений, отправка напрямую в APNs и FCM. Дольше всего согласовывали не код, а тексты: каждое уведомление читали заведующая лабораторией и юрист, и восемь формулировок из шестнадцати вернулись на переделку.
- 05
Проверка, сторы и запуск
7 недельТри недели на сотрудниках клиники и их семьях — шестьдесят человек, — потом два филиала, потом остальные два. Первую сборку в App Store отклонили: аккаунт разработчика был наш, а приложение с медицинскими данными сторы просят публиковать от лица медицинской организации. Аккаунт переоформили на клинику, ревьюеру завели демо-пациента с выдуманной картой: показывать на ревью настоящие анализы нельзя.
Технические решения
Стек выбран под условие «две платформы, шесть месяцев, медицинские данные»: React Native и Expo дают одно приложение на обе платформы, Node.js стоит между ним и двумя чужими системами — и намеренно не хранит медкарту.
Телефон пускает в приложение, но не открывает карту
Код из СМС подтверждает владение номером — и только это. Медкарта привязывается отдельной операцией: совпасть должны телефон, фамилия, имя и дата рождения, и в картотеке не должно найтись второго подходящего кандидата. Не сошлось — в регистратуру с документом. За первый год автоматически привязались 94% подключившихся; около 1 100 человек приложение отправило на стойку.
Согласие — состояние, а не галочка
У записи о согласии есть редакция текста, дата, способ получения и срок; отзыв — такая же запись, как выдача, а не удаление прежней. Доступ родителя к карте ребёнка открывается по заявлению в регистратуре и закрывается автоматически в день, когда подросток начинает распоряжаться данными самостоятельно. Рядом — журнал доступа: у вопроса «кто открывал мои результаты» есть ответ, и наши служебные обращения в нём тоже.
Уведомление, которое ничего не рассказывает
Текст собирается на сервере из закрытого списка шаблонов, подстановок три: время, филиал и номер заказа. Названия исследования, диагноза и специальности врача в шаблонах нет — не «договорились не подставлять», а подставить нечего. Push уходит напрямую в APNs и FCM: expo-notifications умеет отправлять и через ретранслятор Expo, это заметно проще, но тогда текст уведомления шёл бы через чужой сервис.
Часть результатов приложение не показывает
Лаборатория помечает исследования, которые пациенту объясняет врач. Такой результат в приложение не уходит вовсе: уведомление говорит, что результат готов и нужен приём, и предлагает записаться. Отсечка стоит на сервере, а не в интерфейсе — приложение этот файл не получает и не может показать его по ошибке, потому что его нет в ответе.
Одно приложение на две платформы — и чем за это заплатили
Два мобильных разработчика и шесть месяцев на iOS и Android: нативно пришлось бы удваивать команду или выпускать платформы по очереди. React Native закрывает это, Expo — сборку и обновление по воздуху: ошибку в часовом поясе напоминаний починили за день, не дожидаясь ревью. Заплатили двумя вещами: пуш-сервис Expo не используем, а хранение файла результата пришлось писать нативным модулем — готовые обёртки клали файл в каталог, который забирает системная резервная копия.
Бэкенд, который не хранит медкарту
Расписание и результаты Node.js берёт из системы клиники и из лаборатории на запрос. У себя лежит только то, без чего приложение не работает: связь пациента с картой, согласия, токены устройств и журнал доступа. Причина простая: копия медкарты — второе место, откуда она может утечь. Кэш всё-таки есть, и он назван: список ближайших приёмов живёт пять минут, иначе экран открывался бы секундами. Файл результата не кэшируется — ссылка на него живёт две минуты и срабатывает один раз.
Что осталось за рамками
Часть не входила в проект сознательно, часть упёрлась не в код.
Оплата. Приём оплачивают на стойке или по счёту; онлайн-оплата и работа со страховыми в приложение не вошли — это отдельный контур и отдельный договор.
Приём онлайн. Просили чат с врачом и видеоконсультацию — отложили: у дистанционного приёма своя идентификация, своя запись в карту и свои требования к хранению, довеском к записи он не делается.
Дубли карт. Разбор нашёл около 3 400 человек с двумя картами, заведёнными в разных филиалах. Приложение их не склеивает: объединять карты — решение врача и регистратуры, а не программы, поэтому пациент видит ту карту, к которой привязан.
Показатели, которые ведёт сам пациент, — давление, сахар, вес. От них отказались на этом этапе: то, что человек заносит сам, кто-то должен смотреть, а пока не решено кто, приложение обещало бы наблюдение, которого нет.
Те, у кого нет смартфона. 18 000 пациентов из 55 000 значит и обратное: 37 000 по-прежнему звонят. Колл-центр никто не сокращал, и половина записей по-прежнему идёт голосом.
Сейчас в работе: вторая лаборатория со своим форматом выгрузки и разбор того, почему из 1 100 человек, которых приложение отправило в регистратуру за привязкой карты, дошли примерно две трети.
Другие проекты
Финтех
Splitta
Рассрочка для интернет-магазинов: проверка покупателя, график платежей и возврат — на реальных платежах с первого дня.
7 недель
от первой встречи до продакшена
Next.js · Node.js · Docker
Производство
Naryado
Мебельное производство: заявка, план цеха и отгрузка идут одним номером. Пять систем, которые уже стояли, обмениваются данными через общий контур, а не через таблицы.
5 систем
работают на одном номере заявки
Python · PostgreSQL · Redis
Контакты
Пришлите описание задачи
Ответ с объёмом работ, сроками и оценкой бюджета придёт в течение 24 часов.
Первый звонок — 30 минут, без обязательств с вашей стороны.