# Generated by Django 6.1 on 2026-09-07 02:50 import django.db.models.deletion from django.conf import settings from django.db import migrations, models class Migration(migrations.Migration): initial = True dependencies = [ ('expenses', '0010_alter_expense_amount_usd'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ migrations.CreateModel( name='ItemCatalog', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(max_length=50, unique=True, verbose_name='Código Ítem (CAT-XXX-XX)')), ('name', models.CharField(max_length=200, verbose_name='Descripción del Bien / Servicio')), ('unit', models.CharField(choices=[('UN', 'Unidad (UN)'), ('MES', 'Mes de Servicio'), ('DIA', 'Día / Jornada'), ('HORA', 'Hora Especialista'), ('LITRO', 'Litros'), ('GLB', 'Servicio Global'), ('LIC', 'Licencia Anual / Mensual')], default='UN', max_length=20, verbose_name='Unidad de Medida')), ('reference_price_clp', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='Precio Referencial Neto (CLP)')), ('reference_price_usd', models.DecimalField(decimal_places=2, default=0, max_digits=10, verbose_name='Precio Referencial (USD)')), ('sla_days', models.IntegerField(default=3, verbose_name='SLA / Plazo de Entrega (Días)')), ('specifications', models.TextField(blank=True, verbose_name='Especificaciones Técnicas')), ('is_active', models.BooleanField(default=True, verbose_name='Ítem Activo en Catálogo')), ('category', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='catalog_items', to='expenses.category', verbose_name='Categoría Contable')), ('preferred_vendor', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='catalog_items', to='expenses.vendor', verbose_name='Proveedor Homologado / Preferido')), ], options={ 'verbose_name': 'Ítem de Catálogo', 'verbose_name_plural': 'Catálogo de Ítems y Servicios', 'ordering': ['code'], }, ), migrations.CreateModel( name='PurchaseOrder', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(default='OC-2026-0001', max_length=50, unique=True, verbose_name='Correlativo OC')), ('issue_date', models.DateField(verbose_name='Fecha de Emisión')), ('expected_delivery_date', models.DateField(blank=True, null=True, verbose_name='Fecha Estimada de Entrega')), ('payment_terms', models.CharField(default='30 Días Contra Factura', max_length=100, verbose_name='Condiciones de Pago')), ('delivery_address', models.CharField(default='Casa Matriz EFINTEL / Terreno Faena', max_length=255, verbose_name='Lugar de Entrega')), ('net_amount_clp', models.DecimalField(decimal_places=2, default=0, max_digits=15, verbose_name='Monto Neto (CLP)')), ('tax_rate', models.DecimalField(decimal_places=2, default=19.0, max_digits=5, verbose_name='Tasa IVA (%)')), ('tax_amount_clp', models.DecimalField(decimal_places=2, default=0, max_digits=15, verbose_name='Monto IVA (CLP)')), ('total_amount_clp', models.DecimalField(decimal_places=2, default=0, max_digits=15, verbose_name='Monto Total (CLP)')), ('status', models.CharField(choices=[('EMITIDA', 'Emitida'), ('ENVIADA_PROVEEDOR', 'Enviada al Proveedor'), ('RECEPCION_PARCIAL', 'Recepción Parcial'), ('RECEPCION_TOTAL', 'Recepción Conforme Total'), ('CONCILIADA_MATCH', '3-Way Match Conciliado'), ('CANCELADA', 'Cancelada')], default='EMITIDA', max_length=30, verbose_name='Estado de Orden de Compra')), ('terms_and_conditions', models.TextField(blank=True, verbose_name='Términos y Condiciones Especiales')), ('notes', models.TextField(blank=True, verbose_name='Notas Internas')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('issuer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='issued_purchase_orders', to=settings.AUTH_USER_MODEL, verbose_name='Emitido por')), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='purchase_orders', to='expenses.project', verbose_name='Proyecto')), ('vendor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='purchase_orders', to='expenses.vendor', verbose_name='Proveedor')), ], options={ 'verbose_name': 'Orden de Compra', 'verbose_name_plural': 'Órdenes de Compra (OC)', 'ordering': ['-issue_date', '-created_at'], }, ), migrations.CreateModel( name='GoodsReceipt', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(default='REC-2026-0001', max_length=50, unique=True, verbose_name='N° Acta Recepción')), ('dispatch_guide_number', models.CharField(max_length=50, verbose_name='N° Guía de Despacho / Acta Terreno')), ('receipt_date', models.DateField(verbose_name='Fecha de Recepción')), ('technical_conformity', models.BooleanField(default=True, verbose_name='Conformidad Técnica Aprobada')), ('notes', models.TextField(blank=True, verbose_name='Observaciones de Entrega / Inspección')), ('created_at', models.DateTimeField(auto_now_add=True)), ('received_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='received_deliveries', to=settings.AUTH_USER_MODEL, verbose_name='Receptor Conforme')), ('purchase_order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='receipts', to='procurement.purchaseorder', verbose_name='Orden de Compra')), ], options={ 'verbose_name': 'Recepción de Bienes / Servicios', 'verbose_name_plural': 'Recepciones de Bienes y Servicios', 'ordering': ['-receipt_date'], }, ), migrations.CreateModel( name='PurchaseOrderItem', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('description', models.CharField(max_length=255, verbose_name='Descripción del Bien / Servicio')), ('quantity', models.DecimalField(decimal_places=2, default=1, max_digits=10, verbose_name='Cantidad')), ('unit_price_net', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='Precio Unitario Neto (CLP)')), ('subtotal_net', models.DecimalField(decimal_places=2, default=0, max_digits=12, verbose_name='Subtotal Neto (CLP)')), ('catalog_item', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='procurement.itemcatalog', verbose_name='Ítem del Catálogo')), ('purchase_order', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='procurement.purchaseorder', verbose_name='Orden de Compra')), ], ), migrations.CreateModel( name='PurchaseRequisition', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('code', models.CharField(default='REQ-2026-0001', max_length=50, unique=True, verbose_name='Código Requisición')), ('purpose', models.TextField(verbose_name='Justificación Técnica y Destino I+D+i')), ('priority', models.CharField(choices=[('BAJA', 'Baja'), ('MEDIA', 'Media'), ('ALTA', 'Alta'), ('CRITICA', 'Crítica / Faena Urgente')], default='MEDIA', max_length=30, verbose_name='Prioridad')), ('status', models.CharField(choices=[('BORRADOR', 'Borrador'), ('SOLICITADA', 'Solicitada (Pendiente Aprobación)'), ('APROBADA_TECNICA', 'Aprobada Técnicamente'), ('APROBADA_FINANZAS', 'Aprobada por Finanzas'), ('RECHAZADA', 'Rechazada'), ('CONVERTIDA_OC', 'Orden de Compra Generada')], default='BORRADOR', max_length=30, verbose_name='Estado de Aprobación')), ('required_date', models.DateField(verbose_name='Fecha Requerida en Sitio')), ('approved_at', models.DateTimeField(blank=True, null=True, verbose_name='Fecha de Aprobación')), ('rejection_reason', models.TextField(blank=True, verbose_name='Motivo de Rechazo')), ('total_estimated_clp', models.DecimalField(decimal_places=2, default=0, max_digits=15, verbose_name='Total Estimado Neto (CLP)')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('approved_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='approved_requisitions', to=settings.AUTH_USER_MODEL, verbose_name='Aprobado por')), ('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='purchase_requisitions', to='expenses.project', verbose_name='Proyecto / Centro de Costo')), ('requester', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='purchase_requisitions', to=settings.AUTH_USER_MODEL, verbose_name='Solicitante')), ], options={ 'verbose_name': 'Requisición de Compra', 'verbose_name_plural': 'Requisiciones de Compra', 'ordering': ['-created_at'], }, ), migrations.AddField( model_name='purchaseorder', name='requisition', field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='purchase_orders', to='procurement.purchaserequisition', verbose_name='Requisición de Origen'), ), migrations.CreateModel( name='RequisitionItem', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('description', models.CharField(max_length=255, verbose_name='Descripción / Detalle')), ('quantity', models.DecimalField(decimal_places=2, default=1, max_digits=10, verbose_name='Cantidad')), ('unit_price', models.DecimalField(decimal_places=2, max_digits=12, verbose_name='Precio Unitario Estimado (CLP)')), ('subtotal', models.DecimalField(decimal_places=2, default=0, max_digits=12, verbose_name='Subtotal (CLP)')), ('catalog_item', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='requisition_items', to='procurement.itemcatalog', verbose_name='Ítem del Catálogo')), ('requisition', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='items', to='procurement.purchaserequisition', verbose_name='Requisición')), ], ), migrations.CreateModel( name='ThreeWayMatch', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('dte_invoice_number', models.CharField(max_length=50, verbose_name='N° Factura Electrónica (DTE 33)')), ('dte_invoice_rut', models.CharField(max_length=20, verbose_name='RUT Emisor Factura')), ('dte_invoice_date', models.DateField(verbose_name='Fecha Emisión Factura')), ('dte_net_amount', models.DecimalField(decimal_places=2, max_digits=15, verbose_name='Monto Neto Factura (CLP)')), ('dte_tax_amount', models.DecimalField(decimal_places=2, max_digits=15, verbose_name='Monto IVA Factura (CLP)')), ('dte_total_amount', models.DecimalField(decimal_places=2, max_digits=15, verbose_name='Monto Total Factura (CLP)')), ('price_difference_clp', models.DecimalField(decimal_places=2, default=0, max_digits=12, verbose_name='Diferencia de Monto Neto (CLP)')), ('quantity_difference', models.DecimalField(decimal_places=2, default=0, max_digits=10, verbose_name='Diferencia en Cantidades')), ('match_status', models.CharField(choices=[('MATCH_PERFECTO', 'Match Perfecto (Tolerancia 0% OK)'), ('DISCREPANCIA_PRECIO', 'Discrepancia en Precio / Monto Neto'), ('DISCREPANCIA_CANTIDAD', 'Discrepancia en Cantidades Recibidas'), ('PENDIENTE_RECEPCION', 'Pendiente de Recepción en Bodega/Faena'), ('RECHAZADO', 'Rechazado por Auditoría')], default='PENDIENTE_RECEPCION', max_length=30, verbose_name='Resultado del 3-Way Match')), ('matched_at', models.DateTimeField(blank=True, null=True, verbose_name='Fecha de Conciliación')), ('resolution_notes', models.TextField(blank=True, verbose_name='Notas de Resolución / Observación Contable')), ('created_at', models.DateTimeField(auto_now_add=True)), ('updated_at', models.DateTimeField(auto_now=True)), ('goods_receipt', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='matches', to='procurement.goodsreceipt', verbose_name='Recepción Conforme')), ('matched_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL, verbose_name='Auditor / Conciliador')), ('purchase_order', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='three_way_match', to='procurement.purchaseorder', verbose_name='Orden de Compra')), ], options={ 'verbose_name': 'Conciliación 3-Way Match', 'verbose_name_plural': 'Conciliaciones 3-Way Match (Tolerancia 0%)', 'ordering': ['-created_at'], }, ), ]