144 lines
5.3 KiB
Python
144 lines
5.3 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select, func, desc
|
|
from typing import Optional
|
|
import base64
|
|
import os
|
|
from app.database import get_db
|
|
from app.models.user import User
|
|
from app.models.document import Document
|
|
from app.schemas.document import ScanRequest, DocumentResponse, DocumentListResponse
|
|
from app.services.ai_service import analyze_document
|
|
from app.utils.security import get_current_user
|
|
from app.config import settings
|
|
|
|
router = APIRouter(prefix="/api/documents", tags=["documents"])
|
|
|
|
@router.post("/scan", response_model=DocumentResponse)
|
|
async def scan_document(
|
|
req: ScanRequest,
|
|
user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db)
|
|
):
|
|
# Check scan limit for free users
|
|
if user.plan == "free" and user.scan_count_today >= settings.FREE_SCAN_LIMIT:
|
|
raise HTTPException(status_code=429, detail="Limite de scans diários atingido. Faça upgrade para Premium.")
|
|
|
|
# Calculate file size
|
|
image_data = req.image
|
|
if "," in image_data:
|
|
image_data_clean = image_data.split(",", 1)[1]
|
|
else:
|
|
image_data_clean = image_data
|
|
file_size = len(base64.b64decode(image_data_clean))
|
|
|
|
# AI analysis
|
|
try:
|
|
result = await analyze_document(req.image)
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"Erro na análise IA: {str(e)}")
|
|
|
|
# Save document
|
|
doc = Document(
|
|
user_id=user.id,
|
|
title=result.get("title", "Documento sem título"),
|
|
category=result.get("category", "outro"),
|
|
original_image=req.image,
|
|
extracted_text=result.get("extracted_text", ""),
|
|
summary=result.get("summary", ""),
|
|
extracted_data=result.get("extracted_data", {}),
|
|
risk_alerts=result.get("risk_alerts", []),
|
|
tags=result.get("tags", []),
|
|
file_size=file_size
|
|
)
|
|
db.add(doc)
|
|
|
|
# Update scan count
|
|
user.scan_count_today += 1
|
|
await db.commit()
|
|
await db.refresh(doc)
|
|
|
|
return DocumentResponse(
|
|
id=doc.id, title=doc.title, category=doc.category,
|
|
extracted_text=doc.extracted_text, summary=doc.summary,
|
|
extracted_data=doc.extracted_data, risk_alerts=doc.risk_alerts,
|
|
tags=doc.tags, file_size=doc.file_size, created_at=doc.created_at
|
|
)
|
|
|
|
@router.get("/", response_model=DocumentListResponse)
|
|
async def list_documents(
|
|
search: Optional[str] = None,
|
|
category: Optional[str] = None,
|
|
page: int = Query(1, ge=1),
|
|
limit: int = Query(20, ge=1, le=100),
|
|
user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db)
|
|
):
|
|
query = select(Document).where(Document.user_id == user.id)
|
|
count_query = select(func.count(Document.id)).where(Document.user_id == user.id)
|
|
|
|
if category:
|
|
query = query.where(Document.category == category)
|
|
count_query = count_query.where(Document.category == category)
|
|
if search:
|
|
search_filter = Document.extracted_text.ilike(f"%{search}%")
|
|
query = query.where(search_filter)
|
|
count_query = count_query.where(search_filter)
|
|
|
|
total = (await db.execute(count_query)).scalar()
|
|
result = await db.execute(query.order_by(desc(Document.created_at)).offset((page-1)*limit).limit(limit))
|
|
docs = result.scalars().all()
|
|
|
|
return DocumentListResponse(
|
|
documents=[DocumentResponse(
|
|
id=d.id, title=d.title, category=d.category,
|
|
extracted_text=d.extracted_text, summary=d.summary,
|
|
extracted_data=d.extracted_data, risk_alerts=d.risk_alerts,
|
|
tags=d.tags, file_size=d.file_size, created_at=d.created_at
|
|
) for d in docs],
|
|
total=total
|
|
)
|
|
|
|
@router.get("/{doc_id}", response_model=DocumentResponse)
|
|
async def get_document(
|
|
doc_id: int,
|
|
user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db)
|
|
):
|
|
result = await db.execute(select(Document).where(Document.id == doc_id, Document.user_id == user.id))
|
|
doc = result.scalar_one_or_none()
|
|
if not doc:
|
|
raise HTTPException(status_code=404, detail="Documento não encontrado")
|
|
return DocumentResponse(
|
|
id=doc.id, title=doc.title, category=doc.category,
|
|
extracted_text=doc.extracted_text, summary=doc.summary,
|
|
extracted_data=doc.extracted_data, risk_alerts=doc.risk_alerts,
|
|
tags=doc.tags, file_size=doc.file_size, created_at=doc.created_at
|
|
)
|
|
|
|
@router.get("/{doc_id}/image")
|
|
async def get_document_image(
|
|
doc_id: int,
|
|
user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db)
|
|
):
|
|
result = await db.execute(select(Document).where(Document.id == doc_id, Document.user_id == user.id))
|
|
doc = result.scalar_one_or_none()
|
|
if not doc:
|
|
raise HTTPException(status_code=404, detail="Documento não encontrado")
|
|
return {"image": doc.original_image}
|
|
|
|
@router.delete("/{doc_id}")
|
|
async def delete_document(
|
|
doc_id: int,
|
|
user: User = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db)
|
|
):
|
|
result = await db.execute(select(Document).where(Document.id == doc_id, Document.user_id == user.id))
|
|
doc = result.scalar_one_or_none()
|
|
if not doc:
|
|
raise HTTPException(status_code=404, detail="Documento não encontrado")
|
|
await db.delete(doc)
|
|
await db.commit()
|
|
return {"message": "Documento excluído"}
|