2025-12-24 03:14:37 +03:00

138 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
API роутеры для работы с документами
"""
from uuid import UUID
from fastapi import APIRouter, status, UploadFile, File, Depends, Request
from fastapi.responses import JSONResponse
from typing import List, Annotated
from dishka.integrations.fastapi import FromDishka, inject
from src.domain.repositories.user_repository import IUserRepository
from src.presentation.middleware.auth_middleware import get_current_user
from src.presentation.schemas.document_schemas import (
DocumentCreate,
DocumentUpdate,
DocumentResponse
)
from src.application.use_cases.document_use_cases import DocumentUseCases
from src.domain.entities.user import User
router = APIRouter(prefix="/documents", tags=["documents"])
@router.post("", response_model=DocumentResponse, status_code=status.HTTP_201_CREATED)
@inject
async def create_document(
document_data: DocumentCreate,
request: Request,
user_repo: Annotated[IUserRepository, FromDishka()],
use_cases: Annotated[DocumentUseCases, FromDishka()]
):
"""Создать документ"""
current_user = await get_current_user(request, user_repo)
document = await use_cases.create_document(
collection_id=document_data.collection_id,
title=document_data.title,
content=document_data.content,
metadata=document_data.metadata
)
return DocumentResponse.from_entity(document)
@router.post("/upload", response_model=DocumentResponse, status_code=status.HTTP_201_CREATED)
@inject
async def upload_document(
collection_id: UUID,
request: Request,
user_repo: Annotated[IUserRepository, FromDishka()],
use_cases: Annotated[DocumentUseCases, FromDishka()],
file: UploadFile = File(...)
):
"""Загрузить и распарсить PDF документ или изображение"""
current_user = await get_current_user(request, user_repo)
if not file.filename:
raise JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"detail": "Имя файла не указано"}
)
supported_formats = ['.pdf', '.png', '.jpg', '.jpeg', '.tiff', '.bmp']
file_ext = file.filename.lower().rsplit('.', 1)[-1] if '.' in file.filename else ''
if f'.{file_ext}' not in supported_formats:
raise JSONResponse(
status_code=status.HTTP_400_BAD_REQUEST,
content={"detail": f"Неподдерживаемый формат файла. Поддерживаются: {', '.join(supported_formats)}"}
)
document = await use_cases.upload_and_parse_document(
collection_id=collection_id,
file=file.file,
filename=file.filename,
user_id=current_user.user_id
)
return DocumentResponse.from_entity(document)
@router.get("/{document_id}", response_model=DocumentResponse)
@inject
async def get_document(
document_id: UUID,
use_cases: Annotated[DocumentUseCases, FromDishka()]
):
"""Получить документ по ID"""
document = await use_cases.get_document(document_id)
return DocumentResponse.from_entity(document)
@router.put("/{document_id}", response_model=DocumentResponse)
@inject
async def update_document(
document_id: UUID,
document_data: DocumentUpdate,
request: Request,
user_repo: Annotated[IUserRepository, FromDishka()],
use_cases: Annotated[DocumentUseCases, FromDishka()]
):
"""Обновить документ"""
current_user = await get_current_user(request, user_repo)
document = await use_cases.update_document(
document_id=document_id,
user_id=current_user.user_id,
title=document_data.title,
content=document_data.content,
metadata=document_data.metadata
)
return DocumentResponse.from_entity(document)
@router.delete("/{document_id}", status_code=status.HTTP_204_NO_CONTENT)
@inject
async def delete_document(
document_id: UUID,
request: Request,
user_repo: Annotated[IUserRepository, FromDishka()],
use_cases: Annotated[DocumentUseCases, FromDishka()]
):
"""Удалить документ"""
current_user = await get_current_user(request, user_repo)
await use_cases.delete_document(document_id, current_user.user_id)
return JSONResponse(status_code=status.HTTP_204_NO_CONTENT, content=None)
@router.get("/collection/{collection_id}", response_model=List[DocumentResponse])
@inject
async def list_collection_documents(
collection_id: UUID,
use_cases: Annotated[DocumentUseCases, FromDishka()],
skip: int = 0,
limit: int = 100
):
"""Получить документы коллекции"""
documents = await use_cases.list_collection_documents(
collection_id=collection_id,
skip=skip,
limit=limit
)
return [DocumentResponse.from_entity(d) for d in documents]