feat: FK polimorfica Document -> {partida, cove, edocument} + backfill (T2025-09-004)
Reemplaza el matching fragil por nombre de archivo con FK reales: - 3 FK nullables (CASCADE) en Document; resolucion central en save() por document_type + nombre (core.document_links), cubre toda ruta de creacion incluida la ingesta del microservicio; set explicito en create_vu_record. - Comando backfill_document_links (idempotente, dry-run) para filas existentes. - Lectura/descarga/borrado SIEMPRE por la FK (id); el nombre solo ESTABLECE la FK en save()/backfill. Prefetch con select_related(pedimento, fuente) sin N+1. - Migraciones: 0004 (campos), 0005 (indices CONCURRENTLY IF NOT EXISTS, idempotente via SeparateDatabaseAndState), 0006 (ANALYZE document para estadisticas del planner). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -33,7 +33,7 @@ from core.permissions import (
|
||||
user_has_permission,
|
||||
IsInternalService,
|
||||
)
|
||||
from core.partida_docs import patron_regex_partida
|
||||
from core.document_links import ids_documentos_entidad
|
||||
|
||||
import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -725,14 +725,7 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
# incluir_legacy=False: el borrado es destructivo, no se elimina por match difuso.
|
||||
doc_ids = []
|
||||
for partida in partidas:
|
||||
docs = Document.objects.filter(
|
||||
pedimento_id=partida.pedimento_id,
|
||||
archivo__iregex=patron_regex_partida(
|
||||
partida.pedimento.pedimento_app, partida.numero_partida,
|
||||
incluir_legacy=False,
|
||||
),
|
||||
).values_list('id', flat=True)
|
||||
doc_ids.extend(docs)
|
||||
doc_ids.extend(ids_documentos_entidad(partida, 'partida'))
|
||||
|
||||
queryset = self.get_queryset()
|
||||
existing_documents = queryset.filter(id__in=doc_ids)
|
||||
@@ -863,11 +856,7 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
# Buscar documentos que contengan el numero_cove en el nombre de archivo
|
||||
doc_ids = []
|
||||
for cove in coves:
|
||||
docs = Document.objects.filter(
|
||||
pedimento_id=cove.pedimento.id,
|
||||
archivo__icontains=cove.numero_cove
|
||||
).values_list('id', flat=True)
|
||||
doc_ids.extend(docs)
|
||||
doc_ids.extend(ids_documentos_entidad(cove, 'cove'))
|
||||
|
||||
queryset = self.get_queryset()
|
||||
existing_documents = queryset.filter(id__in=doc_ids)
|
||||
@@ -996,11 +985,7 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
# Buscar documentos que contengan el numero_edocument en el nombre de archivo
|
||||
doc_ids = []
|
||||
for edoc in edocs:
|
||||
docs = Document.objects.filter(
|
||||
pedimento_id=edoc.pedimento.id,
|
||||
archivo__icontains=edoc.numero_edocument
|
||||
).values_list('id', flat=True)
|
||||
doc_ids.extend(docs)
|
||||
doc_ids.extend(ids_documentos_entidad(edoc, 'edocument'))
|
||||
|
||||
queryset = self.get_queryset()
|
||||
existing_documents = queryset.filter(id__in=doc_ids)
|
||||
@@ -1907,6 +1892,10 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
document.delete()
|
||||
raise Exception(f"El archivo no se encuentra en storage tras guardarlo: {file.name}")
|
||||
document.archivo = ruta
|
||||
# Ligar explícitamente la sub-entidad recién creada
|
||||
# (exacto, sin depender del matching por nombre).
|
||||
_campo_fk = {'partida': 'partida', 'cove': 'cove', 'edoc': 'edocument'}[tab_seccion]
|
||||
setattr(document, _campo_fk, expediente_obj)
|
||||
document.save()
|
||||
else:
|
||||
document.delete()
|
||||
@@ -2008,14 +1997,7 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
# la descarga no es destructiva, así que sí incluye archivos legacy.
|
||||
doc_ids = []
|
||||
for partida in partidas:
|
||||
docs = Document.objects.filter(
|
||||
pedimento_id=partida.pedimento_id,
|
||||
archivo__iregex=patron_regex_partida(
|
||||
partida.pedimento.pedimento_app, partida.numero_partida,
|
||||
incluir_legacy=True,
|
||||
),
|
||||
).values_list('id', flat=True)
|
||||
doc_ids.extend(docs)
|
||||
doc_ids.extend(ids_documentos_entidad(partida, 'partida'))
|
||||
|
||||
queryset = self.get_queryset()
|
||||
docs_qs = queryset.filter(id__in=doc_ids)
|
||||
@@ -2071,11 +2053,7 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
|
||||
doc_ids = []
|
||||
for cove in coves:
|
||||
docs = Document.objects.filter(
|
||||
pedimento_id=cove.pedimento.id,
|
||||
archivo__icontains=cove.numero_cove
|
||||
).values_list('id', flat=True)
|
||||
doc_ids.extend(docs)
|
||||
doc_ids.extend(ids_documentos_entidad(cove, 'cove'))
|
||||
|
||||
queryset = self.get_queryset()
|
||||
docs_qs = queryset.filter(id__in=doc_ids)
|
||||
@@ -2131,11 +2109,7 @@ class DocumentViewSet(viewsets.ModelViewSet, DocumentosFiltradosMixin):
|
||||
|
||||
doc_ids = []
|
||||
for edoc in edocs:
|
||||
docs = Document.objects.filter(
|
||||
pedimento_id=edoc.pedimento.id,
|
||||
archivo__icontains=edoc.numero_edocument
|
||||
).values_list('id', flat=True)
|
||||
doc_ids.extend(docs)
|
||||
doc_ids.extend(ids_documentos_entidad(edoc, 'edocument'))
|
||||
|
||||
queryset = self.get_queryset()
|
||||
docs_qs = queryset.filter(id__in=doc_ids)
|
||||
|
||||
Reference in New Issue
Block a user