Files
shveitechbot/handlers/client/checkout.py
2026-02-15 15:04:50 +07:00

184 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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("<b>👤 Укажите ваше имя:</b>", 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"<i>👤 Имя: {ctx.name}</i>\n\n<b>📱 Укажите ваш номер телефона:</b>",
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"❌ <i>{msg.text}</i> не является действительным номером, попробуйте ещё раз.",
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"<i>👤 Имя: {ctx.name}</i>\n<i>📱 Номер телефона: {ctx.phone}</i>\n\n<b>📍 Укажите ваш адрес (город, улица):</b>",
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(
"<b>‼️ Проверьте правильность ваших данных.</b>\n\n"
"━━━━━━━━━━━━━━\n\n"
f"<i>👤 Имя: {ctx.name}</i>\n"
f"<i>📱 Номер телефона: {ctx.phone}</i>\n"
f"<i>📍 Ваш адрес: {ctx.address}</i>\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(
"<b>🟢 Ваш заказ успешно отправлен!</b>\n"
"<i>📦 Мы свяжемся с вами для уточнения деталей в ближайшее время.</i>\n\n"
"<b>‼️ Чтобы убедиться, что вы общаетесь с доверенным контактом ШВЕЙТЕХЦЕНТР, перешлите любое сообщение человека в этот чат.</b>",
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"<i>👤 Имя: {ctx.name}</i>\n"
f"<i>📱 Номер телефона: {ctx.phone}</i>\n"
f"<i>📍 Адрес: {ctx.address}</i>\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