#Автоматизация задач
✅ Сложность: medium | Скоупы: task, crm | Стек: Node.js
#Что делаем
Создаём сервис, который следит за изменением стадий сделок в CRM и автоматически создаёт задачи при переходе сделки на определённый этап. Например, когда сделка переходит в стадию «В работе», создаётся задача для менеджера с описанием и дедлайном. Это устраняет человеческий фактор и стандартизирует бизнес-процессы.
#Необходимо
- API-ключ Вайбкод с правами
task, crm - Node.js 18+
#Полный код
// task-automation.js
// Автоматическое создание задач при смене стадии сделки
const API_KEY = process.env.VIBE_API_KEY;
const BASE_URL = process.env.VIBE_BASE_URL; // например https://vibecode.bitrix24.tech
const HEADERS = {
'X-Api-Key': API_KEY,
'Content-Type': 'application/json',
};
// Конфигурация: какие задачи создавать при переходе на стадию
const STAGE_TASKS = {
EXECUTING: {
title: 'Подготовить документы и начать исполнение',
description: 'Сделка перешла в работу. Необходимо подготовить все документы и начать исполнение обязательств.',
deadlineDays: 5,
priority: 2, // высокий
},
PREPAYMENT_INVOICE: {
title: 'Выставить счёт и проконтролировать оплату',
description: 'Необходимо выставить счёт на предоплату и отследить поступление средств.',
deadlineDays: 3,
priority: 2,
},
FINAL_INVOICE: {
title: 'Финальная сверка и закрытие',
description: 'Финальный этап сделки. Подготовить закрывающие документы.',
deadlineDays: 7,
priority: 1,
},
};
// Хранилище последних известных стадий сделок
const dealStages = new Map();
// Получаем активные сделки через Entity API
async function fetchActiveDeals() {
const response = await fetch(
`${BASE_URL}/v1/deals/search`,
{
method: 'POST',
headers: HEADERS,
body: JSON.stringify({
// Фильтруем незакрытые сделки (исключаем WON и LOSE стадии)
// Примечание: стадии с множественными воронками имеют C-префикс (C2:WON, C4:LOSE)
filter: {
'!stageId': 'WON',
},
select: ['id', 'title', 'stageId', 'assignedById'],
}),
}
);
const { data } = await response.json();
return data || [];
}
// Создаём задачу через Entity API
async function createTask(deal, taskConfig) {
const deadline = new Date();
deadline.setDate(deadline.getDate() + taskConfig.deadlineDays);
const response = await fetch(`${BASE_URL}/v1/tasks`, {
method: 'POST',
headers: HEADERS,
body: JSON.stringify({
title: `${taskConfig.title} — ${deal.title}`,
description: [
taskConfig.description,
'',
`Сделка: ${deal.title} (ID: ${deal.id})`,
].join('\n'),
responsibleId: deal.assignedById,
priority: taskConfig.priority,
deadline: deadline.toISOString(),
}),
});
const { data } = await response.json();
console.log(` 📝 Задача создана: #${data.id} — ${taskConfig.title}`);
return data.id;
}
// Основной цикл: проверка изменений стадий
async function checkStageChanges() {
const timestamp = new Date().toISOString();
console.log(`\n[${timestamp}] Проверяем изменения стадий...`);
const deals = await fetchActiveDeals();
for (const deal of deals) {
const dealId = deal.id;
const currentStage = deal.stageId;
const previousStage = dealStages.get(dealId);
// Обновляем известную стадию
dealStages.set(dealId, currentStage);
// Если стадия изменилась и для новой стадии есть конфигурация задачи
if (previousStage && previousStage !== currentStage) {
console.log(`\n🔄 Сделка #${dealId} "${deal.title}": ${previousStage} → ${currentStage}`);
const taskConfig = STAGE_TASKS[currentStage];
if (taskConfig) {
await createTask(deal, taskConfig);
} else {
console.log(` Для стадии ${currentStage} задача не настроена`);
}
}
}
// Очищаем закрытые сделки из хранилища
const activeIds = new Set(deals.map((d) => d.id));
for (const [id] of dealStages) {
if (!activeIds.has(id)) {
dealStages.delete(id);
}
}
}
// Запуск с интервалом
async function start() {
console.log('✅ Сервис автоматизации задач запущен');
console.log(` Отслеживаемые стадии: ${Object.keys(STAGE_TASKS).join(', ')}`);
// Первый запуск — заполняем начальное состояние
console.log('\nЗагружаем текущее состояние сделок...');
const deals = await fetchActiveDeals();
for (const deal of deals) {
dealStages.set(deal.id, deal.stageId);
}
console.log(`Загружено ${deals.length} активных сделок\n`);
// Запускаем проверку каждые 60 секунд
setInterval(checkStageChanges, 60_000);
}
start().catch(console.error);
#Как это работает
- При запуске сервис загружает все открытые сделки через Entity API (
POST /v1/deals/search) и запоминает их текущие стадии. - Каждые 60 секунд происходит повторный опрос сделок.
- Если у сделки изменилась стадия, сервис проверяет конфигурацию
STAGE_TASKS— определены ли задачи для новой стадии. - При совпадении создаётся задача через Entity API (
POST /v1/tasks) с заголовком, описанием и дедлайном. - Закрытые сделки автоматически удаляются из отслеживания для экономии памяти.
Примечание: Чек-листы задач пока создаются через интерфейс Битрикс24 или прямой REST API. Метод
task.checklistitem.addне имеет entity-обёртки в Вайбкод.
#Что можно улучшить
- Использовать webhooks вместо polling для мгновенной реакции на изменения
- Добавить конфигурацию через YAML/JSON файл, чтобы менеджеры могли настраивать правила без кода
- Реализовать дедупликацию: не создавать задачу, если аналогичная уже существует для этой сделки
- Добавить логирование в файл и уведомления об ошибках в Telegram/Slack