from typing import Optional from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from sqlalchemy.orm import aliased from db.models import Category class CategoriesRepository: async def get_category_by_id( self, session: AsyncSession, category_id: int ) -> Optional[Category]: stmt = select(Category).where(Category.id == category_id) return await session.scalar(stmt) async def get_categories_by_parent_id( self, session: AsyncSession, parent_id: Optional[int] = None ) -> list[Category]: stmt = select(Category).where(Category.parent_id == parent_id) result = await session.scalars(stmt) return list(result) async def get_category_path(self, session: AsyncSession, category_id: int): base = select(Category.id, Category.parent_id, Category.name).where( Category.id == category_id ) cte = base.cte(name="path", recursive=True) parent = aliased(Category) cte = cte.union_all( select(parent.id, parent.parent_id, parent.name).join( cte, cte.c.parent_id == parent.id ) ) stmt = select(cte) result = await session.execute(stmt) rows = result.all() return list(reversed(rows)) async def add_category( self, session: AsyncSession, *, name: str, parent_id: Optional[int] ) -> Category: category = Category(name=name, parent_id=parent_id) session.add(category) await session.commit() return category