"""A study objective decides what a learner is shown, not just what is counted. Revision ID: c7d8e9f0a1b2 Revises: b6c7d8e9f0a1 """ import sqlalchemy as sa from alembic import op from sqlalchemy import inspect revision = "c7d8e9f0a1b2" down_revision = "b6c7d8e9f0a1" branch_labels = None depends_on = None def _has_column(table: str, column: str) -> bool: return column in {c["name"] for c in inspect(op.get_bind()).get_columns(table)} def upgrade(): # `create_all` at startup may already have added these; each step checks. for column in ( # Objectives are chosen from a list of families — USMLE, COMLEX, boards — # because a flat list of every exam is not a choice anyone can make. sa.Column("family", sa.String(80), nullable=True), sa.Column("description", sa.String(300), nullable=True), # Which readings this objective shows. Someone revising a basic-science # step has no use for bedside dosing, and a view they can open but must # never act on is worse than one they were never offered. sa.Column("article_views", sa.JSON, nullable=True), ): if not _has_column("exams", column.name): op.add_column("exams", column) op.execute("UPDATE exams SET family = 'Boards' WHERE slug = 'pediatrics-boards' AND family IS NULL") op.execute("UPDATE exams SET family = 'USMLE' WHERE slug LIKE 'usmle-%' AND family IS NULL") op.execute("UPDATE exams SET family = 'Other' WHERE family IS NULL") def downgrade(): for column in ("article_views", "description", "family"): if _has_column("exams", column): op.drop_column("exams", column)