* настроена структура проекта * подключены handlers и routers * реализовано главное меню * добавлены разделы: профиль, контакты, о компании, мои записи * реализована FSM-машина состояний для записи * добавлен сервисный слой booking_service * реализовано сохранение записей в памяти * добавлено подтверждение записи * реализована отмена записи * исправлены конфликты FSM и кнопок меню * добавлена отдельная клавиатура во время записи * выполнен рефакторинг импортов и структуры проекта * улучшен пользовательский сценарий записи
122 lines
3.1 KiB
Python
122 lines
3.1 KiB
Python
from aiogram import Router, F
|
|
from aiogram.types import Message
|
|
from aiogram.fsm.context import FSMContext
|
|
from aiogram.filters import StateFilter
|
|
|
|
from app.states.booking import BookingState
|
|
from app.services.booking_service import create_booking
|
|
from app.keyboards.menu import menu, cancel_menu
|
|
|
|
router = Router()
|
|
|
|
|
|
# отмена записи на любом шаге
|
|
@router.message(F.text.lower() == "отмена")
|
|
async def cancel(message: Message, state: FSMContext):
|
|
await state.clear()
|
|
await message.answer(
|
|
"❌ Запись отменена",
|
|
reply_markup=menu
|
|
)
|
|
|
|
|
|
# старт записи
|
|
@router.message(F.text == "📅 Записаться")
|
|
async def start_booking(message: Message, state: FSMContext):
|
|
await state.clear()
|
|
|
|
await state.set_state(BookingState.service)
|
|
|
|
await message.answer(
|
|
"Выберите услугу:\n"
|
|
"1. Массаж\n"
|
|
"2. SPA\n"
|
|
"3. Косметология",
|
|
reply_markup=cancel_menu
|
|
)
|
|
|
|
|
|
# выбор услуги
|
|
@router.message(StateFilter(BookingState.service))
|
|
async def choose_service(message: Message, state: FSMContext):
|
|
|
|
forbidden = [
|
|
"📅 Записаться",
|
|
"👤 Профиль",
|
|
"📖 Мои записи",
|
|
"ℹ️ О компании",
|
|
"📞 Контакты"
|
|
]
|
|
|
|
if message.text in forbidden:
|
|
await message.answer(
|
|
"⚠️ Сначала завершите запись или напишите 'отмена'"
|
|
)
|
|
return
|
|
|
|
await state.update_data(service=message.text)
|
|
|
|
await state.set_state(BookingState.date)
|
|
|
|
await message.answer(
|
|
"Введите дату (например 20.06)"
|
|
)
|
|
|
|
|
|
# выбор даты
|
|
@router.message(StateFilter(BookingState.date))
|
|
async def choose_date(message: Message, state: FSMContext):
|
|
|
|
forbidden = [
|
|
"📅 Записаться",
|
|
"👤 Профиль",
|
|
"📖 Мои записи",
|
|
"ℹ️ О компании",
|
|
"📞 Контакты"
|
|
]
|
|
|
|
if message.text in forbidden:
|
|
await message.answer(
|
|
"⚠️ Сначала завершите запись или напишите 'отмена'"
|
|
)
|
|
return
|
|
|
|
await state.update_data(date=message.text)
|
|
|
|
data = await state.get_data()
|
|
|
|
await state.set_state(BookingState.confirm)
|
|
|
|
await message.answer(
|
|
f"Услуга: {data['service']}\n"
|
|
f"Дата: {data['date']}\n\n"
|
|
f"Напишите 'да' для подтверждения"
|
|
)
|
|
|
|
|
|
# подтверждение
|
|
@router.message(StateFilter(BookingState.confirm))
|
|
async def confirm_booking(message: Message, state: FSMContext):
|
|
|
|
if message.text.lower() != "да":
|
|
await state.clear()
|
|
|
|
await message.answer(
|
|
"❌ Запись отменена",
|
|
reply_markup=menu
|
|
)
|
|
|
|
data = await state.get_data()
|
|
|
|
create_booking(
|
|
user_id=message.from_user.id,
|
|
service=data["service"],
|
|
date=data["date"]
|
|
)
|
|
|
|
await state.clear()
|
|
|
|
await message.answer(
|
|
"✅ Вы успешно записаны!",
|
|
reply_markup=menu
|
|
) |