Spaces:
Runtime error
Runtime error
| from datetime import datetime | |
| from typing import Optional | |
| from sqlalchemy import BigInteger, String, ForeignKey, Integer, DateTime, Boolean | |
| from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column, relationship | |
| from sqlalchemy.ext.asyncio import AsyncAttrs, async_sessionmaker, create_async_engine | |
| from app.config.config import DATABASE_URL | |
| engine = create_async_engine(DATABASE_URL) # подключение и создание БД | |
| async_session = async_sessionmaker(engine, expire_on_commit=False) | |
| class Base(AsyncAttrs, DeclarativeBase): | |
| """Base class for all models""" | |
| pass | |
| class User(Base): | |
| """User model for storing telegram user data""" | |
| __tablename__ = 'users' | |
| id: Mapped[int] = mapped_column(primary_key=True) | |
| tg_id: Mapped[int] = mapped_column(BigInteger, unique=True, nullable=False) | |
| name: Mapped[str] = mapped_column(String(100), nullable=True) | |
| login: Mapped[str] = mapped_column(String(100), nullable=True) | |
| contact: Mapped[str] = mapped_column(String(100), nullable=True) | |
| subscription_status: Mapped[str] = mapped_column( | |
| String(20), default='inactive') | |
| # Relationships | |
| test_attempts = relationship("TestAttempt", back_populates="user") | |
| feedback = relationship("Feedback", back_populates="user") | |
| class Service(Base): | |
| """Service model for storing available services""" | |
| __tablename__ = 'services' | |
| id: Mapped[int] = mapped_column(primary_key=True) | |
| service_name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False) | |
| service_description: Mapped[str] = mapped_column(String(500)) | |
| service_price: Mapped[int] = mapped_column(BigInteger, nullable=False) | |
| is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) | |
| # Relationships | |
| feedback = relationship("Feedback", back_populates="service") | |
| class Test(Base): | |
| """Test model for storing quiz/test information""" | |
| __tablename__ = 'tests' | |
| id: Mapped[int] = mapped_column(primary_key=True) | |
| test_name: Mapped[str] = mapped_column(String(100), unique=True, nullable=False) | |
| test_type: Mapped[str] = mapped_column(String(20), nullable=False) | |
| test_description: Mapped[str] = mapped_column(String(250)) | |
| is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) | |
| completion_message: Mapped[Optional[str]] = mapped_column(String(1000)) | |
| # Relationships | |
| questions = relationship("TestQuestion", back_populates="test", cascade="all, delete-orphan") | |
| results = relationship("TestResult", back_populates="test", cascade="all, delete-orphan") | |
| attempts = relationship("TestAttempt", back_populates="test") | |
| class TestQuestion(Base): | |
| """Model for storing test questions""" | |
| __tablename__ = 'test_questions' | |
| id: Mapped[int] = mapped_column(primary_key=True) | |
| test_id: Mapped[int] = mapped_column(ForeignKey('tests.id', ondelete='CASCADE'), nullable=False) | |
| question_content: Mapped[str] = mapped_column(String(150), nullable=False) | |
| question_variants: Mapped[str] = mapped_column(String(500), nullable=False) # JSON string | |
| question_points: Mapped[str] = mapped_column(String(100), nullable=False) # JSON string | |
| # Relationships | |
| test = relationship("Test", back_populates="questions") | |
| class TestResult(Base): | |
| """Model for storing possible test results""" | |
| __tablename__ = 'test_results' | |
| id: Mapped[int] = mapped_column(primary_key=True) | |
| test_id: Mapped[int] = mapped_column(ForeignKey('tests.id', ondelete='CASCADE'), nullable=False) | |
| min_points: Mapped[int] = mapped_column(Integer, nullable=False) | |
| max_points: Mapped[int] = mapped_column(Integer, nullable=False) | |
| result_text: Mapped[str] = mapped_column(String(1000), nullable=False) | |
| # Relationships | |
| test = relationship("Test", back_populates="results") | |
| class TestAttempt(Base): | |
| """Model for storing user test attempts""" | |
| __tablename__ = 'test_attempts' | |
| id: Mapped[int] = mapped_column(primary_key=True) | |
| user_id: Mapped[int] = mapped_column(ForeignKey('users.id', ondelete='CASCADE'), nullable=False) | |
| test_id: Mapped[int] = mapped_column(ForeignKey('tests.id', ondelete='CASCADE'), nullable=False) | |
| score: Mapped[int] = mapped_column(Integer, nullable=True) | |
| result: Mapped[Optional[str]] = mapped_column(String(1000), nullable=True) | |
| completed_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.now, nullable=True) | |
| # Relationships | |
| user = relationship("User", back_populates="test_attempts") | |
| test = relationship("Test", back_populates="attempts") | |
| class TestAnswer(Base): | |
| """Stores individual answers for each question""" | |
| __tablename__ = 'test_answers' | |
| id: Mapped[int] = mapped_column(primary_key=True) | |
| attempt_id: Mapped[int] = mapped_column(ForeignKey('test_attempts.id', ondelete='CASCADE')) | |
| question_id: Mapped[int] = mapped_column(ForeignKey('test_questions.id', ondelete='CASCADE')) | |
| answer_given: Mapped[str] = mapped_column(String(500)) | |
| points_earned: Mapped[int] = mapped_column(Integer, nullable=True) | |
| class LeadMagnet(Base): | |
| """Model for storing lead magnets/content triggers""" | |
| __tablename__ = 'lead_magnets' | |
| id: Mapped[int] = mapped_column(primary_key=True) | |
| trigger: Mapped[str] = mapped_column(String(50), unique=True, nullable=False) | |
| content: Mapped[str] = mapped_column(String(500), nullable=False) | |
| is_active: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) | |
| class Feedback(Base): | |
| """Model for storing user feedback""" | |
| __tablename__ = 'feedback' | |
| id: Mapped[int] = mapped_column(primary_key=True) | |
| user_id: Mapped[int] = mapped_column(ForeignKey('users.id', ondelete='CASCADE'), nullable=False) | |
| service_id: Mapped[int] = mapped_column(ForeignKey('services.id', ondelete='CASCADE'), nullable=False) | |
| rating: Mapped[int] = mapped_column(Integer, nullable=False) | |
| review: Mapped[str] = mapped_column(String(1000)) | |
| is_new: Mapped[bool] = mapped_column(Boolean, default=True, nullable=False) | |
| # Relationships | |
| user = relationship("User", back_populates="feedback") | |
| service = relationship("Service", back_populates="feedback") | |
| async def async_main(): | |
| """Initialize database tables""" | |
| async with engine.begin() as conn: | |
| await conn.run_sync(Base.metadata.create_all) |