""" 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]