import logging from sqlalchemy.ext.asyncio import AsyncSession from db.models.orders import OrderStatus from repositories.order_items import OrderItemRepository from repositories.orders import OrderRepository logger = logging.getLogger(__name__) class OrderServiceException(Exception): ... class OrderService: def __init__( self, order_repo: OrderRepository, order_items_repo: OrderItemRepository ): self.order_repo = order_repo self.order_items_repo = order_items_repo async def get_order_count(self, session: AsyncSession, customer: int) -> int: orders = await self.order_repo.get_orders_by_user(session, customer) return len(orders) async def add_to_cart( self, session: AsyncSession, *, customer: int, product_id: int, quantity: int = 1, ) -> int: order = await self.order_repo.get_draft_order_by_user(session, customer) if not order: order = await self.order_repo.create_order( session, customer, OrderStatus.DRAFT ) 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: order_item = await self.order_items_repo.create_order_item( session, order_id=order.id, product_id=product_id, quantity=quantity ) else: await self.order_items_repo.update_order_item_quantity( session, order_item.id, quantity=order_item.quantity + quantity ) return order_item.quantity + quantity async def remove_from_cart( self, session: AsyncSession, *, customer: int, product_id: int, quantity: int = 1, ) -> int: order = await self.order_repo.get_draft_order_by_user(session, customer) if not order: raise OrderServiceException( "attempt of removing product from non-existing cart, potential callback_query exploit, ignoring..." ) 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: raise OrderServiceException( "attempt of decreasing quantity of non-existing order_item, potential callback_query exploit, ignoring..." ) new_quantity = max(0, order_item.quantity - quantity) await self.order_items_repo.update_order_item_quantity( session, order_item_id=order_item.id, quantity=new_quantity ) return new_quantity async def get_cart_product_amount( self, session: AsyncSession, *, customer: int, product_id: 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_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: AsyncSession, *, customer: int, product_id: int ) -> None: order = await self.order_repo.get_draft_order_by_user(session, customer) if not order: raise OrderServiceException( "attempt of clearing a non-existing cart, potential callback_query exploit, ignoring..." ) 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: raise OrderServiceException( "attempt of clearing an order_item that isn't in a cart, potential callback_query exploit, ignoring..." ) 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)