Архитектура решения
Основной workflow: Cron (1 число каждого месяца) → Bitrix24 (получить задачи) → Function (обработка данных) → Bitrix24 (закрыть старую сделку) → Bitrix24 (создать новую сделку) → Bitrix24 (добавить товар в сделку)
Детальная схема workflow
1. Триггер - Cron
0 0 1 * * (каждое 1 число месяца в 00:00)
2. Получение задач за прошлый месяц
Node: HTTP Request (Bitrix24 REST API)
javascript Скопировать
Закрыть блок
// Расчет дат для прошлого месяца
const now = new Date();
const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
const startDate = lastMonth.toISOString().split('T')[0];
const endDate = new Date(now.getFullYear(), now.getMonth(), 0).toISOString().split('T')[0];
// Запрос к API задач
GET /rest/tasks.task.list?
filter[CREATED_DATE][>=]=${startDate}&
filter[CREATED_DATE][<=]=${endDate}&
filter[UF_CRM_TASK][]=COMPANY_${companyId}
3. Обработка данных задач
Node: Function
javascript Скопировать
Закрыть блок
// Группировка задач по компаниям и подсчет времени
const companies = {};
for (const task of $input.all()) {
const taskData = task.json.result.tasks || [];
for (const taskItem of taskData) {
const companyId = taskItem.ufCrmTask?.[0]?.replace('COMPANY_', '');
const timeSpent = parseFloat(taskItem.timeSpentInLogs || 0);
if (!companies[companyId]) {
companies[companyId] = {
companyId: companyId,
totalHours: 0,
tasks: []
};
}
companies[companyId].totalHours += timeSpent;
companies[companyId].tasks.push({
id: taskItem.id,
title: taskItem.title,
timeSpent: timeSpent
});
}
}
return Object.values(companies).map(company => ({ json: company }));
4. Для каждой компании - закрытие старой сделки
Node: HTTP Request (Bitrix24)
javascript Скопировать
Закрыть блок
// Поиск активной сделки за прошлый месяц
GET /rest/crm.deal.list?
filter[COMPANY_ID]=${companyId}&
filter[STAGE_ID]=WORK& // статус "В работе"
filter[TITLE]=Работы за ${previousMonthName}
Node: HTTP Request (Bitrix24) - Закрытие сделки
javascript Скопировать
Закрыть блок
POST /rest/crm.deal.update?
id=${dealId}&
fields[STAGE_ID]=WON& // или нужный статус "Выполнено"
fields[CLOSEDATE]=${new Date().toISOString().split('T')[0]}
5. Создание новой сделки на текущий месяц
Node: HTTP Request (Bitrix24)
javascript Скопировать
Закрыть блок
POST /rest/crm.deal.add?
fields[TITLE]=Работы за ${currentMonthName}&
fields[COMPANY_ID]=${companyId}&
fields[STAGE_ID]=WORK&
fields[OPENED]=Y&
fields[BEGINDATE]=${new Date().toISOString().split('T')[0]}
6. Добавление товара “Работы за прошлый месяц” в старую сделку
Node: HTTP Request (Bitrix24)
javascript Скопировать
Закрыть блок
POST /rest/crm.deal.productrows.set?
id=${previousDealId}&
rows[0][PRODUCT_NAME]=Работы за ${previousMonthName}&
rows[0][QUANTITY]=${totalHours}&
rows[0][PRICE]=100& // цена за час
rows[0][MEASURE_CODE]=796& // код единицы измерения "час"
Полный код workflow для n8n
json Скопировать
Закрыть блок
{
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 0 1 * *"
}
]
}
},
"name": "Monthly Trigger",
"type": "n8n-nodes-base.cron",
"typeVersion": 1,
"position": [240, 300]
},
{
"parameters": {
"functionCode": "// Расчет дат\nconst now = new Date();\nconst lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);\nconst startDate = lastMonth.toISOString().split('T')[0];\nconst endDate = new Date(now.getFullYear(), now.getMonth(), 0).toISOString().split('T')[0];\n\nconst monthNames = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];\nconst previousMonthName = monthNames[lastMonth.getMonth()];\nconst currentMonthName = monthNames[now.getMonth()];\n\nreturn [{\n json: {\n startDate,\n endDate,\n previousMonthName,\n currentMonthName,\n webhook_url: 'https://your-bitrix24.bitrix24.ru/rest/USER_ID/WEBHOOK_CODE'\n }\n}];"
},
"name": "Prepare Dates",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [440, 300]
},
{
"parameters": {
"url": "={{$json.webhook_url}}/tasks.task.list",
"options": {
"qs": {
"filter[CREATED_DATE][>=]": "={{$json.startDate}}",
"filter[CREATED_DATE][<=]": "={{$json.endDate}}",
"select[]": ["ID", "TITLE", "TIME_SPENT_IN_LOGS", "UF_CRM_TASK"]
}
}
},
"name": "Get Tasks",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [640, 300]
},
{
"parameters": {
"functionCode": "// Группировка задач по компаниям\nconst companies = {};\nconst tasks = $json.result.tasks || [];\nconst dates = $('Prepare Dates').first().json;\n\nfor (const task of tasks) {\n if (!task.ufCrmTask || !task.ufCrmTask[0]) continue;\n \n const companyId = task.ufCrmTask[0].replace('COMPANY_', '');\n const timeSpent = parseFloat(task.timeSpentInLogs || 0);\n \n if (!companies[companyId]) {\n companies[companyId] = {\n companyId: companyId,\n totalHours: 0,\n tasks: [],\n ...dates\n };\n }\n \n companies[companyId].totalHours += timeSpent;\n companies[companyId].tasks.push({\n id: task.id,\n title: task.title,\n timeSpent: timeSpent\n });\n}\n\nreturn Object.values(companies).map(company => ({ json: company }));"
},
"name": "Process Tasks",
"type": "n8n-nodes-base.function",
"typeVersion": 1,
"position": [840, 300]
},
{
"parameters": {
"url": "={{$json.webhook_url}}/crm.deal.list",
"options": {
"qs": {
"filter[COMPANY_ID]": "={{$json.companyId}}",
"filter[TITLE]": "Работы за {{$json.previousMonthName}}",
"select[]": ["ID", "TITLE", "STAGE_ID"]
}
}
},
"name": "Find Previous Deal",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [1040, 300]
},
{
"parameters": {
"url": "={{$json.webhook_url}}/crm.deal.productrows.set",
"options": {
"qs": {
"id": "={{$json.previousDealId}}",
"rows[0][PRODUCT_NAME]": "Работы за {{$json.previousMonthName}}",
"rows[0][QUANTITY]": "={{$json.totalHours}}",
"rows[0][PRICE]": "100",
"rows[0][MEASURE_CODE]": "796"
}
}
},
"name": "Add Product to Previous Deal",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [1240, 200]
},
{
"parameters": {
"url": "={{$json.webhook_url}}/crm.deal.update",
"options": {
"qs": {
"id": "={{$json.previousDealId}}",
"fields[STAGE_ID]": "WON",
"fields[CLOSEDATE]": "={{new Date().toISOString().split('T')[0]}}"
}
}
},
"name": "Close Previous Deal",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [1240, 300]
},
{
"parameters": {
"url": "={{$json.webhook_url}}/crm.deal.add",
"options": {
"qs": {
"fields[TITLE]": "Работы за {{$json.currentMonthName}}",
"fields[COMPANY_ID]": "={{$json.companyId}}",
"fields[STAGE_ID]": "WORK",
"fields[OPENED]": "Y",
"fields[BEGINDATE]": "={{new Date().toISOString().split('T')[0]}}"
}
}
},
"name": "Create New Deal",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [1240, 400]
}
],
"connections": {
"Monthly Trigger": {
"main": [
[
{
"node": "Prepare Dates",
"type": "main",
"index": 0
}
]
]
},
"Prepare Dates": {
"main": [
[
{
"node": "Get Tasks",
"type": "main",
"index": 0
}
]
]
},
"Get Tasks": {
"main": [
[
{
"node": "Process Tasks",
"type": "main",
"index": 0
}
]
]
},
"Process Tasks": {
"main": [
[
{
"node": "Find Previous Deal",
"type": "main",
"index": 0
}
]
]
},
"Find Previous Deal": {
"main": [
[
{
"node": "Add Product to Previous Deal",
"type": "main",
"index": 0
},
{
"node": "Close Previous Deal",
"type": "main",
"index": 0
},
{
"node": "Create New Deal",
"type": "main",
"index": 0
}
]
]
}
}
}
Настройка
- Webhook Битрикс24: Получите URL вида `https://your-bitrix24.bitrix24.ru/rest/USER_ID/WEBHOOK_CODE`
- Права доступа: Убедитесь, что webhook имеет права на:
<li>tasks (чтение задач)
- crm (работа со сделками)
- crm.product.* (работа с товарами в сделках)
- Единицы измерения: Код 796 = "час", при необходимости замените на нужный
- Статусы сделок: Замените "WORK" и "WON" на актуальные ID статусов в вашем Битрикс24
Дополнительные возможности
- Добавьте уведомления в Telegram/Slack о завершении процесса
- Логирование в Google Sheets для аналитики
- Обработка ошибок и повторные попытки
- Детализированный отчет по задачам в письме менеджеру
Этот workflow автоматизирует весь процесс создания ежемесячных сделок с точным учетом времени выполнения задач.
Давайте установим n8n на CentOS 9 пошагово:
- Сначала установим Node.js:bash Скопировать
Закрыть блок
# Установка NodeSource репозитория
curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -ка Node.js
sudo dnf install -y nodejs
Проверка версии
node --version npm --version
2. Установка необходимых зависимостей:
```bash
sudo dnf install gcc-c++ make
- Установка n8n:bash Скопировать
Закрыть блок
# Глобальная установка n8n
sudo npm install n8n -g
Проверка установки
n8n --version
4. Создание рабочей директории:
```bash
sudo mkdir -p /opt/n8n
cd /opt/n8n
# Создаем .env файл
sudo nano .env
Содержимое .env:
env Скопировать
Закрыть блок
BITRIX_WEBHOOK_URL=https://your-domain.bitrix24.ru/rest/1/your-webhook-code
N8N_BASIC_AUTH_ACTIVE=true
N8N_BASIC_AUTH_USER=admin
N8N_BASIC_AUTH_PASSWORD=YourSecurePassword
N8N_HOST=localhost
N8N_PORT=5678
N8N_PROTOCOL=http
NODE_ENV=production
- Создание systemd сервиса:bash Скопировать
Закрыть блок
sudo nano /etc/systemd/system/n8n.service
Содержимое n8n.service:
ini Скопировать
Закрыть блок
[Unit]
Description=n8n
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/n8n
EnvironmentFile=/opt/n8n/.env
ExecStart=/usr/bin/n8n start
Restart=always
KillMode=process
[Install]
WantedBy=multi-user.target
- Запуск сервиса:bash Скопировать
Закрыть блок
# Перезагрузка демона systemd
sudo systemctl daemon-reload
Включение автозапуска
sudo systemctl enable n8n
Запуск сервиса
sudo systemctl start n8n
Проверка статуса
sudo systemctl status n8n
7. Настройка firewall:
```bash
# Открываем порт 5678
sudo firewall-cmd --permanent --add-port=5678/tcp
sudo firewall-cmd --reload
- Проверка доступности:bash Скопировать
Закрыть блок
# Проверяем что сервис слушает порт
sudo ss -tulpn | grep 5678
Теперь n8n должен быть доступен по адресу:
http://your-server-ip:5678
При первом входе используйте учетные данные, которые вы указали в .env файле:
- Username: admin
- Password: YourSecurePassword
Для безопасности рекомендуется настроить Nginx как reverse proxy с SSL:
- Установка и настройка Nginx:bash Скопировать
Закрыть блок
# Установка Nginx
sudo dnf install nginx
Создание конфига
sudo nano /etc/nginx/conf.d/n8n.conf
Конфигурация Nginx:
```nginx
server {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:5678;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
}
}
bash Скопировать
Закрыть блок
# Проверка конфигурации
sudo nginx -t
# Перезапуск Nginx
sudo systemctl restart nginx
- Установка SSL (опционально):bash Скопировать
Закрыть блок
# Установка certbot
sudo dnf install certbot python3-certbot-nginx
Получение SSL сертификата
sudo certbot --nginx -d your-domain.com
После установки проверьте что всё работает:
```bash
# Проверка логов n8n
sudo journalctl -u n8n -f
# Проверка статуса
sudo systemctl status n8n
Продолжим с настройкой workflow для работы с Битрикс24.
asdasdasdasd