Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 44 additions & 14 deletions workout_api/atleta/controller.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
from datetime import datetime
from datetime import datetime
from uuid import uuid4
from fastapi import APIRouter, Body, HTTPException, status
from fastapi import APIRouter, Body, HTTPException, Query, status
from pydantic import UUID4
from sqlalchemy.future import select
from sqlalchemy.exc import IntegrityError

from workout_api.atleta.schemas import AtletaIn, AtletaOut, AtletaUpdate
from workout_api.atleta.schemas import (
AtletaIn,
AtletaOut,
AtletaUpdate,
AtletaListOut
)
from workout_api.atleta.models import AtletaModel
from workout_api.categorias.models import CategoriaModel
from workout_api.centro_treinamento.models import CentroTreinamentoModel

from workout_api.contrib.dependencies import DatabaseDependency
from sqlalchemy.future import select

from fastapi_pagination import Page, paginate, add_pagination

router = APIRouter()


@router.post(
'/',
summary='Criar um novo atleta',
Expand Down Expand Up @@ -45,6 +54,7 @@ async def post(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f'O centro de treinamento {centro_treinamento_nome} não foi encontrado.'
)

try:
atleta_out = AtletaOut(id=uuid4(), created_at=datetime.utcnow(), **atleta_in.model_dump())
atleta_model = AtletaModel(**atleta_out.model_dump(exclude={'categoria', 'centro_treinamento'}))
Expand All @@ -54,7 +64,14 @@ async def post(

db_session.add(atleta_model)
await db_session.commit()
except IntegrityError:
await db_session.rollback()
raise HTTPException(
status_code=status.HTTP_303_SEE_OTHER,
detail=f"Já existe um atleta cadastrado com o cpf: {atleta_in.cpf}"
)
except Exception:
await db_session.rollback()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail='Ocorreu um erro ao inserir os dados no banco'
Expand All @@ -64,15 +81,25 @@ async def post(


@router.get(
'/',
summary='Consultar todos os Atletas',
'/',
summary='Consultar todos os Atletas com filtros e paginação',
status_code=status.HTTP_200_OK,
response_model=list[AtletaOut],
response_model=Page[AtletaListOut],
)
async def query(db_session: DatabaseDependency) -> list[AtletaOut]:
atletas: list[AtletaOut] = (await db_session.execute(select(AtletaModel))).scalars().all()

return [AtletaOut.model_validate(atleta) for atleta in atletas]
async def query(
db_session: DatabaseDependency,
nome: str | None = Query(default=None, description="Filtrar por nome do atleta"),
cpf: str | None = Query(default=None, description="Filtrar por CPF do atleta"),
):
stmt = select(AtletaModel)

if nome:
stmt = stmt.filter(AtletaModel.nome.ilike(f"%{nome}%"))
if cpf:
stmt = stmt.filter(AtletaModel.cpf == cpf)

result = (await db_session.execute(stmt)).scalars().all()
return paginate(result)


@router.get(
Expand All @@ -82,7 +109,7 @@ async def query(db_session: DatabaseDependency) -> list[AtletaOut]:
response_model=AtletaOut,
)
async def get(id: UUID4, db_session: DatabaseDependency) -> AtletaOut:
atleta: AtletaOut = (
atleta = (
await db_session.execute(select(AtletaModel).filter_by(id=id))
).scalars().first()

Expand All @@ -102,7 +129,7 @@ async def get(id: UUID4, db_session: DatabaseDependency) -> AtletaOut:
response_model=AtletaOut,
)
async def patch(id: UUID4, db_session: DatabaseDependency, atleta_up: AtletaUpdate = Body(...)) -> AtletaOut:
atleta: AtletaOut = (
atleta = (
await db_session.execute(select(AtletaModel).filter_by(id=id))
).scalars().first()

Expand All @@ -128,7 +155,7 @@ async def patch(id: UUID4, db_session: DatabaseDependency, atleta_up: AtletaUpda
status_code=status.HTTP_204_NO_CONTENT
)
async def delete(id: UUID4, db_session: DatabaseDependency) -> None:
atleta: AtletaOut = (
atleta = (
await db_session.execute(select(AtletaModel).filter_by(id=id))
).scalars().first()

Expand All @@ -140,3 +167,6 @@ async def delete(id: UUID4, db_session: DatabaseDependency) -> None:

await db_session.delete(atleta)
await db_session.commit()


add_pagination(router)
9 changes: 8 additions & 1 deletion workout_api/atleta/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,14 @@ class Atleta(BaseSchema):
sexo: Annotated[str, Field(description='Sexo do atleta', example='M', max_length=1)]
categoria: Annotated[CategoriaIn, Field(description='Categoria do atleta')]
centro_treinamento: Annotated[CentroTreinamentoAtleta, Field(description='Centro de treinamento do atleta')]

class AtletaListOut(BaseSchema):
nome: Annotated[str, Field(description="Nome do atleta", example="Joao")]
centro_treinamento: CentroTreinamentoAtleta
categoria: CategoriaIn

class Config:
orm_mode = True

class AtletaIn(Atleta):
pass
Expand All @@ -26,4 +33,4 @@ class AtletaOut(Atleta, OutMixin):

class AtletaUpdate(BaseSchema):
nome: Annotated[Optional[str], Field(None, description='Nome do atleta', example='Joao', max_length=50)]
idade: Annotated[Optional[int], Field(None, description='Idade do atleta', example=25)]
idade: Annotated[Optional[int], Field(None, description='Idade do atleta', example=25)]
3 changes: 3 additions & 0 deletions workout_api/main.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from fastapi import FastAPI
from workout_api.routers import api_router
from fastapi_pagination import add_pagination # ⬅️ Import necessário

app = FastAPI(title='WorkoutApi')
app.include_router(api_router)

add_pagination(app) # ⬅️ Ativa a paginação global