Добавлена система управления записями и улучшен процесс бронирования

- Реализован выбор мастера
- Добавлен выбор даты и времени
- Добавлено подтверждение записи
- Реализован раздел «Мои записи»
- Добавлена отмена записи
- Добавлена возможность редактирования записи
- Реализована проверка занятых временных слотов
- Улучшена логика FSM и пользовательский сценарий бронирования
This commit is contained in:
grigorij
2026-06-13 20:28:32 +04:00
parent 8d95ad3931
commit 8b20de1da5
6 changed files with 252 additions and 42 deletions
+37 -4
View File
@@ -7,7 +7,11 @@ from aiogram.types import Message, CallbackQuery
from app.keyboards.services import get_services_keyboard from app.keyboards.services import get_services_keyboard
from app.keyboards.masters import get_masters_keyboard from app.keyboards.masters import get_masters_keyboard
from app.states.booking import BookingState from app.states.booking import BookingState
from app.services.booking_service import create_booking from app.services.booking_service import (
create_booking,
update_booking,
get_busy_times
)
from app.keyboards.menu import menu, cancel_menu from app.keyboards.menu import menu, cancel_menu
from app.keyboards.calendar import get_dates_keyboard from app.keyboards.calendar import get_dates_keyboard
from app.keyboards.time_slots import get_time_keyboard from app.keyboards.time_slots import get_time_keyboard
@@ -121,13 +125,22 @@ async def choose_date(
date=selected_date date=selected_date
) )
data = await state.get_data()
busy_times = get_busy_times(
master=data["master"],
date=selected_date
)
await state.set_state( await state.set_state(
BookingState.time BookingState.time
) )
await callback.message.edit_text( await callback.message.edit_text(
"🕒 Выберите время:", "🕒 Выберите время:",
reply_markup=get_time_keyboard() reply_markup=get_time_keyboard(
busy_times
)
) )
await callback.answer() await callback.answer()
@@ -179,18 +192,38 @@ async def confirm_booking_callback(
): ):
data = await state.get_data() 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["service"],
master=data["master"],
date=data["date"],
time=data["time"]
)
result_text = "✅ Запись успешно обновлена"
else:
create_booking( create_booking(
user_id=callback.from_user.id, user_id=callback.from_user.id,
service=data["service"], service=data["service"],
date=data["date"],
master=data["master"], master=data["master"],
date=data["date"],
time=data["time"] time=data["time"]
) )
result_text = "✅ Запись успешно создана"
await state.clear() await state.clear()
await callback.message.edit_text( await callback.message.edit_text(
"✅ Запись успешно создана" result_text
) )
await callback.answer() await callback.answer()
+90 -23
View File
@@ -1,32 +1,99 @@
from aiogram import Router, F from aiogram import Router, F
from aiogram.types import Message from aiogram.types import (
Message,
CallbackQuery
)
from aiogram.fsm.context import FSMContext from aiogram.fsm.context import FSMContext
from app.db.memory import bookings from app.states.booking import BookingState
from app.keyboards.services import get_services_keyboard
from app.services.booking_service import (
get_user_bookings,
cancel_booking,
)
from app.keyboards.my_booking import (
get_booking_actions
)
router = Router() router = Router()
@router.message(F.text == "📖 Мои записи")
async def my_bookings(message: Message, state: FSMContext):
await state.clear()
user_id = message.from_user.id @router.message(
F.text == "📖 Мои записи"
user_bookings = [ )
b for b in bookings if b["user_id"] == user_id async def my_bookings(
] message: Message
):
if not user_bookings: bookings = get_user_bookings(
await message.answer("У вас нет записей") message.from_user.id
return
text = "📖 Ваши записи:\n\n"
for b in user_bookings:
text += (
f"💆 {b['service']}\n"
f"📅 {b['date']}\n"
f"🕒 {b['time']}\n\n"
) )
await message.answer(text) if not bookings:
await message.answer(
"У вас нет активных записей"
)
return
for booking in bookings:
await message.answer(
f"💆 {booking['service']}\n"
f"👤 {booking['master']}\n"
f"📅 {booking['date']}\n"
f"🕒 {booking['time']}",
reply_markup=get_booking_actions(
booking["id"]
)
)
@router.callback_query(
F.data.startswith(
"cancel_booking_"
)
)
async def cancel_booking_handler(
callback: CallbackQuery
):
booking_id = int(
callback.data.split("_")[-1]
)
cancel_booking(
booking_id
)
await callback.message.edit_text(
"❌ Запись отменена"
)
await callback.answer()
@router.callback_query(
F.data.startswith("edit_booking_")
)
async def edit_booking_handler(
callback: CallbackQuery,
state: FSMContext
):
booking_id = int(
callback.data.split("_")[-1]
)
await state.update_data(
editing_booking_id=booking_id
)
await state.set_state(
BookingState.service
)
await callback.message.edit_text(
"✏️ Выберите новую услугу:",
reply_markup=get_services_keyboard()
)
await callback.answer()
+25
View File
@@ -0,0 +1,25 @@
from aiogram.types import (
InlineKeyboardMarkup,
InlineKeyboardButton
)
def get_booking_actions(
booking_id: int
):
return InlineKeyboardMarkup(
inline_keyboard=[
[
InlineKeyboardButton(
text="✏️ Изменить",
callback_data=f"edit_booking_{booking_id}"
)
],
[
InlineKeyboardButton(
text="❌ Отменить",
callback_data=f"cancel_booking_{booking_id}"
)
]
]
)
+17 -6
View File
@@ -1,7 +1,13 @@
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton from aiogram.types import InlineKeyboardMarkup
from aiogram.types import InlineKeyboardButton
def get_time_keyboard(): def get_time_keyboard(
busy_times=None
):
if busy_times is None:
busy_times = []
times = [ times = [
"10:00", "10:00",
@@ -10,17 +16,22 @@ def get_time_keyboard():
"13:00", "13:00",
"14:00", "14:00",
"15:00", "15:00",
"16:00" "16:00",
"17:00"
] ]
buttons = [] buttons = []
for t in times: for time in times:
if time in busy_times:
continue
buttons.append( buttons.append(
[ [
InlineKeyboardButton( InlineKeyboardButton(
text=t, text=time,
callback_data=f"time_{t}" callback_data=f"time_{time}"
) )
] ]
) )
+5 -1
View File
@@ -10,7 +10,11 @@ from app.handlers.profile import router as profile_router
from app.handlers.mybookings import router as mybooking_router from app.handlers.mybookings import router as mybooking_router
from app.handlers.about import router as about_router from app.handlers.about import router as about_router
from app.handlers.contacts import router as contacts_router from app.handlers.contacts import router as contacts_router
from app.services.booking_service import (
create_booking,
update_booking,
get_busy_times
)
async def main(): async def main():
bot = Bot(token=BOT_TOKEN) bot = Bot(token=BOT_TOKEN)
+70
View File
@@ -9,6 +9,7 @@ def create_booking(
time: str time: str
): ):
booking = { booking = {
"id": len(bookings) + 1,
"user_id": user_id, "user_id": user_id,
"service": service, "service": service,
"date": date, "date": date,
@@ -20,3 +21,72 @@ def create_booking(
bookings.append(booking) bookings.append(booking)
return booking return booking
def get_busy_times(
master: str,
date: str
):
busy_times = []
for booking in bookings:
if (
booking["master"] == master
and booking["date"] == date
and booking["status"] == "active"
):
busy_times.append(
booking["time"]
)
return busy_times
def get_user_bookings(
user_id: int
):
result = []
for booking in bookings:
if (
booking["user_id"] == user_id
and booking["status"] == "active"
):
result.append(booking)
return result
def cancel_booking(
booking_id: int
):
for booking in bookings:
if booking["id"] == booking_id:
booking["status"] = "cancelled"
return True
return False
def update_booking(
booking_id: int,
service: str,
master: str,
date: str,
time: str
):
for booking in bookings:
if booking["id"] == booking_id:
booking["service"] = service
booking["master"] = master
booking["date"] = date
booking["time"] = time
return booking
return None