Изменения в /api/n8n/documents/attach: ✅ Принимает массив документов (не одиночный объект) ✅ Умная обработка S3 путей: - /bucket/path → https://s3.twcstorage.ru/bucket/path - bucket/path → https://s3.twcstorage.ru/bucket/path - https://... → без изменений ✅ Поддержка обоих форматов полей: - file / file_url - filename / file_name ✅ Batch-обработка с детальной статистикой ✅ Возвращает результаты для каждого документа отдельно ✅ Логирование успешных и неуспешных операций Формат ответа: { total_processed: N, successful: M, failed: K, results: [...], errors: [...] } Тесты: - TEST_REAL_DATA.sh - тест с реальными данными из n8n - TEST_QUICK.sh - быстрые тесты Документация обновлена с примерами batch-обработки
9.9 KiB
9.9 KiB
📎 API для привязки документов к проекту/заявке
✅ Готово к использованию!
🎯 Эндпоинт
POST https://crm.clientright.ru/api/n8n/documents/attach
📋 Формат входных данных
Тип: JSON массив документов
[
{
"claim_id": "CLM-2025-11-02-WNRZZZ",
"event_type": "delay_flight",
"contact_id": "320096",
"project_id": "396868",
"ticket_id": "396936",
"filename": "boarding_pass.pdf",
"file_type": "flight_delay_boarding_or_ticket",
"file": "/bucket/path/to/file.pdf"
}
]
Поля документа:
| Параметр | Тип | Обязательно | Описание | Пример |
|---|---|---|---|---|
contact_id |
string | ✅ Да | ID контакта в vTiger | "320096" |
project_id |
string | ✅ Да | ID проекта (полиса) в vTiger | "396874" |
file или file_url |
string | ✅ Да | Путь к файлу в S3 (с/без хоста) | "/bucket/path/file.pdf" |
filename или file_name |
string | ✅ Да | Имя файла | "boarding_pass.pdf" |
ticket_id |
string | ⚠️ Опц. | ID заявки Если указан → HelpDesk Если НЕ указан → Project |
"396935" |
file_type |
string | ⚠️ Опц. | Тип документа | "flight_delay_boarding_or_ticket" |
claim_id |
string | ⚠️ Опц. | ID заявки (для логирования) | "CLM-2025-11-02-..." |
event_type |
string | ⚠️ Опц. | Тип события (для логирования) | "delay_flight" |
🔧 Умная обработка путей:
Эндпоинт автоматически определяет формат пути и добавляет хост S3 если нужно:
| Входной формат | Обработка | Результат |
|---|---|---|
/bucket/path/file.pdf |
➕ Добавляем хост | https://s3.twcstorage.ru/bucket/path/file.pdf |
bucket/path/file.pdf |
➕ Добавляем / и хост |
https://s3.twcstorage.ru/bucket/path/file.pdf |
https://s3.twcstorage.ru/... |
✅ Уже полный URL | https://s3.twcstorage.ru/... |
🔧 Логика работы
┌─────────────────────────────────────────────┐
│ POST /api/n8n/documents/attach │
└─────────────────┬───────────────────────────┘
│
▼
┌────────────────┐
│ ticket_id есть?│
└────────┬───────┘
│
┌─────────┴─────────┐
│ │
ДА НЕТ
│ │
▼ ▼
┌───────────────┐ ┌──────────────┐
│ Привязка к │ │ Привязка к │
│ HelpDesk │ │ Project │
│ (заявке) │ │ (проекту) │
└───────────────┘ └──────────────┘
📤 Примеры запросов
1️⃣ Один документ к заявке (реальный пример)
curl -X POST "https://crm.clientright.ru/api/n8n/documents/attach" \
-H "Content-Type: application/json" \
-d '[
{
"claim_id": "CLM-2025-11-02-WNRZZZ",
"event_type": "delay_flight",
"contact_id": "320096",
"project_id": "396868",
"ticket_id": "396936",
"filename": "flight_delay_boarding_or_ticket.pdf",
"file_type": "flight_delay_boarding_or_ticket",
"file": "/f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c/crm2/CRM_Active_Files/Documents/HelpDesk/ЗАЯВКА_827_396936/flight_delay_boarding_or_ticket.pdf"
}
]'
Ответ:
{
"success": true,
"total_processed": 1,
"successful": 1,
"failed": 0,
"results": [
{
"document_id": "15x396941",
"document_numeric_id": "396941",
"attached_to": "ticket",
"attached_to_id": "396936",
"file_name": "flight_delay_boarding_or_ticket.pdf",
"file_type": "flight_delay_boarding_or_ticket",
"s3_bucket": "f9825c87-4e3558f6-f9b6-405c-ad3d-d1535c49b61c",
"s3_key": "crm2/CRM_Active_Files/Documents/HelpDesk/ЗАЯВКА_827_396936/flight_delay_boarding_or_ticket.pdf",
"file_size": 85320,
"message": "Документ создан с правильными S3 метаданными и привязан к проекту"
}
],
"errors": null
}
2️⃣ Несколько документов за раз (batch)
curl -X POST "https://crm.clientright.ru/api/n8n/documents/attach" \
-H "Content-Type: application/json" \
-d '[
{
"contact_id": "320096",
"project_id": "396868",
"ticket_id": "396936",
"filename": "boarding_pass.pdf",
"file_type": "flight_delay_boarding_or_ticket",
"file": "/bucket/path/boarding_pass.pdf"
},
{
"contact_id": "320096",
"project_id": "396868",
"ticket_id": "396936",
"filename": "delay_confirmation.pdf",
"file_type": "flight_delay_confirmation",
"file": "/bucket/path/delay_confirmation.pdf"
}
]'
Ответ:
{
"success": true,
"total_processed": 2,
"successful": 2,
"failed": 0,
"results": [
{
"document_id": "15x396941",
"attached_to": "ticket",
"file_name": "boarding_pass.pdf",
"...": "..."
},
{
"document_id": "15x396942",
"attached_to": "ticket",
"file_name": "delay_confirmation.pdf",
"...": "..."
}
],
"errors": null
}
3️⃣ Привязка к проекту (без ticket_id)
curl -X POST "https://crm.clientright.ru/api/n8n/documents/attach" \
-H "Content-Type: application/json" \
-d '[
{
"contact_id": "320096",
"project_id": "396874",
"filename": "policy_scan.pdf",
"file_type": "Скан полиса ERV",
"file": "https://s3.twcstorage.ru/bucket/path/policy.pdf"
}
]'
Ответ:
{
"success": true,
"total_processed": 1,
"successful": 1,
"failed": 0,
"results": [
{
"document_id": "15x396940",
"attached_to": "project",
"attached_to_id": "396874",
"file_name": "policy_scan.pdf",
"...": "..."
}
],
"errors": null
}
🗂️ Типы файлов (file_type)
Примеры значений для file_type:
| Тип | Описание |
|---|---|
flight_delay_boarding_or_ticket |
Посадочный талон / билет при задержке рейса |
flight_delay_confirmation |
Подтверждение задержки рейса |
flight_cancel_confirmation |
Подтверждение отмены рейса |
medical_receipt |
Медицинский чек |
medical_report |
Медицинское заключение |
luggage_delay_report |
Акт о задержке багажа |
passport_scan |
Скан паспорта |
policy_scan |
Скан страхового полиса |
other |
Прочие документы |
📊 Интеграция с n8n
В workflow после загрузки файла в S3:
// HTTP Request Node: POST /api/n8n/documents/attach
{
"contact_id": "{{ $json.contact_id }}",
"project_id": "{{ $json.project_id }}",
"ticket_id": "{{ $json.ticket_id }}", // Опционально
"file_url": "{{ $json.s3_url }}",
"file_name": "{{ $json.original_filename }}",
"file_type": "{{ $json.document_type }}"
}
Ответ сохранить в Redis:
// Добавить в session:
{
...session_data,
documents: [
...session_data.documents,
{
document_id: $json.result.document_id,
file_name: $json.result.file_name,
file_type: $json.result.file_type,
attached_to: $json.result.attached_to,
uploaded_at: new Date().toISOString()
}
]
}
🔍 Логи
Backend (FastAPI):
cd /var/www/fastuser/data/www/crm.clientright.ru/erv_platform
docker-compose logs -f backend | grep "Attaching document"
Пример вывода:
📎 Attaching document: boarding_pass.pdf (type: flight_delay_boarding_or_ticket)
Contact: 320096, Project: 396874, Ticket: 396935
📤 Sending to CRM: {...}
✅ Document attached successfully. Response: {...}
CRM (PHP):
tail -f /var/www/fastuser/data/www/crm.clientright.ru/logs/upload_documents.log
Пример вывода:
[2025-11-02 16:30:15] 🚀 Начинаем создание документов...
[2025-11-02 16:30:15] 📄 Обрабатываем файл #0: boarding_pass.pdf
[2025-11-02 16:30:16] ✅ Документ создан: 15x396941 (numeric: 396941)
[2025-11-02 16:30:16] 📎 Привязываем к HelpDesk ticket_id: 396935
[2025-11-02 16:30:17] ✅ Документ привязан к HelpDesk #396935
⚠️ Обработка ошибок
400 Bad Request - Отсутствуют обязательные поля
{
"detail": "Обязательные поля: contact_id, project_id, file_url, file_name"
}
500 Internal Server Error - Ошибка CRM
{
"detail": "CRM error: Не найден Project ID 999999"
}
504 Gateway Timeout - Таймаут CRM
{
"detail": "Таймаут загрузки в CRM"
}
✅ Готово к использованию!
Эндпоинт протестирован и готов к интеграции в n8n workflow! 🚀