import logging from typing import Optional from aiogram import Router, F from aiogram.types import CallbackQuery, Message from aiogram.fsm.context import FSMContext from sqlalchemy.ext.asyncio import AsyncSession from config import NOTIFICATION_CHANNEL from dto.checkout import CheckoutContext from misc.kb.admins import customer_contacts from misc.kb.client import ( order_confirmation, order_specs_confirmation, return_menu, ) from misc.states import CheckoutStorage from misc.texts import get_order_item_list from misc.utils import is_valid_phone from repositories.orders import OrderRepository from services.orders import OrderService router = Router() logger = logging.getLogger(__name__) @router.callback_query(F.data == "checkout") async def checkout( cb: CallbackQuery, state: FSMContext, session: AsyncSession, order_service: OrderService, ): await state.clear() cart = await order_service.build_full_cart_dto(session, cb.from_user.id) await cb.message.edit_text( text=get_order_item_list(cart), reply_markup=order_confirmation(cart.order_id) ) @router.callback_query(F.data.startswith("confirm_order:")) async def order_confirm( cb: CallbackQuery, state: FSMContext, session: AsyncSession, order_repo: OrderRepository, ): await state.clear() order_id = cb.data.split(":")[1] if not order_id.isdigit(): await cb.message.edit_text("🍃 Что-то пошло не так.", reply_markup=return_menu) return order = await order_repo.get_order_by_id(session, int(order_id)) if not order or order.customer != cb.from_user.id: await cb.message.edit_text("🍃 Что-то пошло не так.", reply_markup=return_menu) return await cb.message.edit_text("👤 Укажите ваше имя:", reply_markup=return_menu) ctx = CheckoutContext(orig_msg=cb.message, order_id=order.id) await state.set_state(CheckoutStorage.name) await state.set_data({"ctx": ctx}) @router.message(CheckoutStorage.name) async def checkout_name(msg: Message, state: FSMContext): data = await state.get_data() ctx: CheckoutContext = data.get("ctx", CheckoutContext) await state.clear() ctx.name = msg.text await msg.delete() await ctx.orig_msg.edit_text( f"👤 Имя: {ctx.name}\n\n📱 Укажите ваш номер телефона:", reply_markup=return_menu, ) await state.set_state(CheckoutStorage.phone) await state.set_data({"ctx": ctx}) @router.message(CheckoutStorage.phone) async def checkout_phone(msg: Message, state: FSMContext): data = await state.get_data() ctx: CheckoutContext = data.get("ctx", CheckoutContext) await state.clear() await msg.delete() if not is_valid_phone(msg.text): await ctx.orig_msg.edit_text( f"❌ {msg.text} не является действительным номером, попробуйте ещё раз.", reply_markup=return_menu, ) await state.set_state(CheckoutStorage.phone) await state.set_data({"ctx": ctx}) return ctx.phone = msg.text await ctx.orig_msg.edit_text( f"👤 Имя: {ctx.name}\n📱 Номер телефона: {ctx.phone}\n\n📍 Укажите ваш адрес (город, улица):", reply_markup=return_menu, ) await state.set_state(CheckoutStorage.address) await state.set_data({"ctx": ctx}) @router.message(CheckoutStorage.address) async def checkout_address(msg: Message, state: FSMContext): data = await state.get_data() ctx: CheckoutContext = data.get("ctx", CheckoutContext) await state.clear() await msg.delete() ctx.address = msg.text await ctx.orig_msg.edit_text( "‼️ Проверьте правильность ваших данных.\n\n" "━━━━━━━━━━━━━━\n\n" f"👤 Имя: {ctx.name}\n" f"📱 Номер телефона: {ctx.phone}\n" f"📍 Ваш адрес: {ctx.address}\n\n" "━━━━━━━━━━━━━━", reply_markup=order_specs_confirmation(ctx.order_id), ) await state.set_state(CheckoutStorage.confirmation) await state.set_data({"ctx": ctx}) @router.callback_query(CheckoutStorage.confirmation) @router.callback_query(F.data.startswith("payment:")) async def payment_create( cb: CallbackQuery, state: FSMContext, session: AsyncSession, order_service: OrderService, order_repo: OrderRepository, ): data = await state.get_data() ctx: Optional[CheckoutContext] = data.get("ctx") if not ctx: await cb.message.edit_text( "🍃 Что-то пошло не так, повторите попытку позже...", reply_markup=return_menu, ) logger.warning("ctx not found on confirmation screen") return await state.clear() try: await cb.message.edit_text( "🟢 Ваш заказ успешно отправлен!\n" "📦 Мы свяжемся с вами для уточнения деталей в ближайшее время.\n\n" "‼️ Чтобы убедиться, что вы общаетесь с доверенным контактом ШВЕЙТЕХЦЕНТР, перешлите любое сообщение человека в этот чат.", reply_markup=return_menu, ) cart = await order_service.build_full_cart_dto(session, cb.from_user.id) await cb.bot.send_message( NOTIFICATION_CHANNEL, "🟢 Новый заказ.\n\n" "━━━━━━━━━━━━━━\n\n" f"👤 Имя: {ctx.name}\n" f"📱 Номер телефона: {ctx.phone}\n" f"📍 Адрес: {ctx.address}\n\n" "━━━━━━━━━━━━━━\n" f"{get_order_item_list(cart)}", reply_markup=customer_contacts( cb.from_user.id, bool(cb.from_user.username), cb.from_user.username ), ) await order_repo.remove_order_by_customer(session, cb.from_user.id) except Exception as e: await cb.message.edit_text( "🍃 Что-то пошло не так, повторите попытку позже...", reply_markup=return_menu, ) logger.exception(e) return