2025-10-24 16:19:58 +03:00
|
|
|
|
"""
|
|
|
|
|
|
Claims API Routes - Обработка заявок
|
|
|
|
|
|
"""
|
|
|
|
|
|
from fastapi import APIRouter, HTTPException
|
2025-11-14 19:06:36 +03:00
|
|
|
|
from .models import (
|
|
|
|
|
|
ClaimCreateRequest,
|
|
|
|
|
|
ClaimResponse,
|
|
|
|
|
|
TicketFormDescriptionRequest,
|
|
|
|
|
|
)
|
2025-10-24 16:19:58 +03:00
|
|
|
|
import uuid
|
|
|
|
|
|
from datetime import datetime
|
2025-11-14 19:06:36 +03:00
|
|
|
|
import json
|
|
|
|
|
|
import logging
|
|
|
|
|
|
from ..services.redis_service import redis_service
|
|
|
|
|
|
from ..config import settings
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
|
|
|
|
|
router = APIRouter(prefix="/api/v1/claims", tags=["Claims"])
|
2025-11-14 19:06:36 +03:00
|
|
|
|
logger = logging.getLogger(__name__)
|
2025-10-24 16:19:58 +03:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.post("/create", response_model=ClaimResponse)
|
|
|
|
|
|
async def create_claim(claim: ClaimCreateRequest):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Создать новую заявку
|
|
|
|
|
|
|
|
|
|
|
|
Принимает данные формы и создает заявку в системе
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
# Генерируем ID и номер заявки
|
|
|
|
|
|
claim_id = str(uuid.uuid4())
|
|
|
|
|
|
claim_number = f"ERV-{datetime.now().strftime('%Y%m%d')}-{claim_id[:8].upper()}"
|
|
|
|
|
|
|
|
|
|
|
|
# TODO: Сохранить в PostgreSQL
|
|
|
|
|
|
# TODO: Отправить в очередь RabbitMQ для обработки
|
|
|
|
|
|
# TODO: Интеграция с CRM
|
|
|
|
|
|
|
|
|
|
|
|
return ClaimResponse(
|
|
|
|
|
|
success=True,
|
|
|
|
|
|
claim_id=claim_id,
|
|
|
|
|
|
claim_number=claim_number,
|
|
|
|
|
|
message=f"Заявка {claim_number} успешно создана"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
|
status_code=500,
|
|
|
|
|
|
detail=f"Ошибка при создании заявки: {str(e)}"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.get("/{claim_id}")
|
|
|
|
|
|
async def get_claim(claim_id: str):
|
|
|
|
|
|
"""Получить информацию о заявке по ID"""
|
|
|
|
|
|
# TODO: Получить из БД
|
|
|
|
|
|
return {
|
|
|
|
|
|
"claim_id": claim_id,
|
|
|
|
|
|
"status": "processing",
|
|
|
|
|
|
"message": "Заявка в обработке"
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-11-14 19:06:36 +03:00
|
|
|
|
|
|
|
|
|
|
@router.post("/description")
|
|
|
|
|
|
async def publish_ticket_form_description(payload: TicketFormDescriptionRequest):
|
|
|
|
|
|
"""
|
|
|
|
|
|
Публикует свободное описание проблемы в Redis канал ticket_form:description
|
|
|
|
|
|
(слушается воркфлоу в n8n)
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
channel = payload.channel or f"{settings.redis_prefix}description"
|
|
|
|
|
|
event = {
|
|
|
|
|
|
"type": "ticket_form_description",
|
|
|
|
|
|
"session_id": payload.session_id,
|
|
|
|
|
|
"claim_id": payload.claim_id,
|
|
|
|
|
|
"phone": payload.phone,
|
|
|
|
|
|
"email": payload.email,
|
|
|
|
|
|
"description": payload.problem_description.strip(),
|
|
|
|
|
|
"source": payload.source,
|
|
|
|
|
|
"timestamp": datetime.utcnow().isoformat(),
|
|
|
|
|
|
}
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
"📝 TicketForm description received",
|
|
|
|
|
|
extra={"session_id": payload.session_id, "claim_id": payload.claim_id},
|
|
|
|
|
|
)
|
|
|
|
|
|
await redis_service.publish(channel, json.dumps(event, ensure_ascii=False))
|
|
|
|
|
|
logger.info(
|
|
|
|
|
|
"📡 TicketForm description published",
|
|
|
|
|
|
extra={"channel": channel, "session_id": payload.session_id},
|
|
|
|
|
|
)
|
|
|
|
|
|
return {
|
|
|
|
|
|
"success": True,
|
|
|
|
|
|
"channel": channel,
|
|
|
|
|
|
"event": event,
|
|
|
|
|
|
}
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
logger.exception("❌ Failed to publish ticket form description")
|
|
|
|
|
|
raise HTTPException(
|
|
|
|
|
|
status_code=500,
|
|
|
|
|
|
detail=f"Не удалось опубликовать описание: {e}"
|
|
|
|
|
|
)
|
|
|
|
|
|
|