Внутренняя CRM AI-агентства · Беларусь
GoodDayAI CRM
Своя CRM для своей же воронки — на той же базе, что сайт и боты
Задача
У агентства уже был публичный сайт с формой записи и Telegram-бот, которые писали клиентов в одну таблицу Supabase. Не хватало рабочего инструмента поверх этих данных: воронки продаж с понятными статусами, аналитики по деньгам и месту зависания сделок, и способа считать общую прибыль и делить её между совладельцами — при этом не выставляя реальные имена и суммы клиентов на публичном сайте или в боте, к которому есть доступ у посторонних.
Какие проблемы решили
Данные клиентов и сделок нельзя показывать на публичном сайте, но воронку вести где-то нужно.
Отдельный Next.js-проект и отдельный Vercel-деплой с собственным доменом: у публичного сайта нет ни одного роута, отдающего клиентов. Вход по паролю за HMAC-подписанной httpOnly-кукой, проверка в middleware на каждом запросе, антибрутфорс, `noindex` и строгий CSP.
Сделки проходят 15 разных стадий — от первого контакта до продления или паузы — и легко перепутать, что после чего идёт.
Канбан-доска с машиной статусов: у каждой стадии свой набор разрешённых переходов, недопустимый прыжок отклоняется на уровне API, а не только в интерфейсе. Карточка двигается drag-and-drop или кнопкой, фильтры — по источнику, сумме, «напомнить сегодня» и давно нетронутым.
Сумма сделки хранилась одной строкой на клиента — нельзя было отдельно завести разовое внедрение и отдельно ежемесячную подписку, и месячный платёж в отчёте засчитывался только один раз.
Разнесли на два поля: разовая плата за внедрение считается доходом один раз при заработанной сделке, ежемесячная подписка — отдельным показателем MRR по клиентам, которые сейчас реально платят (продление и пауза размечены и не смешиваются).
Прибыль двух совладельцев считалась вручную, без единого места, где видно доход, расход и итоговую долю каждого.
Раздел «Расходы»: общая касса по категориям в нескольких валютах, прибыль = доход из выигранных сделок минус расходы, доля каждого совладельца — по настраиваемому проценту, который можно менять прямо в интерфейсе.
У части клиентов есть франшиза-партнёры, и им нельзя видеть чужих клиентов или общую кассу.
Мультиарендность по полю `tenant`: у франшизы свой аккаунт и пароль, видит только своих клиентов, разделы расходов и аналитики владельца ей недоступны — изоляция проверяется в каждом API-роуте, а не только скрытием кнопки.
Пропущенный звонок или забытое напоминание тянется по цепочке заявок незамеченным.
Несколько независимых напоминаний «связаться» на одного клиента, каждое со своей заметкой; изменение статуса и другие действия пишутся в журнал `crm_log` с именем того, кто их совершил.
Что сделали
- Канбан-доска на 15 статусов воронки с проверкой допустимых переходов и drag-and-drop
- Карточка клиента: услуги, разовое внедрение и ежемесячная подписка отдельными полями, реквизиты, заметка, история действий
- Аналитика: win rate, MRR, воронка с конверсией по стадиям, средний чек, «где застряли»
- Расходы и прибыль: общая касса по категориям и валютам, доля каждого совладельца настраивается в интерфейсе
- Франшизы: отдельные аккаунты партнёров с изоляцией клиентов по `tenant` на уровне каждого API-роута
- Реферальная программа: персональные ссылки на подарок другу, вознаграждение начисляется только после его первой оплаты
- AI поверх воронки: черновик сообщения клиенту, ответ на вопрос по всей базе сделок, скоринг лида со следующим шагом
- Несколько независимых напоминаний «связаться» на клиента и общий журнал действий с именем автора
- Отдельный скрытый Vercel-деплой, пароль за HMAC-кукой, антибрутфорс, `noindex` и строгий CSP
Как это выглядит

