# Generated by Django 5.2.15 on 2026-06-11 23:06

import django.core.validators
import django.db.models.deletion
import django.db.models.functions.text
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ('auth', '0012_alter_user_first_name_max_length'),
        ('authentication', '0025_userprofile_minimize_sidebar'),
        ('eveonline', '0025_remove_evecharacter_last_updated_and_more'),
        ('eveuniverse', '0012_alter_evebloodline_eve_ship_type'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='General',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
            ],
            options={
                'permissions': (('basic_access', 'Can access Fit Check'), ('manage_doctrines', 'Can manage doctrines and fits'), ('review_submissions', 'Can review fit submissions'), ('view_compliance_reports', 'Can view org-wide compliance reports')),
                'managed': False,
                'default_permissions': (),
            },
        ),
        migrations.CreateModel(
            name='SdeAttribute',
            fields=[
                ('attribute_id', models.PositiveIntegerField(primary_key=True, serialize=False)),
                ('name', models.CharField(db_index=True, max_length=100)),
                ('display_name', models.CharField(blank=True, db_index=True, max_length=150)),
                ('high_is_good', models.BooleanField(default=True)),
                ('unit_name', models.CharField(blank=True, max_length=50)),
                ('published', models.BooleanField(default=True)),
            ],
        ),
        migrations.CreateModel(
            name='SdeLoadRecord',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('sde_build', models.CharField(max_length=128)),
                ('loaded_at', models.DateTimeField(auto_now_add=True)),
                ('type_count', models.PositiveIntegerField(default=0)),
            ],
            options={
                'get_latest_by': 'loaded_at',
            },
        ),
        migrations.CreateModel(
            name='Doctrine',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100, unique=True)),
                ('description', models.TextField(blank=True)),
                ('is_active', models.BooleanField(default=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('created_by', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
                ('groups', models.ManyToManyField(blank=True, help_text='Restrict visibility to these Auth groups. Empty plus no states = visible to all.', related_name='+', to='auth.group')),
                ('states', models.ManyToManyField(blank=True, help_text='Restrict visibility to these member states.', related_name='+', to='authentication.state')),
            ],
            options={
                'default_permissions': (),
            },
        ),
        migrations.CreateModel(
            name='DoctrineFit',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=100)),
                ('description', models.TextField(blank=True)),
                ('eft_source', models.TextField(help_text='Raw EFT text as imported, preserved verbatim.')),
                ('version', models.PositiveIntegerField(default=1)),
                ('is_active', models.BooleanField(default=True)),
                ('strict_extras', models.BooleanField(default=False, help_text='When set, modules outside the doctrine fail the check instead of warning.')),
                ('default_policy', models.CharField(choices=[('EX', 'Exact type only'), ('VA', 'Variant family (meta filtered)'), ('MB', 'Any equivalent that meets or beats attributes')], default='VA', max_length=2)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('doctrine', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='fits', to='fitcheck.doctrine')),
                ('last_imported_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
                ('ship_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='eveuniverse.evetype')),
            ],
            options={
                'default_permissions': (),
            },
        ),
        migrations.CreateModel(
            name='DoctrineFitItem',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('section', models.CharField(choices=[('HIGH', 'High slots'), ('MED', 'Mid slots'), ('LOW', 'Low slots'), ('RIG', 'Rigs'), ('SUBSYS', 'Subsystems'), ('DRONE', 'Drone bay'), ('FIGHTER', 'Fighter bay'), ('CARGO', 'Cargo'), ('IMPLANT', 'Implants')], max_length=8)),
                ('quantity', models.PositiveIntegerField(default=1)),
                ('policy', models.CharField(choices=[('EX', 'Exact type only'), ('VA', 'Variant family (meta filtered)'), ('MB', 'Any equivalent that meets or beats attributes')], max_length=2)),
                ('min_meta_level', models.PositiveSmallIntegerField(blank=True, help_text="Substitutes need at least this meta level. Empty = this module's own level.", null=True)),
                ('allowed_meta_groups', models.JSONField(blank=True, default=list, help_text='Meta group IDs allowed as substitutes (e.g. [2, 4] = Tech II + Faction). Empty = all.')),
                ('checked_attributes', models.JSONField(blank=True, default=list, help_text='Attribute IDs compared under meet-or-beat. Empty = sensible defaults.')),
                ('allow_mutated', models.BooleanField(default=True, help_text='Allow abyssal/mutated modules under meet-or-beat when their rolls qualify.')),
                ('min_quantity_pct', models.PositiveSmallIntegerField(default=100, help_text='Consumable leeway for bay/cargo items: pass at this percent of the listed quantity.', validators=[django.core.validators.MinValueValidator(1), django.core.validators.MaxValueValidator(100)])),
                ('notes', models.CharField(blank=True, max_length=255)),
                ('charge_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='eveuniverse.evetype')),
                ('fit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='fitcheck.doctrinefit')),
                ('module_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='eveuniverse.evetype')),
            ],
            options={
                'default_permissions': (),
            },
        ),
        migrations.CreateModel(
            name='FitItemOverride',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('mode', models.CharField(choices=[('I', 'Always allow'), ('E', 'Never allow')], max_length=1)),
                ('alt_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='eveuniverse.evetype')),
                ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='overrides', to='fitcheck.doctrinefititem')),
            ],
            options={
                'default_permissions': (),
            },
        ),
        migrations.CreateModel(
            name='FitSubmission',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('fit_version', models.PositiveIntegerField(help_text='Version of the doctrine fit this submission was checked against.')),
                ('source', models.CharField(choices=[('EFT', 'EFT paste'), ('ESI', 'ESI import')], max_length=3)),
                ('eft_text', models.TextField(blank=True, help_text='Raw paste, or the ESI fit rendered to EFT for reviewers.')),
                ('esi_fitting_id', models.PositiveIntegerField(blank=True, null=True)),
                ('verdict', models.CharField(choices=[('C', 'Compliant'), ('S', 'Compliant with substitutions'), ('N', 'Non-compliant'), ('E', 'Could not be checked')], max_length=1)),
                ('status', models.CharField(choices=[('P', 'Pending review'), ('A', 'Approved'), ('R', 'Rejected')], default='P', max_length=1)),
                ('reviewed_at', models.DateTimeField(blank=True, null=True)),
                ('review_comment', models.TextField(blank=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('character', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='eveonline.evecharacter')),
                ('doctrine_fit', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='submissions', to='fitcheck.doctrinefit')),
                ('reviewed_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
                ('ship_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='eveuniverse.evetype')),
                ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'default_permissions': (),
            },
        ),
        migrations.CreateModel(
            name='ComplianceFinding',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('section', models.CharField(blank=True, choices=[('HIGH', 'High slots'), ('MED', 'Mid slots'), ('LOW', 'Low slots'), ('RIG', 'Rigs'), ('SUBSYS', 'Subsystems'), ('DRONE', 'Drone bay'), ('FIGHTER', 'Fighter bay'), ('CARGO', 'Cargo'), ('IMPLANT', 'Implants')], default='', max_length=8)),
                ('code', models.CharField(choices=[('OK', 'Exact match'), ('SUB', 'Allowed substitute'), ('BAD', 'Not an allowed substitute'), ('MIS', 'Missing'), ('EXT', 'Not part of the fit'), ('QTY', 'Quantity short'), ('HUL', 'Wrong hull'), ('UNR', 'Unrecognized item'), ('IMP', 'Required implant missing'), ('UNV', 'Listed but not verifiable')], max_length=3)),
                ('expected_qty', models.PositiveIntegerField(blank=True, null=True)),
                ('actual_qty', models.PositiveIntegerField(blank=True, null=True)),
                ('message', models.CharField(max_length=500)),
                ('allowed_alternatives', models.JSONField(blank=True, default=list)),
                ('attribute_results', models.JSONField(blank=True, default=list)),
                ('sort_order', models.PositiveSmallIntegerField(default=0)),
                ('actual_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='eveuniverse.evetype')),
                ('expected_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='eveuniverse.evetype')),
                ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='findings', to='fitcheck.fitsubmission')),
            ],
            options={
                'ordering': ['sort_order', 'pk'],
                'default_permissions': (),
            },
        ),
        migrations.CreateModel(
            name='SdeType',
            fields=[
                ('type_id', models.PositiveIntegerField(primary_key=True, serialize=False)),
                ('name', models.CharField(db_index=True, max_length=200)),
                ('group_id', models.PositiveIntegerField()),
                ('category_id', models.PositiveIntegerField(db_index=True)),
                ('variation_parent_type_id', models.PositiveIntegerField(blank=True, db_index=True, null=True)),
                ('meta_group_id', models.PositiveIntegerField(blank=True, null=True)),
                ('meta_level', models.PositiveSmallIntegerField(blank=True, null=True)),
                ('slot_kind', models.CharField(choices=[('HIGH', 'High slot module'), ('MED', 'Mid slot module'), ('LOW', 'Low slot module'), ('RIG', 'Rig'), ('SUBSYS', 'Subsystem'), ('DRONE', 'Drone'), ('FIGHTER', 'Fighter'), ('CHARGE', 'Charge'), ('SHIP', 'Ship'), ('IMPLANT', 'Implant'), ('OTHER', 'Other')], default='OTHER', max_length=8)),
                ('published', models.BooleanField(default=True)),
            ],
            options={
                'indexes': [models.Index(django.db.models.functions.text.Upper('name'), name='fitcheck_sdetype_name_upper'), models.Index(fields=['category_id', 'published'], name='fitcheck_sd_categor_708efc_idx')],
            },
        ),
        migrations.CreateModel(
            name='SdeMutaplasmidMapping',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('mutator_type_id', models.PositiveIntegerField()),
                ('mutable_attributes', models.JSONField(blank=True, default=list)),
                ('abyssal_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mutation_sources', to='fitcheck.sdetype')),
                ('source_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='mutation_results', to='fitcheck.sdetype')),
            ],
        ),
        migrations.CreateModel(
            name='SdeTypeAttribute',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('value', models.FloatField()),
                ('attribute', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='fitcheck.sdeattribute')),
                ('eve_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='attributes', to='fitcheck.sdetype')),
            ],
        ),
        migrations.CreateModel(
            name='SubmissionActionLog',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('action', models.CharField(choices=[('SUB', 'Submitted'), ('CHK', 'Auto-checked'), ('RCK', 'Re-checked'), ('APP', 'Approved'), ('REJ', 'Rejected'), ('COM', 'Commented')], max_length=3)),
                ('comment', models.TextField(blank=True)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('actor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to=settings.AUTH_USER_MODEL)),
                ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='log', to='fitcheck.fitsubmission')),
            ],
            options={
                'ordering': ['created_at'],
                'default_permissions': (),
            },
        ),
        migrations.CreateModel(
            name='SubmissionItem',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('section', models.CharField(choices=[('HIGH', 'High slots'), ('MED', 'Mid slots'), ('LOW', 'Low slots'), ('RIG', 'Rigs'), ('SUBSYS', 'Subsystems'), ('DRONE', 'Drone bay'), ('FIGHTER', 'Fighter bay'), ('CARGO', 'Cargo'), ('IMPLANT', 'Implants')], max_length=8)),
                ('quantity', models.PositiveIntegerField(default=1)),
                ('mutated_attributes', models.JSONField(blank=True, null=True)),
                ('mutation_source', models.CharField(blank=True, choices=[('PYFA', 'Pyfa EFT export'), ('MAN', 'Self-reported'), ('ESI', 'ESI verified')], default='', max_length=4)),
                ('charge_type', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='eveuniverse.evetype')),
                ('eve_type', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='eveuniverse.evetype')),
                ('submission', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='fitcheck.fitsubmission')),
            ],
            options={
                'default_permissions': (),
            },
        ),
        migrations.AddConstraint(
            model_name='doctrinefit',
            constraint=models.UniqueConstraint(fields=('doctrine', 'name'), name='fitcheck_unique_fit_name'),
        ),
        migrations.AddIndex(
            model_name='doctrinefititem',
            index=models.Index(fields=['fit', 'section'], name='fitcheck_do_fit_id_3428f9_idx'),
        ),
        migrations.AddConstraint(
            model_name='doctrinefititem',
            constraint=models.UniqueConstraint(fields=('fit', 'section', 'module_type'), name='fitcheck_unique_fit_item'),
        ),
        migrations.AddConstraint(
            model_name='fititemoverride',
            constraint=models.UniqueConstraint(fields=('item', 'alt_type'), name='fitcheck_unique_override'),
        ),
        migrations.AddIndex(
            model_name='fitsubmission',
            index=models.Index(fields=['user', '-created_at'], name='fitcheck_fi_user_id_79b45c_idx'),
        ),
        migrations.AddIndex(
            model_name='fitsubmission',
            index=models.Index(fields=['status', '-created_at'], name='fitcheck_fi_status_ef1f69_idx'),
        ),
        migrations.AddIndex(
            model_name='fitsubmission',
            index=models.Index(fields=['doctrine_fit', 'status'], name='fitcheck_fi_doctrin_90a0c7_idx'),
        ),
        migrations.AddConstraint(
            model_name='sdemutaplasmidmapping',
            constraint=models.UniqueConstraint(fields=('abyssal_type', 'source_type', 'mutator_type_id'), name='fitcheck_unique_mutaplasmid_mapping'),
        ),
        migrations.AddConstraint(
            model_name='sdetypeattribute',
            constraint=models.UniqueConstraint(fields=('eve_type', 'attribute'), name='fitcheck_unique_type_attribute'),
        ),
    ]
