Перейти к основному содержимому

Модель данных

Зачем нужно

Документ собирает реализационную модель домена олимпиад в один контракт: event, season, tour, participant, registration, venue, LMS activity binding, competition-facing submission refs, checking/status refs, score snapshots, result, publication и documents.

Правила модели

  • Сезон, тур, зачёт и delivery mode являются независимыми измерениями.
  • Участник может существовать без identity account.
  • Регистрация, участие в сезоне и участие в туре не являются одной сущностью.
  • Способ прохождения хранится на уровне TourParticipation.
  • Тур исполняется как LMS activity или temporary LMS-compatible activity adapter. Competitions хранит activity refs, структуру задач для результата и score snapshots, а не полноценный task runtime.
  • Task-bank является источником задач, подборок и версий задач. Он не является runtime прохождения Олимпиады.
  • Submission и result сохраняют историю, даже если participant позже привязан к аккаунту.
  • Publication status отделён от calculation/finalization status.
  • Learning Workspace / Learning Group владеет учебными группами и каноническим списком учеников преподавателя.
  • competition_group является снимком/проекцией регистрации конкретного сезона, а не общим списком учеников преподавателя.
  • Пользователь работает в преподавательском режиме с выбранной организацией; административные и площадочные функции являются подслоями этого режима.
  • Родитель может зарегистрировать ребёнка, но прохождение тура выполняется ребёнком в детском режиме.
  • Официальный пакет данных для ГИР требуется только для официального сценария регламента.
  • Сырые official-поля участника принадлежат identity/protected attributes. Competitions хранит requirement, status, protected ref и audit, но не сырой СНИЛС, дату рождения ребёнка или родительские контакты.
  • После завершения Олимпиады activity или её производная версия может быть опубликована как LMS trainer/review mode. Training attempts остаются LMS-owned и не меняют competition result.

Event and season

competition_event

Стабильное мероприятие: олимпиада, конкурс или турнир.

competition_season

Сезон мероприятия.

Поля: event_id, title, status, registration_policy, fee_policy, starts_at, ends_at.

competition_grade_category

Класс, параллель, возрастная категория или дивизион.

competition_tour

Тур сезона.

Поля: season_id, position, format, status, starts_at, ends_at, settings.

competition_track

Зачёт: очный, онлайн, официальный, тренировочный, возрастной, региональный.

competition_award_policy

Правила award thresholds для track/category/tour/season.

Participants and access

competition_participant

Соревновательная запись ученика. Канонический учебный субъект — student_profile_id, если участник связан с identity family. Дополнительно может быть связана с organization_student_id как external ref на identity-owned ученика организации, с identity_user_id для самостоятельного входа или claim, либо оставаться без аккаунта.

Правила:

  • organization_student принадлежит identity и не становится участником олимпиады автоматически;
  • competition_participant принадлежит competitions и хранит соревновательный lifecycle, регистрацию, работы и результаты;
  • если участник пришёл из организации, organization_student_id, identity_organization_id и organization_membership_id используются как external refs для dedupe, доступа и отображения;
  • organization_student_snapshot фиксирует ФИО, класс и служебные атрибуты на момент регистрации, чтобы результат и документы не ломались при изменениях в identity;
  • organization_student -> competition_participant -> access_claim -> optional link to student_profile/user является допустимым flow;
  • student_profile и organization_student не склеиваются автоматически: похожие ФИО создают review/claim flow, но не silent merge;
  • merge организации не удаляет исторические participants и results.

competition_registration

Заявка на участие.

Регистрация поддерживает два шага:

  1. Предварительная регистрация: создаёт намерение участвовать, фиксирует сезон, класс/категорию, источник регистрации, выбранную Learning Group или ребёнка семьи.
  2. Дозаполнение и подтверждение: собирает обязательные поля конкретного регламента, проверяет оплату/entitlement при необходимости и переводит регистрацию в submitted/approved.

Поля модели: status, stage, source, submitted_by_user_id, participant_id, group_id, learning_workspace_id, learning_group_id, required_fields_status, teacher_name_text, official_data_package_required, official_data_package_status, official_data_ref, parent_contact_ref, parent_invite_ref, official_data_collected_by_user_id, official_data_collected_at, official_data_verified_by_user_id, official_data_verified_at.

teacher_name_text — свободное текстовое поле анкеты участника. Оно не создаёт автоматическую связь с identity_user_id преподавателя и не выдаёт прав доступа.

Для родительского сценария source = parent, а participant ребёнка помечается как требующий child-mode прохождения тура.

competition_official_data_package

Логический package requirement для официальной передачи данных в ГИР. Состав official data package: СНИЛС ребёнка, дата рождения ребёнка, email родителя и телефон родителя.

Ownership:

  • СНИЛС ребёнка, дата рождения ребёнка, email родителя и телефон родителя хранятся в identity profile/protected attributes или family contact records;
  • competitions хранит только official_data_package_required, official_data_package_status, official_data_ref, parent_contact_ref, parent_invite_ref, collector/verifier поля и audit;
  • official_data_ref является protected identity ref на official data package/attribute set, а не encrypted raw field внутри competitions;
  • ручной ввод учителем допустим только через разрешённый official flow и identity-owned collection session;
  • parent_contact_ref и parent_invite_ref фиксируют связь с contact/invite, но не выдают учителю родительские права.

competition_season_participation

Активное участие в сезоне.

competition_tour_participation

Участие в конкретном туре: delivery mode, track, venue, admission status.

competition_access_claim

Процедура получения доступа к записи участника ребёнком или родителем.

Правило уникальности: после успешной привязки student_profile_id к участнику в рамках одного сезона не может существовать второй активный competition_participant с тем же student_profile_id. Для linked account дополнительно сохраняется правило ADR-031: один active participant на identity_user_id в сезоне. Merge дублей выполняется до approve claim.

Learning groups, organizations, venues

competition_group

Season-specific snapshot/registration projection от Learning Workspace / Learning Group.

Поля: season_id, learning_workspace_id, learning_group_id, competition_organization_id, primary_teacher_user_id, title_snapshot, member_snapshot, snapshot_taken_at, status.

Правила:

  • канонический список учеников, состав группы, учебная история и роли преподавателя живут в Learning Workspace / Learning Group;
  • competitions может зафиксировать состав группы на момент регистрации, чтобы сохранить воспроизводимость сезона;
  • изменение Learning Group после регистрации не меняет уже отправленные registrations без явного действия преподавателя;
  • группу можно использовать для пакетной регистрации и отправки ответов в туре;
  • competition_group нельзя использовать как общий раздел «мои ученики» вне сезона.

competition_organization

Локальная олимпиадная проекция организации или площадки участия.

Канонические данные организации остаются в identity. Competitions хранит только соревновательный контекст: identity_organization_id, display_name_snapshot, participation_status, season_scope, snapshot_taken_at.

Правила:

  • identity_organization_id — external ref на identity.organizations.id;
  • competition_organization_id — ссылка на локальную season projection в таблицах competitions;
  • competitions не редактирует название, тип, географию, membership, teams или students организации как source of truth;
  • при identity.organization.merged historical projection сохраняется, новые регистрации идут через primary organization, а relink season projection выполняется явным admin action.

competition_group_member

Участник в олимпиадной проекции группы.

Поля: group_id, participant_id, learning_group_member_id, member_snapshot, registration_projection_status.

Правила:

  • запись является проекцией участника сезона, а не canonical membership;
  • удаление или перенос ученика в Learning Group не удаляет historical participant, submission, result или document;
  • добавление нового ученика до окончания окна тура может создать новую registration/tour participation, если это разрешено регламентом.

competition_organization_role

Роль выбранной организации в сезоне: organizer, closed_group_host, open_venue.

Эта роль определяет доступные подслои преподавательского режима, но не создаёт отдельный top-level organization или venue контекст.

competition_venue

Очная площадка.

Площадка может быть официальной или неофициальной в зависимости от регламента тура и result_track. Очный формат сам по себе не делает тур официальным.

Поля условий площадки: access_rules, required_documents, guardian_policy, facility_rules, technical_capabilities, participant_public_comment, admin_internal_comment.

Публичная карточка площадки получает только participant-safe поля: адрес после публикации, карту/координаты, правила входа, документы, правила сопровождающих, facility rules и participant_public_comment. technical_capabilities и admin_internal_comment остаются административными.

competition_venue_assignment

Назначение участника на площадку.

competition_teacher_conduct_application

Заявка преподавателя или координатора на проведение тура для своих учеников. Заявка не заменяет регистрацию участников и не создаёт competition_group автоматически.

Поля: season_id, tour_id, identity_organization_id, competition_organization_id, submitted_by_user_id, location_text, expected_participant_count, planned_date_from, planned_date_to, grade_categories, delivery_mode, contact_snapshot, photo_report_required, status, admin_comment.

Связи:

  • approval_required определяется policy; для обычного первого тура статус submitted может быть достаточен для регистрации учеников и доступа к открытым материалам;
  • approved требуется только для сценариев, где это задано policy: площадка, официальный финал, ранний доступ к закрытым материалам или risk/admin policy;
  • после отправки заявки преподаватель всё равно выбирает Learning Group и создаёт competition_group snapshot, если регистрирует учеников;
  • фотоотчёт может ссылаться на teacher_conduct_application_id, competition_group_id, venue_id или их комбинацию;
  • данные заявки могут использоваться для инструкций, операционного контроля, уведомлений и благодарственных писем.

competition_teacher_material

Teacher-facing материал сезона или тура: афиша, баннер, текст анонса, инструкция, бланк, список участников, шаблон отчёта, итоговая новость, благодарность.

Поля: season_id, tour_id, teacher_conduct_application_id, material_type, title, description, file_ref, text_content, visibility, available_from, available_until, status, generated, source_ref.

Материалы могут использовать общий publication/file contour, но competitions хранит отдельную teacher-facing сущность для доступности, статуса и аудита.

external_teacher_profile

Competition-specific projection / access record внешнего преподавателя. Канонический профиль преподавателя — identity-owned EducatorProfile; competitions не создаёт второй источник истины по личности преподавателя.

Поля: identity_user_id, display_name_snapshot, organization_name, verification_status, verification_source, allowed_season_refs, verified_by_user_id, verified_at, revoked_at.

Правила:

  • external_teacher_profile не является canonical educator profile;
  • права не выдаются из факта наличия profile;
  • права идут через selected organization, Learning Workspace, grants и capabilities;
  • если нужен verification lifecycle, он относится к application/projection, а не к личности преподавателя целиком.

Activity and task structure

competition_tour_activity_binding

Связь тура, класса/категории и зачёта с LMS activity или temporary LMS-compatible activity adapter.

Поля: season_id, tour_id, grade_category_id, track_id, lms_activity_ref, task_bank_source_ref, adapter_ref, mode, status, locked_at, activity_snapshot_ref, audit_ref.

Правила:

  • mode: lms_activity или temporary_adapter;
  • binding должен быть locked до открытия тура;
  • изменение после lock требует новой версии или admin override с audit;
  • task-bank refs являются content/source refs, а не runtime refs.

competition_tour_task_structure

Зафиксированная структура задач тура для расчёта результатов и отображения баллов по задачам.

Поля: activity_binding_id, grade_category_id, task_count, max_total_score, structure_snapshot, locked_at.

competition_tour_task_item

Задача внутри activity structure, достаточная для competitions-level результата.

Поля: activity_binding_id, task_structure_id, task_number, display_title, max_score, lms_activity_item_ref, task_bank_problem_version_ref, scoring_snapshot.

Competitions не хранит как каноническую модель: текст задачи, варианты ответов, правильный ответ, подробную схему проверки, тренировочные попытки, LMS progress или разборы как продукт LMS.

Temporary LMS-compatible activity adapter

Временный adapter разрешён только ради первого олимпиадного запуска. Он повторяет будущий контракт LMS activity, хранит locked activity snapshot для конкретного тура, не создаёт отдельную библиотеку задач в competitions и имеет migration trigger в LMS activity runtime.

competition_training_publication

Публикация прошедшей activity или derived LMS activity как тренировочного набора. Не влияет на соревновательные результаты.

Поля: source_activity_binding_id, source_tour_task_structure_id, lms_ref, storefront_ref, training_mode, visibility, status, scheduled_at, published_at.

Правила:

  • lms_ref указывает на LMS-урок, тренажёр, разбор или mock contest и не заменяется storefront_ref;
  • storefront_ref является публичной проекцией или ссылкой на карточку, но не source of truth учебной активности;
  • training_mode: practice, timed_practice, review_mode, mock_contest;
  • status: draft, scheduled, published, paused, archived;
  • тренировочная попытка в LMS не создаёт competition_submission, не меняет score snapshot и не влияет на результат.

Delivery and submissions

competition_submission

Competition-facing ref/status работы участника в LMS activity runtime или temporary adapter.

Поля: tour_participation_id, activity_binding_id, lms_activity_attempt_ref, adapter_attempt_ref, status, submitted_at, locked_at, attempt_status_snapshot.

Raw answers хранятся в LMS runtime или temporary adapter, если execution уже LMS-owned. Competitions хранит только refs/status/snapshots, нужные для соревновательного lifecycle и аудита.

competition_answer_item

Competition-facing item result / score snapshot ref по конкретной задаче. Не должен становиться raw answer model, если execution живёт в LMS.

competition_submission_file

Файл, фото, PDF или скан.

Для финального тура MVP допускает загрузку файлов, zip и изображений пакетом без обязательной привязки каждого файла к конкретному ученику. Поздняя загрузка фиксируется в metadata и audit.

competition_check

Проверка работы: LMS-owned checking runtime, temporary adapter checking, manual override или imported mode.

competition_score

Immutable score snapshot за задачу, часть или работу: lms_activity_item_ref, task_number, score, max_score, checking_status, source runtime/check ref, version and audit.

Results and publication

competition_result

Итоговый результат участника в track/category/tour/season.

award_status_key использует детализированный справочник award statuses: diploma_1, diploma_2, diploma_3, honorable_mention_1, honorable_mention_2, participation_certificate, no_award.

Отдельная reference table предпочтительнее enum-only поля, чтобы можно было хранить display name, порядок, тип документа и локализацию без миграции enum.

competition_ranking

Место и ранжирование внутри зачёта.

competition_publication

Публикация личных или публичных результатов, работ, материалов.

Результаты публикуются по классам и зачётам. Пороговые правила наград могут задаваться процентными ориентирами от распределения результатов и требуют ручного утверждения перед публикацией. Отдельный flag удержания результата скрывает результат от публикации до решения администратора.

Documents

competition_award_document

Диплом, грамота, сертификат, благодарность.

competition_document_generation_job

Batch generation job.

Audit

competition_audit_log

Аудит действий, влияющих на участие, доступ, работы, баллы, результаты, публикации и документы.