diff --git a/manicure_bot.db b/manicure_bot.db index 7f4d47a..955b065 100644 Binary files a/manicure_bot.db and b/manicure_bot.db differ diff --git a/requirements.txt b/requirements.txt index 421d6f1..6b0002e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ aiogram-calendar==0.5.0 aiohappyeyeballs==2.4.0 aiohttp==3.10.5 aiosignal==1.3.1 +aiosqlite==0.20.0 alembic==1.13.2 annotated-types==0.7.0 anyio==4.6.0 diff --git a/src/api/dao.py b/src/api/dao.py new file mode 100644 index 0000000..d92cc50 --- /dev/null +++ b/src/api/dao.py @@ -0,0 +1,116 @@ +import json +import logging +from datetime import date + +from sqlalchemy import select +from sqlalchemy.exc import SQLAlchemyError +from sqlalchemy.orm import joinedload + +from src.dao.base import BaseDAO +from src.database import User, Service, Appointment, Photo, AvailableTimeSlot +from src.database.db import async_session_maker +from src.database.models import AppointmentStatus + +logger = logging.getLogger(__name__) + + +class UserDAO(BaseDAO): + model = User + + +class ServiceDAO(BaseDAO): + model = Service + + +class AppointmentDAO(BaseDAO): + model = Appointment + + @classmethod + async def get_appointments(cls, user_id: int = None): + async with async_session_maker() as session: + filters = [] + if user_id is not None: + filters.append(cls.model.user_id == user_id) + + active_appointments = await session.execute( + select(cls.model).filter( + *filters, + cls.model.status.in_([AppointmentStatus.ACTIVE.value, AppointmentStatus.CONFIRMED.value]) + ).options(joinedload(cls.model.services)) + ) + archived_appointments = await session.execute( + select(cls.model).filter( + *filters, + cls.model.status == AppointmentStatus.ARCHIVED.value + ).options(joinedload(cls.model.services)) + ) + return active_appointments.unique().scalars().all(), archived_appointments.unique().scalars().all() + + @classmethod + async def add_service(cls, appointment_id: int, service: Service): + """Добавляет услугу к записи""" + async with async_session_maker() as session: + try: + # Загружаем запись вместе с услугами + stmt = select(cls.model).options( + joinedload(cls.model.services) + ).where(cls.model.id == appointment_id) + result = await session.execute(stmt) + appointment = result.unique().scalar_one_or_none() + + if appointment: + # Получаем service из текущей сессии + service = await session.merge(service) + if service not in appointment.services: + appointment.services.append(service) + await session.commit() + return True + return True + return False + except SQLAlchemyError: + await session.rollback() + return False + + @classmethod + async def delete_with_services(cls, appointment_id: int): + """Удаляет запись вместе со всеми связанными услугами""" + async with async_session_maker() as session: + try: + # Загружаем запись вместе с услугами + stmt = select(cls.model).options( + joinedload(cls.model.services) + ).where(cls.model.id == appointment_id) + result = await session.execute(stmt) + appointment = result.unique().scalar_one_or_none() + + if appointment: + # Очищаем связи с услугами + appointment.services = [] + # Удаляем саму запись + await session.delete(appointment) + await session.commit() + return True + return False + except SQLAlchemyError: + await session.rollback() + return False + + +class PhotoDAO(BaseDAO): + model = Photo + + +class AvailableTimeSlotDAO(BaseDAO): + model = AvailableTimeSlot + + @classmethod + async def add_or_update(cls, date: date, slots: list[str]): + existing_slot = await cls.find_one_or_none(date=date) + time_slots = json.dumps(slots) + + if existing_slot: + # Обновляем существующую запись + await cls.update(existing_slot.id, time_slots=time_slots) + else: + # Добавляем новую запись + await cls.add(date=date, time_slots=time_slots) diff --git a/src/api/router.py b/src/api/router.py index ab99f8e..67cdbda 100644 --- a/src/api/router.py +++ b/src/api/router.py @@ -4,14 +4,14 @@ from fastapi.requests import Request from fastapi.responses import JSONResponse -from src.api.schemas import AppointmentData, Schedule, ServiceData, ServiceResponse +from src.api.dao import AppointmentDAO, AvailableTimeSlotDAO, ServiceDAO, UserDAO + +from src.api.schemas import AppointmentData, Schedule, ServiceData from src.api.utils import archive_appointment from src.bot.bot_instance import bot from src.bot.handlers.reminder_router import schedule_reminder from src.bot.keyboards import contact_button, main_keyboard from src.config import settings -from src.database import Appointment, AvailableTimeSlot, Service, User -from src.database.db import get_db from src.database.models import AppointmentStatus from src.middlewares.scheduler import scheduler @@ -28,10 +28,9 @@ async def create_appointment(request: Request): formatted_time = validated_data.appointment_time.strftime("%H:%M") formatted_date = validated_data.appointment_date.strftime("%d.%m.%Y") - with get_db() as db: - user = db.query(User).filter(User.id == validated_data.user_id).first() - if not user: - raise HTTPException(status_code=404, detail="Пользователь не найден") + user = await UserDAO.find_one_or_none(id=validated_data.user_id) + if not user: + raise HTTPException(status_code=404, detail="Пользователь не найден") # Формируем сообщение для пользователя message = ( @@ -62,32 +61,28 @@ async def create_appointment(request: Request): ) # Добавление заявки в базу данных - with get_db() as db: - appointment = Appointment( - user_id=validated_data.user_id, - name=validated_data.name, - date=validated_data.appointment_date, - time=validated_data.appointment_time, - total_price=validated_data.total_price, - status=AppointmentStatus.ACTIVE.value - ) - db.add(appointment) - db.commit() # Сохраняем изменения - - # Добавление услуг в ассоциативную таблицу - for service_name in validated_data.services: - service = db.query(Service).filter(Service.name == service_name).first() - if service: - appointment.services.append(service) # Добавляем услуги к записи - - db.commit() # Сохраняем изменения с услугами - - change_time = datetime.combine( - validated_data.appointment_date, - validated_data.appointment_time - ) + timedelta(hours=2) - scheduler.add_job(archive_appointment, "date", run_date=change_time, args=[appointment.id]) - schedule_reminder(appointment) + appointment = await AppointmentDAO.add( + user_id=validated_data.user_id, + name=validated_data.name, + date=validated_data.appointment_date, + time=validated_data.appointment_time, + total_price=validated_data.total_price, + status=AppointmentStatus.ACTIVE.value + ) + + # Добавление услуг к заявке + for service_name in validated_data.services: + service = await ServiceDAO.find_one_or_none(name=service_name) + if service: + await AppointmentDAO.add_service(appointment.id, service) + + change_time = datetime.combine( + validated_data.appointment_date, + validated_data.appointment_time + ) + timedelta(hours=2) + # + timedelta(hours=2) + scheduler.add_job(archive_appointment, "date", run_date=change_time, args=[appointment.id]) + schedule_reminder(appointment) kb = main_keyboard(user_id=validated_data.user_id, first_name=validated_data.name) inline_kb = contact_button() @@ -102,119 +97,95 @@ async def create_appointment(request: Request): @router.delete("/appointment/{appointment_id}") async def delete_appointment(appointment_id: int): - with get_db() as db: - appointment = db.query(Appointment).filter(Appointment.id == appointment_id).first() - if appointment: - db.delete(appointment) - db.commit() - return JSONResponse(status_code=200, content={"message": "Запись удалена"}) - return JSONResponse(status_code=404, content={"message": "Запись не найдена"}) + is_deleted = await AppointmentDAO.delete_with_services(appointment_id) + if is_deleted: + return JSONResponse(status_code=200, content={"message": "Запись удалена"}) + return JSONResponse(status_code=404, content={"message": "Запись не найдена"}) @router.get("/all-slots/{date}") async def get_all_slots(date: date): - with get_db() as db: - slot = db.query(AvailableTimeSlot).filter(AvailableTimeSlot.date == date).first() - if slot: - return {"slots": slot.get_time_slots()} - return JSONResponse(status_code=404, content={"message": "Слоты не найдены"}) + slot = await AvailableTimeSlotDAO.find_one_or_none(date=date) + if slot: + return {"slots": slot.get_time_slots()} + return JSONResponse(status_code=404, content={"message": "Слоты не найдены"}) @router.get("/available-slots/{date}") async def get_available_slots(date: date): - with get_db() as db: - slot = db.query(AvailableTimeSlot).filter(AvailableTimeSlot.date == date).first() + slot = await AvailableTimeSlotDAO.find_one_or_none(date=date) + if slot: # Отфильтровываем уже забронированные места - booked_times = db.query(Appointment.time).filter(Appointment.date == date).all() - booked_times = {t[0].strftime("%H:%M") for t in booked_times} - # Удаляем забронированные слоты из списка доступных слотов - if slot: - available_slots = [time for time in slot.get_time_slots() if time not in booked_times] - return {"slots": available_slots} - return JSONResponse(status_code=404, content={"message": "Слоты не найдены"}) + booked_times = await AppointmentDAO.find_all(date=date) + booked_times = {time.time.strftime("%H:%M") for time in booked_times} + available_slots = [time for time in slot.get_time_slots() if time not in booked_times] + return {"slots": available_slots} + return JSONResponse(status_code=404, content={"message": "Слоты не найдены"}) @router.post("/schedule") async def save_schedule(schedule: Schedule): - with get_db() as db: - existing_slots = db.query(AvailableTimeSlot).filter(AvailableTimeSlot.date == schedule.date).first() + if not schedule.slots or len(schedule.slots) == 0: + # Если слоты не выбраны, удаляем запись для данной даты + await AvailableTimeSlotDAO.delete(date=schedule.date) + return {"status": "deleted"} - if not schedule.slots or len(schedule.slots) == 0: - # Если слоты не выбраны, удаляем запись для данной даты - if existing_slots: - db.query(AvailableTimeSlot).filter(AvailableTimeSlot.date == schedule.date).delete() - db.commit() - - # Если слоты выбраны, обновляем существующую запись - if existing_slots: - existing_slots.set_time_slots(schedule.slots) - else: - # Если записи не существует, создаем новую - new_slot = AvailableTimeSlot(date=schedule.date) - new_slot.set_time_slots(schedule.slots) - db.add(new_slot) - - db.commit() - - return {"status": "success"} + # Если слоты выбраны, добавляем или обновляем запись + await AvailableTimeSlotDAO.add_or_update(schedule.date, schedule.slots) + return {"status": "success"} @router.get("/schedules") async def get_schedules(): - with get_db() as db: - schedules = db.query(AvailableTimeSlot).all() - response = {} - for slot in schedules: - response[slot.date] = slot.get_time_slots() + schedules = await AvailableTimeSlotDAO.find_all() + response = {} + for slot in schedules: + response[slot.date] = slot.get_time_slots() - return [{"date": date, "slots": times} for date, times in response.items()] + return [{"date": date, "slots": times} for date, times in response.items()] -@router.post("/services", response_model=ServiceResponse, status_code=201) +@router.post("/services", status_code=201) async def create_service(request: Request): data = await request.json() validated_data = ServiceData(**data) - service = Service( + service = await ServiceDAO.add( name=validated_data.name, price=validated_data.price, duration=validated_data.duration, description=validated_data.description ) - with get_db() as db: - db.add(service) - db.commit() - db.refresh(service) + if not service: + raise HTTPException(status_code=400, detail="Failed to create service") return service -@router.put("/services/{service_id}", response_model=ServiceResponse, status_code=200) +@router.put("/services/{service_id}", status_code=200) async def update_service(service_id: int, request: Request): data = await request.json() - with get_db() as db: - service = db.query(Service).filter(Service.id == service_id).first() - if not service: - raise HTTPException(status_code=404, detail="Service not found") + # Найти существующую услугу + service = await ServiceDAO.find_one_or_none(id=service_id) + if not service: + raise HTTPException(status_code=404, detail="Service not found") - service.name = data['name'] - service.price = data['price'] - service.duration = data['duration'] - service.description = data['description'] + # Обновить атрибуты + for key, value in data.items(): + setattr(service, key, value) - db.commit() - db.refresh(service) - - return service + # Сохранить изменения + result = await ServiceDAO.update(service_id, **data) # Убедитесь, что передаете нужные данные + if result: + return await ServiceDAO.find_one_or_none(id=service_id) # Возвращаем обновленную запись + else: + raise HTTPException(status_code=500, detail="Failed to update service") @router.delete("/services/{service_id}") async def delete_service(service_id: int): - with get_db() as db: - service = db.query(Service).filter(Service.id == service_id).first() - if service: - db.delete(service) - db.commit() - return JSONResponse(status_code=200, content={"message": "Услуга удалена"}) - return JSONResponse(status_code=404, content={"message": "Услуга не найдена"}) + service = await ServiceDAO.delete(id=service_id) + if service: + return JSONResponse(status_code=200, content={"message": "Услуга удалена"}) + return JSONResponse(status_code=404, content={"message": "Услуга не найдена"}) diff --git a/src/api/utils.py b/src/api/utils.py index 76992aa..f576cb3 100644 --- a/src/api/utils.py +++ b/src/api/utils.py @@ -1,13 +1,10 @@ -from src.database import Appointment -from src.database.db import get_db +from src.api.dao import AppointmentDAO from src.database.models import AppointmentStatus async def archive_appointment(appointment_id: int): - with get_db() as db: - appointment = db.query(Appointment).filter(Appointment.id == appointment_id).first() - if appointment: - appointment.status = AppointmentStatus.ARCHIVED.value - db.commit() - print("Запись перенесена в архив") + appointment = await AppointmentDAO.update(appointment_id, status=AppointmentStatus.ARCHIVED.value) + if appointment: + print("Запись перенесена в архив") + else: print("Запись не найдена") diff --git a/src/bot/handlers/examples_of_works_router.py b/src/bot/handlers/examples_of_works_router.py index 35f1d4f..d36b486 100644 --- a/src/bot/handlers/examples_of_works_router.py +++ b/src/bot/handlers/examples_of_works_router.py @@ -8,7 +8,7 @@ @router.message(F.text == "💅Примеры работ") async def show_photo(message: types.Message): - photos = get_photos() + photos = await get_photos() media = [types.InputMediaPhoto(media=photo.photo_url) for photo in photos] await message.answer("Вот фото нескольких работ:") await message.answer_media_group(media, reply_markup=main_keyboard( diff --git a/src/bot/handlers/reminder_router.py b/src/bot/handlers/reminder_router.py index 6bb78a6..9c6404f 100644 --- a/src/bot/handlers/reminder_router.py +++ b/src/bot/handlers/reminder_router.py @@ -7,10 +7,9 @@ InlineKeyboardMarkup ) +from src.api.dao import AppointmentDAO from src.bot.bot_instance import bot from src.config import settings -from src.database import Appointment -from src.database.db import get_db from src.database.models import AppointmentStatus from src.middlewares.scheduler import scheduler @@ -47,31 +46,27 @@ async def process_callback_button(callback_query: CallbackQuery): action, appointment_id = callback_query.data.split('_') appointment_id = int(appointment_id) - with get_db() as db: - appointment = db.query(Appointment).filter(Appointment.id == appointment_id).first() - - if appointment is None: - return - - user_id = appointment.user_id - appointment_time = appointment.time.strftime('%H:%M') - client_name = appointment.name - - if action == 'confirm': - appointment.status = AppointmentStatus.CONFIRMED.value - client_message = "Спасибо за подтверждение! Жду Вас в назначенное время. 🌼" - elif action == 'cancel': - db.delete(appointment) - client_message = "Ваша запись отменена. Спасибо! 🌼" - - admin_message = ( - f"🔔 {'Клиент подтвердил' if action == 'confirm' else 'Клиент отменил'} запись:\n\n" - f"👤 Имя клиента: {client_name}\n" - f"👤 Профиль: @{callback_query.from_user.username}\n" - f"⏰ Время: {appointment_time}\n" - ) - - db.commit() + appointment = await AppointmentDAO.find_one_or_none(id=appointment_id) + if appointment is None: + return + + user_id = appointment.user_id + appointment_time = appointment.time.strftime('%H:%M') + client_name = appointment.name + + if action == 'confirm': + await AppointmentDAO.update(appointment_id, status=AppointmentStatus.CONFIRMED.value) + client_message = "Спасибо за подтверждение! Жду Вас в назначенное время. 🌼" + elif action == 'cancel': + await AppointmentDAO.delete(id=appointment_id) + client_message = "Ваша запись отменена. Спасибо! 🌼" + + admin_message = ( + f"🔔 {'Клиент подтвердил' if action == 'confirm' else 'Клиент отменил'} запись:\n\n" + f"👤 Имя клиента: {client_name}\n" + f"👤 Профиль: @{callback_query.from_user.username}\n" + f"⏰ Время: {appointment_time}\n" + ) await bot.send_message(chat_id=user_id, text=client_message) await bot.send_message(chat_id=settings.MASTER_CHAT_ID, text=admin_message) diff --git a/src/bot/handlers/user_router.py b/src/bot/handlers/user_router.py index ccf5709..4048882 100644 --- a/src/bot/handlers/user_router.py +++ b/src/bot/handlers/user_router.py @@ -2,8 +2,7 @@ from aiogram.filters import CommandStart from aiogram.types import Message -from src.database import User -from src.database.db import get_db +from src.api.dao import UserDAO from src.utils import greet_user router = Router() @@ -14,15 +13,13 @@ async def cmd_start(message: Message) -> None: """ Обрабатывает команду /start. """ - with get_db() as db: - user = db.query(User).filter(User.id == message.from_user.id).first() + user = await UserDAO.find_one_or_none(id=message.from_user.id) - if not user: - db.add(User( - id=message.from_user.id, - name=message.from_user.first_name, - username=message.from_user.username - )) - db.commit() + if not user: + user = UserDAO.add( + id=message.from_user.id, + name=message.from_user.first_name, + username=message.from_user.username + ) await greet_user(message, is_new_user=not user) diff --git a/src/dao/base.py b/src/dao/base.py new file mode 100644 index 0000000..138ca07 --- /dev/null +++ b/src/dao/base.py @@ -0,0 +1,66 @@ +from sqlalchemy import delete, insert, select, update +from sqlalchemy.exc import SQLAlchemyError + +from src.database.db import async_session_maker +import logging + + +class BaseDAO: + model = None + + # Метод было решено скрестить с find_one_or_none, т.к. они выполняют одну и ту же функцию + # @classmethod + # async def find_by_id(cls, model_id: int): + # async with async_session_maker() as session: + # query = select(cls.model).filter_by(id=model_id) + # result = await session.execute(query) + # return result.mappings().one_or_none() + + @classmethod + async def find_one_or_none(cls, **filter_by): + async with async_session_maker() as session: + query = select(cls.model).filter_by(**filter_by) + result = await session.execute(query) + return result.scalar_one_or_none() + + @classmethod + async def find_all(cls, **filter_by): + async with async_session_maker() as session: + query = select(cls.model).filter_by(**filter_by) + result = await session.execute(query) + return result.scalars().all() + + @classmethod + async def add(cls, **data): + async with async_session_maker() as session: + async with session.begin(): + new_instance = cls.model(**data) + session.add(new_instance) + try: + await session.commit() + except SQLAlchemyError as e: + await session.rollback() + return new_instance + + @classmethod + async def delete(cls, **filter_by): + async with async_session_maker() as session: + query = delete(cls.model).filter_by(**filter_by) + result = await session.execute(query) + await session.commit() + return result.rowcount > 0 + + @classmethod + async def update(cls, id: int, **data): + try: + query = update(cls.model).where(cls.model.id == id).values(**data) + async with async_session_maker() as session: + await session.execute(query) + await session.commit() + return True + except SQLAlchemyError as e: + logging.error(f"SQLAlchemyError: {e}") + return False + except Exception as e: + logging.error(f"Exception: {e}") + return False diff --git a/src/database/db.py b/src/database/db.py index 18fc79d..ea5b4fa 100644 --- a/src/database/db.py +++ b/src/database/db.py @@ -1,18 +1,6 @@ -from contextlib import contextmanager - -from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker +from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine, AsyncSession from src.config import settings -engine = create_engine(settings.DATABASE_URL) -SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) - - -@contextmanager -def get_db(): - db = SessionLocal() - try: - yield db - finally: - db.close() +engine = create_async_engine(settings.DATABASE_URL) +async_session_maker = async_sessionmaker(engine, autoflush=False, expire_on_commit=False, class_=AsyncSession) diff --git a/src/middlewares/scheduler.py b/src/middlewares/scheduler.py index 8a9ce6c..ed37ed7 100644 --- a/src/middlewares/scheduler.py +++ b/src/middlewares/scheduler.py @@ -11,11 +11,7 @@ MOSCOW_TZ = pytz.timezone("Europe/Moscow") -jobstores = { - 'default': SQLAlchemyJobStore(url=settings.DATABASE_URL) -} - -scheduler = AsyncIOScheduler(jobstores=jobstores, timezone=MOSCOW_TZ) +scheduler = AsyncIOScheduler(timezone=MOSCOW_TZ) class SchedulerMiddleware(BaseMiddleware): diff --git a/src/pages/router.py b/src/pages/router.py index ca47fdd..1f1bc84 100644 --- a/src/pages/router.py +++ b/src/pages/router.py @@ -3,12 +3,8 @@ from fastapi.responses import HTMLResponse from fastapi.templating import Jinja2Templates -from sqlalchemy.orm import joinedload - +from src.api.dao import ServiceDAO, AppointmentDAO, UserDAO from src.config import settings -from src.database import Appointment, Service, User -from src.database.db import get_db -from src.database.models import AppointmentStatus router = APIRouter(prefix='', tags=['Фронтенд']) templates = Jinja2Templates(directory='src/templates') @@ -24,8 +20,7 @@ async def get_home_page(request: Request): @router.get("/form", response_class=HTMLResponse) async def get_service_form(request: Request, user_id: int = None, first_name: str = None): - with get_db() as db: - services = db.query(Service).all() + services = await ServiceDAO.find_all() data_page = {"request": request, "user_id": user_id, "first_name": first_name, @@ -37,31 +32,24 @@ async def get_service_form(request: Request, user_id: int = None, first_name: st @router.get("/appointments", response_class=HTMLResponse) async def get_user_appointments(request: Request, user_id: int = None): data_page = {"request": request, "access": False, 'title_h1': "Мои записи"} - with get_db() as db: - user_check = db.query(User).filter(User.id == user_id).first() - services = db.query(Service).all() - data_page['services'] = services + user_check = await UserDAO.find_one_or_none(id=user_id) - if user_id is None or user_check is None: - data_page['message'] = 'Пользователь не указан или не найден в базе данных' - return templates.TemplateResponse("appointments.html", data_page) - else: - active_appointments = db.query(Appointment).filter( - Appointment.user_id == user_id, Appointment.status.in_([ - AppointmentStatus.ACTIVE.value, - AppointmentStatus.CONFIRMED.value - ])).all() - archived_appointments = db.query(Appointment).filter( - Appointment.user_id == user_id, Appointment.status == AppointmentStatus.ARCHIVED.value - ).all() - data_page['access'] = True - data_page['active_appointments'] = active_appointments - data_page['archived_appointments'] = archived_appointments + if user_id is None or user_check is None: + data_page['message'] = 'Пользователь не указан или не найден в базе данных' + return templates.TemplateResponse("appointments.html", data_page) - if not active_appointments and not archived_appointments: - data_page['message'] = 'У вас нет записей!' + active_appointments, archived_appointments = await AppointmentDAO.get_appointments(user_id) + services = await ServiceDAO.find_all() - return templates.TemplateResponse("appointments.html", data_page) + data_page['access'] = True + if not active_appointments and not archived_appointments: + data_page['message'] = 'У вас нет записей!' + else: + data_page['services'] = services + data_page['active_appointments'] = active_appointments + data_page['archived_appointments'] = archived_appointments + + return templates.TemplateResponse("appointments.html", data_page) @router.get("/admin/appointments", response_class=HTMLResponse) @@ -71,17 +59,10 @@ async def get_admin_panel(request: Request, admin_id: int = None): data_page['message'] = 'У вас нет прав для получения информации о записях!' return templates.TemplateResponse("appointments.html", data_page) else: - data_page['access'] = True - with get_db() as db: - active_appointments = db.query(Appointment).filter( - Appointment.status.in_([AppointmentStatus.ACTIVE.value, AppointmentStatus.CONFIRMED.value]) - ).options(joinedload(Appointment.services)).all() - archived_appointments = db.query(Appointment).filter( - Appointment.status == AppointmentStatus.ARCHIVED.value - ).options(joinedload(Appointment.services)).all() - - services = db.query(Service).all() + active_appointments, archived_appointments = await AppointmentDAO.get_appointments() + services = await ServiceDAO.find_all() + data_page['access'] = True data_page['active_appointments'] = active_appointments data_page['archived_appointments'] = archived_appointments data_page['services'] = services @@ -104,8 +85,7 @@ async def get_admin_interface(request: Request, admin_id: int = None): @router.get("/services", response_class=HTMLResponse) async def get_services(request: Request, user_id: int = None): data_page = {"request": request, "access": True, "title": "Прайс-лист"} - with get_db() as db: - services = db.query(Service).all() + services = await ServiceDAO.find_all() data_page['services'] = services return templates.TemplateResponse("services.html", data_page) @@ -113,12 +93,12 @@ async def get_services(request: Request, user_id: int = None): @router.get("/admin/services", response_class=HTMLResponse) async def get_admin_services(request: Request, admin_id: int = None): data_page = {"request": request, "access": False, "title": "Администрирование прайс-листа"} - with get_db() as db: - services = db.query(Service).all() - data_page['services'] = services if admin_id is None or admin_id != settings.MASTER_USER_ID: data_page['message'] = 'У вас нет прав!' return templates.TemplateResponse("services.html", data_page) - else: - data_page['access'] = True - return templates.TemplateResponse("services.html", data_page) + + services = await ServiceDAO.find_all() + + data_page['access'] = True + data_page['services'] = services + return templates.TemplateResponse("services.html", data_page) diff --git a/src/utils.py b/src/utils.py index 3fa42d1..881d94e 100644 --- a/src/utils.py +++ b/src/utils.py @@ -2,14 +2,12 @@ from aiogram.types import Message +from src.api.dao import PhotoDAO, AvailableTimeSlotDAO from src.bot.keyboards import main_keyboard -from src.database import AvailableTimeSlot, Photo -from src.database.db import get_db -def get_photos(): - with get_db() as db: - photos = db.query(Photo).all() +async def get_photos(): + photos = await PhotoDAO.find_all() return photos @@ -30,8 +28,4 @@ async def greet_user(message: Message, is_new_user: bool) -> None: async def delete_old_schedule_entries(): threshold_date = datetime.now().date() + timedelta(days=1) - print(f"Запуск задачи на удаление записей старше {threshold_date}") - with get_db() as db: - db.query(AvailableTimeSlot).filter(AvailableTimeSlot.date < threshold_date).delete() - db.commit() - print("Старые записи успешно удалены.") + await AvailableTimeSlotDAO.delete(date__lt=threshold_date)