91 lines
2.8 KiB
Python
91 lines
2.8 KiB
Python
"""student_progress composite score columns
|
|
|
|
Revision ID: 0005
|
|
Revises: 0004
|
|
Create Date: 2026-08-28
|
|
|
|
Menambah kolom composite evaluation ke student_progress:
|
|
- exercise_passed (Boolean)
|
|
- quiz_score_earned (Integer)
|
|
- quiz_score_total (Integer)
|
|
- composite_percent (Float)
|
|
|
|
Backfill data legacy:
|
|
- state='completed' → exercise_passed=true
|
|
- state='scored' → quiz_score_earned=score_earned, quiz_score_total=score_total
|
|
Legacy 'completed'/'scored' diubah ke 'in_progress' (akan di-recompute jadi
|
|
'done' oleh logika composite di backend). Constraint ck_student_progress_state
|
|
diperluas dari 3-state menjadi 5-state ('not_started','in_progress',
|
|
'completed','scored','done').
|
|
"""
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision = "0005"
|
|
down_revision = "0004"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.add_column(
|
|
"student_progress",
|
|
sa.Column("exercise_passed", sa.Boolean(), nullable=True),
|
|
)
|
|
op.add_column(
|
|
"student_progress",
|
|
sa.Column("quiz_score_earned", sa.Integer(), nullable=True),
|
|
)
|
|
op.add_column(
|
|
"student_progress",
|
|
sa.Column("quiz_score_total", sa.Integer(), nullable=True),
|
|
)
|
|
op.add_column(
|
|
"student_progress",
|
|
sa.Column("composite_percent", sa.Float(), nullable=True),
|
|
)
|
|
|
|
# Perluas constraint state menjadi 5-state SEBELUM backfill update,
|
|
# agar nilai 'in_progress' diizinkan saat UPDATE di bawah.
|
|
op.drop_constraint(
|
|
"ck_student_progress_state", "student_progress", type_="check"
|
|
)
|
|
op.create_check_constraint(
|
|
"ck_student_progress_state",
|
|
"student_progress",
|
|
"state IN ('not_started','in_progress','completed','scored','done')",
|
|
)
|
|
|
|
# Backfill: completed → exercise lulus; scored → ambil skor kuis lama.
|
|
op.execute(
|
|
"UPDATE student_progress SET exercise_passed = true "
|
|
"WHERE state = 'completed'"
|
|
)
|
|
op.execute(
|
|
"UPDATE student_progress "
|
|
"SET quiz_score_earned = score_earned, quiz_score_total = score_total "
|
|
"WHERE state = 'scored'"
|
|
)
|
|
# Legacy 'completed'/'scored' belum punya composite → turunkan ke
|
|
# 'in_progress' agar backend menghitung ulang jadi 'done'/'in_progress'.
|
|
op.execute(
|
|
"UPDATE student_progress SET state = 'in_progress' "
|
|
"WHERE state IN ('completed', 'scored')"
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_constraint(
|
|
"ck_student_progress_state", "student_progress", type_="check"
|
|
)
|
|
op.create_check_constraint(
|
|
"ck_student_progress_state",
|
|
"student_progress",
|
|
"state IN ('not_started','completed','scored')",
|
|
)
|
|
op.drop_column("student_progress", "composite_percent")
|
|
op.drop_column("student_progress", "quiz_score_total")
|
|
op.drop_column("student_progress", "quiz_score_earned")
|
|
op.drop_column("student_progress", "exercise_passed")
|