diff --git a/src/fastfood_two/application/contracts/requests.py b/src/fastfood_two/application/contracts/requests.py index f365f9a..9b0ca00 100644 --- a/src/fastfood_two/application/contracts/requests.py +++ b/src/fastfood_two/application/contracts/requests.py @@ -18,3 +18,8 @@ class UpdateMenuDTO: @dataclass(frozen=True) class DeleteMenuDTO: id: UUID + + +@dataclass(frozen=True) +class GetMenuByIdDTO: + id: UUID diff --git a/src/fastfood_two/application/usecases/menu/get_menu_by_id.py b/src/fastfood_two/application/usecases/menu/get_menu_by_id.py new file mode 100644 index 0000000..689c302 --- /dev/null +++ b/src/fastfood_two/application/usecases/menu/get_menu_by_id.py @@ -0,0 +1,26 @@ +from fastfood_two.application.abstractions.interactor import Interactor +from fastfood_two.application.contracts.requests import GetMenuByIdDTO +from fastfood_two.application.contracts.responses import MenuDTO +from fastfood_two.domain.menu.error import MenuNotFoundError +from fastfood_two.domain.menu.gateway import MenuGateway +from fastfood_two.domain.menu.menu_entity import MenuId + + +class GetMenuById(Interactor[GetMenuByIdDTO, MenuDTO]): + def __init__(self, gateway: MenuGateway) -> None: + self._menu_gateway = gateway + + async def __call__(self, request: GetMenuByIdDTO) -> MenuDTO: + + menu = await self._menu_gateway.get_menu_by_id( + id=MenuId(request.id), + ) + + if not menu: + raise MenuNotFoundError(message="Menu not found") + + return MenuDTO( + id=menu.id.value, + title=menu.title.value, + description=menu.description.value, + ) diff --git a/src/fastfood_two/infrastructure/menu_gateway.py b/src/fastfood_two/infrastructure/menu_gateway.py index 7fc6f4c..060196d 100644 --- a/src/fastfood_two/infrastructure/menu_gateway.py +++ b/src/fastfood_two/infrastructure/menu_gateway.py @@ -16,7 +16,11 @@ class MenuGatewayImpl: menus = await self._session.execute(query) return [db_entity_to_domain(menu.tuple()) for menu in menus] - async def get_menu_by_id(self, id: MenuId) -> Menu | None: ... + async def get_menu_by_id(self, id: MenuId) -> Menu | None: + query = text("SELECT * FROM menu WHERE id = :id;") + menu = (await self._session.execute(query, {"id": id.value})).tuples().first() + + return db_entity_to_domain(menu) if menu else None async def insert_menu(self, menu: Menu) -> Menu: query = text("INSERT INTO menu (id, title, description) VALUES (:id, :title, :description);") diff --git a/src/fastfood_two/presentation/fastapi_backend/dependencies.py b/src/fastfood_two/presentation/fastapi_backend/dependencies.py index 3163774..3706816 100644 --- a/src/fastfood_two/presentation/fastapi_backend/dependencies.py +++ b/src/fastfood_two/presentation/fastapi_backend/dependencies.py @@ -8,6 +8,7 @@ from fastfood_two.application.config import Config from fastfood_two.application.usecases.menu.add_menu import AddMenu from fastfood_two.application.usecases.menu.delete_menu import DeleteMenu from fastfood_two.application.usecases.menu.get_all_menus import GetAllMenus +from fastfood_two.application.usecases.menu.get_menu_by_id import GetMenuById from fastfood_two.application.usecases.menu.update_menu import UpdateMenu from fastfood_two.domain.menu.gateway import MenuGateway from fastfood_two.presentation.fastapi_backend.depends.config import get_settings @@ -21,6 +22,7 @@ from fastfood_two.presentation.fastapi_backend.depends.usecases import ( add_menu_usecase, delete_menu_usecase, get_all_menus_usecase, + get_menu_by_id_usecase, update_menu_usecase, ) @@ -47,5 +49,6 @@ def init_dependencies(app: FastAPI) -> None: app.dependency_overrides[AddMenu] = add_menu_usecase app.dependency_overrides[UpdateMenu] = update_menu_usecase app.dependency_overrides[DeleteMenu] = delete_menu_usecase + app.dependency_overrides[GetMenuById] = get_menu_by_id_usecase logger.info("Dependencies initialized") diff --git a/src/fastfood_two/presentation/fastapi_backend/depends/usecases.py b/src/fastfood_two/presentation/fastapi_backend/depends/usecases.py index 35025f8..d9d0e31 100644 --- a/src/fastfood_two/presentation/fastapi_backend/depends/usecases.py +++ b/src/fastfood_two/presentation/fastapi_backend/depends/usecases.py @@ -5,6 +5,7 @@ from fastapi import Depends from fastfood_two.application.usecases.menu.add_menu import AddMenu from fastfood_two.application.usecases.menu.delete_menu import DeleteMenu from fastfood_two.application.usecases.menu.get_all_menus import GetAllMenus +from fastfood_two.application.usecases.menu.get_menu_by_id import GetMenuById from fastfood_two.application.usecases.menu.update_menu import UpdateMenu from fastfood_two.domain.menu.gateway import MenuGateway from fastfood_two.presentation.fastapi_backend.depends.stub import Stub @@ -24,3 +25,7 @@ def update_menu_usecase(gateway: Annotated[MenuGateway, Depends(Stub(MenuGateway def delete_menu_usecase(gateway: Annotated[MenuGateway, Depends(Stub(MenuGateway))]) -> DeleteMenu: return DeleteMenu(gateway=gateway) + + +def get_menu_by_id_usecase(gateway: Annotated[MenuGateway, Depends(Stub(MenuGateway))]) -> GetMenuById: + return GetMenuById(gateway=gateway) diff --git a/src/fastfood_two/presentation/fastapi_backend/routers/menu.py b/src/fastfood_two/presentation/fastapi_backend/routers/menu.py index 8225a4b..bbc8bb9 100644 --- a/src/fastfood_two/presentation/fastapi_backend/routers/menu.py +++ b/src/fastfood_two/presentation/fastapi_backend/routers/menu.py @@ -6,12 +6,14 @@ from fastapi import APIRouter, Depends from fastfood_two.application.contracts.requests import ( AddMenuDTO, DeleteMenuDTO, + GetMenuByIdDTO, UpdateMenuDTO, ) from fastfood_two.application.contracts.responses import MenuDTO from fastfood_two.application.usecases.menu.add_menu import AddMenu from fastfood_two.application.usecases.menu.delete_menu import DeleteMenu from fastfood_two.application.usecases.menu.get_all_menus import GetAllMenus +from fastfood_two.application.usecases.menu.get_menu_by_id import GetMenuById from fastfood_two.application.usecases.menu.update_menu import UpdateMenu from fastfood_two.presentation.fastapi_backend.depends.stub import Stub from fastfood_two.presentation.fastapi_backend.pdmodels.menu import ( @@ -129,3 +131,30 @@ async def delete_menu( ) ) return + + +@router.get("/{menu_id}", response_model=MenuDTO) +async def get_menu_by_id( + menu_id: UUID, + usecase: Annotated[GetMenuById, Depends(Stub(GetMenuById))], +) -> MenuDTO: + """Get menus by id. + + Endpoint allows to get food menu item by id + + Parameters + ---------- + menu_id: UUID + requaired id of the menu item + + Returns + ------- + MenuDTO + menu item + """ + menu = await usecase( + request=GetMenuByIdDTO( + id=menu_id, + ) + ) + return menu