2026-02-04 16:50:33 +02:00

121 lines
5.6 KiB
Python

"""initial
Revision ID: 0001_initial
Revises:
Create Date: 2026-02-03 18:30:00
"""
from alembic import op
import sqlalchemy as sa
revision = "0001_initial"
down_revision = None
branch_labels = None
depends_on = None
def upgrade() -> None:
op.create_table(
"users",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("email", sa.String(length=255), nullable=False),
sa.Column("password_hash", sa.String(length=255), nullable=False),
sa.Column("role", sa.Enum("admin", "learner", name="role_enum"), nullable=False),
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
)
op.create_index(op.f("ix_users_email"), "users", ["email"], unique=True)
op.create_table(
"courses",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("title", sa.String(length=255), nullable=False),
sa.Column("description", sa.Text()),
sa.Column("is_published", sa.Boolean(), nullable=False, server_default=sa.false()),
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.Column("updated_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
)
op.create_table(
"modules",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("course_id", sa.Integer(), sa.ForeignKey("courses.id", ondelete="CASCADE"), nullable=False),
sa.Column("order_index", sa.Integer(), nullable=False),
sa.Column("type", sa.Enum("content", "quiz", name="module_type_enum"), nullable=False),
sa.Column("title", sa.String(length=255), nullable=False),
sa.Column("content_text", sa.Text()),
sa.Column("pass_score", sa.Integer()),
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
)
op.create_index(op.f("ix_modules_course_id"), "modules", ["course_id"])
op.create_table(
"quiz_questions",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("module_id", sa.Integer(), sa.ForeignKey("modules.id", ondelete="CASCADE"), nullable=False),
sa.Column("prompt", sa.Text(), nullable=False),
sa.Column("question_type", sa.Enum("mcq", name="question_type_enum"), nullable=False),
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
)
op.create_index(op.f("ix_quiz_questions_module_id"), "quiz_questions", ["module_id"])
op.create_table(
"quiz_choices",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("question_id", sa.Integer(), sa.ForeignKey("quiz_questions.id", ondelete="CASCADE"), nullable=False),
sa.Column("text", sa.Text(), nullable=False),
sa.Column("is_correct", sa.Boolean(), nullable=False, server_default=sa.false()),
)
op.create_index(op.f("ix_quiz_choices_question_id"), "quiz_choices", ["question_id"])
op.create_table(
"enrollments",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False),
sa.Column("course_id", sa.Integer(), sa.ForeignKey("courses.id", ondelete="CASCADE"), nullable=False),
sa.Column("enrolled_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.UniqueConstraint("user_id", "course_id", name="uq_enrollment"),
)
op.create_index(op.f("ix_enrollments_user_id"), "enrollments", ["user_id"])
op.create_index(op.f("ix_enrollments_course_id"), "enrollments", ["course_id"])
op.create_table(
"module_progress",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False),
sa.Column("module_id", sa.Integer(), sa.ForeignKey("modules.id", ondelete="CASCADE"), nullable=False),
sa.Column("status", sa.Enum("locked", "unlocked", "completed", name="progress_status_enum"), nullable=False),
sa.Column("completed_at", sa.DateTime(timezone=True)),
sa.Column("score", sa.Float()),
sa.UniqueConstraint("user_id", "module_id", name="uq_module_progress"),
)
op.create_index(op.f("ix_module_progress_user_id"), "module_progress", ["user_id"])
op.create_index(op.f("ix_module_progress_module_id"), "module_progress", ["module_id"])
op.create_table(
"quiz_attempts",
sa.Column("id", sa.Integer(), primary_key=True),
sa.Column("user_id", sa.Integer(), sa.ForeignKey("users.id", ondelete="CASCADE"), nullable=False),
sa.Column("module_id", sa.Integer(), sa.ForeignKey("modules.id", ondelete="CASCADE"), nullable=False),
sa.Column("submitted_at", sa.DateTime(timezone=True), server_default=sa.func.now()),
sa.Column("score", sa.Float(), nullable=False),
sa.Column("passed", sa.Boolean(), nullable=False),
sa.Column("answers_json", sa.JSON(), nullable=False),
)
op.create_index(op.f("ix_quiz_attempts_user_id"), "quiz_attempts", ["user_id"])
op.create_index(op.f("ix_quiz_attempts_module_id"), "quiz_attempts", ["module_id"])
def downgrade() -> None:
op.drop_table("quiz_attempts")
op.drop_table("module_progress")
op.drop_table("enrollments")
op.drop_table("quiz_choices")
op.drop_table("quiz_questions")
op.drop_table("modules")
op.drop_table("courses")
op.drop_table("users")
op.execute("DROP TYPE IF EXISTS role_enum")
op.execute("DROP TYPE IF EXISTS module_type_enum")
op.execute("DROP TYPE IF EXISTS progress_status_enum")
op.execute("DROP TYPE IF EXISTS question_type_enum")