Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
150 lines
18 KiB
Markdown
150 lines
18 KiB
Markdown
# Y&P Lead Radar
|
|
|
|
Сервис находит новые объявления на List.am по фильтрам клиента, доставляет их агентам в Telegram
|
|
и ведёт каждый объект как лид в CRM до сделки. Домен: `listcrm.yandpconsulting.com`.
|
|
|
|
Написан с нуля по ТЗ. Из прежней CRM (`../crmyerevan-…`) взят только модуль парсера —
|
|
см. [docs/PARSER.md](docs/PARSER.md).
|
|
|
|
## Структура
|
|
|
|
| Путь | Назначение |
|
|
| ----------------- | -------------------------------------------------------------------------- |
|
|
| `apps/api` | Бэкенд: Fastify, Postgres (Drizzle). Один API для веб-кабинета и Mini App |
|
|
| `apps/web` | Веб-кабинет и Mini App: React, Tailwind, тема сайта yandpconsulting.com |
|
|
| `packages/shared` | Тарифы и лимиты, роли, воронки по умолчанию, сопоставление с фильтрами |
|
|
|
|
## Запуск на своём компьютере
|
|
|
|
Нужны Node 22+, pnpm 10, Docker.
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
pnpm install
|
|
pnpm db:up # Postgres в Docker, порт 5433
|
|
pnpm db:migrate
|
|
pnpm --filter @lr/api superadmin <email> "Имя" # печатает пароль суперадмина
|
|
pnpm dev:api # http://localhost:3100
|
|
pnpm dev:web # http://localhost:5174
|
|
```
|
|
|
|
Проверки: `pnpm typecheck && pnpm test` (тестам API нужен запущенный Postgres и база
|
|
`leadradar_test`).
|
|
|
|
После изменения `apps/api/src/db/schema.ts`: `pnpm db:generate && pnpm db:migrate` — появится новый
|
|
файл миграции в `apps/api/drizzle/`; старые файлы миграций не правятся и не удаляются.
|
|
|
|
## Что готово
|
|
|
|
- Схема данных всех сущностей ТЗ (раздел 9).
|
|
- Вход по email и паролю, через Telegram Login и Telegram Mini App; подтверждение email и
|
|
сброс пароля (письма пока пишутся в лог API — почтовый сервис не выбран).
|
|
- Компании, тарифы и лимит участников, роли, приглашения, удаление агента.
|
|
- Состояние подписки: активна → просрочена (15 дней) → только чтение.
|
|
- Суперадмин: компании, тариф, дата окончания, отсрочка, вход в кабинет, состояние парсера.
|
|
- **Парсер → общая база → фильтры → лиды**: все категории недвижимости list.am, в базу идут
|
|
объявления не старше 3 дней, оттуда — клиентам по общим и личным фильтрам.
|
|
- **Бот**: уведомление о лиде с кнопкой «Беру», атомарный захват, «Взял(а) Имя» у остальных,
|
|
привязка Telegram, /pause и /resume, тихие часы. Очередь сообщений с повторами и лимитом темпа.
|
|
- **Пул**: возврат через 24 часа без смены статуса, предупреждение за 2 часа, повторное «Беру».
|
|
- **Воронка объекта**: статусы, отказ с причиной, сделка с комиссией, назначение и
|
|
переназначение, комментарии, напоминания, история, «Это агент», лиды вручную.
|
|
- **Воронка клиента**: покупатели и арендаторы, запрос клиента, подбор подходящих объектов из CRM,
|
|
отметки «предложен» и «показан», переназначение руководителем, напоминания в боте.
|
|
- **Общая сделка**: объект и клиент из CRM закрываются один раз, комиссия записывается одной
|
|
строкой из двух частей: с собственника — агенту объекта, с покупателя или арендатора — агенту
|
|
клиента; если стороны в CRM нет, обе части получает агент второй стороны. Суммы и дату исправляет
|
|
руководитель.
|
|
- **Оплата агентов**: оклад, процент с части комиссии агента (отдельно для продажи и аренды) или
|
|
оклад + процент; план на месяц (сделки, комиссия) и бонус за него — суммой или надбавкой к
|
|
проценту. Ведомость «Кому сколько платить» за месяц; строка сотрудника раскрывает его сделки,
|
|
начисления, ручные записи (премия, штраф, аванс) и отметку «выплачено». Выплата закрывает месяц:
|
|
он считается по условиям и курсам на день выплаты, а изменения его сделок и недоплата переходят
|
|
перерасчётом в ближайший месяц без выплаты. Агент видит свои условия, сделки, начисления и историю
|
|
выплат в «Настройках».
|
|
- **Динамика и рейтинг**: сделки и комиссия по месяцам — по компании и по каждому сотруднику
|
|
(агент видит только свою); рейтинг месяца виден всем: место, число сделок, выполнение плана,
|
|
без сумм. Ведомость со сделками выгружается файлом для Excel.
|
|
- **Суперадмину в Telegram** приходит уведомление о каждой новой регистрации и о компании,
|
|
созданной самостоятельно: имя, email, Telegram. **Приветствие бота** (ответ на /start тому, кто
|
|
ещё не привязал Telegram): текст на трёх языках и до 10 файлов — в разделе «Сообщения». Следом бот
|
|
спрашивает язык кнопками; выбор запоминается, на нём бот отвечает и создаётся аккаунт.
|
|
- **Отчёты в Telegram** (включает руководитель в настройках компании): итоги недели по
|
|
понедельникам и итоги месяца с ведомостью первого числа, в 9 утра по Еревану.
|
|
- **Настройка воронок**: руководитель переименовывает, добавляет, удаляет и переставляет
|
|
промежуточные статусы и причины отказа в обеих воронках.
|
|
- **База** (Team, Agency): объекты и клиенты (покупатели, арендаторы), закрытые сделкой или отказом; у клиента — связанные
|
|
объекты. Раз в сутки объекты из CRM проверяются на list.am: снятое объявление получает отметку
|
|
и дату. Повторно опубликованный объект приходит новым лидом с блоком «Уже был в работе».
|
|
- **Аналитика** (Team, Agency, руководителю): сводка, воронка, таблица по агентам (взято, скорость
|
|
реакции, возвраты в пул, конверсия по этапам, сделки, комиссии), причины отказа, выгрузка в CSV;
|
|
отдельно по объектам и по клиентам.
|
|
- **Суперадмин — «Объявления»**: вся общая база объявлений с поиском, фильтрами и карточкой
|
|
«кому ушло лидом». **Настройки парсера** в админке: включение, свежесть в днях, пауза, число
|
|
страниц, категории, ключ ридера Jina, проверка снятых объявлений — без перезапуска сервиса. **Ночная пауза** (в тех же настройках, по умолчанию 22:00–8:00
|
|
по Еревану): парсер и проверка снятых не работают (экономия токенов Jina), сторож парсера ночью молчит.
|
|
**Догрузка фото** (кнопка на странице парсера): объявления за последние 24 часа, ставшие лидами,
|
|
у которых в базе только обложка или фото не открываются, — заново читается галерея со страницы
|
|
List.am (без переписывания текста моделью); идёт в фоне пачками, прогресс виден в админке.
|
|
- **Биллинг**: счета за установку, фикс и «%» с расшифровкой по сделкам; смена тарифа со
|
|
следующего месяца; напоминания за 7, 3 и 1 день и при просрочке; ручная отметка оплаты
|
|
суперадмином; контракт платёжного провайдера для онлайн-оплаты — см. [docs/BILLING.md](docs/BILLING.md).
|
|
- **Суперадмин — «Счета» и «Сообщения»**: сводка (активные компании, выручка за месяц, просрочки),
|
|
счета всех компаний, курсы валют; сообщения в Telegram всем, компании, руководителям или одному
|
|
пользователю с журналом отправок.
|
|
- **Поддержка**: всё, что человек пишет боту (текст, фото, файл), попадает в обращение. Суперадмин
|
|
отвечает в разделе «Поддержка» — ответ уходит в тот же чат — и закрывает кнопкой «Проблема решена».
|
|
В кабинете у пользователей есть раздел «Поддержка» с подсказкой, как написать.
|
|
- **Характеристики объявления**: со страницы List.am берутся удобства по разделам, «можно с детьми»,
|
|
«можно с животными», мебель, ремонт, предоплата и остальные поля. Видны в карточке объекта;
|
|
правила про детей и животных — ещё и в уведомлении бота. Телефон автора не собирается.
|
|
- **Кто будет жить** (карточка клиента): один, с другом, пара; дети и животные с количеством и
|
|
возрастом; до 10 фото. Подбор не предлагает объекты, где с детьми или животными прямо нельзя.
|
|
- **Анкета соискателя**: у каждого агента своя ссылка на клиентский бот (команда `/anketa` в основном
|
|
боте или кнопка в разделе «Клиенты»). Соискатель отвечает на вопросы — в CRM появляется клиент,
|
|
закреплённый за агентом, а агент получает в бот вопрос «Показать подходящие объекты?».
|
|
- **Страница подборки для клиента**: `<кабинет>/<компания>/<код>` — объекты, прикреплённые к клиенту,
|
|
и запись на показ по дням. Адрес и ссылка на List.am на странице скрыты. Запись на показ приходит
|
|
создателю ссылки в бот и появляется в карточке клиента.
|
|
- **Фото и текст на странице клиента** (логика из бота `list-am-bot`): для объектов, которые показывают
|
|
клиенту, догружается полный набор фото объявления; фото отдаёт сам сервис, срезая сверху 8 % высоты
|
|
(`CROP_TOP_PERCENT`); текст собирается по шаблону-карточке, а с ключом `OPENROUTER_API_KEY`
|
|
дополняется абзацем из описания. Адреса в тексте нет.
|
|
- **Карточка объекта**: все фото объявления (обрезанные, догружаются в фоне после первого открытия),
|
|
«Описание для клиента» с кнопкой копирования и поле «Телефон собственника» — номер агент берёт из
|
|
объявления сам; он сохраняется в карточке и, если в общей базе его не было, в базе объявлений.
|
|
- **Комиссия агентства**: руководитель задаёт в настройках процент или фикс — отдельно для объектов и
|
|
клиентов, продажи и аренды. В карточке видно условие и ожидаемую сумму; агент может поменять условие
|
|
для своей карточки. При закрытии сделки сумма комиссии подставляется по условию.
|
|
- **Оплата агентов**: руководитель задаёт каждому сотруднику оклад, процент с комиссии по его сделкам
|
|
или оклад + процент («Команда»). Там же таблица «Кому сколько платить» за выбранный месяц; агент
|
|
видит свои условия и начисления в настройках.
|
|
- **Отделы** (раздел «Команда»): руководитель создаёт отделы, назначает и снимает сотрудников, задаёт фильтры
|
|
отдела. У отдела свои объекты и клиенты: сотрудник видит только данные своего отдела, руководитель и
|
|
суперадмин — все отделы (с выбором отдела в списках). Одно объявление под фильтрами двух отделов приходит
|
|
каждому своей карточкой; уведомления — сотрудникам отдела. При смене отдела объекты и клиенты сотрудника
|
|
переходят с ним. Удалить можно отдел без сотрудников, клиентов и объектов в работе.
|
|
- **Рабочий список объектов** показывает только актуальное: снятые с List.am и закрытые сделкой или отказом
|
|
объекты не попадают в список, поиск, подбор, страницу клиента и витрину — они остаются в базе и в «Базе»
|
|
(фильтр «Сняты с List.am»).
|
|
- **Избранное и «Не просмотренные»**: звёздочка в списке и карточке, у каждого своя; фильтры сочетаются со
|
|
всеми остальными. **Цена в АМД или ДОЛ**: границы задаются в выбранной валюте, цены объектов в другой
|
|
валюте пересчитываются по курсу из админки («Счета»); при смене валюты введённые границы пересчитываются.
|
|
- **«Отправить в бот»** в карточке объекта: фото, описание и комиссия приходят основным ботом в личный чат
|
|
того, кто нажал. Без привязанного Telegram — инструкция и кнопка привязки.
|
|
- **Демо-компании**: `scripts/seed-demo.mjs` создаёт «Демо: Аренда» и «Демо: Продажа» на настоящих
|
|
объявлениях из базы, `scripts/seed-demo-backdate.sql` раскладывает их историю по трём неделям.
|
|
- **Мастер первой настройки**: первый фильтр, привязка бота, приглашение агентов.
|
|
- **Mini App**: тот же кабинет в Telegram с входом без пароля и нижней панелью разделов.
|
|
Тариф Solo в браузере видит только подписку и профиль — рабочие разделы открываются в Telegram.
|
|
- Веб-кабинет: объекты (таблица и канбан), карточка, клиенты, база, аналитика, фильтры, команда,
|
|
настройки, подписка, админка; три языка, тёмная и светлая тема.
|
|
- **Боевая сборка**: Docker-образы, ежедневная резервная копия, скрипт выкладки —
|
|
см. [docs/DEPLOY.md](docs/DEPLOY.md).
|
|
|
|
## Что дальше
|
|
|
|
1. Выкладка на VPS по [docs/DEPLOY.md](docs/DEPLOY.md): домен, боевой бот, первая выкладка.
|
|
2. Ручная приёмка на боевом стенде — что осталось, перечислено в [docs/ACCEPTANCE.md](docs/ACCEPTANCE.md).
|
|
3. Платёжный провайдер, почтовый сервис, вычитка армянских текстов.
|