service/repo.submenu typehint

develop
Сергей Ванюшкин 2024-02-04 17:13:37 +03:00
parent 181c6f10af
commit 35659529b4
3 changed files with 45 additions and 32 deletions

View File

@ -5,40 +5,45 @@ from sqlalchemy import delete, distinct, func, select, update
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import aliased from sqlalchemy.orm import aliased
from fastfood import models, schemas
from fastfood.dbase import get_async_session from fastfood.dbase import get_async_session
from fastfood.models import Dish, SubMenu
from fastfood.schemas import MenuBase
class SubMenuRepository: class SubMenuRepository:
def __init__(self, session: AsyncSession = Depends(get_async_session)): def __init__(self, session: AsyncSession = Depends(get_async_session)):
self.db = session self.db = session
async def get_submenus(self, menu_id: UUID): async def get_submenus(self, menu_id: UUID) -> list[SubMenu]:
query = select(models.SubMenu).where( query = select(SubMenu).where(
models.SubMenu.parent_menu == menu_id, SubMenu.parent_menu == menu_id,
) )
submenus = await self.db.execute(query) submenus = await self.db.execute(query)
return submenus return [x for x in submenus.scalars().all()]
async def create_submenu_item( async def create_submenu_item(
self, self,
menu_id: UUID, menu_id: UUID,
submenu: schemas.MenuBase, submenu: MenuBase,
): ) -> SubMenu:
new_submenu = models.SubMenu(**submenu.model_dump()) new_submenu = SubMenu(**submenu.model_dump())
new_submenu.parent_menu = menu_id new_submenu.parent_menu = menu_id
self.db.add(new_submenu) self.db.add(new_submenu)
await self.db.commit() await self.db.commit()
await self.db.refresh(new_submenu) await self.db.refresh(new_submenu)
return new_submenu
full_sub = await self.get_submenu_item(menu_id, new_submenu.id)
if full_sub is None:
raise TypeError
return full_sub
async def get_submenu_item( async def get_submenu_item(
self, self,
menu_id: UUID, menu_id: UUID,
submenu_id: UUID, submenu_id: UUID,
): ) -> SubMenu | None:
s = aliased(models.SubMenu) s = aliased(SubMenu)
d = aliased(models.Dish) d = aliased(Dish)
query = ( query = (
select(s, func.count(distinct(d.id)).label('dishes_count')) select(s, func.count(distinct(d.id)).label('dishes_count'))
.join(d, s.id == d.parent_submenu, isouter=True) .join(d, s.id == d.parent_submenu, isouter=True)
@ -55,22 +60,23 @@ class SubMenuRepository:
self, self,
menu_id: UUID, menu_id: UUID,
submenu_id: UUID, submenu_id: UUID,
submenu_data: schemas.MenuBase, submenu_data: MenuBase,
): ) -> SubMenu:
query = ( query = (
update(models.SubMenu) update(SubMenu)
.where(models.SubMenu.id == submenu_id) .where(SubMenu.id == submenu_id)
.values(**submenu_data.model_dump()) .values(**submenu_data.model_dump())
) )
await self.db.execute(query) await self.db.execute(query)
await self.db.commit() await self.db.commit()
qr = select(models.SubMenu).where(models.SubMenu.id == submenu_id) qr = select(SubMenu).where(SubMenu.id == submenu_id)
updated_submenu = await self.db.execute(qr) updated_submenu = await self.db.execute(qr)
return updated_submenu return updated_submenu.scalar_one()
async def delete_submenu_item(self, menu_id: UUID, submenu_id: UUID): async def delete_submenu_item(self, menu_id: UUID, submenu_id: UUID) -> int:
query = delete(models.SubMenu).where( query = delete(SubMenu).where(
models.SubMenu.id == submenu_id, SubMenu.id == submenu_id,
) )
await self.db.execute(query) await self.db.execute(query)
await self.db.commit() await self.db.commit()
return 200

View File

@ -1,4 +1,3 @@
from typing import Optional
from uuid import UUID from uuid import UUID
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException
@ -12,14 +11,14 @@ router = APIRouter(
) )
@router.get('/', response_model=Optional[list[SubMenuRead]]) @router.get('/', response_model=list[SubMenuRead])
async def get_submenus( async def get_submenus(
menu_id: UUID, menu_id: UUID,
submenu: SubmenuService = Depends(), submenu: SubmenuService = Depends(),
background_tasks: BackgroundTasks = BackgroundTasks(), background_tasks: BackgroundTasks = BackgroundTasks(),
): ):
result = await submenu.read_submenus(menu_id=menu_id) result = await submenu.read_submenus(menu_id=menu_id)
return result.scalars().all() return result
@router.post('/', status_code=201, response_model=SubMenuRead) @router.post('/', status_code=201, response_model=SubMenuRead)
@ -54,7 +53,7 @@ async def get_submenu(
@router.patch( @router.patch(
'/{submenu_id}', '/{submenu_id}',
response_model=MenuBase, response_model=SubMenuRead,
) )
async def update_submenu( async def update_submenu(
menu_id: UUID, menu_id: UUID,
@ -68,7 +67,7 @@ async def update_submenu(
submenu_id=submenu_id, submenu_id=submenu_id,
submenu_data=submenu_data, submenu_data=submenu_data,
) )
return result.scalars().one() return result
@router.delete('/{submenu_id}') @router.delete('/{submenu_id}')

View File

@ -6,7 +6,7 @@ from fastapi import BackgroundTasks, Depends
from fastfood.dbase import get_async_redis_client from fastfood.dbase import get_async_redis_client
from fastfood.repository.redis import RedisRepository from fastfood.repository.redis import RedisRepository
from fastfood.repository.submenu import SubMenuRepository from fastfood.repository.submenu import SubMenuRepository
from fastfood.schemas import MenuBase from fastfood.schemas import MenuBase, SubMenuRead
class SubmenuService: class SubmenuService:
@ -15,14 +15,23 @@ class SubmenuService:
submenu_repo: SubMenuRepository = Depends(), submenu_repo: SubMenuRepository = Depends(),
redis_client: redis.Redis = Depends(get_async_redis_client), redis_client: redis.Redis = Depends(get_async_redis_client),
background_tasks: BackgroundTasks = None, background_tasks: BackgroundTasks = None,
): ) -> None:
self.submenu_repo = submenu_repo self.submenu_repo = submenu_repo
self.cache_client = RedisRepository(redis_client) self.cache_client = RedisRepository(redis_client)
self.background_tasks = background_tasks self.background_tasks = background_tasks
async def read_submenus(self, menu_id: UUID): async def read_submenus(self, menu_id: UUID) -> list[SubMenuRead]:
data = await self.submenu_repo.get_submenus(menu_id=menu_id) data = await self.submenu_repo.get_submenus(menu_id=menu_id)
return data submenus = []
for r in data:
submenu = r.__dict__
subq = await self.submenu_repo.get_submenu_item(menu_id, r.id)
if subq is not None:
submenu['dishes_count'] = len(subq.dishes)
submenu = SubMenuRead(**submenu)
submenus.append(submenu)
return submenus
async def create_submenu(self, menu_id: UUID, submenu_data: MenuBase): async def create_submenu(self, menu_id: UUID, submenu_data: MenuBase):
data = await self.submenu_repo.create_submenu_item( data = await self.submenu_repo.create_submenu_item(
@ -44,5 +53,4 @@ class SubmenuService:
return data return data
async def del_menu(self, menu_id: UUID, submenu_id: UUID): async def del_menu(self, menu_id: UUID, submenu_id: UUID):
data = await self.submenu_repo.delete_submenu_item(menu_id, submenu_id) return await self.submenu_repo.delete_submenu_item(menu_id, submenu_id)
return data