# Generated by Django 5.2.17 on 2026-09-28 03:36

import django.db.models.deletion
import django.db.models.expressions
import uuid
from django.conf import settings
from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
        ('organization', '0002_userorganizationassignment'),
        ('parts', '0001_initial'),
        ('service', '0006_handover_closure'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='QuotationFamily',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('number', models.CharField(max_length=22)),
                ('approval_obligation', models.BooleanField(default=False)),
                ('service_case', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='quotation_family', to='service.servicecase')),
                ('service_center', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='organization.servicecenter')),
            ],
            options={
                'ordering': ('created_at', 'pk'),
                'abstract': False,
            },
        ),
        migrations.CreateModel(
            name='QuotationSequence',
            fields=[
                ('service_center', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, primary_key=True, serialize=False, to='organization.servicecenter')),
                ('next_value', models.PositiveBigIntegerField(default=1)),
            ],
            options={
                'constraints': [models.CheckConstraint(condition=models.Q(('next_value__gte', 1)), name='commercial_sequence_positive')],
            },
        ),
        migrations.CreateModel(
            name='ServiceQuotation',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('revision', models.PositiveIntegerField(default=1)),
                ('is_current', models.BooleanField(default=True)),
                ('status', models.CharField(choices=[('DRAFT', 'Draft'), ('SUBMITTED', 'Submitted'), ('APPROVED', 'Approved'), ('REJECTED', 'Rejected'), ('SUPERSEDED', 'Superseded')], default='DRAFT', max_length=10)),
                ('currency', models.CharField(max_length=3)),
                ('customer_note', models.TextField(blank=True, help_text='Do not record passwords, screen PINs, account credentials or OTPs.', max_length=4000)),
                ('internal_note', models.TextField(blank=True, help_text='Do not record passwords, screen PINs, account credentials or OTPs.', max_length=4000)),
                ('valid_until', models.DateTimeField(blank=True, null=True)),
                ('subtotal', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('discount_total', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('tax_total', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('grand_total', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('customer_pay_total', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('covered_total', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('context_snapshot', models.JSONField(blank=True, default=dict)),
                ('scope_snapshot', models.JSONField(blank=True, default=list)),
                ('submitted_at', models.DateTimeField(blank=True, null=True)),
                ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='created_quotations', to=settings.AUTH_USER_MODEL)),
                ('family', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='revisions', to='commercial.quotationfamily')),
                ('submitted_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='submitted_quotations', to=settings.AUTH_USER_MODEL)),
            ],
            options={
                'ordering': ('family_id', 'revision'),
                'permissions': [('manage_servicequotation', 'Manage service quotations'), ('record_quotationdecision', 'Record customer quotation decisions')],
                'abstract': False,
            },
        ),
        migrations.CreateModel(
            name='QuotationLine',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('position', models.PositiveIntegerField()),
                ('kind', models.CharField(choices=[('PART', 'Part'), ('LABOR', 'Labor'), ('SERVICE', 'Service')], max_length=7)),
                ('responsibility', models.CharField(choices=[('CUSTOMER', 'Customer'), ('WARRANTY', 'Warranty'), ('COMPANY', 'Company')], max_length=8)),
                ('description', models.CharField(max_length=500)),
                ('coverage_reason', models.CharField(blank=True, help_text='Do not record passwords, screen PINs, account credentials or OTPs.', max_length=1000)),
                ('part_code', models.CharField(blank=True, max_length=128)),
                ('part_name', models.CharField(blank=True, max_length=500)),
                ('quantity', models.PositiveIntegerField(default=1)),
                ('unit_price', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('subtotal', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('discount', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('taxable_amount', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('tax_rate', models.DecimalField(decimal_places=2, default=0, max_digits=5)),
                ('tax_label', models.CharField(blank=True, max_length=100)),
                ('tax', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('total', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('is_active', models.BooleanField(default=True)),
                ('finding', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='service.servicediagnosticfinding')),
                ('repair_action', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='service.servicerepairaction')),
                ('spare_part', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='parts.sparepart')),
                ('quotation', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='lines', to='commercial.servicequotation')),
            ],
            options={
                'ordering': ('position', 'pk'),
                'abstract': False,
            },
        ),
        migrations.CreateModel(
            name='QuotationDecision',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('outcome', models.CharField(choices=[('APPROVED', 'Approved'), ('REJECTED', 'Rejected')], max_length=8)),
                ('channel', models.CharField(choices=[('IN_PERSON', 'IN_PERSON'), ('PHONE', 'PHONE'), ('SMS', 'SMS'), ('WHATSAPP', 'WHATSAPP'), ('EMAIL', 'EMAIL'), ('OTHER', 'OTHER')], max_length=10)),
                ('recipient_name', models.CharField(max_length=200)),
                ('reference', models.CharField(max_length=500)),
                ('note', models.TextField(blank=True, help_text='Do not record passwords, screen PINs, account credentials or OTPs.', max_length=2000)),
                ('recorded_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
                ('quotation', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='decision', to='commercial.servicequotation')),
            ],
            options={
                'ordering': ('created_at', 'pk'),
                'abstract': False,
            },
        ),
        migrations.CreateModel(
            name='CommercialWorkAuthorization',
            fields=[
                ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
                ('created_at', models.DateTimeField(auto_now_add=True)),
                ('updated_at', models.DateTimeField(auto_now=True)),
                ('operation', models.CharField(choices=[('PERFORM', 'PERFORM'), ('CONSUME', 'CONSUME'), ('COMPLETE', 'COMPLETE')], max_length=8)),
                ('quantity', models.PositiveIntegerField(default=0)),
                ('actor', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
                ('repair_action', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='service.servicerepairaction')),
                ('repair_execution', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='service.servicerepairexecution')),
                ('spare_part', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='parts.sparepart')),
                ('quotation', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='work_authorizations', to='commercial.servicequotation')),
            ],
            options={
                'ordering': ('created_at', 'pk'),
                'abstract': False,
            },
        ),
        migrations.AddConstraint(
            model_name='quotationfamily',
            constraint=models.UniqueConstraint(fields=('service_center', 'number'), name='commercial_number_unique'),
        ),
        migrations.AddConstraint(
            model_name='quotationfamily',
            constraint=models.CheckConstraint(condition=models.Q(('number__regex', '^EST-[0-9]{8,18}$')), name='commercial_number_format'),
        ),
        migrations.AddConstraint(
            model_name='servicequotation',
            constraint=models.UniqueConstraint(fields=('family', 'revision'), name='commercial_revision_unique'),
        ),
        migrations.AddConstraint(
            model_name='servicequotation',
            constraint=models.UniqueConstraint(condition=models.Q(('is_current', True)), fields=('family',), name='commercial_one_current'),
        ),
        migrations.AddConstraint(
            model_name='servicequotation',
            constraint=models.CheckConstraint(condition=models.Q(('revision__gte', 1)), name='commercial_revision_positive'),
        ),
        migrations.AddConstraint(
            model_name='servicequotation',
            constraint=models.CheckConstraint(condition=models.Q(('status__in', ['DRAFT', 'SUBMITTED', 'APPROVED', 'REJECTED', 'SUPERSEDED'])), name='commercial_status_valid'),
        ),
        migrations.AddConstraint(
            model_name='servicequotation',
            constraint=models.CheckConstraint(condition=models.Q(('currency__regex', '^[A-Z]{3}$')), name='commercial_currency_format'),
        ),
        migrations.AddConstraint(
            model_name='servicequotation',
            constraint=models.CheckConstraint(condition=models.Q(('covered_total__gte', 0), ('customer_pay_total', django.db.models.expressions.CombinedExpression(models.F('grand_total'), '-', models.F('covered_total'))), ('customer_pay_total__gte', 0), ('discount_total__gte', 0), ('discount_total__lte', models.F('subtotal')), ('grand_total', django.db.models.expressions.CombinedExpression(django.db.models.expressions.CombinedExpression(models.F('subtotal'), '-', models.F('discount_total')), '+', models.F('tax_total'))), ('grand_total__gte', 0), ('subtotal__gte', 0), ('tax_total__gte', 0)), name='commercial_totals_coherent'),
        ),
        migrations.AddConstraint(
            model_name='servicequotation',
            constraint=models.CheckConstraint(condition=models.Q(models.Q(('status', 'DRAFT'), ('submitted_at__isnull', True), ('submitted_by__isnull', True)), models.Q(('status__in', ['SUBMITTED', 'APPROVED', 'REJECTED', 'SUPERSEDED']), ('submitted_at__isnull', False), ('submitted_by__isnull', False)), _connector='OR'), name='commercial_submission_coherent'),
        ),
        migrations.AddConstraint(
            model_name='quotationline',
            constraint=models.UniqueConstraint(condition=models.Q(('is_active', True)), fields=('quotation', 'position'), name='commercial_line_position_unique'),
        ),
        migrations.AddConstraint(
            model_name='quotationline',
            constraint=models.CheckConstraint(condition=models.Q(('kind__in', ['PART', 'LABOR', 'SERVICE']), ('responsibility__in', ['CUSTOMER', 'WARRANTY', 'COMPANY'])), name='commercial_line_types_valid'),
        ),
        migrations.AddConstraint(
            model_name='quotationline',
            constraint=models.CheckConstraint(condition=models.Q(models.Q(('kind', 'PART'), ('spare_part__isnull', False)), models.Q(('kind__in', ['LABOR', 'SERVICE']), ('spare_part__isnull', True)), _connector='OR'), name='commercial_line_part_coherent'),
        ),
        migrations.AddConstraint(
            model_name='quotationline',
            constraint=models.CheckConstraint(condition=models.Q(('discount__gte', 0), ('discount__lte', models.F('subtotal')), ('quantity__gte', 1), ('quantity__lte', 1000000), ('subtotal', django.db.models.expressions.CombinedExpression(models.F('quantity'), '*', models.F('unit_price'))), ('tax__gte', 0), ('tax_rate__gte', 0), ('tax_rate__lte', 100), ('taxable_amount', django.db.models.expressions.CombinedExpression(models.F('subtotal'), '-', models.F('discount'))), ('total', django.db.models.expressions.CombinedExpression(models.F('taxable_amount'), '+', models.F('tax'))), ('unit_price__gte', 0)), name='commercial_line_money_coherent'),
        ),
        migrations.AddConstraint(
            model_name='quotationdecision',
            constraint=models.CheckConstraint(condition=models.Q(('channel__in', ['IN_PERSON', 'PHONE', 'SMS', 'WHATSAPP', 'EMAIL', 'OTHER']), ('outcome__in', ['APPROVED', 'REJECTED'])), name='commercial_decision_valid'),
        ),
        migrations.AddConstraint(
            model_name='commercialworkauthorization',
            constraint=models.CheckConstraint(condition=models.Q(models.Q(('operation', 'CONSUME'), ('quantity__gte', 1), ('repair_action__isnull', False), ('spare_part__isnull', False)), models.Q(('operation', 'PERFORM'), ('quantity', 0), ('repair_action__isnull', False), ('spare_part__isnull', True)), models.Q(('operation', 'COMPLETE'), ('quantity', 0), ('repair_action__isnull', True), ('spare_part__isnull', True)), _connector='OR'), name='commercial_authorization_coherent'),
        ),
    ]
