From 5d9e0f4589e42d0f43d01384a64f57b0fd4f8108 Mon Sep 17 00:00:00 2001 From: Nachou-u Date: Wed, 9 Sep 2026 08:27:49 -0300 Subject: [PATCH] =?UTF-8?q?CORRECCI=C3=93N:=20Changed=20dangerous=20CASCAD?= =?UTF-8?q?E=20deletions=20to=20PROTECT=20on=20critical=20FKs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- expenses/models.py | 18 +++++++++--------- payroll/models.py | 2 +- procurement/models.py | 16 ++++++++-------- talent/models.py | 2 +- 4 files changed, 19 insertions(+), 19 deletions(-) diff --git a/expenses/models.py b/expenses/models.py index 58cac8a..31e312c 100644 --- a/expenses/models.py +++ b/expenses/models.py @@ -63,7 +63,7 @@ class CatalogModel(TimeStampedModel): class Project(CatalogModel): manager = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='managed_projects', verbose_name="Encargado / Director") - parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children', verbose_name="Portafolio / Proyecto Padre") + parent = models.ForeignKey('self', on_delete=models.PROTECT, null=True, blank=True, related_name='children', verbose_name="Portafolio / Proyecto Padre") assigned_budget_clp = models.DecimalField(max_digits=15, decimal_places=2, default=0, verbose_name="Presupuesto Asignado (CLP)") assigned_budget_usd = models.DecimalField(max_digits=15, decimal_places=2, default=0, verbose_name="Presupuesto Asignado (USD)") @@ -101,7 +101,7 @@ class Project(CatalogModel): class ProjectPhase(TimeStampedModel): - project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='phases', verbose_name="Proyecto") + project = models.ForeignKey(Project, on_delete=models.PROTECT, related_name='phases', verbose_name="Proyecto") phase_number = models.IntegerField(default=1, verbose_name="N° Fase / Hito") name = models.CharField(max_length=150, verbose_name="Nombre de la Fase / Hito") description = models.TextField(blank=True, verbose_name="Descripción de Entregables") @@ -126,7 +126,7 @@ class ProjectPhase(TimeStampedModel): class Category(CatalogModel): - parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children', verbose_name="Categoría Padre") + parent = models.ForeignKey('self', on_delete=models.PROTECT, null=True, blank=True, related_name='children', verbose_name="Categoría Padre") def __str__(self): return f"{self.code}: {self.name}" @@ -161,8 +161,8 @@ class Vendor(TimeStampedModel): class ExpenseReport(models.Model): report_code = models.CharField(max_length=50, unique=True, verbose_name="Código Rendición", default="EXP-REP-001") title = models.CharField(max_length=250, verbose_name="Título del Informe / Viaje") - user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='expense_reports', verbose_name="Responsable Rendidor") - project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='expense_reports', verbose_name="Proyecto Imputado") + user = models.ForeignKey(User, on_delete=models.PROTECT, related_name='expense_reports', verbose_name="Responsable Rendidor") + project = models.ForeignKey(Project, on_delete=models.PROTECT, related_name='expense_reports', verbose_name="Proyecto Imputado") start_date = models.DateField(verbose_name="Fecha de Inicio") end_date = models.DateField(verbose_name="Fecha de Término") @@ -201,7 +201,7 @@ class ExpenseReport(models.Model): class Expense(TimeStampedModel): expense_code = models.CharField(max_length=50, unique=True, default=uuid.uuid4, verbose_name="Código Transacción") report = models.ForeignKey(ExpenseReport, on_delete=models.SET_NULL, null=True, blank=True, related_name='expenses', verbose_name="Informe de Rendición (Opcional)") - project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='expenses', verbose_name="Proyecto") + project = models.ForeignKey(Project, on_delete=models.PROTECT, related_name='expenses', verbose_name="Proyecto") category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True, related_name='expenses', verbose_name="Subcategoría") document_number = models.CharField(max_length=50, blank=True, null=True, verbose_name="N° Folio Boleta / Factura") @@ -228,7 +228,7 @@ class Expense(TimeStampedModel): approval_status = models.CharField(max_length=50, choices=ApprovalStatusEnum.choices, default=ApprovalStatusEnum.EN_REVISION, verbose_name="Estado de Aprobación") - user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='expenses_created', verbose_name="Registrado por") + user = models.ForeignKey(User, on_delete=models.PROTECT, related_name='expenses_created', verbose_name="Registrado por") responsible_person = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='expenses_responsible', verbose_name="Responsable Solicitante / Rendidor") elevated_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='expenses_elevated', verbose_name="Elevado por (Paso 2)") paid_by = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, related_name='expenses_paid', verbose_name="Pagado por (Paso 3)") @@ -289,7 +289,7 @@ class Expense(TimeStampedModel): class VehicleLog(models.Model): expense = models.OneToOneField(Expense, on_delete=models.CASCADE, related_name='vehicle_log', null=True, blank=True, verbose_name="Gasto Asociado") - project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='vehicle_logs', verbose_name="Proyecto") + project = models.ForeignKey(Project, on_delete=models.PROTECT, related_name='vehicle_logs', verbose_name="Proyecto") license_plate = models.CharField(max_length=20, verbose_name="Patente Vehículo") driver_name = models.CharField(max_length=150, verbose_name="Nombre Conductor") @@ -350,7 +350,7 @@ class Document(models.Model): class UserProfile(models.Model): - user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile', verbose_name="Usuario") + user = models.OneToOneField(User, on_delete=models.PROTECT, related_name='profile', verbose_name="Usuario") rut = models.CharField(max_length=20, blank=True, null=True, verbose_name="RUT") job_title = models.CharField(max_length=150, blank=True, null=True, verbose_name="Cargo") description = models.TextField(blank=True, verbose_name="Descripción del Responsable") diff --git a/payroll/models.py b/payroll/models.py index 1a85ddd..94a51b4 100644 --- a/payroll/models.py +++ b/payroll/models.py @@ -107,7 +107,7 @@ class SalarySlip(models.Model): Impuesto Único de Segunda Categoría SII y Aportes Patronales (SIS, Mutual, AFC). """ slip_uuid = models.UUIDField(default=uuid.uuid4, unique=True, editable=False) - employee = models.ForeignKey(EmployeeProfile, on_delete=models.CASCADE, related_name='salary_slips', verbose_name="Colaborador") + employee = models.ForeignKey(EmployeeProfile, on_delete=models.PROTECT, related_name='salary_slips', verbose_name="Colaborador") month = models.IntegerField(verbose_name="Mes (1-12)") year = models.IntegerField(verbose_name="Año (ej. 2026)") diff --git a/procurement/models.py b/procurement/models.py index 55fae1f..2ee62ee 100644 --- a/procurement/models.py +++ b/procurement/models.py @@ -75,8 +75,8 @@ class PurchaseRequisition(models.Model): Inicia el flujo de abastecimiento y aprobación técnica/financiera. """ code = models.CharField(max_length=50, unique=True, verbose_name="Código Requisición", default="REQ-2026-0001") - requester = models.ForeignKey(User, on_delete=models.CASCADE, related_name='purchase_requisitions', verbose_name="Solicitante") - project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='purchase_requisitions', verbose_name="Proyecto / Centro de Costo") + requester = models.ForeignKey(User, on_delete=models.PROTECT, related_name='purchase_requisitions', verbose_name="Solicitante") + project = models.ForeignKey(Project, on_delete=models.PROTECT, related_name='purchase_requisitions', verbose_name="Proyecto / Centro de Costo") purpose = models.TextField(verbose_name="Justificación Técnica y Destino I+D+i") priority = models.CharField(max_length=30, choices=RequisitionPriorityEnum.choices, default=RequisitionPriorityEnum.MEDIA, verbose_name="Prioridad") @@ -130,9 +130,9 @@ class PurchaseOrder(models.Model): """ code = models.CharField(max_length=50, unique=True, verbose_name="Correlativo OC", default="OC-2026-0001") requisition = models.ForeignKey(PurchaseRequisition, on_delete=models.SET_NULL, null=True, blank=True, related_name='purchase_orders', verbose_name="Requisición de Origen") - vendor = models.ForeignKey(Vendor, on_delete=models.CASCADE, related_name='purchase_orders', verbose_name="Proveedor") - project = models.ForeignKey(Project, on_delete=models.CASCADE, related_name='purchase_orders', verbose_name="Proyecto") - issuer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='issued_purchase_orders', verbose_name="Emitido por") + vendor = models.ForeignKey(Vendor, on_delete=models.PROTECT, related_name='purchase_orders', verbose_name="Proveedor") + project = models.ForeignKey(Project, on_delete=models.PROTECT, related_name='purchase_orders', verbose_name="Proyecto") + issuer = models.ForeignKey(User, on_delete=models.PROTECT, related_name='issued_purchase_orders', verbose_name="Emitido por") issue_date = models.DateField(verbose_name="Fecha de Emisión") expected_delivery_date = models.DateField(null=True, blank=True, verbose_name="Fecha Estimada de Entrega") @@ -191,10 +191,10 @@ class GoodsReceipt(models.Model): Recepción Conforme en Bodega o Terreno. """ code = models.CharField(max_length=50, unique=True, verbose_name="N° Acta Recepción", default="REC-2026-0001") - purchase_order = models.ForeignKey(PurchaseOrder, on_delete=models.CASCADE, related_name='receipts', verbose_name="Orden de Compra") + purchase_order = models.ForeignKey(PurchaseOrder, on_delete=models.PROTECT, related_name='receipts', verbose_name="Orden de Compra") 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") - received_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name='received_deliveries', verbose_name="Receptor Conforme") + received_by = models.ForeignKey(User, on_delete=models.PROTECT, related_name='received_deliveries', verbose_name="Receptor Conforme") technical_conformity = models.BooleanField(default=True, verbose_name="Conformidad Técnica Aprobada") notes = models.TextField(blank=True, verbose_name="Observaciones de Entrega / Inspección") @@ -217,7 +217,7 @@ class ThreeWayMatch(models.Model): 2. Recepción Física (Guía de Despacho / Acta de Conformidad) 3. Factura Electrónica SII (DTE 33) """ - purchase_order = models.OneToOneField(PurchaseOrder, on_delete=models.CASCADE, related_name='three_way_match', verbose_name="Orden de Compra") + purchase_order = models.OneToOneField(PurchaseOrder, on_delete=models.PROTECT, related_name='three_way_match', verbose_name="Orden de Compra") goods_receipt = models.ForeignKey(GoodsReceipt, on_delete=models.SET_NULL, null=True, blank=True, related_name='matches', verbose_name="Recepción Conforme") # Datos Factura Electrónica SII DTE 33 diff --git a/talent/models.py b/talent/models.py index 1aa3dd6..12aa318 100644 --- a/talent/models.py +++ b/talent/models.py @@ -107,7 +107,7 @@ class EvaluationRubric7D(models.Model): 7. Capacidad de Innovación e I+D+i: 10% Vigencia: 12 meses. """ - candidate = models.ForeignKey(SpecialistCandidate, on_delete=models.CASCADE, related_name='evaluations', verbose_name="Especialista Candidato") + candidate = models.ForeignKey(SpecialistCandidate, on_delete=models.PROTECT, related_name='evaluations', verbose_name="Especialista Candidato") evaluator = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, verbose_name="Evaluador Líder") evaluation_date = models.DateField(default=date.today, verbose_name="Fecha de Evaluación")