ВетПульс — AI-CRM для ветклиник
Мультиарендный SaaS для ветклиник: AI-диспетчер отвечает клиентам и записывает пациентов, система напоминает о приёмах и возвращает «спящую» базу. Спроектировали и собрали под ключ: и бэкенд, и премиальный сайт с интерактивным демо-кабинетом.
// в демо ответы заскриптованы на трёх примерах; в проде это делает LLM + RAG по услугам и ценам клиники
От сообщения владельца до записи в клинике
Частная ветклиника теряет деньги в трёх точках, и все три висят на одном администраторе: вечерние и выходные обращения уходят в соседнюю клинику; пациент забыл о приёме, и час врача простаивает; сотни питомцев с просроченной вакцинацией, которых некому системно возвращать. Рутина съедает администратора, а на возврат «спящей» базы рук уже не остаётся.
Собрали мультиарендный AI-SaaS (clinic_id везде): AI-диспетчер разбирает обращения и записывает пациентов, а два фоновых движка сами напоминают о приёмах и возвращают «спящую» базу, как на схеме выше. Сверху добавили самостоятельную регистрацию клиники, онбординг-мастер, подключение своей учётной системы (Vetmanager) с шифрованием ключей и кабинет со статистикой «₽ возвращено». Стек: Python, FastAPI, SQLAlchemy, планировщик, LLM за единым интерфейсом провайдера.
Публичная документация не давала однозначно ни сериализацию фильтров, ни ключи полей, ни, самое главное, где брать даты вакцинации: отдельным полем или вычислять из истории приёмов. Реализовали обе стратегии за флагом, изолировали все спорные места в отдельные хелперы с пометкой «проверить на первом реальном ответе», а сам клиент покрыли тестами через симулированные HTTP-ответы, без сети и без ключа.
Жёсткий лимит 20 запросов в минуту заставил спроектировать батчинг и локальный кэш базы под реактивацию. Смысл: строить против спеки, которую нельзя до конца проверить, но так, чтобы докрутка после первого живого ответа была в одну-две строки в одном месте.
Ложно-отрицательный результат: у модалки с position:fixed overflow:hidden клиппит переполнение, а не скроллит: «скролла нет», но текст обрезан. Корень — min-width:auto у flex/grid-элемента, который не сжимается ниже своего содержимого; фикс — min-width:0. Вывод, который переиспользовали дальше: мерить scrollWidth против clientWidth, а не полагаться на скролл документа.
Главный принцип этого кейса не инженерный: проверять, не закрывает ли задачу уже существующий инструмент и есть ли спрос, до того как строить, а не после. Валидация показала, что напоминания и возврат базы во многом делают встроенные функции самих вет-CRM, и этот вывод мы теперь закладываем в работу с самого начала.
- Мультиарендный SaaS end-to-end: самостоятельная регистрация клиники, онбординг, подключение своей учётной системы, AI-диалог с записью, напоминания и реактивация базы, кабинет со статистикой.
- Слой данных с изоляцией по клиникам, покрытый автотестами; боевой клиент Vetmanager за интерфейсом-адаптером с mock-фолбэком.
- Безопасность мультиарендности заложена с нуля: пароли через bcrypt, ключи интеграций шифруются в БД и никогда не отдаются во фронт.
- Отдельно спроектировали и собрали премиальный лендинг и интерактивное продуктовое демо («кабинет клиники»): чистая статика без зависимостей, своя дизайн-система, анимированные интерактивные компоненты, полная адаптивность и доступность.
- Собрали примерно за 2 дня AI-ассистированной разработки (оценка, не хронометраж).
- Внешние сервисы замоканы, а код интеграции написан боевым. Так собран весь сквозной сценарий, от регистрации клиники до напоминаний.