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)