ТЗ: шаблоны, этапы и Гант, задачи с чек-листами, загрузка людей, причины проигрыша, автодействия
Редакция от 05.10.2026. Черновик на согласовании. Основа — разбор Аспро.Cloud (демо-портал, 05.10.2026) и текущего кода бэкенда и фронта. Работа ведётся локально: на staging не выкатываем, пока владелец не скажет.
1. Цель и принципы
Шесть доработок закрывают разницу в ежедневной работе с проектами между нами и Аспро. Аспро — универсальная система для любого бизнеса. Мы берём оттуда механику, но подстраиваем её под агентство мероприятий: у каждого проекта есть дата мероприятия, монтаж и демонтаж, и от них, а не от «начала проекта», считается всё остальное.
- Шаблоны проектов и копирование проекта. Типовое мероприятие создаётся в один клик: этапы, задачи с чек-листами, команда по ролям, смета.
- Задача становится полноценной: чек-лист, подзадачи, наблюдатели, дата начала, связь «после какой задачи».
- Этапы проекта с вехами и диаграмма Ганта.
- Загрузка людей по дням. Таблица «люди × дни»: кто свободен на дату мероприятия.
- Причина проигрыша и источник заявки плюс отчёт «Воронка продаж».
- Автодействия: при смене статуса проекта или за N дней до мероприятия система сама ставит задачу или шлёт уведомление. Правила настраиваются без программиста.
Принципы, общие для всех частей:
- Предупреждать, а не запрещать. Незакрытый чек-лист, открытые подзадачи, невыполненная предыдущая задача, перегруз исполнителя — система показывает это в подтверждении, но действие проходит. Так уже устроено закрытие проекта и табель.
- Не плодить разделы. Этапы и Гант — виды внутри вкладки «Задачи» проекта. Шаблоны — рядом со списком проектов. Причины и источники — поля в существующих формах. Новые пункты меню всего два: «Загрузка людей» в группе «Ресурсы» и «Автодействия» в настройках.
- Даты от мероприятия. В шаблонах и автодействиях сроки задаются как «за 10 дней до мероприятия», «в день монтажа», «через 2 дня после окончания», а не абсолютными датами.
- Одна механика копирования. Копия проекта — это шаблон, который не сохраняется: снять с проекта, применить к новому. Создание из шаблона и копирование используют один и тот же код.
- ИИ только там, где он убирает ручной ввод. «Сформулировать задачу» начинает заполнять настоящий чек-лист, а не вклеивать шаги в описание. Новых ИИ-виджетов не добавляем.
Что не входит: Agile-доски, конструктор бизнес-процессов с ветвлениями, вебхуки и внешние интеграции, заявки с сайта и из Telegram, почта в карточке, кабинет клиента. Это отдельные ТЗ позже.
2. Как устроено сейчас
| Что | Как сейчас | Что это значит для ТЗ |
|---|---|---|
| Даты проекта | start_planned / end_planned (TIMESTAMPTZ) — мероприятие, mount_date (DATE) — монтаж, фактические даты. Отдельной даты демонтажа нет, end_planned играет её роль. Дедлайн контрактации вычисляется: начало минус 1,5 месяца | Это «якоря» для относительных сроков в шаблонах, на Ганте и в автодействиях |
| Статусы проекта | Пресейл (planned … estimating) свободно туда-обратно, затем approved → in_progress → done → closed, плюс lost (можно вернуть в пресейл) и cancelled (только из done). Граф в projects/status.go, дублируется на фронте | Новые статусы не вводим. Переход в lost получает обязательную причину |
| История статусов | Таблицы нет. Есть status_changed_at и событие аудита project.status_changed, которое пишется не всегда (зависит от cfg.Audit.Enabled, не в транзакции, при смене через PUT отдельного события нет) | Нужна таблица истории: без неё нет конверсии по ступеням, срока сделки и надёжного триггера для автодействий |
| Хуки на смену статуса | Нет. UpdateStatus пишет только аудит. Шины событий нет, автоматизации — прямые вызовы через адаптеры в internal/app | Автодействиям нужна точка расширения: запись в историю + очередь запусков |
| Создание проекта | POST /projects, без транзакции. Побочно: дивизионы, kickoff-задача менеджеру (флаг в env), аудит, чат (из транспорта), папки (триггер БД). Нумерации нет | Создание из шаблона должно идти в одной транзакции; kickoff-задача переезжает в автодействие «при создании» |
| Копирование | Есть только копирование версии сметы внутри одного проекта (estimates CopyContent) | Переносим логику копирования разделов и строк на копирование между проектами |
| Задача | Поля: проект, отдел, название, описание, примечание, ответственный (обязателен), соисполнители (task_co_assignees), статус, внутренняя, план/факт часов, обязательность учёта времени, только срок due_date, дата завершения. Нет даты начала, приоритета, тегов. Статусы todo/in_progress/blocked/done/cancelled, на фронте blocked не показывается | Добавляем дату начала, родителя, этап, чек-лист, наблюдателей, связи |
| Проверка срока задачи | Срок не в прошлом и не раньше начала проекта | Мешает создавать задачи по шаблону для уже идущих проектов — нужен обход для создания по шаблону |
| Уведомления по задачам | Только task.assigned (ответственный и соисполнители). О комментариях, смене статуса, сроке — ничего | Наблюдатели без уведомлений бессмысленны: добавляем уведомления о статусе и комментарии |
| Карточка задачи (фронт) | TaskDetailsPage.vue: шапка, «Кратко», «Суть», «Кто и когда», «Время», «Файлы», «Комментарии»; вкладки «Задача / Чат / История» | Чек-лист и подзадачи — новые блоки после «Сути», наблюдатели — в «Кто и когда», связи — блок «Порядок» |
| Доски и ленты | Канбан на нативном HTML5 DnD. Лента «Расписание» (ScheduleWidget.vue) и календарь отсутствий (AbsenceCalendar.vue) — самописные, с выходными из календаря компании. Библиотек для Ганта нет | Гант пишем сами на той же основе, без новой зависимости |
| Загрузка людей | Виджет на главной: часы за текущий месяц / личная норма (168 ч минус отсутствия). По дням нет, плановые часы задач не учитываются | Нужна загрузка по дням с планом из задач |
| Сетка «люди × дни» | GET /absences/calendar — сотрудники × дни, отсутствия, командировки, праздники, до 100 дней | Основа для загрузки: тот же каркас ответа и тот же компонент |
| Занятость вне задач | Командировки: один сотрудник, плановые даты. Логистика: ответственный и водитель, плановые даты. Команда проекта: без дат, только роль и активность | Дни мероприятия считаем занятостью для «выездных» ролей команды |
| Клиенты | Компании с менеджером. Источника клиента или заявки нет нигде | Источник — поле проекта (каждая заявка), не компании |
| Справочники | Общего механизма нет. Категории мероприятий зашиты в код | Заводим одну таблицу справочников с видом записи |
| Воронка на главной | FunnelWidget: группировка проектов по статусу, lost/cancelled строкой снизу | Остаётся. Подробная аналитика — новый отчёт |
| Отчёты | Статусы, финансы, затраты, незапланированные, операции, помощник. CSV на клиенте | Новая вкладка «Воронка продаж» |
| Права | Матрица ролей (internal/permissions/matrix.go) + capabilities для админских разделов (absences_manage) | Новые capability: project_templates_manage, automations_manage, sales_dictionaries_manage |
| Realtime, контракты | Правила в internal/realtime/rules.go, контракты в internal/contractspec | Каждый новый маршрут — правило realtime и описание в контрактах |
3. Задачи: дата начала, чек-лист, подзадачи, наблюдатели, связи
3.1. Дата начала
Новое необязательное поле start_date. Правила:
- Начало не позже срока. Если указан только срок — задача точечная (на Ганте ромбик срока, в загрузке все плановые часы ложатся на рабочие дни перед сроком, см. 6.2).
- Начало может быть в прошлом (задача уже идёт). Проверка «срок не в прошлом» остаётся только для ручного создания.
- В форме задачи «Начало» стоит рядом со «Сроком» в блоке «Кто и когда». На карточке доски показывается диапазон «12–15 окт», если начало задано.
3.2. Чек-лист
Один список пунктов в задаче. Пункт: текст, отметка «сделано», кто и когда отметил, порядок. Ответственного и срока у пункта нет: если пункту нужен свой исполнитель — это подзадача.
- Отмечать пункты могут все, кто может работать с задачей (ответственный, соисполнители, управляющие). Добавлять, править, удалять, менять порядок — так же.
- На карточке доски и в списке — счётчик «3/7». В карточке задачи — блок «Чек-лист» сразу после «Сути»: пункты с галочками, поле «Добавить пункт» (Enter — следующий), перетаскивание для порядка.
- Вставка многострочного текста в поле «Добавить пункт» создаёт по пункту на строку.
- Завершение задачи с неотмеченными пунктами: подтверждение «Не отмечено 2 пункта: …. Завершить всё равно?».
- «Сформулировать» (ИИ в форме задачи) раскладывает
checklist[]в настоящий чек-лист, а не в описание. - Отметка пункта пишется в историю задачи, уведомлений не шлёт.
3.3. Подзадачи
Подзадача — обычная задача со ссылкой на родителя parent_task_id. Один уровень: у подзадачи не может быть своих подзадач.
- Подзадача всегда в том же проекте, что родитель (или обе без проекта). Этап по умолчанию — этап родителя.
- У подзадачи свой ответственный, срок, часы, чек-лист, статус. Часы подзадач в родителя не суммируются: каждая задача отвечает за свои.
- Создать подзадачу может тот, кто может создавать задачи в проекте. В карточке родителя блок «Подзадачи»: строка «Добавить подзадачу» (название + ответственный + срок прямо в строке), список с исполнителем, сроком, статусом, общий прогресс «2 из 5».
- Срок подзадачи позже срока родителя — предупреждение в форме, не запрет.
- Завершение родителя с открытыми подзадачами — подтверждение со списком. Открытые подзадачи при этом не закрываются.
- Удаление родителя — подтверждение «Удалить вместе с N подзадачами». Подзадачи удаляются.
- На доске подзадачи — отдельные карточки с подписью «↳ название родителя». Фильтр «Скрыть подзадачи» (запоминается). В списке — группировка под родителем со сворачиванием.
- Видимость не наследуется: подзадачу видят её участники и все, кто видит проект, как и обычную задачу. Список подзадач в карточке родителя видит каждый, кто видит родителя. Родитель показывается подписью даже тому, кто сам родителя не видит, — только название, без перехода.
3.4. Наблюдатели
Наблюдатель видит задачу и получает уведомления о её ходе, но не работает с ней и не меняет её.
- Таблица
task_watchers(task_id, user_id, added_by, created_at). - Кнопка «Следить» в шапке задачи — для любого, кто видит задачу; «Перестать следить». Добавить другого человека может тот, кто управляет задачей. Автор задачи становится наблюдателем автоматически, если он не ответственный и не соисполнитель (сейчас автор теряет задачу из виду, когда отдаёт её).
- Наблюдатель получает право чтения задачи (
canViewTask) и попадает в чат задачи как участник с правом писать — так проще, чем вводить «чтение без записи» в чатах. - Блок «Кто и когда» показывает наблюдателей аватарами после соисполнителей.
3.5. Связи «после какой задачи»
Связь «Б начинается после окончания А», с запасом в днях (может быть отрицательным: «за 2 дня до окончания А»). Других типов связей (начало–начало и т. п.) в первой версии нет: в Аспро они есть, но для мероприятий хватает одного.
- Только между задачами одного проекта. Циклы запрещены (проверка на сервере).
- В карточке задачи блок «Порядок»: «Ждёт: Согласовать макет (до 12 окт)», «Следом: Печать баннеров». Добавить связь — выбор задачи проекта поиском.
- Начать задачу, у которой предыдущая не завершена, можно — с подтверждением «Ещё не готово: …. Начать всё равно?».
- Когда предыдущая задача завершена, ответственному следующей приходит уведомление
task.predecessor_done«Можно начинать: …». - Сдвиг срока задачи, у которой есть последующие: после сохранения предложение «Сдвинуть 3 следующие задачи на +2 дня?» со списком. Автоматически ничего не двигается.
3.6. Уведомления по задачам
| Тип | Кому | Когда |
|---|---|---|
task.assigned (есть) | Новый ответственный, новые соисполнители | Как сейчас |
task.status_changed | Автор и наблюдатели, кроме того, кто сменил | Задача завершена, отложена или возвращена в работу. Переход «Планируется → В работе» не шлётся — это шум |
task.comment | Ответственный, соисполнители, автор, наблюдатели, кроме автора комментария | Новый комментарий |
task.predecessor_done | Ответственный следующей задачи | Предыдущая завершена |
Все новые типы управляются общими настройками уведомлений пользователя (в системе / на почту), ключ от повторов — тип + задача + событие.
4. Этапы проекта, вехи и диаграмма Ганта
4.1. Этапы
Этап — именованная фаза работ внутри проекта: «Подготовка», «Производство», «Монтаж», «Мероприятие», «Демонтаж и закрытие». Этапы не заменяют статусы проекта: статус — где проект в воронке и производстве, этап — как разбита работа.
- Таблица
project_stages(id, project_id, name, position, color, created_at). У задачи полеstage_id(необязательное). - Даты этапа не вводятся, а считаются: от самого раннего начала до самого позднего срока его задач и вех. Пустой этап дат не имеет.
- Прогресс этапа — доля завершённых задач (отменённые не считаются). Текущий этап — первый по порядку, где есть незавершённые задачи.
- Управляют этапами те, кто управляет проектом (
canManageProject). Удаление этапа: задачи остаются в проекте без этапа. - Проект без этапов работает как сейчас: все задачи в группе «Без этапа».
4.2. Вехи
Веха — контрольная дата без длительности: «Договор подписан», «Макеты согласованы», «Техника на площадке». Отметка «достигнута».
- Таблица
project_milestones(id, project_id, stage_id, title, date, done_at, done_by, position). - Вехи системные — показываются всегда, из полей проекта, только чтение: дедлайн контрактации, монтаж, начало мероприятия, окончание мероприятия. Правятся в карточке проекта, как сейчас.
- Отметить веху может тот, кто управляет проектом. Просроченная неотмеченная веха подсвечивается красным на Ганте и в «Ходе работ», в «Что дальше» появляется подсказка.
4.3. Где это видно
Во вкладке «Задачи» проекта переключатель вида: Доска (как сейчас) / Ход работ / Гант. Выбор запоминается.
Ход работ — аналог «Порядка работ» в Аспро. Полоса этапов сверху с прогрессом, ниже этапы по порядку: задачи этапа (галочка, название, исполнитель, срок), вехи этапа (ромбик, дата, отметка), строки «Добавить задачу» и «Добавить веху». Этапы сворачиваются, перетаскиваются для смены порядка; задачу можно перетащить в другой этап. Внизу — «Без этапа».
4.4. Диаграмма Ганта
Пишем сами на основе ScheduleWidget/AbsenceCalendar, без новой библиотеки.
- Строки: этапы (сворачиваются) → задачи → подзадачи. Слева колонки «Задача», «Исполнитель», «Начало», «Срок».
- Полосы: задача с началом и сроком — полоса; только со сроком — ромбик на сроке с подсказкой «нет даты начала»; этап — тонкая сводная полоса по своим задачам; вехи — ромбики; завершённые задачи приглушены, просроченные — красные.
- Фон: выходные и праздники из календаря компании затенены; вертикальные линии «Сегодня», «Монтаж», «Мероприятие» (полоса на все дни мероприятия), «Окончание».
- Связи: стрелки от конца предыдущей задачи к началу следующей. Нарушенная связь (следующая начинается раньше, чем кончается предыдущая с запасом) — стрелка красная.
- Масштаб: дни / недели; кнопки «К сегодня», «Весь проект».
- Правка (для тех, кто управляет задачей): перетаскивание полосы двигает начало и срок вместе, перетаскивание края меняет одну дату, протягивание от края полосы к другой полосе создаёт связь. После сдвига с последующими задачами — то же предложение «Сдвинуть следующие?», что в карточке. Каждое изменение можно отменить (тост с «Отменить», как на доске).
- Клик по полосе открывает карточку задачи в боковой панели.
- Телефон: Гант только для чтения с горизонтальной прокруткой; править — в «Ходе работ».
- Экспорт: PNG картинки диаграммы (для отправки клиенту) — кнопка в углу.
4.5. Лента проектов
В списке проектов к видам «Таблица / Доска» добавляется «Лента»: строка на проект, по горизонтали дни. На строке — точка дедлайна контрактации, полоса монтажа, полоса мероприятия, конец. Цвет — статус проекта. Фильтры списка проектов действуют и здесь. Это ответ на вопрос «что у нас на какие даты» без открытия каждого проекта. Правки на ленте нет.
5. Шаблоны проектов и копирование проекта
5.1. Что лежит в шаблоне
| Часть | Как хранится в шаблоне | Что происходит при создании проекта |
|---|---|---|
| Основное | Название шаблона, описание, категория мероприятия, дивизион по умолчанию, текст описания проекта | Подставляется в форму, можно поменять |
| Этапы | Название, порядок, цвет | Создаются как есть |
| Задачи | Название, описание, этап, родитель (подзадачи), роль исполнителя (из ролей проекта: менеджер, ведущий, инженер, техник, логист…), план часов, внутренняя, обязательность учёта времени, начало и срок относительно якоря, чек-лист | Исполнитель — участник команды с этой ролью (первый по списку), если такого нет — менеджер проекта. Даты считаются от якоря |
| Связи задач | Пары задач шаблона с запасом | Восстанавливаются между созданными задачами |
| Вехи | Название, этап, дата относительно якоря | Создаются |
| Команда | Роли (и при желании конкретные люди по умолчанию) | Заполняется команда людьми по умолчанию; роль без человека в команду не добавляется, её задачи уходят менеджеру |
| Смета | Разделы и строки действующей версии; все строки становятся ручными с теми же суммами (привязки к старому проекту не переносятся) | Создаётся черновик сметы версии 1 |
Якоря дат: начало мероприятия (по умолчанию), монтаж, окончание мероприятия, создание проекта. Смещение — в календарных днях, со знаком: «−10 от мероприятия», «0 от монтажа», «+2 от окончания». Опция «только рабочие дни» на уровне шаблона: если включена, смещение считается в рабочих днях по календарю компании, а дата, попавшая на выходной, сдвигается на ближайший рабочий день раньше.
Не входит в шаблон: файлы, ТЗ, документы, платежи, бюджет и факт, логистика, командировки, обязательства, часы, чат.
5.2. Создание проекта из шаблона
- В диалоге «Новый проект» сверху выбор «С нуля / Из шаблона». Список шаблонов с описанием и составом («5 этапов, 34 задачи, смета на 1,2 млн»).
- После выбора форма заполняется данными шаблона. Обязательны даты, от которых зависят задачи шаблона (если в шаблоне есть привязки к монтажу — монтаж обязателен).
- Перед кнопкой «Создать» — сводка: что будет создано, сколько задач получат исполнителя по роли, сколько уйдут менеджеру. Задачи, чьи сроки при этих датах уже в прошлом, переносятся на сегодня — сводка показывает их число.
- Всё создаётся в одной транзакции: проект, дивизионы, команда, этапы, задачи, чек-листы, связи, вехи, смета. Чат и папки — как сейчас, после фиксации. Ошибка любой части — проект не создаётся.
- В карточке проекта в «Обзоре» строка «Создан по шаблону «…»».
Изменение шаблона потом на созданные проекты не влияет.
5.3. Сохранить проект как шаблон
В меню карточки проекта «Сохранить как шаблон». Диалог: название шаблона, якорь по умолчанию, галочки состава (этапы и задачи, вехи, команда, смета). Даты задач пересчитываются в смещения от выбранного якоря проекта. Исполнители превращаются в роли по их роли в команде проекта; если человек не в команде — роль «менеджер». Статусы и отметки сбрасываются. Отменённые задачи не берутся.
5.4. Копирование проекта
В меню карточки проекта «Копировать». Диалог: название (по умолчанию «… (копия)»), клиент (по умолчанию тот же), новые даты мероприятия и монтажа, галочки: этапы и задачи, вехи, команда (те же люди), смета, требования к оборудованию, описание. Даты задач сдвигаются на разницу между старым и новым началом мероприятия. Новый проект — в статусе «Запланирован».
Технически это «снять шаблон в памяти» + «создать из шаблона», с отличием: команда копируется людьми, а не ролями.
5.5. Управление шаблонами
Страница «Проекты → Шаблоны» (кнопка рядом с «Новый проект» в списке проектов, отдельного пункта меню нет).
- Таблица: название, категория, состав, сколько проектов создано, активен, кто изменил.
- Редактор шаблона: основное; этапы со списком задач в виде «Хода работ», где вместо дат — смещения («за 10 дн. до мероприятия»); вехи; команда по ролям; смета (просмотр и замена из проекта — смету в шаблоне руками не правим, её берут из удачного проекта).
- Ниже редактора — предпросмотр: «Если мероприятие 20 ноября, задачи лягут так» в виде Ганта.
- Неактивный шаблон не предлагается при создании, но не удаляется. Удаление — только если по шаблону ничего не создано, иначе только деактивация.
- Создавать и править шаблоны: capability
project_templates_manage(администратор, генеральный директор, руководители дивизионов). Пользоваться — все, кто может создавать проекты.
6. Загрузка людей по дням
6.1. Экран
Новый пункт меню «Загрузка людей» в группе «Ресурсы». Строка — сотрудник, колонка — день (2 недели / месяц, листание). Сверху фильтры: дивизион, отдел, роль в проектах, проект (только люди его команды), поиск по имени. Переключатель План / Факт.
Ячейка:
- План — процент дневной нормы по плановым часам задач (см. 6.2). Цвет: до 50 % — светлый, 50–100 % — обычный, больше 100 % — красный.
- Факт (прошедшие дни) — отмеченные часы из учёта времени.
- Значки поверх: отпуск/больничный/отгул (ячейка заштрихована, норма 0 или 4 ч), командировка, рейс логистики (водитель или ответственный), мероприятие проекта (для «выездных» ролей, см. 6.2).
- Выходные и праздники затенены.
Клик по ячейке — всплывающая панель: задачи дня с часами, командировка, перевозка, мероприятия; ссылки в карточки. Справа от имени — итог периода: план / норма.
6.2. Как считается план
- Норма дня — 8 ч в рабочий день по календарю компании, 4 ч в день с половиной отсутствия, 0 в выходной, праздник и полный день отсутствия.
- Плановые часы задачи распределяются поровну по рабочим дням от начала до срока. Нет начала — часы ложатся на рабочие дни перед сроком из расчёта 8 ч в день (40 часов → 5 рабочих дней до срока). Нет плановых часов — задача в процент не входит, но видна в панели дня.
- Учитываются задачи в статусах «Планируется» и «В работе» (и «Заблокирована»), где человек ответственный. Соисполнитель получает те же часы (часы задачи — оценка на каждого участника; так проще и понятнее, чем делить).
- Мероприятия: дни от монтажа до окончания мероприятия у проектов в статусах «Подтверждён» и «В работе» отмечаются значком у участников команды с «выездными» ролями (ведущий, инженер, техник, логист). Процент не меняют: время на площадке и так должно быть задачами.
- Командировка и рейс — значок и отметка «в отъезде», процент не меняют.
6.3. Подсказка при назначении
В форме задачи при выборе ответственного и соисполнителей рядом с именем — короткая сводка на даты задачи: «120 % в эти дни», «в отпуске 12–14 окт», «в командировке». То же в одобрении заявки на людей в команду проекта. Это подсказка, не запрет.
6.4. Кто что видит
| Кто | Что видит |
|---|---|
| Сотрудник | Свою строку целиком |
| Руководитель отдела, дивизиона | Своих людей целиком |
| Генеральный директор, администратор | Всех целиком |
| Менеджер проекта | Людей своих проектов и людей из отделов, куда можно подать заявку, — только процент и занятость (отпуск, отъезд, мероприятие), без названий чужих задач и проектов |
Права берутся из существующих объектов: «чужие табели» (others_timesheets) для полного доступа, менеджер проекта — по роли в проекте.
Виджет «Загрузка сотрудников» на главной остаётся месячным и получает ссылку «По дням →».
7. Причина проигрыша, источник заявки и отчёт «Воронка продаж»
7.1. Справочники
Таблица sales_dictionary_items(id, kind, name, position, is_active), вид lost_reason или lead_source. Правка в «Настройки → Компания → Справочники продаж» (capability sales_dictionaries_manage: администратор, генеральный директор, руководитель отдела продаж). Записи не удаляются, если использованы, — только скрываются.
Начальные значения:
- Причины проигрыша: Дорого; Выбрали другого подрядчика; Мероприятие отменено или перенесено; Не успеваем по срокам; Нет нужного оборудования или людей; Клиент пропал; Не наш формат; Другое.
- Источники заявки: Повторный клиент; Рекомендация; Сайт; Тендер или площадка закупок; Входящий звонок или письмо; Выставка или мероприятие; Холодный контакт; Другое.
7.2. Источник заявки
Поле проекта lead_source_id в основных полях формы проекта рядом с компанией. Необязательное. Если у компании уже были проекты — по умолчанию «Повторный клиент». Видно в карточке, в списке проектов (колонка, фильтр) и в экспорте.
7.3. Причина проигрыша
- При переводе в «Проигран» (из карточки, из быстрого меню в списке, с доски) открывается диалог: причина (обязательно), комментарий, кому ушли (свободный текст, необязательно). Без причины перевести нельзя — это единственное жёсткое требование в ТЗ, потому что без него отчёт бесполезен.
- Поля проекта:
lost_reason_id,lost_comment,lost_competitor. При возврате из «Проигран» в пресейл поля очищаются, но остаются в истории статусов. - В быстром меню списка «Проигран» больше не меняется сразу с «Отменить», а открывает диалог.
- Перевод в «Отменён» получает необязательный комментарий.
- Уже проигранные проекты без причины показываются в отчёте как «Не указана».
7.4. История статусов
Таблица project_status_history(id, project_id, from_status, to_status, changed_by, changed_at, lost_reason_id, comment). Запись — в той же транзакции, что смена статуса, и через PATCH /status, и через PUT /projects/:id, и при создании проекта (from_status пустой). Однократное заполнение из журнала аудита там, где он есть. Вкладка «История» проекта показывает смены статуса из этой таблицы. Эта же запись — триггер для автодействий (раздел 8).
7.5. Отчёт «Воронка продаж»
Новая вкладка в «Отчёты». Фильтры: период, дивизион, менеджер, источник, категория мероприятия. Доступ — как у остальных отчётов (reports_dashboards), денежные суммы — по праву видеть бюджет клиента.
- Плитки: новых заявок за период; выиграно (дошли до «Подтверждён») — штук и сумма; проиграно — штук и сумма; конверсия = выиграно / (выиграно + проиграно); средний срок от заявки до подтверждения, дней.
- Воронка по ступеням: сколько заявок периода дошло до каждой пресейл-ступени и до «Подтверждён», процент перехода между ступенями. Считается по истории статусов.
- Причины проигрыша: столбцы по числу и сумме, клик — список проектов.
- Источники: таблица источник → заявок, выиграно, конверсия, сумма выигранного.
- Менеджеры: таблица менеджер → заявок, выиграно, проиграно, конверсия, сумма, средний срок.
- Экспорт CSV, как у остальных отчётов.
8. Автодействия
8.1. Что такое правило
Правило = когда + для каких проектов + что сделать.
Когда (триггер):
- Проект создан.
- Проект перешёл в статус X (любой из статусов проекта).
- За N дней до / через N дней после даты проекта: монтаж, начало мероприятия, окончание мероприятия. Срабатывает раз в сутки утром по часовому поясу компании, только для проектов в статусах «Подтверждён» и «В работе».
Для каких проектов (условия, все необязательные): дивизион, категория мероприятия, создан по шаблону X, источник заявки.
Что сделать (действие):
| Действие | Параметры |
|---|---|
| Поставить задачу | Название (можно вставлять {проект}, {клиент}, {дата мероприятия}), описание, исполнитель — роль в проекте / менеджер проекта / конкретный сотрудник, срок — через N дней от срабатывания или относительно даты проекта, план часов, чек-лист, этап (по названию, если в проекте есть такой) |
| Добавить задачи из шаблона | Шаблон проекта: из него берутся этапы, задачи и вехи (без команды и сметы). Пример: при «Подтверждён» добавить пакет задач подготовки |
| Уведомить | Кому — роли в проекте / менеджер / руководитель дивизиона / конкретные люди; текст с подстановками; ссылка на проект |
| Написать в чат проекта | Системное сообщение с подстановками («Проект подтверждён, монтаж 12 ноября») |
Правило может содержать несколько действий по порядку. Действия, которые меняют статус проекта, в первой версии не делаем — так исключаются циклы.
8.2. Как выполняется
- Смена статуса или создание проекта в той же транзакции пишет запись в историю статусов и ставит подходящие правила в очередь
automation_runs. Воркер выполняет их в течение нескольких секунд: пользователь не ждёт и ошибка автодействия не ломает смену статуса. - Один раз: правило срабатывает для проекта один раз на каждое событие. Для «перешёл в статус» — один раз за жизнь проекта, если в правиле не включено «при каждом входе в статус» (проект может вернуться из «Проигран» и снова пройти пресейл). Ключ от повторов — правило + проект + событие.
- Каждое выполненное действие видно во вкладке «История» проекта: «Автодействие «Подготовка к монтажу» поставило задачу «Проверить технику» (Петров)». Ошибка — там же и в журнале автодействий для администратора.
- Задача, поставленная автодействием, помечена «Создано автоматически» и ссылкой на правило.
8.3. Настройка
«Настройки → Система → Автодействия» (capability automations_manage: администратор, генеральный директор).
- Экран — колонки по триггерам, как в Аспро: «Создан», статусы проекта по порядку, «Даты проекта». В колонке — карточки правил с кратким текстом «Сразу → задача логисту «Заказать транспорт»». Переключатель «Вкл/выкл» на карточке.
- Редактор правила в боковой панели. Внизу — «Проверить на проекте»: выбор проекта, система показывает, что бы создала (задачи с исполнителями и сроками, получателей), ничего не создавая.
- Журнал запусков: дата, правило, проект, результат, ошибка.
8.4. Что переезжает в автодействия
- Kickoff-задача менеджеру при создании проекта пока остаётся прежней (настройка в env); перенести её в правило «Проект создан → задача менеджеру» можно, выключив флаг. Решение реализации: не менять поведение без отдельного согласия.
- Автоматизации командировок, логистики, затрат, финансовые ворота и «Что дальше» остаются в коде: они завязаны на деньги и документы, настраивать их не нужно.
8.5. Начальный набор правил (выключены, кроме kickoff)
- Подтверждён → задача менеджеру «Подписать договор» на 3 дня; уведомление руководителю дивизиона.
- Подтверждён → задача логисту «Заказать транспорт» за 7 дней до монтажа.
- За 3 дня до монтажа → задача ведущему «Проверить готовность оборудования» с чек-листом.
- Через 2 дня после окончания мероприятия → задача менеджеру «Собрать фотоотчёт и закрывающие документы».
- Проигран → уведомление руководителю отдела продаж с причиной.
9. Данные, API, права, уведомления
9.1. Схема (миграции с 0187, порядок по этапам)
| Миграция | Что |
|---|---|
tasks_start_parent_stage | tasks.start_date TIMESTAMPTZ NULL, tasks.parent_task_id BIGINT NULL REFERENCES tasks ON DELETE CASCADE, tasks.stage_id BIGINT NULL, tasks.automation_rule_id BIGINT NULL; индексы по parent_task_id, stage_id и (assignee_id, due_date) |
task_checklist | task_checklist_items(id, task_id, title, is_done, done_by, done_at, position, created_at), индекс (task_id, position) |
task_watchers | task_watchers(task_id, user_id, added_by, created_at), PK (task_id, user_id), индекс по user_id |
task_dependencies | task_dependencies(predecessor_id, successor_id, lag_days INT NOT NULL DEFAULT 0), PK по паре, индекс по successor_id |
project_stages_milestones | project_stages, project_milestones; FK tasks.stage_id → project_stages ON DELETE SET NULL |
project_templates | project_templates(id, name, description, event_category, department_id, project_description, workdays_only, is_active, created_by, updated_by, timestamps), project_template_items (этапы, задачи, вехи — одна таблица с видом и parent_item_id, или три таблицы — решить при реализации), project_template_dependencies, project_template_team, project_template_estimate (снимок сметы JSONB); projects.template_id NULL |
sales_dictionaries | sales_dictionary_items; projects.lead_source_id, lost_reason_id, lost_comment, lost_competitor (все NULL); начальные значения |
project_status_history | Таблица истории, индексы (project_id, changed_at) и (to_status, changed_at); заполнение из audit_events |
automations | automation_rules(id, name, is_active, trigger_kind, trigger_status, anchor, offset_days, repeat_each_entry, conditions JSONB, actions JSONB, created_by, timestamps), automation_runs(id, rule_id, project_id, event_key, status, result JSONB, error, created_at, done_at), уникальный (rule_id, project_id, event_key); начальные правила |
Все ADD COLUMN — с NULL или DEFAULT. Деньги в снимке сметы шаблона — строками с двумя знаками, читаются в money.Money.
9.2. API (новое и изменённое)
Задачи:
POST/PUT /tasks— новые поляstart_date,parent_task_id,stage_id,watcher_ids; в ответеchecklist_total/done,subtask_total/done,parent(id, название),watcher_ids,predecessors[],successors[].GET /tasks/:id/checklist,POST /tasks/:id/checklist(в т. ч. массивом строк),PATCH /tasks/:id/checklist/:item_id,DELETE …,PUT /tasks/:id/checklist/order.GET /tasks/:id/subtasks.POST /tasks/:id/watch,DELETE /tasks/:id/watch,PUT /tasks/:id/watchers.POST /tasks/:id/dependencies,DELETE /tasks/:id/dependencies/:predecessor_id.POST /tasks/shift— сдвиг набора задач на N дней (для «Сдвинуть следующие?» и Ганта), одной транзакцией.GET /tasks— фильтрыparent_task_id,stage_id,without_subtasks,from/toпо датам.
Проекты:
GET/POST /projects/:id/stages,PUT/DELETE /projects/:id/stages/:stage_id,PUT /projects/:id/stages/order.GET/POST /projects/:id/milestones,PUT/DELETE …/:milestone_id.GET /projects/:id/plan— этапы, задачи с датами и связями, вехи, системные даты одним ответом (для «Хода работ» и Ганта; праздники — изGET /calendar).- Лента проектов строится из обычного
GET /projects— отдельного маршрута нет. POST /projects/:id/copy,POST /projects/:id/save-as-template.POST /projects—template_idиlead_source_id;GET /projects/template-preview?template_id&dates…— сводка перед созданием.PATCH /projects/:id/status—{status, lost_reason_id, lost_comment, lost_competitor, comment};400 lost_reason_requiredбез причины.GET /projects/:id/status-history.
Шаблоны: GET/POST /project-templates, GET/PUT/DELETE /project-templates/:id, POST /project-templates/:id/preview.
Загрузка: GET /workload?from&to&department_id&project_id&role&mode=plan|fact (до 62 дней), GET /workload/users?user_ids&from&to — краткая сводка для подсказки в форме.
Продажи: GET/POST /sales-dictionaries?kind, PUT /sales-dictionaries/:id; GET /reports/sales-funnel?….
Автодействия: GET/POST /automations, GET/PUT/DELETE /automations/:id, POST /automations/:id/dry-run {project_id}, GET /automations/runs?….
Все списки — через transport.RespondList. Каждый маршрут — правило в internal/realtime/rules.go (новые части проекта stages, schedule; сущность task для чек-листа, подзадач, наблюдателей) и описание в internal/contractspec; после каждого этапа — перегенерация контрактов.
9.3. Права
| Действие | Кто |
|---|---|
| Чек-лист, подзадачи, связи задачи | Кто может работать с задачей (чек-лист) или управлять ею (подзадачи, связи) — существующие проверки |
| Следить за задачей | Кто видит задачу; добавлять других — кто управляет |
| Этапы, вехи, правка на Ганте | canManageProject / управление задачей |
| Создать проект из шаблона, копировать | Кто может создавать проекты; копирование — ещё и видеть исходный |
| Шаблоны: создать, править | project_templates_manage |
| Загрузка людей | Раздел 6.4 |
| Справочники продаж | sales_dictionaries_manage |
| Отчёт «Воронка продаж» | reports_dashboards |
| Автодействия | automations_manage |
Capability добавляются тем же способом, что absences_manage (WithCapabilities, тип AppCapability на фронте, routeAccess.ts). docs/rbac_matrix.md и docs/concepts/permissions-matrix.md обновляются.
9.4. Уведомления
Новые типы: task.status_changed, task.comment, task.predecessor_done, automation.notify (текст правила), automation.failed (администратору, раз в сутки сводкой). Маршрутизация на фронте — по entityType задачи/проекта, как сейчас.
9.5. Помощник
get_taskиlist_tasksотдают чек-лист, подзадачи, этап, наблюдателей.- «Сформулировать задачу» заполняет чек-лист.
- Новый инструмент чтения
workload— «кто свободен 12–14 ноября среди техников» — с теми же правами, что экран. - Новых ИИ-кнопок нет.
10. Этапы работ и приёмка
Порядок выбран так, чтобы каждый этап опирался на предыдущий: шаблонам нужны этапы, чек-листы и подзадачи; Ганту — дата начала и связи; автодействиям — история статусов.
| Этап | Состав | Ориентир |
|---|---|---|
| 1. Задачи | Дата начала, чек-лист, подзадачи, наблюдатели, связи, «сдвинуть следующие», новые уведомления, «Сформулировать» → чек-лист; доска и список с подзадачами; показ статуса blocked на фронте | 3–4 дня |
| 2. Этапы и Гант | Этапы, вехи, системные вехи, «Ход работ», Гант с правкой и связями, лента проектов, PNG | 4–5 дней |
| 3. Шаблоны и копирование | Шаблоны (хранение, редактор, предпросмотр), создание из шаблона в транзакции, «Сохранить как шаблон», «Копировать проект» | 4–5 дней |
| 4. Загрузка людей | Экран «люди × дни» план/факт, панель дня, подсказка при назначении и в заявке на людей, права, ссылка с главной, инструмент помощника | 2–3 дня |
| 5. Продажи | Справочники, источник, обязательная причина проигрыша, история статусов с заполнением из аудита, отчёт «Воронка продаж» | 2–3 дня |
| 6. Автодействия | Правила, очередь и воркер, триггеры статуса и дат, четыре действия, проверка на проекте, журнал, перенос kickoff, начальный набор | 4–5 дней |
Приёмочный сценарий (сквозной, на локальной базе)
- Администратор создаёт шаблон «Выставочный стенд» из прошлого проекта: 5 этапов, 30 задач с чек-листами и связями, вехи, команда по ролям, смета.
- Менеджер создаёт проект из шаблона: источник «Рекомендация», мероприятие через 20 дней, монтаж за 2 дня до него. Сводка показывает, кому уйдут задачи; после создания задачи стоят на правильных датах, у ролей — нужные люди.
- На Ганте менеджер сдвигает «Согласование макета» на 2 дня, соглашается сдвинуть следующие; стрелки связей остаются целыми.
- Ведущий отмечает пункты чек-листа, добавляет подзадачу технику; автор задачи как наблюдатель получает уведомление о завершении.
- В «Загрузке людей» видно, что техник на дни монтажа перегружен (красный) и что у второго техника отпуск; менеджер переназначает задачу, подсказка в форме это подтверждает.
- Проект переводится в «Подтверждён» — автодействие ставит логисту «Заказать транспорт» со сроком за 7 дней до монтажа, в чат проекта приходит сообщение, в «Истории» видна запись.
- Второй проект переводится в «Проигран» — без причины не даёт, с причиной «Дорого» проходит; в отчёте «Воронка продаж» видна причина, источник и конверсия.
- Проект копируется на новую дату — задачи сдвинуты, файлов, денег и логистики в копии нет.
- Каждый шаг сверяется с базой (записи в
project_status_history,automation_runs,task_checklist_itemsи т. д.).
Готовность каждого этапа
- Бэкенд: миграции на локальной scratch-базе вверх и вниз, тесты сервисов и HTTP,
go vet,go test ./..., контракты перегенерированы,go test ./internal/contractcheck/...зелёный. - Фронт: типы, линтер, сборка, e2e на сценарий этапа, проверка в браузере на локальном стенде (Docker, шлюз 8088), телефонная ширина.
- Документация:
docs/concepts/(новые страницы:task-structure.md,project-stages-gantt.md,project-templates.md,workload.md,sales-funnel.md,automations.md), справка «Как сделать» для сотрудников,docs/rbac_matrix.md. - Коммиты в ветку
stagingлокально. Не пушим и не выкатываем, пока владелец не скажет.
11. Решения, которые нужно подтвердить
Ниже — что выбрано по умолчанию. Если ответ другой, ТЗ правится до начала соответствующего этапа.
- Подзадачи — один уровень. В Аспро глубже, но больше одного уровня на доске и в загрузке читается плохо.
- Связи — только «после окончания» с запасом в днях. Остальные три типа из Аспро не делаем.
- Соисполнитель в загрузке получает те же плановые часы, что и ответственный. Альтернатива — делить часы поровну.
- «Выездные» роли для отметки дней мероприятия: ведущий, инженер, техник, логист. Список можно расширить.
- Причина проигрыша обязательна. Источник заявки — нет.
- Источник — у проекта (каждой заявки), не у компании.
- Задачи из шаблона со сроком в прошлом переносятся на сегодня. Альтернатива — создавать просроченными.
- Смета в шаблоне не правится руками — только берётся из проекта.
- Автодействия «перешёл в статус» срабатывают один раз за жизнь проекта, если не отмечено «при каждом входе».
- Шаблоны создают руководители дивизионов и выше, а не каждый менеджер.
- Работа только локально: коммиты в
stagingбез пуша. Пушить в GitHub (без выката на сервер) можно? По умолчанию — нет.