Files
demo_spa_bot/app/handlers/booking.py
T
DevProject Agent a6a1e0d8a9 📝 Логирование + graceful shutdown
- Добавлен app/logger.py — loguru с ротацией (консоль, файл, ошибки)
- main.py: логи старта/стопа, graceful shutdown (SIGTERM/SIGINT/stop_signal)
- Все хендлеры: логирование ключевых действий пользователя
- Логи сохраняются в logs/bot_YYYY-MM-DD.log, ротация 30 дней
- Ошибки отдельно в logs/errors_*
2026-06-14 19:43:46 +04:00

273 lines
6.4 KiB
Python

import re
from aiogram import Router, F
from aiogram.fsm.context import FSMContext
from aiogram.filters import StateFilter
from aiogram.types import Message, CallbackQuery
from app.keyboards.services import get_services_keyboard
from app.keyboards.masters import get_masters_keyboard
from app.states.booking import BookingState
from app.services.booking_service import (
create_booking,
update_booking,
get_busy_times
)
from app.keyboards.menu import menu, cancel_menu
from app.keyboards.calendar import get_dates_keyboard
from app.keyboards.time_slots import get_time_keyboard
from app.keyboards.confirm_booking import get_confirm_booking_keyboard
from app.logger import logger
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(
"Выберите услугу:",
reply_markup=get_services_keyboard()
)
@router.callback_query(
StateFilter(BookingState.service),
F.data.startswith("service_")
)
async def choose_service(
callback: CallbackQuery,
state: FSMContext
):
from app.config import SERVICES
services = SERVICES
service_name = services[callback.data]
logger.debug("User {uid} selected service: {srv}", uid=callback.from_user.id, srv=service_name)
await state.update_data(
service=service_name
)
await state.set_state(
BookingState.master
)
await callback.message.edit_text(
"👤 Выберите специалиста:",
reply_markup=get_masters_keyboard()
)
await callback.answer()
#выбор мастера
@router.callback_query(
StateFilter(BookingState.master),
F.data.startswith("master_")
)
async def choose_master(
callback: CallbackQuery,
state: FSMContext
):
from app.config import MASTERS
masters = MASTERS
master_name = masters[callback.data]
logger.debug("User {uid} selected master: {m}", uid=callback.from_user.id, m=master_name)
await state.update_data(
master=master_name
)
await state.set_state(
BookingState.date
)
await callback.message.edit_text(
"📅 Выберите дату:",
reply_markup=get_dates_keyboard()
)
await callback.answer()
# выбор даты
@router.callback_query(
StateFilter(BookingState.date),
F.data.startswith("date_")
)
async def choose_date(
callback: CallbackQuery,
state: FSMContext
):
selected_date = callback.data.replace(
"date_",
""
)
await state.update_data(
date=selected_date
)
logger.debug("User {uid} selected date: {d}", uid=callback.from_user.id, d=selected_date)
data = await state.get_data()
busy_times = get_busy_times(
master=data.get('master', '?'),
date=selected_date
)
await state.set_state(
BookingState.time
)
await callback.message.edit_text(
"🕒 Выберите время:",
reply_markup=get_time_keyboard(
busy_times
)
)
await callback.answer()
@router.callback_query(
StateFilter(BookingState.time),
F.data.startswith("time_")
)
async def choose_time(
callback: CallbackQuery,
state: FSMContext
):
selected_time = callback.data.replace(
"time_",
""
)
await state.update_data(
time=selected_time
)
logger.debug("User {uid} selected time: {t}", uid=callback.from_user.id, t=selected_time)
data = await state.get_data()
await state.set_state(
BookingState.confirm
)
await callback.message.edit_text(
f"📋 Проверьте запись:\n\n"
f"💆 Услуга: {data.get('service', '?')}\n"
f"📅 Дата: {data.get('date', '?')}\n"
f"👤 Мастер:{data.get('master', '?')}\n"
f"🕒 Время: {selected_time}",
reply_markup=get_confirm_booking_keyboard()
)
await callback.answer()
# подтверждение
@router.callback_query(
StateFilter(BookingState.confirm),
F.data == "confirm_booking"
)
async def confirm_booking_callback(
callback: CallbackQuery,
state: FSMContext
):
data = await state.get_data()
editing_booking_id = data.get(
"editing_booking_id"
)
if editing_booking_id:
update_booking(
booking_id=editing_booking_id,
service=data.get('service', '?'),
master=data.get('master', '?'),
date=data.get('date', '?'),
time=data.get('time', '?')
)
result_text = "✅ Запись успешно обновлена"
else:
create_booking(
user_id=callback.from_user.id,
service=data.get('service', '?'),
master=data.get('master', '?'),
date=data.get('date', '?'),
time=data.get('time', '?')
)
result_text = "✅ Запись успешно создана"
await state.clear()
await callback.message.edit_text(
result_text
)
await callback.answer()
@router.callback_query(
StateFilter(BookingState.confirm),
F.data == "cancel_booking"
)
async def cancel_booking_callback(
callback: CallbackQuery,
state: FSMContext
):
await state.clear()
await callback.message.edit_text(
"❌ Запись отменена"
)
await callback.answer()
@router.callback_query(
StateFilter(BookingState.confirm),
F.data == "edit_booking"
)
async def edit_booking_callback(
callback: CallbackQuery,
state: FSMContext
):
old_data = await state.get_data()
await state.clear()
await state.update_data(
service=old_data.get("service")
)
await state.set_state(
BookingState.service
)
from app.keyboards.services import get_services_keyboard
await callback.message.edit_text(
"Выберите услугу:",
reply_markup=get_services_keyboard()
)