155 lines
5.8 KiB
Python
155 lines
5.8 KiB
Python
|
|
"""
|
|||
|
|
Upload API Routes - Загрузка файлов с OCR
|
|||
|
|
"""
|
|||
|
|
from fastapi import APIRouter, UploadFile, File, HTTPException
|
|||
|
|
from typing import List
|
|||
|
|
import httpx
|
|||
|
|
import uuid
|
|||
|
|
import os
|
|||
|
|
from ..config import settings
|
|||
|
|
import logging
|
|||
|
|
|
|||
|
|
router = APIRouter(prefix="/api/v1/upload", tags=["Upload"])
|
|||
|
|
logger = logging.getLogger(__name__)
|
|||
|
|
|
|||
|
|
UPLOAD_DIR = "/tmp/erv_uploads"
|
|||
|
|
os.makedirs(UPLOAD_DIR, exist_ok=True)
|
|||
|
|
|
|||
|
|
|
|||
|
|
@router.post("/policy")
|
|||
|
|
async def upload_policy(file: UploadFile = File(...)):
|
|||
|
|
"""
|
|||
|
|
Загрузить скан полиса + OCR обработка
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
- file_id: ID загруженного файла
|
|||
|
|
- ocr_text: распознанный текст
|
|||
|
|
- extracted_data: извлеченные данные (номер полиса, серия, даты)
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
# Генерируем уникальный ID
|
|||
|
|
file_id = str(uuid.uuid4())
|
|||
|
|
file_ext = file.filename.split('.')[-1] if '.' in file.filename else 'jpg'
|
|||
|
|
file_path = f"{UPLOAD_DIR}/{file_id}.{file_ext}"
|
|||
|
|
|
|||
|
|
# Сохраняем файл
|
|||
|
|
with open(file_path, "wb") as f:
|
|||
|
|
content = await file.read()
|
|||
|
|
f.write(content)
|
|||
|
|
|
|||
|
|
logger.info(f"📄 File saved: {file_path}")
|
|||
|
|
|
|||
|
|
# Отправляем на OCR
|
|||
|
|
try:
|
|||
|
|
async with httpx.AsyncClient(timeout=60.0) as client:
|
|||
|
|
with open(file_path, "rb") as f:
|
|||
|
|
files = {"file": (file.filename, f, file.content_type)}
|
|||
|
|
response = await client.post(
|
|||
|
|
f"{settings.ocr_api_url}/process",
|
|||
|
|
files=files
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if response.status_code == 200:
|
|||
|
|
ocr_result = response.json()
|
|||
|
|
logger.info(f"✅ OCR completed for policy")
|
|||
|
|
|
|||
|
|
# TODO: Извлечь номер полиса, серию, даты из OCR текста
|
|||
|
|
# Используем regex или AI для парсинга
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"success": True,
|
|||
|
|
"file_id": file_id,
|
|||
|
|
"ocr_text": ocr_result.get("text", ""),
|
|||
|
|
"extracted_data": {
|
|||
|
|
"policy_number": None, # TODO: парсинг
|
|||
|
|
"policy_series": None,
|
|||
|
|
"start_date": None,
|
|||
|
|
"end_date": None
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else:
|
|||
|
|
logger.error(f"OCR error: {response.status_code}")
|
|||
|
|
raise HTTPException(status_code=500, detail="OCR service error")
|
|||
|
|
|
|||
|
|
except Exception as ocr_error:
|
|||
|
|
logger.error(f"OCR processing error: {ocr_error}")
|
|||
|
|
# Возвращаем без OCR
|
|||
|
|
return {
|
|||
|
|
"success": True,
|
|||
|
|
"file_id": file_id,
|
|||
|
|
"ocr_text": "",
|
|||
|
|
"extracted_data": {},
|
|||
|
|
"message": "Файл загружен, но OCR не удалось выполнить"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"File upload error: {e}")
|
|||
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|||
|
|
|
|||
|
|
|
|||
|
|
@router.post("/passport")
|
|||
|
|
async def upload_passport(file: UploadFile = File(...)):
|
|||
|
|
"""
|
|||
|
|
Загрузить скан паспорта + OCR для ФИО
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
- file_id: ID загруженного файла
|
|||
|
|
- ocr_text: распознанный текст
|
|||
|
|
- extracted_data: ФИО, дата рождения, серия/номер
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
file_id = str(uuid.uuid4())
|
|||
|
|
file_ext = file.filename.split('.')[-1] if '.' in file.filename else 'jpg'
|
|||
|
|
file_path = f"{UPLOAD_DIR}/{file_id}.{file_ext}"
|
|||
|
|
|
|||
|
|
with open(file_path, "wb") as f:
|
|||
|
|
content = await file.read()
|
|||
|
|
f.write(content)
|
|||
|
|
|
|||
|
|
logger.info(f"📄 Passport saved: {file_path}")
|
|||
|
|
|
|||
|
|
# OCR обработка
|
|||
|
|
try:
|
|||
|
|
async with httpx.AsyncClient(timeout=60.0) as client:
|
|||
|
|
with open(file_path, "rb") as f:
|
|||
|
|
files = {"file": (file.filename, f, file.content_type)}
|
|||
|
|
response = await client.post(
|
|||
|
|
f"{settings.ocr_api_url}/process",
|
|||
|
|
files=files
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
if response.status_code == 200:
|
|||
|
|
ocr_result = response.json()
|
|||
|
|
logger.info(f"✅ OCR completed for passport")
|
|||
|
|
|
|||
|
|
# TODO: Извлечь ФИО через regex или AI
|
|||
|
|
|
|||
|
|
return {
|
|||
|
|
"success": True,
|
|||
|
|
"file_id": file_id,
|
|||
|
|
"ocr_text": ocr_result.get("text", ""),
|
|||
|
|
"extracted_data": {
|
|||
|
|
"full_name": None, # TODO: парсинг
|
|||
|
|
"birth_date": None,
|
|||
|
|
"passport_series": None,
|
|||
|
|
"passport_number": None
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else:
|
|||
|
|
raise HTTPException(status_code=500, detail="OCR service error")
|
|||
|
|
|
|||
|
|
except Exception as ocr_error:
|
|||
|
|
logger.error(f"OCR error: {ocr_error}")
|
|||
|
|
return {
|
|||
|
|
"success": True,
|
|||
|
|
"file_id": file_id,
|
|||
|
|
"ocr_text": "",
|
|||
|
|
"extracted_data": {},
|
|||
|
|
"message": "Файл загружен, но OCR не удалось"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
logger.error(f"Passport upload error: {e}")
|
|||
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|||
|
|
|