138 lines
4.8 KiB
Python
138 lines
4.8 KiB
Python
"""
|
||
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]
|
||
|