"""Контент редактора: тест + активная версия + дерево вопросов с правильными вариантами. Порт `getEditorContent` + `loadQuestionsForVersion` (только includeCorrect=true вариант) из `services/testAttemptService.js`. """ from __future__ import annotations from sqlalchemy import text from ..db import get_engine from ..messages import RU from .test_access import is_test_author class HttpError(Exception): def __init__(self, status: int, message: str): super().__init__(message) self.status = status self.message = message def load_questions_for_version(conn, test_version_id, *, include_correct: bool) -> list[dict]: qrows = conn.execute( text( 'SELECT id, text, question_order, has_multiple_answers ' 'FROM questions WHERE test_version_id = :v ORDER BY question_order' ), {'v': test_version_id}, ).mappings().all() out = [] for r in qrows: orows = conn.execute( text( 'SELECT id, text, is_correct, option_order ' 'FROM answer_options WHERE question_id = :q ORDER BY option_order' ), {'q': r['id']}, ).mappings().all() options = [] for o in orows: base = { 'id': str(o['id']), 'text': o['text'], 'optionOrder': o['option_order'], } if include_correct: base['isCorrect'] = bool(o['is_correct']) options.append(base) out.append( { 'id': str(r['id']), 'text': r['text'], 'questionOrder': r['question_order'], 'hasMultipleAnswers': bool(r['has_multiple_answers']), 'options': options, } ) return out def get_editor_content(user_id: str, test_id: str) -> dict: eng = get_engine() with eng.connect() as conn: tr = conn.execute( text( 'SELECT id, title, description, passing_threshold, created_by ' 'FROM tests WHERE id = :id' ), {'id': test_id}, ).mappings().first() if not tr: raise HttpError(404, 'Тест не найден.') if not is_test_author(tr['created_by'], user_id): raise HttpError(403, 'Доступ запрещён.') tv = conn.execute( text( 'SELECT id FROM test_versions WHERE test_id = :id AND is_active = true LIMIT 1' ), {'id': test_id}, ).mappings().first() if not tv: raise HttpError(400, 'Нет активной версии теста.') version_id = tv['id'] questions = load_questions_for_version(conn, version_id, include_correct=True) return { 'test': { 'id': str(tr['id']), 'title': tr['title'], 'description': tr['description'], 'passingThreshold': tr['passing_threshold'], }, 'activeVersionId': str(version_id), 'questions': questions, }