"""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")