From e8a61c05b34a7b54c8ac95e3911e744e33fd64ed Mon Sep 17 00:00:00 2001 From: hexdev Date: Sun, 8 Feb 2026 13:31:28 +0700 Subject: [PATCH] Fixed type hints, added cart item counter on main --- config.py | 2 +- handlers/client.py | 29 +++++++++++++++++++++++------ misc/kb/client.py | 14 +++++++------- repositories/order_items.py | 10 +++++++++- services/orders.py | 18 +++++++++++++++++- 5 files changed, 57 insertions(+), 16 deletions(-) diff --git a/config.py b/config.py index 663d60c..fe57ef4 100644 --- a/config.py +++ b/config.py @@ -16,4 +16,4 @@ POSTGRES_URL = os.getenv( ### Constants ### -PAGE_SIZE = 5 +PAGE_SIZE = 6 diff --git a/handlers/client.py b/handlers/client.py index b7f334a..3f89c30 100644 --- a/handlers/client.py +++ b/handlers/client.py @@ -22,20 +22,29 @@ router = Router() @router.message(Command("start")) -async def main_menu(msg: Message, state: FSMContext): +async def main_menu( + msg: Message, state: FSMContext, session: AsyncSession, order_service: OrderService +): await state.clear() + cart_items = await order_service.get_cart_items_count(session, msg.from_user.id) await msg.answer( - "hii!", reply_markup=main_menu_kb(msg.from_user.id) + "hii!", reply_markup=main_menu_kb(cart_items) ) # TODO: Write a welcome message @router.callback_query(F.data.startswith("menu:")) -async def main_menu_cb(cb: CallbackQuery, state: FSMContext): +async def main_menu_cb( + cb: CallbackQuery, + state: FSMContext, + session: AsyncSession, + order_service: OrderService, +): await state.clear() + cart_items = await order_service.get_cart_items_count(session, cb.from_user.id) await cb.message.edit_text( - "hii!", reply_markup=main_menu_kb(cb.from_user.id) + "hii!", reply_markup=main_menu_kb(cart_items) ) # TODO: Write a welcome message @@ -198,8 +207,16 @@ async def product_card( return if not os.path.isfile(product.img_path): - await cb.answer("something has gone wrong, try again later...") - return # TODO: Add logging + Admin notifications + await cb.message.edit_text( + get_product_description(product), + reply_markup=render_product_interactions( + product_id=product.id, + category_id=product.category_id, + show_cart=bool(order_item), + cart_amount=order_item, + ), + ) + return await cb.message.delete() msg = await cb.message.answer_photo( diff --git a/misc/kb/client.py b/misc/kb/client.py index 70c67bf..527f192 100644 --- a/misc/kb/client.py +++ b/misc/kb/client.py @@ -7,10 +7,10 @@ from db.models import Category from db.models.products import Product -def cart_btn(user_id: int) -> InlineKeyboardButton: +def cart_btn(cart_items: int) -> InlineKeyboardButton: return InlineKeyboardButton( - text="🛒 Корзина ()", callback_data="cart" - ) # TODO: Database integration, get cart items count + text=f"🛒 Корзина ({cart_items})", callback_data="cart" + ) def get_back_to_catalogue( @@ -21,14 +21,14 @@ def get_back_to_catalogue( ).as_markup() -def main_menu_kb(user_id: int) -> InlineKeyboardMarkup: +def main_menu_kb(cart_items: int) -> InlineKeyboardMarkup: return InlineKeyboardBuilder( [ [ InlineKeyboardButton(text="📦 Каталог", callback_data="cat:root"), InlineKeyboardButton(text="🔍", callback_data="find"), ], - [cart_btn(user_id)], + [cart_btn(cart_items)], ] ).as_markup() @@ -71,7 +71,7 @@ def render_products( show_next: Optional[bool] = False, ) -> InlineKeyboardMarkup: btns = [ - [InlineKeyboardButton(text=product.name, callback_data=f"product:{product.id}")] + InlineKeyboardButton(text=product.name, callback_data=f"product:{product.id}") for product in products ] @@ -102,7 +102,7 @@ def render_products( ) ] ] - + btns + + [btns[i : i + 2] for i in range(0, len(products), 2)] + [nav] ).as_markup() diff --git a/repositories/order_items.py b/repositories/order_items.py index 79484f8..a85b09d 100644 --- a/repositories/order_items.py +++ b/repositories/order_items.py @@ -2,7 +2,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select, update from typing import Optional -from db.models.orders import OrderItem +from db.models.orders import Order, OrderItem class OrderItemRepository: @@ -12,6 +12,14 @@ class OrderItemRepository: stmt = select(OrderItem).where(OrderItem.id == item_id) return await session.scalar(stmt) + async def get_items_by_order( + self, session: AsyncSession, order_id: int + ) -> list[OrderItem]: + stmt = select(OrderItem).where(OrderItem.order_id == order_id) + result = await session.scalars(stmt) + + return list(result) + async def get_item_by_order_and_product( self, session: AsyncSession, *, order_id: int, product_id: int ) -> Optional[OrderItem]: diff --git a/services/orders.py b/services/orders.py index 5e3ee2a..3d84d4b 100644 --- a/services/orders.py +++ b/services/orders.py @@ -93,9 +93,15 @@ class OrderService: order_item = await self.order_items_repo.get_item_by_order_and_product( session, order_id=order.id, product_id=product_id ) + + if not order_item: + return 0 + return order_item.quantity - async def clear_cart_item(self, session, *, customer: int, product_id: int) -> None: + async def clear_cart_item( + self, session: AsyncSession, *, customer: int, product_id: int + ) -> None: order = await self.order_repo.get_draft_order_by_user(session, customer) if not order: @@ -115,3 +121,13 @@ class OrderService: await self.order_items_repo.update_order_item_quantity( session, order_item_id=order_item.id, quantity=0 ) + + async def get_cart_items_count(self, session: AsyncSession, customer: int) -> int: + order = await self.order_repo.get_draft_order_by_user(session, customer) + if not order: + return 0 + + order_item = await self.order_items_repo.get_items_by_order( + session, order_id=order.id + ) + return len(order_item)