pdf-quiz-generator/backend/alembic/versions/b2c3d4e5f6a7_plan_origin.py
Daniel ebb9e701ee fix: one sessions list, at /sessions, with plan material out of it
The page at /quizzes showed the same fifteen rows twice — once under a
"Sessions" tab as a list, once under a "Library" tab as cards — with
nothing distinguishing them. The navbar carried the duplication too,
with "Sessions" and "History" both pointing at the same page.

Board Review I-XII already exist as study plans. The Library tab was
showing the bulk quizzes those plans were built from, so the same twelve
titles appeared in both systems. Those quizzes are now origin='plan':
still real, still the parent of their questions via source_quiz_id, but
no longer offered as something to pick off a list. Once a learner has
actually sat one it is history, so the session list keeps it.

- QuizzesPage deleted; /sessions is the only listing
- /quizzes/* redirects to /sessions/*, preserving path and query
- submitting a session lands on its analysis, not the old score page
- the answer review drops its score hero, which the analysis owns and
  stated differently; a course quiz keeps its card, having no analysis
- delete-attempt moves to the analysis page, where the session lives

Backend 208/208, frontend 246/246.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TqXevQJhxFrM7jJg82cgZN
2026-09-11 04:10:25 +02:00

47 lines
1.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Mark study-plan source quizzes with origin='plan'
Board Review IXII exist twice over: once as a study plan the learner works
through block by block, and once as the bulk quiz the plan was built from. The
session list showed both, so the same twelve titles appeared under "Sessions"
and again under "Library" with nothing to tell them apart.
Tagging the bulk quizzes keeps them intact — the questions still hang off them
via `source_quiz_id` — while taking them out of the list of things a learner
picks from. A quiz already sat stays in the history regardless; that filtering
lives in the endpoint, not here.
Revision ID: b2c3d4e5f6a7
Revises: a1b2c3d4e5f6
"""
import sqlalchemy as sa
from alembic import op
revision = "b2c3d4e5f6a7"
down_revision = "a1b2c3d4e5f6"
branch_labels = None
depends_on = None
def _has(table: str) -> bool:
return table in sa.inspect(op.get_bind()).get_table_names()
def upgrade() -> None:
# Guarded because create_all() may have built these tables on a fresh
# deploy before Alembic ran.
if not (_has("quizzes") and _has("study_plans")):
return
# Matched on the trimmed title: one of the imports carries a trailing
# space ("Board Review VII ").
op.execute(sa.text("""
UPDATE quizzes SET origin = 'plan'
WHERE course_id IS NULL
AND origin <> 'plan'
AND btrim(title) IN (SELECT btrim(name) FROM study_plans)
"""))
def downgrade() -> None:
if not _has("quizzes"):
return
op.execute(sa.text("UPDATE quizzes SET origin = 'bank' WHERE origin = 'plan'"))