diff --git a/fastfood/crud.py b/fastfood/crud.py index f886bb3..282e2c9 100644 --- a/fastfood/crud.py +++ b/fastfood/crud.py @@ -1,5 +1,6 @@ +from re import sub from uuid import UUID -from sqlalchemy import delete, select, update +from sqlalchemy import delete, func, select, update from sqlalchemy.ext.asyncio import AsyncSession from fastfood import models, schemas @@ -34,7 +35,22 @@ class Crud: async with session: query = select(models.Menu).where(models.Menu.id == menu_id) menu = await session.execute(query) - return menu.scalars().one_or_none() + menu = menu.scalars().one_or_none() + if menu is None: + return None + submenu_query = select(func.count(models.SubMenu.id).label("counter")).filter(models.SubMenu.parent_menu == menu_id) + counter = await session.execute(submenu_query) + + dish_query = ( + select(func.count(models.Dish.id)) + .join(models.SubMenu) + .filter(models.Dish.parent_submenu == models.SubMenu.id) + .filter(models.SubMenu.parent_menu == menu_id) + ) + dishes = await session.execute(dish_query) + menu.submenus_count = counter.scalars().one_or_none() + menu.dishes_count = dishes.scalars().one_or_none() + return menu @staticmethod async def update_menu_item(menu_id: UUID, @@ -82,7 +98,19 @@ class Crud: async with session: query = select(models.SubMenu).where(models.SubMenu.id == submenu_id) submenu = await session.execute(query) - return submenu.scalars().one_or_none() + submenu = submenu.scalars().one_or_none() + if submenu is None: + return None + + dish_query = ( + select(func.count(models.Dish.id)) + .join(models.SubMenu) + .filter(models.Dish.parent_submenu == models.SubMenu.id) + ) + dishes = await session.execute(dish_query) + submenu.dishes_count = dishes.scalars().one_or_none() + + return submenu @staticmethod async def update_submenu_item( diff --git a/fastfood/models.py b/fastfood/models.py index 14b3bff..2c442af 100644 --- a/fastfood/models.py +++ b/fastfood/models.py @@ -1,5 +1,4 @@ import uuid -from decimal import Decimal from typing import Annotated, List, Optional from sqlalchemy import ForeignKey @@ -7,7 +6,7 @@ from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship uuidpk = Annotated[ - int, + uuid.UUID, mapped_column( UUID(as_uuid=True), primary_key=True, @@ -27,16 +26,16 @@ class Menu(Base): __tablename__ = "menu" submenus: Mapped[List["SubMenu"]] = relationship( - "SubMenu", backref="menu", lazy='dynamic', cascade="all,delete", + "SubMenu", backref="menu", lazy='dynamic', cascade="all, delete", ) class SubMenu(Base): __tablename__ = "submenu" - parent_menu: Mapped[uuid.UUID] = mapped_column(ForeignKey("menu.id")) + parent_menu: Mapped[uuid.UUID] = mapped_column(ForeignKey("menu.id", ondelete="CASCADE")) dishes: Mapped[List["Dish"]] = relationship( - "Dish", backref="submenu", lazy="dynamic", cascade="all,delete", + "Dish", backref="submenu", lazy="dynamic", cascade="all, delete", ) @@ -44,4 +43,4 @@ class Dish(Base): __tablename__ = "dish" price: Mapped[float] - parent_submenu: Mapped[uuid.UUID] = mapped_column(ForeignKey("submenu.id")) + parent_submenu: Mapped[uuid.UUID] = mapped_column(ForeignKey("submenu.id", ondelete="CASCADE")) diff --git a/fastfood/routes.py b/fastfood/routes.py index 95b2c6e..736d889 100644 --- a/fastfood/routes.py +++ b/fastfood/routes.py @@ -11,6 +11,11 @@ from fastfood.dbase import get_async_session router = APIRouter() +def price_converter(dish: dict) -> dict: + dish.price = str(dish.price) + return dish + + @router.get("/api/v1/menus", response_model=Optional[List[schemas.Menu]]) async def get_menus(session: AsyncSession = Depends(get_async_session)): result = await crud.get_menus(session=session) @@ -29,7 +34,7 @@ async def add_menu( return result -@router.get("/api/v1/menus/{menu_id}", response_model=schemas.Menu) +@router.get("/api/v1/menus/{menu_id}", response_model=schemas.MenuRead) async def get_menu( menu_id: UUID, session: AsyncSession = Depends(get_async_session), @@ -82,7 +87,7 @@ async def create_submenu_item( return result -@router.get("/api/v1/menus/{menu_id}/submenus/{submenu_id}") +@router.get("/api/v1/menus/{menu_id}/submenus/{submenu_id}", response_model=schemas.SubMenuRead) async def get_submenu( menu_id: UUID, submenu_id: UUID, @@ -139,7 +144,7 @@ async def create_dish( dish=dish, session=session, ) - return result + return price_converter(result) @router.get("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}") @@ -154,14 +159,13 @@ async def get_dish( ) if not result: raise HTTPException(status_code=404, detail="dish not found") - return result + return price_converter(result) @router.patch( - "/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}", - response_model=schemas.DishBase, + "/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}" ) -async def update_submenu( +async def update_dish( menu_id: UUID, submenu_id: UUID, dish_id: UUID, @@ -171,7 +175,7 @@ async def update_submenu( result = await crud.update_dish_item( dish_id=dish_id, dish=dish, session=session, ) - return result + return price_converter(result) @router.delete("/api/v1/menus/{menu_id}/submenus/{submenu_id}/dishes/{dish_id}") diff --git a/fastfood/schemas.py b/fastfood/schemas.py index b30c5bc..a6398af 100644 --- a/fastfood/schemas.py +++ b/fastfood/schemas.py @@ -17,8 +17,16 @@ class Menu(MenuBase): id: UUID +class MenuRead(Menu): + submenus_count: int + dishes_count: int + +class SubMenuRead(Menu): + dishes_count: int + + class DishBase(MenuBase): - price: str + price: float class Dish(DishBase, Menu): diff --git a/fastfood/utils.py b/fastfood/utils.py new file mode 100644 index 0000000..cd49c8a --- /dev/null +++ b/fastfood/utils.py @@ -0,0 +1,4 @@ + +def convert_price(dish: dict): + dish.price = str(dish.price) + return dish