feat: Add detailed logging for description endpoint and n8n workflow docs
Added:
- Detailed logging for /api/v1/claims/description endpoint
- Full event data logging for debugging
- Documentation for n8n workflow setup (N8N_DESCRIPTION_WORKFLOW.md)
The issue: Form hangs on recommendations step because n8n doesn't process description events.
Flow:
1. Frontend sends description to /api/v1/claims/description
2. Backend publishes to Redis channel ticket_form:description
3. Frontend subscribes to SSE /api/v1/events/{session_id} (listens to ocr_events:{session_id})
4. n8n must:
- Subscribe to ticket_form:description channel
- Process description and generate wizard_plan
- Publish wizard_plan back to ocr_events:{session_id} channel
Files:
- backend/app/api/claims.py (enhanced logging)
- docs/N8N_DESCRIPTION_WORKFLOW.md (new documentation)
This commit is contained in:
@@ -692,14 +692,49 @@ async def publish_ticket_form_description(payload: TicketFormDescriptionRequest)
|
||||
"source": payload.source,
|
||||
"timestamp": datetime.utcnow().isoformat(),
|
||||
}
|
||||
|
||||
event_json = json.dumps(event, ensure_ascii=False)
|
||||
|
||||
logger.info(
|
||||
"📝 TicketForm description received",
|
||||
extra={"session_id": payload.session_id, "claim_id": payload.claim_id or "not_set"},
|
||||
extra={
|
||||
"session_id": payload.session_id,
|
||||
"claim_id": payload.claim_id or "not_set",
|
||||
"phone": payload.phone,
|
||||
"description_length": len(payload.problem_description),
|
||||
"channel": channel,
|
||||
},
|
||||
)
|
||||
await redis_service.publish(channel, json.dumps(event, ensure_ascii=False))
|
||||
|
||||
logger.info(
|
||||
"📡 TicketForm description published",
|
||||
extra={"channel": channel, "session_id": payload.session_id},
|
||||
"📡 Publishing to Redis channel",
|
||||
extra={
|
||||
"channel": channel,
|
||||
"event_type": event["type"],
|
||||
"event_keys": list(event.keys()),
|
||||
"json_length": len(event_json),
|
||||
},
|
||||
)
|
||||
|
||||
await redis_service.publish(channel, event_json)
|
||||
|
||||
logger.info(
|
||||
"✅ TicketForm description published to Redis",
|
||||
extra={
|
||||
"channel": channel,
|
||||
"session_id": payload.session_id,
|
||||
"subscribers_notified": True,
|
||||
"event_json_preview": event_json[:500],
|
||||
},
|
||||
)
|
||||
|
||||
# Дополнительная проверка: логируем полный event для отладки
|
||||
logger.debug(
|
||||
"🔍 Full event data published",
|
||||
extra={
|
||||
"channel": channel,
|
||||
"event": event,
|
||||
},
|
||||
)
|
||||
return {
|
||||
"success": True,
|
||||
|
||||
150
docs/N8N_DESCRIPTION_WORKFLOW.md
Normal file
150
docs/N8N_DESCRIPTION_WORKFLOW.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# Настройка n8n Workflow для обработки описания проблемы
|
||||
|
||||
## Проблема
|
||||
|
||||
После отправки описания проблемы форма "тупит" на шаге рекомендаций. Это происходит потому, что n8n не обрабатывает событие из Redis канала.
|
||||
|
||||
## Текущий поток данных
|
||||
|
||||
1. **Frontend** отправляет описание на `/api/v1/claims/description`
|
||||
2. **Backend** публикует событие в Redis канал `ticket_form:description`
|
||||
3. **Frontend** подписывается на SSE `/api/v1/events/{session_id}` (слушает канал `ocr_events:{session_id}`)
|
||||
4. **n8n** должен:
|
||||
- Подписаться на канал `ticket_form:description` (или получить событие из него)
|
||||
- Обработать описание и сгенерировать `wizard_plan`
|
||||
- Опубликовать `wizard_plan` в канал `ocr_events:{session_id}` через POST `/api/v1/events/{session_id}`
|
||||
|
||||
## Структура события в Redis канале `ticket_form:description`
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "ticket_form_description",
|
||||
"session_id": "sess_xxx",
|
||||
"claim_id": "claim_id_xxx" или null,
|
||||
"phone": "79262306381",
|
||||
"email": "user@example.com",
|
||||
"description": "Описание проблемы...",
|
||||
"source": "ticket_form",
|
||||
"timestamp": "2025-11-25T12:30:36.262855"
|
||||
}
|
||||
```
|
||||
|
||||
## Настройка n8n Workflow
|
||||
|
||||
### Шаг 1: Redis Subscribe Node
|
||||
|
||||
1. Добавьте **Redis Subscribe** node
|
||||
2. Настройте подключение к Redis:
|
||||
- Host: `crm.clientright.ru` (или IP вашего Redis)
|
||||
- Port: `6379`
|
||||
- Password: `CRM_Redis_Pass_2025_Secure!`
|
||||
3. Channel: `ticket_form:description`
|
||||
4. Output: `JSON`
|
||||
|
||||
### Шаг 2: Обработка описания
|
||||
|
||||
После получения события из Redis:
|
||||
|
||||
1. Извлеките `session_id` из события: `{{ $json.session_id }}`
|
||||
2. Извлеките `description` из события: `{{ $json.description }}`
|
||||
3. Обработайте описание (AI, RAG и т.д.)
|
||||
4. Сгенерируйте `wizard_plan`
|
||||
|
||||
### Шаг 3: Сохранение wizard_plan в PostgreSQL
|
||||
|
||||
Сохраните `wizard_plan` в таблицу `clpr_claims` используя SQL скрипт (например, `SQL_CLAIMSAVE_UPSERT_SIMPLE.sql`).
|
||||
|
||||
### Шаг 4: Публикация wizard_plan обратно в Redis
|
||||
|
||||
**ВАЖНО:** После генерации `wizard_plan` нужно опубликовать событие обратно в Redis канал `ocr_events:{session_id}`.
|
||||
|
||||
Используйте **HTTP Request** node:
|
||||
|
||||
- **Method:** POST
|
||||
- **URL:** `http://147.45.146.17:8200/api/v1/events/{{ $json.session_id }}`
|
||||
- **Headers:**
|
||||
```json
|
||||
{
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
```
|
||||
- **Body (JSON):**
|
||||
```json
|
||||
{
|
||||
"event_type": "wizard_ready",
|
||||
"status": "ready",
|
||||
"message": "Wizard plan готов",
|
||||
"data": {
|
||||
"claim_id": "{{ $json.claim_id }}",
|
||||
"wizard_plan": {{ $json.wizard_plan }},
|
||||
"answers_prefill": {{ $json.answers_prefill }},
|
||||
"coverage_report": {{ $json.coverage_report }}
|
||||
},
|
||||
"timestamp": "{{ $now.toISO() }}"
|
||||
}
|
||||
```
|
||||
|
||||
**Альтернатива:** Используйте **Redis Publish** node напрямую:
|
||||
|
||||
- Channel: `ocr_events:{{ $json.session_id }}`
|
||||
- Message (JSON):
|
||||
```json
|
||||
{
|
||||
"event_type": "wizard_ready",
|
||||
"status": "ready",
|
||||
"message": "Wizard plan готов",
|
||||
"data": {
|
||||
"claim_id": "{{ $json.claim_id }}",
|
||||
"wizard_plan": {{ $json.wizard_plan }},
|
||||
"answers_prefill": {{ $json.answers_prefill }},
|
||||
"coverage_report": {{ $json.coverage_report }}
|
||||
},
|
||||
"timestamp": "{{ $now.toISO() }}"
|
||||
}
|
||||
```
|
||||
|
||||
## Проверка работы
|
||||
|
||||
1. Откройте консоль браузера (F12)
|
||||
2. Отправьте описание проблемы
|
||||
3. Проверьте логи backend:
|
||||
```bash
|
||||
docker-compose logs -f ticket_form_backend | grep -E "📝|📡|description"
|
||||
```
|
||||
4. Проверьте, что событие опубликовано в Redis:
|
||||
```bash
|
||||
redis-cli -h crm.clientright.ru -p 6379 -a "CRM_Redis_Pass_2025_Secure!" PUBSUB CHANNELS "ticket_form:*"
|
||||
```
|
||||
5. Проверьте, что n8n получил событие (в логах n8n workflow)
|
||||
6. Проверьте, что n8n опубликовал `wizard_plan` обратно в канал `ocr_events:{session_id}`
|
||||
|
||||
## Типичные проблемы
|
||||
|
||||
### Проблема 1: n8n не получает события из Redis
|
||||
|
||||
**Решение:** Проверьте, что Redis Subscribe node правильно настроен и подключен к правильному каналу `ticket_form:description`.
|
||||
|
||||
### Проблема 2: Frontend не получает wizard_plan
|
||||
|
||||
**Решение:** Проверьте, что n8n публикует событие в правильный канал `ocr_events:{session_id}` (не `ocr_events:session_id`, а `ocr_events:{session_id}` где `{session_id}` - это значение из события).
|
||||
|
||||
### Проблема 3: Неправильный формат события
|
||||
|
||||
**Решение:** Убедитесь, что событие содержит поле `event_type: "wizard_ready"` и `status: "ready"`. Backend ожидает этот формат.
|
||||
|
||||
## Пример полного workflow в n8n
|
||||
|
||||
```
|
||||
Redis Subscribe (ticket_form:description)
|
||||
↓
|
||||
Code Node (обработка описания)
|
||||
↓
|
||||
AI/RAG Node (генерация wizard_plan)
|
||||
↓
|
||||
PostgreSQL Node (сохранение wizard_plan)
|
||||
↓
|
||||
HTTP Request Node (POST /api/v1/events/{session_id})
|
||||
или
|
||||
Redis Publish Node (ocr_events:{session_id})
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user