feat: Добавлен эндпоинт для привязки документов к проекту/заявке

Изменения:
 Новый endpoint: POST /api/n8n/documents/attach
 Поддерживает привязку к Project или HelpDesk
 Логика: если указан ticket_id → HelpDesk, иначе → Project
 Полное логирование всех операций
 Интеграция с upload_documents_to_crm.php

Входные данные:
- contact_id (обязательно)
- project_id (обязательно)
- file_url (обязательно)
- file_name (обязательно)
- ticket_id (опционально, для привязки к заявке)
- file_type (опционально, описание документа)

Готово к интеграции в n8n workflow!
This commit is contained in:
AI Assistant
2025-11-02 19:05:53 +03:00
parent d3b7b3bb6a
commit 936cea62ae
3 changed files with 253 additions and 0 deletions

View File

@@ -245,3 +245,126 @@ async def proxy_create_claim(request: Request):
logger.error(f"❌ Error proxying to n8n: {e}")
raise HTTPException(status_code=500, detail=f"Ошибка создания заявки: {str(e)}")
@router.post("/documents/attach")
async def attach_document_to_crm(request: Request):
"""
Привязывает загруженный файл к проекту или заявке в vTiger CRM
Входные данные:
- contact_id: ID контакта
- project_id: ID проекта (обязательно)
- ticket_id: ID заявки (опционально, если указан - привязываем к заявке)
- file_url: URL файла в S3
- file_name: Имя файла
- file_type: Тип файла (описание, например: "flight_delay_boarding_or_ticket")
Логика:
- Если указан ticket_id → привязываем к HelpDesk (заявке)
- Иначе → привязываем к Project (проекту)
"""
CRM_UPLOAD_ENDPOINT = "https://crm.clientright.ru/upload_documents_to_crm.php"
try:
body = await request.json()
contact_id = body.get('contact_id')
project_id = body.get('project_id')
ticket_id = body.get('ticket_id') # Опционально
file_url = body.get('file_url')
file_name = body.get('file_name')
file_type = body.get('file_type', 'Документ')
# Валидация обязательных полей
if not all([contact_id, project_id, file_url, file_name]):
raise HTTPException(
status_code=400,
detail="Обязательные поля: contact_id, project_id, file_url, file_name"
)
logger.info(f"📎 Attaching document: {file_name} (type: {file_type})")
logger.info(f" Contact: {contact_id}, Project: {project_id}, Ticket: {ticket_id or 'N/A'}")
# Формируем payload для upload_documents_to_crm.php
upload_payload = {
"documents": [
{
"file_url": file_url,
"file_name": file_name,
"upload_description": file_type,
"contactid": int(contact_id),
"pages": 1
}
],
"projectid": int(project_id),
"ticket_id": int(ticket_id) if ticket_id else None, # Передаем ticket_id если есть
"user_id": 1
}
logger.info(f"📤 Sending to CRM: {upload_payload}")
# Отправляем запрос к CRM
async with httpx.AsyncClient(timeout=60.0) as client:
response = await client.post(
CRM_UPLOAD_ENDPOINT,
json=upload_payload,
headers={"Content-Type": "application/json"}
)
if response.status_code == 200:
response_text = response.text
logger.info(f"✅ Document attached successfully. Response: {response_text[:300]}")
try:
result = response.json()
# Проверяем успешность
if result.get('success') and result.get('results'):
first_result = result['results'][0]
if first_result.get('status') == 'success':
crm_result = first_result.get('crm_result', {})
return {
"success": True,
"result": {
"document_id": crm_result.get('document_id'),
"document_numeric_id": crm_result.get('document_numeric_id'),
"attached_to": "ticket" if ticket_id else "project",
"attached_to_id": ticket_id if ticket_id else project_id,
"file_name": file_name,
"file_type": file_type,
"s3_bucket": crm_result.get('s3_bucket'),
"s3_key": crm_result.get('s3_key'),
"file_size": crm_result.get('file_size'),
"message": crm_result.get('message')
}
}
else:
# Ошибка в CRM
error_msg = first_result.get('crm_result', {}).get('message', 'Unknown error')
logger.error(f"❌ CRM error: {error_msg}")
raise HTTPException(status_code=500, detail=f"CRM error: {error_msg}")
else:
logger.error(f"❌ Unexpected CRM response: {result}")
raise HTTPException(status_code=500, detail="Неожиданный ответ от CRM")
except Exception as e:
logger.error(f"❌ Failed to parse CRM response: {e}. Response: {response_text[:500]}")
raise HTTPException(status_code=500, detail=f"Ошибка парсинга ответа CRM: {str(e)}")
else:
logger.error(f"❌ CRM returned {response.status_code}: {response.text}")
raise HTTPException(
status_code=response.status_code,
detail=f"CRM error: {response.text}"
)
except httpx.TimeoutException:
logger.error("⏱️ CRM upload timeout")
raise HTTPException(status_code=504, detail="Таймаут загрузки в CRM")
except HTTPException:
raise # Пробрасываем HTTPException как есть
except Exception as e:
logger.error(f"❌ Error attaching document: {e}")
raise HTTPException(status_code=500, detail=f"Ошибка привязки документа: {str(e)}")