Добавлена система управления записями и улучшен процесс бронирования
- Реализован выбор мастера - Добавлен выбор даты и времени - Добавлено подтверждение записи - Реализован раздел «Мои записи» - Добавлена отмена записи - Добавлена возможность редактирования записи - Реализована проверка занятых временных слотов - Улучшена логика FSM и пользовательский сценарий бронирования
This commit is contained in:
+37
-4
@@ -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
@@ -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()
|
||||||
@@ -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}"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
]
|
||||||
|
)
|
||||||
@@ -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
@@ -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)
|
||||||
|
|||||||
@@ -5,10 +5,11 @@ 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
|
||||||
|
|||||||
Reference in New Issue
Block a user