ADD update_menu usecase, fix mapper
parent
2104f39e3b
commit
36627d409c
|
@ -1,7 +1,15 @@
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
|
|
||||||
@dataclass(frozen=True)
|
@dataclass(frozen=True)
|
||||||
class AddMenuDTO:
|
class AddMenuDTO:
|
||||||
title: str
|
title: str
|
||||||
description: str | None
|
description: str | None
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class UpdateMenuDTO:
|
||||||
|
id: UUID
|
||||||
|
title: str | None
|
||||||
|
description: str | None
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
from fastfood_two.application.abstractions.interactor import Interactor
|
||||||
|
from fastfood_two.application.contracts.requests import UpdateMenuDTO
|
||||||
|
from fastfood_two.application.contracts.responses import MenuDTO
|
||||||
|
from fastfood_two.domain.menu.gateway import MenuGateway
|
||||||
|
from fastfood_two.domain.menu.menu_entity import Description, MenuId, Title
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateMenu(Interactor[UpdateMenuDTO, MenuDTO]):
|
||||||
|
def __init__(self, gateway: MenuGateway) -> None:
|
||||||
|
self._menu_gateway = gateway
|
||||||
|
|
||||||
|
async def __call__(self, request: UpdateMenuDTO) -> MenuDTO:
|
||||||
|
|
||||||
|
menu = await self._menu_gateway.update_menu(
|
||||||
|
id=MenuId(request.id),
|
||||||
|
title=Title(request.title) if request.title else None,
|
||||||
|
description=Description(request.description) if request.description else None,
|
||||||
|
)
|
||||||
|
|
||||||
|
return MenuDTO(
|
||||||
|
id=menu.id.value,
|
||||||
|
title=menu.title.value,
|
||||||
|
description=menu.description.value,
|
||||||
|
)
|
|
@ -1,7 +1,7 @@
|
||||||
from typing import Protocol
|
from typing import Protocol
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
from fastfood_two.domain.menu.menu_entity import Menu
|
from fastfood_two.domain.menu.menu_entity import Description, Menu, MenuId, Title
|
||||||
|
|
||||||
|
|
||||||
class MenuGateway(Protocol):
|
class MenuGateway(Protocol):
|
||||||
|
@ -14,7 +14,12 @@ class MenuGateway(Protocol):
|
||||||
async def get_all_menus(self) -> list[Menu]:
|
async def get_all_menus(self) -> list[Menu]:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
async def update_menu(self, updated_menu: Menu) -> Menu | None:
|
async def update_menu(
|
||||||
|
self,
|
||||||
|
id: MenuId,
|
||||||
|
title: Title | None,
|
||||||
|
description: Description | None,
|
||||||
|
) -> Menu:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
async def delete_menu(self, id: UUID) -> None:
|
async def delete_menu(self, id: UUID) -> None:
|
||||||
|
|
|
@ -3,7 +3,7 @@ from uuid import UUID
|
||||||
from sqlalchemy import text
|
from sqlalchemy import text
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
|
||||||
from fastfood_two.domain.menu.menu_entity import Menu
|
from fastfood_two.domain.menu.menu_entity import Description, Menu, MenuId, Title
|
||||||
from fastfood_two.infrastructure.pg_storage.mappers.menu_mapper import (
|
from fastfood_two.infrastructure.pg_storage.mappers.menu_mapper import (
|
||||||
db_entity_to_domain,
|
db_entity_to_domain,
|
||||||
)
|
)
|
||||||
|
@ -16,7 +16,7 @@ class MenuGatewayImpl:
|
||||||
async def get_all_menus(self) -> list[Menu]:
|
async def get_all_menus(self) -> list[Menu]:
|
||||||
query = text("SELECT * FROM menu;")
|
query = text("SELECT * FROM menu;")
|
||||||
menus = await self._session.execute(query)
|
menus = await self._session.execute(query)
|
||||||
return [db_entity_to_domain(menu) for menu in menus]
|
return [db_entity_to_domain(menu.tuple()) for menu in menus]
|
||||||
|
|
||||||
async def get_menu_by_id(self, id: UUID) -> Menu | None: ...
|
async def get_menu_by_id(self, id: UUID) -> Menu | None: ...
|
||||||
|
|
||||||
|
@ -33,6 +33,23 @@ class MenuGatewayImpl:
|
||||||
await self._session.commit()
|
await self._session.commit()
|
||||||
return menu
|
return menu
|
||||||
|
|
||||||
async def update_menu(self, updated_menu: Menu) -> Menu | None: ...
|
async def update_menu(self, id: MenuId, title: Title | None, description: Description | None) -> Menu:
|
||||||
|
query = text(
|
||||||
|
"UPDATE menu SET {}{} {} WHERE id = :id RETURNING *;".format(
|
||||||
|
"title = :title " if title is not None else "",
|
||||||
|
"," if all([title is not None, description is not None]) else "",
|
||||||
|
"description = :description" if description is not None else "",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
menu = await self._session.execute(
|
||||||
|
query,
|
||||||
|
{
|
||||||
|
"id": id.value,
|
||||||
|
"title": title.value if title else None,
|
||||||
|
"description": description.value if description else None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
await self._session.commit()
|
||||||
|
return db_entity_to_domain(menu.one().tuple())
|
||||||
|
|
||||||
async def delete_menu(self, id: UUID) -> None: ...
|
async def delete_menu(self, id: UUID) -> None: ...
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from fastfood_two.domain.menu.menu_entity import Description, Menu, MenuId, Title
|
from fastfood_two.domain.menu.menu_entity import Description, Menu, MenuId, Title
|
||||||
|
|
||||||
|
|
||||||
def db_entity_to_domain(menu) -> Menu:
|
def db_entity_to_domain(menu: tuple[UUID, str, str | None]) -> Menu:
|
||||||
print(menu)
|
print(menu)
|
||||||
return Menu(
|
return Menu(
|
||||||
id=MenuId(menu[0]),
|
id=MenuId(menu[0]),
|
||||||
|
|
|
@ -7,6 +7,7 @@ from fastfood_two.application.common.logger import configure_logger
|
||||||
from fastfood_two.application.config import Config
|
from fastfood_two.application.config import Config
|
||||||
from fastfood_two.application.usecases.menu.add_menu import AddMenu
|
from fastfood_two.application.usecases.menu.add_menu import AddMenu
|
||||||
from fastfood_two.application.usecases.menu.get_all_menus import GetAllMenus
|
from fastfood_two.application.usecases.menu.get_all_menus import GetAllMenus
|
||||||
|
from fastfood_two.application.usecases.menu.update_menu import UpdateMenu
|
||||||
from fastfood_two.domain.menu.gateway import MenuGateway
|
from fastfood_two.domain.menu.gateway import MenuGateway
|
||||||
from fastfood_two.presentation.fastapi_backend.depends.config import get_settings
|
from fastfood_two.presentation.fastapi_backend.depends.config import get_settings
|
||||||
from fastfood_two.presentation.fastapi_backend.depends.gateways import get_menu_gateway
|
from fastfood_two.presentation.fastapi_backend.depends.gateways import get_menu_gateway
|
||||||
|
@ -18,6 +19,7 @@ from fastfood_two.presentation.fastapi_backend.depends.session import (
|
||||||
from fastfood_two.presentation.fastapi_backend.depends.usecases import (
|
from fastfood_two.presentation.fastapi_backend.depends.usecases import (
|
||||||
add_menu_usecase,
|
add_menu_usecase,
|
||||||
get_all_menus_usecase,
|
get_all_menus_usecase,
|
||||||
|
update_menu_usecase,
|
||||||
)
|
)
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -41,5 +43,6 @@ def init_dependencies(app: FastAPI) -> None:
|
||||||
|
|
||||||
app.dependency_overrides[GetAllMenus] = get_all_menus_usecase
|
app.dependency_overrides[GetAllMenus] = get_all_menus_usecase
|
||||||
app.dependency_overrides[AddMenu] = add_menu_usecase
|
app.dependency_overrides[AddMenu] = add_menu_usecase
|
||||||
|
app.dependency_overrides[UpdateMenu] = update_menu_usecase
|
||||||
|
|
||||||
logger.info("Dependencies initialized")
|
logger.info("Dependencies initialized")
|
||||||
|
|
|
@ -4,6 +4,7 @@ from fastapi import Depends
|
||||||
|
|
||||||
from fastfood_two.application.usecases.menu.add_menu import AddMenu
|
from fastfood_two.application.usecases.menu.add_menu import AddMenu
|
||||||
from fastfood_two.application.usecases.menu.get_all_menus import GetAllMenus
|
from fastfood_two.application.usecases.menu.get_all_menus import GetAllMenus
|
||||||
|
from fastfood_two.application.usecases.menu.update_menu import UpdateMenu
|
||||||
from fastfood_two.domain.menu.gateway import MenuGateway
|
from fastfood_two.domain.menu.gateway import MenuGateway
|
||||||
from fastfood_two.presentation.fastapi_backend.depends.stub import Stub
|
from fastfood_two.presentation.fastapi_backend.depends.stub import Stub
|
||||||
|
|
||||||
|
@ -14,3 +15,7 @@ def get_all_menus_usecase(gateway: Annotated[MenuGateway, Depends(Stub(MenuGatew
|
||||||
|
|
||||||
def add_menu_usecase(gateway: Annotated[MenuGateway, Depends(Stub(MenuGateway))]) -> AddMenu:
|
def add_menu_usecase(gateway: Annotated[MenuGateway, Depends(Stub(MenuGateway))]) -> AddMenu:
|
||||||
return AddMenu(gateway=gateway)
|
return AddMenu(gateway=gateway)
|
||||||
|
|
||||||
|
|
||||||
|
def update_menu_usecase(gateway: Annotated[MenuGateway, Depends(Stub(MenuGateway))]) -> UpdateMenu:
|
||||||
|
return UpdateMenu(gateway=gateway)
|
||||||
|
|
|
@ -4,3 +4,8 @@ from pydantic import BaseModel
|
||||||
class AddMenuPDModel(BaseModel):
|
class AddMenuPDModel(BaseModel):
|
||||||
title: str
|
title: str
|
||||||
description: str | None
|
description: str | None
|
||||||
|
|
||||||
|
|
||||||
|
class UpdateMenuPDModel(BaseModel):
|
||||||
|
title: str | None = None
|
||||||
|
description: str | None = None
|
||||||
|
|
|
@ -1,13 +1,18 @@
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
from uuid import UUID
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends
|
from fastapi import APIRouter, Depends
|
||||||
|
|
||||||
from fastfood_two.application.contracts.requests import AddMenuDTO
|
from fastfood_two.application.contracts.requests import AddMenuDTO, UpdateMenuDTO
|
||||||
from fastfood_two.application.contracts.responses import MenuDTO
|
from fastfood_two.application.contracts.responses import MenuDTO
|
||||||
from fastfood_two.application.usecases.menu.add_menu import AddMenu
|
from fastfood_two.application.usecases.menu.add_menu import AddMenu
|
||||||
from fastfood_two.application.usecases.menu.get_all_menus import GetAllMenus
|
from fastfood_two.application.usecases.menu.get_all_menus import GetAllMenus
|
||||||
|
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.depends.stub import Stub
|
||||||
from fastfood_two.presentation.fastapi_backend.pdmodels.menu import AddMenuPDModel
|
from fastfood_two.presentation.fastapi_backend.pdmodels.menu import (
|
||||||
|
AddMenuPDModel,
|
||||||
|
UpdateMenuPDModel,
|
||||||
|
)
|
||||||
|
|
||||||
router = APIRouter(prefix="/menu", tags=["Menu"])
|
router = APIRouter(prefix="/menu", tags=["Menu"])
|
||||||
|
|
||||||
|
@ -19,6 +24,15 @@ async def get_all_menus(
|
||||||
"""Get all menus.
|
"""Get all menus.
|
||||||
|
|
||||||
Endpoint returns list of all available food menus
|
Endpoint returns list of all available food menus
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
None
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
list[MenuDTO]
|
||||||
|
list of created menu items
|
||||||
"""
|
"""
|
||||||
menus = await usecase()
|
menus = await usecase()
|
||||||
return menus
|
return menus
|
||||||
|
@ -29,9 +43,53 @@ async def add_menu(
|
||||||
request: AddMenuPDModel,
|
request: AddMenuPDModel,
|
||||||
usecase: Annotated[AddMenu, Depends(Stub(AddMenu))],
|
usecase: Annotated[AddMenu, Depends(Stub(AddMenu))],
|
||||||
) -> MenuDTO:
|
) -> MenuDTO:
|
||||||
"""Get all menus.
|
"""Add menus.
|
||||||
|
|
||||||
Endpoint returns list of all available food menus
|
Endpoint allows to add new food menu
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
title: str
|
||||||
|
title of the menu
|
||||||
|
description: str
|
||||||
|
description of the menu
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
MenuDTO
|
||||||
|
created menu
|
||||||
"""
|
"""
|
||||||
menus = await usecase(request=AddMenuDTO(title=request.title, description=request.description))
|
menus = await usecase(request=AddMenuDTO(title=request.title, description=request.description))
|
||||||
return menus
|
return menus
|
||||||
|
|
||||||
|
|
||||||
|
@router.patch("/{menu_id}", response_model=MenuDTO)
|
||||||
|
async def update_menu(
|
||||||
|
menu_id: UUID,
|
||||||
|
request: UpdateMenuPDModel,
|
||||||
|
usecase: Annotated[UpdateMenu, Depends(Stub(UpdateMenu))],
|
||||||
|
) -> MenuDTO:
|
||||||
|
"""Update menus.
|
||||||
|
|
||||||
|
Endpoint allows to update food menu
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
title: str | None
|
||||||
|
new title of the menu or None if you don't want to update it
|
||||||
|
description: str | None
|
||||||
|
new description of the menu or None if you don't want to update it
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
MenuDTO
|
||||||
|
updated menu
|
||||||
|
"""
|
||||||
|
menus = await usecase(
|
||||||
|
request=UpdateMenuDTO(
|
||||||
|
id=menu_id,
|
||||||
|
title=request.title,
|
||||||
|
description=request.description,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return menus
|
||||||
|
|
Loading…
Reference in New Issue