Files
shveitechbot/handlers/client/products.py

165 lines
4.8 KiB
Python

import contextlib
import logging
import os
from re import Match
from aiogram import F, Router
from aiogram.fsm.context import FSMContext
from aiogram.types import CallbackQuery, FSInputFile
from sqlalchemy.ext.asyncio import AsyncSession
from config import VERIFIED_ACCOUNTS
from misc.kb import admins
from misc.kb.client import (
render_catalogue,
render_product_interactions,
)
from misc.texts import get_product_description
from repositories.products import ProductRepository
from services.catalogue import CatalogueService
from services.orders import OrderService
router = Router()
logger = logging.getLogger(__name__)
@router.callback_query(
F.data.regexp(r"products:(?P<category_id>.*):(?P<page_id>\d+)").as_("pagination_match")
)
async def products_pagination(
cb: CallbackQuery,
state: FSMContext,
pagination_match: Match[str],
session: AsyncSession,
catalogue_service: CatalogueService,
):
await state.clear()
pagination_data = pagination_match.groupdict()
category_id = int(pagination_data.get("category_id"))
page_id = int(pagination_data.get("page_id", 0))
is_admin = cb.from_user.id in VERIFIED_ACCOUNTS
view = await catalogue_service.build_category_view(
session, category_id, page=page_id, include_hidden=is_admin
)
kb = render_catalogue(view, is_admin=is_admin)
await cb.message.edit_reply_markup(reply_markup=kb)
@router.callback_query(F.data.startswith("product:"))
async def product_card(
cb: CallbackQuery,
state: FSMContext,
session: AsyncSession,
products_repo: ProductRepository,
order_service: OrderService,
):
await state.clear()
product_id = int(cb.data.split(":")[1])
is_admin = cb.from_user.id in VERIFIED_ACCOUNTS
product = await products_repo.get_product_by_id(session, product_id, include_hidden=is_admin)
if not product:
await cb.answer("Товар недоступен.", show_alert=True)
return
if is_admin:
kb = admins.edit_product(product)
else:
order_item = await order_service.get_cart_product_amount(
session, customer=cb.from_user.id, product_id=product_id
)
kb = render_product_interactions(
product_id=product.id,
category_id=product.category_id,
show_cart=bool(order_item),
cart_amount=order_item,
)
if not product.file_id and not (product.img_path and os.path.isfile(product.img_path)):
await cb.message.edit_text(
get_product_description(product),
reply_markup=kb,
)
return
await cb.message.delete()
if product.file_id:
msg = await cb.message.answer_photo(
product.file_id,
caption=get_product_description(product),
reply_markup=kb,
)
return
with contextlib.suppress(Exception):
await cb.message.edit_text("<b>⏳ Загружаем карточку товара...</b>")
msg = await cb.message.answer_photo(
FSInputFile(product.img_path),
caption=get_product_description(product),
reply_markup=kb,
)
if not msg.photo:
logger.warning("didnt get a photo back wahhh :(")
return # TODO: Add logging
await products_repo.add_product_file_id(session, product_id, file_id=msg.photo[-1].file_id)
@router.callback_query(F.data.startswith("cart_action:"))
async def cart_action(
cb: CallbackQuery,
state: FSMContext,
session: AsyncSession,
order_service: OrderService,
products_repo: ProductRepository,
):
await state.clear()
action = cb.data.split(":")[1]
product_id = int(cb.data.split(":")[2])
is_admin = cb.from_user.id in VERIFIED_ACCOUNTS
product = await products_repo.get_product_by_id(session, product_id, include_hidden=is_admin)
if not product:
await cb.answer("Товар недоступен.", show_alert=True)
return
show_cart = True
if action == "add":
quantity = await order_service.add_to_cart(
session, customer=cb.from_user.id, product_id=product_id
)
elif action == "remove":
quantity = await order_service.remove_from_cart(
session, customer=cb.from_user.id, product_id=product_id
)
show_cart = bool(quantity)
else:
show_cart = False
quantity = 0
await order_service.clear_from_cart(
session, customer=cb.from_user.id, product_id=product_id
)
try:
await cb.message.edit_reply_markup(
reply_markup=render_product_interactions(
product_id=product_id,
category_id=product.category_id,
show_cart=show_cart,
cart_amount=quantity,
)
)
except Exception as e:
await cb.answer("🍃")
raise e