# Generated by Django 5.2.13 on 2026-04-23 08:04

import apps.core.storage.paths
import apps.core.storage.validators
import django.contrib.postgres.indexes
import django.contrib.postgres.search
import django.db.models.deletion
import django_fsm
import uuid
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ("core", "0011_alter_notification_verb_repository"),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name="MetadataSchema",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(max_length=120, unique=True)),
                ("description", models.TextField(blank=True)),
                (
                    "mandatory_fields",
                    models.JSONField(
                        blank=True,
                        default=list,
                        help_text='List of mandatory field codes, e.g. ["title","abstract","license_type"].',
                    ),
                ),
                (
                    "controlled_vocabularies",
                    models.JSONField(
                        blank=True,
                        default=dict,
                        help_text="Mapping of field code → list of allowed values.",
                    ),
                ),
                (
                    "auto_classification_rules",
                    models.JSONField(
                        blank=True,
                        default=list,
                        help_text='List of rules: {"if_keyword": str, "then_collection_slug": str}.',
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
            ],
            options={
                "ordering": ["name"],
            },
        ),
        migrations.CreateModel(
            name="Author",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("first_name", models.CharField(max_length=120)),
                ("last_name", models.CharField(max_length=120)),
                (
                    "orcid",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        help_text="ORCID iD in the form 0000-0000-0000-0000.",
                        max_length=19,
                        null=True,
                        unique=True,
                    ),
                ),
                ("email", models.EmailField(blank=True, max_length=254)),
                ("affiliation_text", models.CharField(blank=True, max_length=255)),
                ("verified_at", models.DateTimeField(blank=True, null=True)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
                (
                    "institution",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="repository_authors",
                        to="core.institution",
                    ),
                ),
            ],
            options={
                "ordering": ["last_name", "first_name"],
            },
        ),
        migrations.CreateModel(
            name="Collection",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(max_length=160)),
                ("slug", models.SlugField(max_length=120, unique=True)),
                ("description", models.TextField(blank=True)),
                (
                    "visibility",
                    models.CharField(
                        choices=[
                            ("public_open", "Public — Open Access"),
                            ("authenticated", "Authenticated only"),
                            ("restricted", "Restricted (named users / groups)"),
                            ("internal", "Internal (not publicly searchable)"),
                        ],
                        db_index=True,
                        default="public_open",
                        max_length=24,
                    ),
                ),
                ("qa_workflow_enabled", models.BooleanField(default=True)),
                ("qa_turnaround_days", models.PositiveSmallIntegerField(default=14)),
                ("retention_period_days", models.PositiveIntegerField(blank=True, null=True)),
                (
                    "retention_action",
                    models.CharField(
                        choices=[
                            ("archive", "Archive"),
                            ("flag", "Flag for review"),
                            ("withdraw", "Withdraw"),
                        ],
                        default="flag",
                        max_length=16,
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
                (
                    "managed_by",
                    models.ManyToManyField(
                        blank=True,
                        help_text="Collection Managers responsible for QA on this collection.",
                        related_name="managed_repository_collections",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "parent",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="children",
                        to="repository_documents.collection",
                    ),
                ),
                (
                    "metadata_schema",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="collections",
                        to="repository_documents.metadataschema",
                    ),
                ),
            ],
            options={
                "ordering": ["name"],
            },
        ),
        migrations.CreateModel(
            name="Document",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                (
                    "document_uid",
                    models.UUIDField(
                        db_index=True, default=uuid.uuid4, editable=False, unique=True
                    ),
                ),
                (
                    "public_document_id",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        help_text="Human-friendly Document ID assigned on first save.",
                        max_length=32,
                        unique=True,
                    ),
                ),
                ("title", models.CharField(max_length=400)),
                ("abstract", models.TextField(blank=True)),
                (
                    "file",
                    models.FileField(
                        max_length=512,
                        upload_to=apps.core.storage.paths.upload_to_repository,
                        validators=[
                            apps.core.storage.validators.FileValidator(
                                allowed_categories=[
                                    "document",
                                    "data",
                                    "image",
                                    "archive",
                                    "media",
                                ],
                                module="repository",
                            )
                        ],
                    ),
                ),
                (
                    "file_hash",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        help_text="SHA-256 of the file payload — used for duplicate detection.",
                        max_length=64,
                    ),
                ),
                ("file_size_bytes", models.PositiveBigIntegerField(default=0)),
                (
                    "document_type",
                    models.CharField(
                        choices=[
                            ("thesis", "Thesis / Dissertation"),
                            ("journal_article", "Journal article"),
                            ("conference_paper", "Conference paper"),
                            ("policy_brief", "Policy brief"),
                            ("technical_report", "Technical report"),
                            ("project_report", "Project report"),
                            ("dataset", "Dataset"),
                            ("innovation_document", "Innovation technical document"),
                            ("publication", "Publication"),
                            ("other", "Other"),
                        ],
                        db_index=True,
                        default="other",
                        max_length=32,
                    ),
                ),
                ("doi", models.CharField(blank=True, db_index=True, max_length=120)),
                (
                    "license_type",
                    models.CharField(
                        choices=[
                            ("cc_by", "CC BY 4.0"),
                            ("cc_by_sa", "CC BY-SA 4.0"),
                            ("cc_by_nc", "CC BY-NC 4.0"),
                            ("cc_by_nc_sa", "CC BY-NC-SA 4.0"),
                            ("cc0", "CC0 1.0 Universal"),
                            ("all_rights_reserved", "All rights reserved"),
                            ("other", "Other (see notes)"),
                        ],
                        default="cc_by",
                        max_length=32,
                    ),
                ),
                ("license_notes", models.CharField(blank=True, max_length=255)),
                ("language", models.CharField(default="en", max_length=8)),
                ("year", models.PositiveSmallIntegerField(blank=True, null=True)),
                (
                    "visibility",
                    models.CharField(
                        choices=[
                            ("inherit", "Inherit from collection"),
                            ("public_open", "Public — Open Access"),
                            ("authenticated", "Authenticated only"),
                            ("restricted", "Restricted"),
                            ("internal", "Internal"),
                        ],
                        default="inherit",
                        help_text="Document-level override; INHERIT = use collection.visibility.",
                        max_length=24,
                    ),
                ),
                (
                    "grant_reference",
                    models.CharField(
                        blank=True,
                        db_index=True,
                        help_text="RIMS public_grant_id of the funding grant, when applicable.",
                        max_length=64,
                    ),
                ),
                (
                    "grant_closed_flag",
                    models.BooleanField(
                        default=False,
                        help_text="True when the linked RIMS grant has been closed (PRD REPO-SP5).",
                    ),
                ),
                ("submitted_at", models.DateTimeField(blank=True, null=True)),
                ("published_at", models.DateTimeField(blank=True, null=True)),
                ("withdrawn_at", models.DateTimeField(blank=True, null=True)),
                ("withdrawn_reason", models.TextField(blank=True)),
                (
                    "status",
                    django_fsm.FSMField(
                        choices=[
                            ("draft", "Draft"),
                            ("submitted", "Submitted"),
                            ("under_qa", "Under QA review"),
                            ("revision_required", "Revision required"),
                            ("approved", "Approved"),
                            ("published", "Published"),
                            ("rejected", "Rejected"),
                            ("withdrawn", "Withdrawn"),
                        ],
                        db_index=True,
                        default="draft",
                        max_length=32,
                        protected=True,
                    ),
                ),
                (
                    "source_system",
                    models.CharField(
                        default="manual",
                        help_text="manual | rims | bulk | email | api",
                        max_length=24,
                    ),
                ),
                ("extracted_text", models.TextField(blank=True)),
                ("ai_metadata", models.JSONField(blank=True, default=dict)),
                ("ai_summary", models.TextField(blank=True)),
                ("ai_summary_generated_at", models.DateTimeField(blank=True, null=True)),
                ("preview_supported", models.BooleanField(default=False)),
                (
                    "thumbnail",
                    models.ImageField(
                        blank=True,
                        max_length=512,
                        null=True,
                        upload_to=apps.core.storage.paths.upload_to_repository_thumbnails,
                    ),
                ),
                (
                    "search_vector",
                    django.contrib.postgres.search.SearchVectorField(editable=False, null=True),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
                (
                    "collection",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.PROTECT,
                        related_name="documents",
                        to="repository_documents.collection",
                    ),
                ),
                (
                    "submitted_by",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="repository_documents_submitted",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "ordering": ["-published_at", "-created_at"],
                "permissions": [
                    ("download_document", "Can download a Repository document"),
                    ("comment_document", "Can comment on a Repository document"),
                    ("share_document", "Can share a Repository document with others"),
                    (
                        "manage_document",
                        "Can manage (withdraw / reinstate / edit) a Repository document",
                    ),
                    ("ingest_via_rims", "Can ingest documents via the RIMS API endpoint"),
                ],
            },
        ),
        migrations.CreateModel(
            name="AccessRequest",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("justification", models.TextField()),
                (
                    "status",
                    models.CharField(
                        choices=[
                            ("pending", "Pending"),
                            ("approved", "Approved"),
                            ("denied", "Denied"),
                        ],
                        db_index=True,
                        default="pending",
                        max_length=16,
                    ),
                ),
                ("decided_at", models.DateTimeField(blank=True, null=True)),
                ("decision_note", models.TextField(blank=True)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                (
                    "decided_by",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="repository_access_requests_decided",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "requester",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="repository_access_requests",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "document",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="access_requests",
                        to="repository_documents.document",
                    ),
                ),
            ],
            options={
                "ordering": ["-created_at"],
            },
        ),
        migrations.CreateModel(
            name="DocumentAuthor",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("order", models.PositiveSmallIntegerField(default=0)),
                (
                    "role",
                    models.CharField(
                        choices=[
                            ("primary", "Primary author"),
                            ("co_author", "Co-author"),
                            ("contributor", "Contributor"),
                        ],
                        default="co_author",
                        max_length=16,
                    ),
                ),
                (
                    "author",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        to="repository_documents.author",
                    ),
                ),
                (
                    "document",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        to="repository_documents.document",
                    ),
                ),
            ],
            options={
                "ordering": ["order", "pk"],
            },
        ),
        migrations.AddField(
            model_name="document",
            name="authors",
            field=models.ManyToManyField(
                related_name="documents",
                through="repository_documents.DocumentAuthor",
                to="repository_documents.author",
            ),
        ),
        migrations.CreateModel(
            name="DocumentComment",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                (
                    "section_anchor",
                    models.CharField(
                        blank=True,
                        help_text="Page / section reference, e.g. 'p.4 ¶2'.",
                        max_length=120,
                    ),
                ),
                ("text", models.TextField()),
                ("is_resolved", models.BooleanField(default=False)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                ("updated_at", models.DateTimeField(auto_now=True)),
                (
                    "author",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="repository_comments",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "document",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="comments",
                        to="repository_documents.document",
                    ),
                ),
                (
                    "parent",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="replies",
                        to="repository_documents.documentcomment",
                    ),
                ),
            ],
            options={
                "ordering": ["created_at"],
            },
        ),
        migrations.CreateModel(
            name="DocumentReviewTask",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("scope", models.TextField()),
                ("instructions", models.TextField(blank=True)),
                ("due_date", models.DateField(blank=True, null=True)),
                (
                    "status",
                    models.CharField(
                        choices=[
                            ("pending", "Pending"),
                            ("in_progress", "In progress"),
                            ("completed", "Completed"),
                        ],
                        db_index=True,
                        default="pending",
                        max_length=16,
                    ),
                ),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                (
                    "assignee",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="repository_review_tasks",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "created_by",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="repository_review_tasks_created",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "document",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="review_tasks",
                        to="repository_documents.document",
                    ),
                ),
            ],
            options={
                "ordering": ["-created_at"],
            },
        ),
        migrations.CreateModel(
            name="DocumentShare",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                (
                    "permission_level",
                    models.CharField(
                        choices=[("view", "View only"), ("comment", "Comment"), ("edit", "Edit")],
                        default="view",
                        max_length=16,
                    ),
                ),
                ("granted_at", models.DateTimeField(auto_now_add=True)),
                ("revoked_at", models.DateTimeField(blank=True, null=True)),
                (
                    "collaborator",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="repository_shared_with_me",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
                (
                    "document",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="shares",
                        to="repository_documents.document",
                    ),
                ),
                (
                    "granted_by",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="repository_shares_granted",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "ordering": ["-granted_at"],
            },
        ),
        migrations.CreateModel(
            name="DocumentVersion",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                (
                    "version_number",
                    models.CharField(
                        help_text='Sequential, e.g. "1.0", "1.1", "2.0".', max_length=16
                    ),
                ),
                (
                    "file",
                    models.FileField(
                        max_length=512,
                        upload_to=apps.core.storage.paths.upload_to_repository,
                        validators=[
                            apps.core.storage.validators.FileValidator(
                                allowed_categories=[
                                    "document",
                                    "data",
                                    "image",
                                    "archive",
                                    "media",
                                ],
                                module="repository",
                            )
                        ],
                    ),
                ),
                ("file_hash", models.CharField(blank=True, db_index=True, max_length=64)),
                ("uploaded_at", models.DateTimeField(auto_now_add=True)),
                ("changelog", models.TextField(blank=True)),
                ("is_immutable", models.BooleanField(default=True)),
                (
                    "document",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="versions",
                        to="repository_documents.document",
                    ),
                ),
                (
                    "uploaded_by",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="repository_document_versions_uploaded",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "ordering": ["-uploaded_at"],
            },
        ),
        migrations.CreateModel(
            name="IntegrationOutbox",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                (
                    "target",
                    models.CharField(
                        choices=[
                            ("mel", "M&EL"),
                            ("rims", "RIMS"),
                            ("rep", "REP"),
                            ("smehub", "SME-Hub"),
                        ],
                        db_index=True,
                        max_length=12,
                    ),
                ),
                ("event_type", models.CharField(max_length=64)),
                ("payload", models.JSONField(default=dict)),
                (
                    "status",
                    models.CharField(
                        choices=[("pending", "Pending"), ("sent", "Sent"), ("failed", "Failed")],
                        db_index=True,
                        default="pending",
                        max_length=12,
                    ),
                ),
                ("retry_count", models.PositiveSmallIntegerField(default=0)),
                ("error", models.TextField(blank=True)),
                ("sent_at", models.DateTimeField(blank=True, null=True)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
            ],
            options={
                "ordering": ["-created_at"],
                "indexes": [
                    models.Index(fields=["target", "status"], name="repository__target_e8f095_idx")
                ],
            },
        ),
        migrations.CreateModel(
            name="QARecord",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("pre_check_passed", models.BooleanField(default=False)),
                ("pre_check_notes", models.JSONField(blank=True, default=dict)),
                (
                    "decision",
                    models.CharField(
                        choices=[
                            ("pending", "Pending review"),
                            ("approve", "Approved"),
                            ("reject", "Rejected"),
                            ("revision", "Revision required"),
                        ],
                        default="pending",
                        max_length=16,
                    ),
                ),
                ("comments", models.TextField(blank=True)),
                ("assigned_at", models.DateTimeField(auto_now_add=True)),
                ("decided_at", models.DateTimeField(blank=True, null=True)),
                (
                    "document",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="qa_records",
                        to="repository_documents.document",
                    ),
                ),
                (
                    "reviewer",
                    models.ForeignKey(
                        blank=True,
                        null=True,
                        on_delete=django.db.models.deletion.SET_NULL,
                        related_name="repository_qa_records",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "ordering": ["-assigned_at"],
            },
        ),
        migrations.CreateModel(
            name="SavedSearch",
            fields=[
                (
                    "id",
                    models.BigAutoField(
                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
                    ),
                ),
                ("name", models.CharField(max_length=120)),
                (
                    "query",
                    models.JSONField(
                        default=dict, help_text='{"q": "<query>", "filters": {...}, "sort": "..."}'
                    ),
                ),
                ("alert_enabled", models.BooleanField(default=False)),
                ("last_alert_at", models.DateTimeField(blank=True, null=True)),
                ("created_at", models.DateTimeField(auto_now_add=True)),
                (
                    "user",
                    models.ForeignKey(
                        on_delete=django.db.models.deletion.CASCADE,
                        related_name="repository_saved_searches",
                        to=settings.AUTH_USER_MODEL,
                    ),
                ),
            ],
            options={
                "ordering": ["-created_at"],
            },
        ),
        migrations.AddIndex(
            model_name="author",
            index=models.Index(
                fields=["last_name", "first_name"], name="repository__last_na_ed5419_idx"
            ),
        ),
        migrations.AddConstraint(
            model_name="documentauthor",
            constraint=models.UniqueConstraint(
                fields=("document", "author"), name="uniq_document_author"
            ),
        ),
        migrations.AddIndex(
            model_name="document",
            index=django.contrib.postgres.indexes.GinIndex(
                fields=["search_vector"], name="repo_doc_search_gin"
            ),
        ),
        migrations.AddIndex(
            model_name="document",
            index=models.Index(
                fields=["status", "collection"], name="repository__status_83b8bd_idx"
            ),
        ),
        migrations.AddIndex(
            model_name="document",
            index=models.Index(
                fields=["document_type", "year"], name="repository__documen_b1fc7d_idx"
            ),
        ),
        migrations.AddIndex(
            model_name="document",
            index=models.Index(fields=["grant_reference"], name="repository__grant_r_83f1af_idx"),
        ),
        migrations.AddConstraint(
            model_name="documentshare",
            constraint=models.UniqueConstraint(
                fields=("document", "collaborator"), name="uniq_document_share"
            ),
        ),
        migrations.AddConstraint(
            model_name="documentversion",
            constraint=models.UniqueConstraint(
                fields=("document", "version_number"), name="uniq_document_version_number"
            ),
        ),
    ]
