# Changelog — EFC Backend Historial de cambios por ticket (más reciente arriba). Cada entrada: fecha, ticket, tipo, repos afectados, qué se hizo y por qué. Reglas del flujo en `../CLAUDE.md`. ## T2025-09-004 — Pertenencia documento→entidad (matching de partidas + FK polimórfica) - **Fecha:** 2026-06-24 - **Tipo:** feature - **Repos:** backend + microservice (el fix del stack legacy de descarga está en `microservice/CHANGELOG.md`; frontend sin cambios) - **Branch:** `feature/T2025-09-004` · **PR:** (pendiente de aceptación manual) - **Qué se hizo:** - Matching documento→partida con frontera `(_|.|$)` en `core/partida_docs.py` (cubre los 3 formatos de nombre sin confundir la partida 1 con 11/100). - FK reales `document.partida` / `cove` / `edocument` (nullable, `CASCADE`); los acuses cuelgan de su cove/edoc padre; los documentos nativos (PC, remesa, subidas generales) quedan sin FK. - Resolución central en `Document.save()` vía `core/document_links.py`: liga la FK por `document_type` + nombre de archivo en toda ruta de creación (incluida la ingesta del microservicio); set explícito de la FK en `create_vu_record`. - Comando `backfill_document_links` para poblar la FK en filas existentes (idempotente). - Comando `backfill_document_links_legacy` para documentos LEGADOS de cove/edoc con nomenclatura vieja (otro `pedimento_app`/prefijo, p.ej. `vu_EDC_0201_800_..._{numero}` en un pedimento `25-80-...`): liga por el `numero_cove`/`numero_edocument` único presente en el nombre, sin exigir app ni prefijo. Solo cove/edoc (llaves únicas); partida y nativos quedan fuera. Correr DESPUÉS del backfill estricto. - Comando `dedup_documents` para limpiar documentos duplicados legados (misma entidad + mismo tipo): conserva el más reciente con archivo válido en storage, borra el resto (archivo MinIO si no lo referencia otra fila + fila + ajuste de cuota), `--dry-run`, conteo previo, idempotente. Los duplicados eran **pre-fix**: la descarga ya reemplaza en vez de re-crear desde jun-2026 (microservicio, `post_or_update_document`), verificado con 0 duplicados creados después del fix. Solo aplica a docs ligados a entidad. - Lectura, descarga y borrado SIEMPRE por la FK (id), nunca por nombre. El nombre solo ESTABLECE la FK (en `Document.save()` para altas y en el backfill para filas viejas). - **Rastreo del stack legacy (docs sin ligar/duplicados con datos de hoy):** el signal `api/customs/signals/procesamiento.py` (post_save de Pedimento/Cove/EDocument, p.ej. al cargar un datastage) dispara el stack VIEJO de descarga (`tasks/microservice.py` → api_v1 → `utils/peticiones.py` del microservicio), que armaba el nombre con campos crudos (no `pedimento_app`, prefijo `vu_EDC`) y posteaba sin reemplazar → docs sin FK + partidas duplicadas. El auto-proceso (Celery beat `microservice_v2.process_all_organizations`) ya usa el stack v2 correcto. Fix del módulo viejo en `microservice/CHANGELOG.md`. El signal/api_v1 se dejan activos (decisión: arreglar `peticiones.py`, no retirarlos); unificar a un solo stack queda como follow-up. - **Por qué:** retirar el matching frágil por nombre de archivo (`icontains`/prefijo, que confundía entidades y se rompía con formatos nuevos) y tener la pertenencia documento→entidad como dato real, consultable e íntegro. - **Migraciones:** `0004_document_subentidad_fk` (campos, metadata-only), `0005_document_subentidad_idx` (índices con `CREATE INDEX CONCURRENTLY IF NOT EXISTS`, `atomic=False`, idempotente vía `SeparateDatabaseAndState`), `0006_analyze_document` (`ANALYZE document`: refresca estadísticas del planner — sin esto, el prefetch hacía seq scan sobre ~5M filas y los endpoints tardaban ~9s). La tabla `document` tiene ~5M filas: cada índice tarda minutos y NO debe interrumpirse. Recuperación si se corta: índices válidos → `migrate --fake record 0005`; alguno INVALID → `DROP INDEX IF EXISTS "";` y reintentar `migrate record`. - **Despliegue (orden obligatorio):** aplicar migraciones (0004-0006) → **correr el backfill completo** → recién entonces la lectura/descarga/borrado por FK es correcta. Como NO hay fallback por nombre, un documento sin backfillear queda invisible hasta ligar su FK.