AI и автоматизация

Клиент Задачи Счет Отчёт. Битрикс24 и n8n с cloude 4 на борту.

Клиент Задачи Счет Отчёт. Битрикс24 и n8n с cloude 4 на борту.

Архитектура решения

 Основной 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