From aa6bff1ec9116c42b29a33cf7e9e049083fcce7b Mon Sep 17 00:00:00 2001 From: Matheus Afonso Date: Sun, 22 Oct 2023 19:28:19 -0300 Subject: [PATCH] feat: add dependents rules --- .../versions/2023-10-22-02-46_532e4deb3c37.py | 48 +++++++++++++++++++ gestao/db/models/dependent.py | 23 +++++++++ gestao/web/api/router.py | 2 +- gestao/web/api/user/schema.py | 9 +++- gestao/web/api/user/views.py | 36 +++++++++----- 5 files changed, 104 insertions(+), 14 deletions(-) create mode 100644 gestao/db/migrations/versions/2023-10-22-02-46_532e4deb3c37.py create mode 100644 gestao/db/models/dependent.py diff --git a/gestao/db/migrations/versions/2023-10-22-02-46_532e4deb3c37.py b/gestao/db/migrations/versions/2023-10-22-02-46_532e4deb3c37.py new file mode 100644 index 0000000..49dc333 --- /dev/null +++ b/gestao/db/migrations/versions/2023-10-22-02-46_532e4deb3c37.py @@ -0,0 +1,48 @@ +"""dependent table + +Revision ID: 532e4deb3c37 +Revises: 071cefd86342 +Create Date: 2023-10-22 02:46:30.124158 + +""" +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = "532e4deb3c37" +down_revision = "071cefd86342" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + op.create_table( + "dependent", + sa.Column("id", sa.String(length=200), primary_key=True, nullable=False), + sa.Column( + "user_id", + sa.String(length=200), + sa.ForeignKey("user.id", ondelete="CASCADE"), + nullable=False, + ), + sa.Column("name", sa.String(length=200), nullable=False), + sa.Column("birth_date", sa.Date(), nullable=False), + sa.Column("relationship", sa.String(length=200), nullable=False), + sa.Column( + "created_at", + sa.DateTime(timezone=True), + server_default=sa.func.now(), + nullable=False, + ), + sa.Column( + "updated_at", + sa.DateTime(timezone=True), + server_default=sa.func.now(), + nullable=False, + ), + schema="public", + ) + + +def downgrade() -> None: + op.drop_table("dependent") diff --git a/gestao/db/models/dependent.py b/gestao/db/models/dependent.py new file mode 100644 index 0000000..75d4722 --- /dev/null +++ b/gestao/db/models/dependent.py @@ -0,0 +1,23 @@ +from datetime import date, datetime + +import ormar + +from gestao.db.base import BaseMeta +from gestao.db.models.user import User + + +class Dependent(ormar.Model): + class Meta(BaseMeta): + tablename = "dependent" + + id: str = ormar.String(max_length=200, primary_key=True) + user_id: User = ormar.ForeignKey(User, ondelete=ormar.ReferentialAction.CASCADE) + name: str = ormar.String(max_length=200) + birth_date: date = ormar.Date() + relationship: str = ormar.String(max_length=200) + created_at: datetime = ormar.DateTime(timezone=True, default=datetime.now) + updated_at: datetime = ormar.DateTime( + timezone=True, + default=datetime.now, + onupdate=datetime.now, + ) diff --git a/gestao/web/api/router.py b/gestao/web/api/router.py index 9c98314..3788ffd 100644 --- a/gestao/web/api/router.py +++ b/gestao/web/api/router.py @@ -5,4 +5,4 @@ api_router = APIRouter() api_router.include_router(monitoring.router) api_router.include_router(echo.router, prefix="/echo", tags=["echo"]) -api_router.include_router(user.router, prefix="/user", tags=["user"]) +api_router.include_router(user.router, prefix="/users", tags=["users"]) diff --git a/gestao/web/api/user/schema.py b/gestao/web/api/user/schema.py index d61e3c8..4086acb 100644 --- a/gestao/web/api/user/schema.py +++ b/gestao/web/api/user/schema.py @@ -1,9 +1,15 @@ from datetime import date -from typing import Optional +from typing import List, Optional from pydantic import BaseModel +class CreateUserDependentDTO(BaseModel): + name: str + birth_date: date + relationship: str + + class CreateUserDTO(BaseModel): name: str address: str @@ -33,6 +39,7 @@ class CreateUserDTO(BaseModel): pattern: str dispatcher: str dispatched_date: date + dependents: Optional[List[CreateUserDependentDTO]] class UpdateUserDTO(BaseModel): diff --git a/gestao/web/api/user/views.py b/gestao/web/api/user/views.py index 8ef9f39..98ed083 100644 --- a/gestao/web/api/user/views.py +++ b/gestao/web/api/user/views.py @@ -1,15 +1,17 @@ +import logging from typing import List from uuid import uuid4 from fastapi import APIRouter, HTTPException +from gestao.db.models.dependent import Dependent from gestao.db.models.user import User from gestao.web.api.user.schema import CreateUserDTO, UpdateUserDTO router = APIRouter() -@router.get("/") +@router.get("/", response_model_exclude={"dependents__user_id"}) async def get_users( limit: int = 10, offset: int = 0, @@ -17,39 +19,48 @@ async def get_users( return await User.objects.limit(limit).offset(offset).all() -@router.get("/{user_id}") +@router.get("/{user_id}", response_model_exclude={"dependents__user_id"}) async def get_user(user_id: str) -> User: try: - return await User.objects.get(id=user_id) + return await User.objects.select_related(User.dependents).get(id=user_id) except Exception: + logging.error("Error occurred while get user", exc_info=True) raise HTTPException(status_code=404, detail="User not found") -@router.post("/") +@router.post("/", response_model_exclude={"dependents__user_id"}) async def create_user(create_user: CreateUserDTO) -> User: try: - return await User.objects.create( - **{ - "id": str(uuid4()), - **create_user.dict(), - } - ) + create_user_dict = create_user.dict() + dependents = create_user_dict.pop("dependents", []) + user_id = str(uuid4()) + await User.objects.create(id=user_id, **create_user_dict) + if dependents: + await Dependent.objects.bulk_create( + [ + Dependent(id=str(uuid4()), user_id=user_id, **dependent) + for dependent in dependents + ], + ) + return await User.objects.select_related(User.dependents).get(id=user_id) except Exception: + logging.error("Error occurred while creating user", exc_info=True) raise HTTPException( status_code=400, detail="Error occurred while creating user", ) -@router.put("/{user_id}") +@router.put("/{user_id}", response_model_exclude={"dependents__user_id"}) async def update_user(user_id: str, update_user: UpdateUserDTO) -> User: try: await User.objects.filter(id=user_id).update( each=True, **update_user.dict(exclude_none=True), ) - return await User.objects.get(id=user_id) + return await User.objects.select_related(User.dependents).get(id=user_id) except Exception: + logging.error("Error occurred while updating user", exc_info=True) raise HTTPException( status_code=404, detail="Error occurred while updating user", @@ -61,6 +72,7 @@ async def delete_user(user_id: str) -> None: try: await User.objects.delete(id=user_id) except Exception: + logging.error("Error occurred while deleting user", exc_info=True) raise HTTPException( status_code=404, detail="Error occurred while deleting user",