This commit is contained in:
2025-09-23 11:36:55 +05:00
parent 046b610a34
commit f2cf7aaecf
18 changed files with 2427 additions and 465 deletions

View File

@@ -0,0 +1,334 @@
"""
Репозитории для работы с моделями базы данных системы тестирования
"""
from typing import Optional, List
from sqlalchemy.orm import Session
from sqlalchemy import and_, or_
from database.models import (
User, Message, BotSettings, Test, TestCategory, Question,
AnswerOption, TestResult, UserAnswer, Image
)
import logging
logger = logging.getLogger(__name__)
class UserRepository:
"""Репозиторий для работы с пользователями"""
@staticmethod
def create_user(session: Session, telegram_id: int, username: str = None,
first_name: str = None, last_name: str = None) -> User:
"""Создание нового пользователя"""
user = User(
telegram_id=telegram_id,
username=username,
first_name=first_name,
last_name=last_name
)
session.add(user)
session.flush() # Получаем ID без коммита
return user
@staticmethod
def get_user_by_telegram_id(session: Session, telegram_id: int) -> Optional[User]:
"""Получение пользователя по Telegram ID"""
return session.query(User).filter(User.telegram_id == telegram_id).first()
@staticmethod
def get_user_by_id(session: Session, user_id: int) -> Optional[User]:
"""Получение пользователя по ID"""
return session.query(User).filter(User.id == user_id).first()
@staticmethod
def get_all_users(session: Session, active_only: bool = True) -> List[User]:
"""Получение всех пользователей"""
query = session.query(User)
if active_only:
query = query.filter(User.is_active == True)
return query.all()
@staticmethod
def update_user(session: Session, telegram_id: int, **kwargs) -> Optional[User]:
"""Обновление данных пользователя"""
user = UserRepository.get_user_by_telegram_id(session, telegram_id)
if user:
for key, value in kwargs.items():
if hasattr(user, key):
setattr(user, key, value)
session.flush()
return user
@staticmethod
def get_or_create_user(session: Session, telegram_id: int, **kwargs) -> tuple[User, bool]:
"""Получение или создание пользователя. Возвращает (user, created)"""
user = UserRepository.get_user_by_telegram_id(session, telegram_id)
if user:
return user, False
else:
user = UserRepository.create_user(session, telegram_id, **kwargs)
return user, True
class MessageRepository:
"""Репозиторий для работы с сообщениями"""
@staticmethod
def create_message(session: Session, telegram_message_id: int, user_id: int,
text: str = None, message_type: str = 'text') -> Message:
"""Создание нового сообщения"""
message = Message(
telegram_message_id=telegram_message_id,
user_id=user_id,
text=text,
message_type=message_type
)
session.add(message)
session.flush()
return message
@staticmethod
def get_messages_by_user(session: Session, user_id: int, limit: int = 100) -> List[Message]:
"""Получение сообщений пользователя"""
return (session.query(Message)
.filter(Message.user_id == user_id)
.order_by(Message.created_at.desc())
.limit(limit)
.all())
@staticmethod
def get_recent_messages(session: Session, limit: int = 100) -> List[Message]:
"""Получение последних сообщений"""
return (session.query(Message)
.order_by(Message.created_at.desc())
.limit(limit)
.all())
class SettingsRepository:
"""Репозиторий для работы с настройками бота"""
@staticmethod
def get_setting(session: Session, key: str) -> Optional[str]:
"""Получение значения настройки"""
setting = session.query(BotSettings).filter(BotSettings.key == key).first()
return setting.value if setting else None
@staticmethod
def set_setting(session: Session, key: str, value: str, description: str = None) -> BotSettings:
"""Установка значения настройки"""
setting = session.query(BotSettings).filter(BotSettings.key == key).first()
if setting:
setting.value = value
if description:
setting.description = description
else:
setting = BotSettings(key=key, value=value, description=description)
session.add(setting)
session.flush()
return setting
@staticmethod
def get_all_settings(session: Session) -> List[BotSettings]:
"""Получение всех настроек"""
return session.query(BotSettings).all()
@staticmethod
def delete_setting(session: Session, key: str) -> bool:
"""Удаление настройки"""
setting = session.query(BotSettings).filter(BotSettings.key == key).first()
if setting:
session.delete(setting)
session.flush()
return True
return False
class ImageRepository:
"""Репозиторий для работы с изображениями"""
@staticmethod
def create_image(session: Session, filename: str, content_type: str,
image_data: bytes, alt_text: str = None) -> Image:
"""Создание записи изображения"""
image = Image(
filename=filename,
content_type=content_type,
file_size=len(image_data),
image_data=image_data,
alt_text=alt_text
)
session.add(image)
session.flush()
return image
@staticmethod
def get_image_by_id(session: Session, image_id: int) -> Optional[Image]:
"""Получение изображения по ID"""
return session.query(Image).filter(Image.id == image_id).first()
@staticmethod
def get_image_by_filename(session: Session, filename: str) -> Optional[Image]:
"""Получение изображения по имени файла"""
return session.query(Image).filter(Image.filename == filename).first()
@staticmethod
def get_all_images(session: Session) -> List[Image]:
"""Получение всех изображений"""
return session.query(Image).all()
@staticmethod
def delete_image(session: Session, image_id: int) -> bool:
"""Удаление изображения"""
image = session.query(Image).filter(Image.id == image_id).first()
if image:
session.delete(image)
return True
return False
class TestRepository:
"""Репозиторий для работы с тестами"""
def __init__(self, session: Session):
self.session = session
def create_test(
self,
title: str,
description: str = None,
category_id: int = None,
is_active: bool = True,
time_limit_minutes: int = None
) -> 'Test':
"""Создание нового теста"""
from database.models import Test
test = Test(
title=title,
description=description,
category_id=category_id,
is_active=is_active,
time_limit_minutes=time_limit_minutes
)
self.session.add(test)
self.session.commit()
self.session.refresh(test)
return test
def get_test_by_id(self, test_id: int) -> Optional['Test']:
"""Получение теста по ID"""
from database.models import Test
return self.session.query(Test).filter(Test.id == test_id).first()
def get_tests(
self,
is_active: bool = None,
category_id: int = None,
limit: int = None
) -> List['Test']:
"""Получение списка тестов с фильтрацией"""
from database.models import Test
query = self.session.query(Test)
if is_active is not None:
query = query.filter(Test.is_active == is_active)
if category_id is not None:
query = query.filter(Test.category_id == category_id)
if limit:
query = query.limit(limit)
return query.all()
def update_test(self, test_id: int, **kwargs) -> Optional['Test']:
"""Обновление теста"""
from database.models import Test
test = self.session.query(Test).filter(Test.id == test_id).first()
if test:
for key, value in kwargs.items():
if hasattr(test, key):
setattr(test, key, value)
self.session.commit()
self.session.refresh(test)
return test
def delete_test(self, test_id: int) -> bool:
"""Удаление теста"""
from database.models import Test
test = self.session.query(Test).filter(Test.id == test_id).first()
if test:
self.session.delete(test)
self.session.commit()
return True
return False
class QuestionRepository:
"""Репозиторий для работы с вопросами"""
def __init__(self, session: Session):
self.session = session
def create_question(
self,
test_id: int,
question_text: str,
question_type: str = "single_choice",
order_number: int = 1,
points: int = 1,
image_id: int = None
) -> 'Question':
"""Создание нового вопроса"""
from database.models import Question
question = Question(
test_id=test_id,
question_text=question_text,
question_type=question_type,
order_number=order_number,
points=points,
image_id=image_id
)
self.session.add(question)
self.session.commit()
self.session.refresh(question)
return question
def get_question_by_id(self, question_id: int) -> Optional['Question']:
"""Получение вопроса по ID"""
from database.models import Question
return self.session.query(Question).filter(Question.id == question_id).first()
def get_questions_by_test_id(self, test_id: int) -> List['Question']:
"""Получение всех вопросов для теста"""
from database.models import Question
return self.session.query(Question).filter(
Question.test_id == test_id
).order_by(Question.order_number).all()
def update_question(self, question_id: int, **kwargs) -> Optional['Question']:
"""Обновление вопроса"""
from database.models import Question
question = self.session.query(Question).filter(Question.id == question_id).first()
if question:
for key, value in kwargs.items():
if hasattr(question, key):
setattr(question, key, value)
self.session.commit()
self.session.refresh(question)
return question
def delete_question(self, question_id: int) -> bool:
"""Удаление вопроса"""
from database.models import Question
question = self.session.query(Question).filter(Question.id == question_id).first()
if question:
self.session.delete(question)
self.session.commit()
return True
return False