# Generated by Django 5.2.17 on 2026-09-28 05:10

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):

    dependencies = [
        ('commercial', '0002_history_integrity'),
        ('inventory', '0011_control_integrity'),
        ('organization', '0002_userorganizationassignment'),
        ('service', '0006_handover_closure'),
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='InvoiceSequence',
            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='invoice_sequence_positive')],
            },
        ),
        migrations.CreateModel(
            name='ServiceInvoice',
            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)),
                ('status', models.CharField(choices=[('DRAFT', 'Draft'), ('FINALIZED', 'Finalized')], default='DRAFT', max_length=9)),
                ('currency', models.CharField(max_length=3)),
                ('generation', models.PositiveIntegerField(default=1)),
                ('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)),
                ('warranty_covered_total', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('company_covered_total', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('context_snapshot', models.JSONField(blank=True, default=dict)),
                ('note', models.TextField(blank=True, max_length=4000)),
                ('finalized_at', models.DateTimeField(blank=True, null=True)),
                ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)),
                ('finalized_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='+', to=settings.AUTH_USER_MODEL)),
                ('quotation', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='commercial.servicequotation')),
                ('service_case', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='invoice', to='service.servicecase')),
                ('service_center', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='organization.servicecenter')),
            ],
            options={
                'ordering': ('created_at', 'pk'),
                'permissions': [('manage_serviceinvoice', 'Prepare and reconcile service invoices'), ('finalize_serviceinvoice', 'Finalize immutable service invoices')],
                'abstract': False,
            },
        ),
        migrations.CreateModel(
            name='InvoiceLine',
            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)),
                ('generation', models.PositiveIntegerField()),
                ('is_active', models.BooleanField(default=True)),
                ('kind', models.CharField(max_length=7)),
                ('responsibility', models.CharField(max_length=8)),
                ('description', models.CharField(max_length=500)),
                ('part_code', models.CharField(blank=True, max_length=128)),
                ('part_name', models.CharField(blank=True, max_length=500)),
                ('quantity', models.PositiveIntegerField()),
                ('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)),
                ('additional_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, 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)),
                ('customer_pay', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('warranty_covered', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('company_covered', models.DecimalField(decimal_places=2, default=0, max_digits=14)),
                ('confirmation_note', models.TextField(blank=True, max_length=2000)),
                ('confirmed_by', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
                ('quotation_line', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='commercial.quotationline')),
                ('invoice', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='lines', to='commercial.serviceinvoice')),
            ],
            options={
                'ordering': ('created_at', 'pk'),
                'abstract': False,
            },
        ),
        migrations.CreateModel(
            name='InvoiceAllocation',
            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)),
                ('quantity', models.PositiveIntegerField()),
                ('mode', models.CharField(choices=[('AUTO', 'Automatic'), ('MANUAL', 'Manual')], max_length=6)),
                ('reason', models.TextField(blank=True, max_length=2000)),
                ('actor', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)),
                ('consumption', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='inventory.partsdisposition')),
                ('line', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='allocations', to='commercial.invoiceline')),
            ],
            options={
                'ordering': ('created_at', 'pk'),
                'abstract': False,
                'constraints': [models.UniqueConstraint(fields=('line', 'consumption'), name='invoice_allocation_source_unique'), models.CheckConstraint(condition=models.Q(('quantity__gte', 1), ('quantity__lte', 1000000)), name='invoice_allocation_quantity'), models.CheckConstraint(condition=models.Q(('mode', 'AUTO'), models.Q(('mode', 'MANUAL'), models.Q(('reason', ''), _negated=True)), _connector='OR'), name='invoice_allocation_mode')],
            },
        ),
        migrations.AddConstraint(
            model_name='serviceinvoice',
            constraint=models.UniqueConstraint(fields=('service_center', 'number'), name='invoice_number_unique'),
        ),
        migrations.AddConstraint(
            model_name='serviceinvoice',
            constraint=models.CheckConstraint(condition=models.Q(('number__regex', '^INV-[0-9]{8,18}$')), name='invoice_number_format'),
        ),
        migrations.AddConstraint(
            model_name='serviceinvoice',
            constraint=models.CheckConstraint(condition=models.Q(('currency__regex', '^[A-Z]{3}$'), ('generation__gte', 1)), name='invoice_currency_generation'),
        ),
        migrations.AddConstraint(
            model_name='serviceinvoice',
            constraint=models.CheckConstraint(condition=models.Q(models.Q(('finalized_at', None), ('finalized_by', None), ('status', 'DRAFT')), models.Q(('finalized_at__isnull', False), ('finalized_by__isnull', False), ('status', 'FINALIZED')), _connector='OR'), name='invoice_finalization_coherent'),
        ),
        migrations.AddConstraint(
            model_name='serviceinvoice',
            constraint=models.CheckConstraint(condition=models.Q(('company_covered_total__gte', 0), ('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__exact', django.db.models.expressions.CombinedExpression(django.db.models.expressions.CombinedExpression(models.F('customer_pay_total'), '+', models.F('warranty_covered_total')), '+', models.F('company_covered_total'))), ('grand_total__gte', 0), ('subtotal__gte', 0), ('tax_total__gte', 0), ('warranty_covered_total__gte', 0)), name='invoice_totals_coherent'),
        ),
        migrations.AddConstraint(
            model_name='invoiceline',
            constraint=models.UniqueConstraint(condition=models.Q(('is_active', True)), fields=('invoice', 'quotation_line'), name='invoice_active_quote_line'),
        ),
        migrations.AddConstraint(
            model_name='invoiceline',
            constraint=models.CheckConstraint(condition=models.Q(('generation__gte', 1), ('kind__in', ['PART', 'LABOR', 'SERVICE']), ('responsibility__in', ['CUSTOMER', 'WARRANTY', 'COMPANY'])), name='invoice_line_types'),
        ),
        migrations.AddConstraint(
            model_name='invoiceline',
            constraint=models.CheckConstraint(condition=models.Q(('additional_discount__gte', 0), ('additional_discount__lte', models.F('discount')), ('company_covered__gte', 0), ('customer_pay__gte', 0), ('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'))), ('total__exact', django.db.models.expressions.CombinedExpression(django.db.models.expressions.CombinedExpression(models.F('customer_pay'), '+', models.F('warranty_covered')), '+', models.F('company_covered'))), ('unit_price__gte', 0), ('warranty_covered__gte', 0)), name='invoice_line_money'),
        ),
        migrations.AddConstraint(
            model_name='invoiceline',
            constraint=models.CheckConstraint(condition=models.Q(models.Q(('company_covered', 0), ('customer_pay', models.F('total')), ('responsibility', 'CUSTOMER'), ('warranty_covered', 0)), models.Q(('company_covered', 0), ('customer_pay', 0), ('responsibility', 'WARRANTY'), ('warranty_covered', models.F('total'))), models.Q(('company_covered', models.F('total')), ('customer_pay', 0), ('responsibility', 'COMPANY'), ('warranty_covered', 0)), _connector='OR'), name='invoice_line_payer'),
        ),
    ]
