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

- Реализован выбор мастера
- Добавлен выбор даты и времени
- Добавлено подтверждение записи
- Реализован раздел «Мои записи»
- Добавлена отмена записи
- Добавлена возможность редактирования записи
- Реализована проверка занятых временных слотов
- Улучшена логика 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
+42 -9
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()
create_booking( editing_booking_id = data.get(
user_id=callback.from_user.id, "editing_booking_id"
service=data["service"],
date=data["date"],
master=data["master"],
time=data["time"]
) )
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(
user_id=callback.from_user.id,
service=data["service"],
master=data["master"],
date=data["date"],
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()
+87 -20
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 == "📖 Мои записи"
)
async def my_bookings(
message: Message
):
bookings = get_user_bookings(
message.from_user.id
)
user_bookings = [ if not bookings:
b for b in bookings if b["user_id"] == user_id await message.answer(
] "У вас нет активных записей"
)
if not user_bookings:
await message.answer("У вас нет записей")
return return
text = "📖 Ваши записи:\n\n" for booking in bookings:
await message.answer(
for b in user_bookings: f"💆 {booking['service']}\n"
text += ( f"👤 {booking['master']}\n"
f"💆 {b['service']}\n" f"📅 {booking['date']}\n"
f"📅 {b['date']}\n" f"🕒 {booking['time']}",
f"🕒 {b['time']}\n\n" reply_markup=get_booking_actions(
booking["id"]
)
) )
await message.answer(text)
@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)
+75 -5
View File
@@ -2,13 +2,14 @@ from app.db.memory import bookings
def create_booking( def create_booking(
user_id: int, user_id: int,
service: str, service: str,
date: str, date: str,
master:str, master: str,
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