← Volver a Casos
Backend Engineering4 min19 sept 2026

Contract Renewal: contratos, evidencia y recordatorios confiables

Backend para revisar contratos desde PDF o Excel, conservar evidencia, calcular plazos de preaviso y publicar recordatorios con trazabilidad e idempotencia.

Arquitectura de Contract Renewal: ingreso de documentos, revisión, PostgreSQL y entrega de recordatorios

Contract Renewal & Deadline Tracker es un backend para convertir información de contratos en fechas de seguimiento verificables. Recibe documentos, propone datos con evidencia de origen y exige revisión humana antes de programar recordatorios.

El problema central es que una fecha extraída de un documento no basta para decidir cuándo avisar. Hay que identificar el fin del período vigente, el tipo de renovación y el plazo de preaviso, resolver ambigüedades y conservar la explicación de cada decisión.

De documento a dato revisado#

El flujo comienza con un PDF de texto o un archivo Excel. En PDF, el sistema detecta duplicados por contenido y ejecuta el análisis en un subproceso con límites. En Excel, cada fila representa un contrato y la evidencia conserva referencias a las celdas originales; el libro completo se valida antes de confirmar la importación.

La revisión se concentra en cuatro datos: contraparte, fin del período vigente, tipo de renovación y plazo de preaviso. La extracción propone valores; un operador los confirma o corrige con evidencia. Los datos ausentes o las cláusulas no compatibles permanecen visibles.

PDF o Excel → evidencia → revisión humana → fechas → recordatorio

Esta separación evita que una sugerencia del extractor se convierta directamente en una decisión operativa.

Un backend modular con responsabilidades claras#

La API está construida con FastAPI. PostgreSQL conserva metadatos, texto normalizado, hallazgos, datos revisados, alertas y auditoría. SQLAlchemy modela la persistencia y Alembic gestiona las migraciones; los archivos originales se almacenan en un directorio o volumen configurado.

La API y el worker periódico comparten el modelo de dominio y la base de datos. Los módulos separan ingreso de documentos, extracción, revisión, aritmética de fechas y publicación de alertas. El transporte HTTP queda a cargo de un servicio de webhooks independiente.

La interfaz actual es la API con OpenAPI. Docker Compose inicia PostgreSQL y la API; el worker se ejecuta como proceso separado. Esta arquitectura mantiene el alcance local sin introducir una cola adicional para el seguimiento de contratos.

Revisión y auditoría en una transacción#

Una revisión bloquea el contrato, comprueba su versión y actualiza los datos canónicos junto con un historial de auditoría de solo anexado. En la misma transacción se cancelan los recordatorios obsoletos que todavía no se han enviado.

El control de versión permite detectar revisiones desactualizadas. La transacción evita que una corrección quede guardada sin su auditoría o que permanezca pendiente una alerta basada en datos anteriores.

Fechas e idempotencia#

El cálculo utiliza días calendario y distingue la fecha límite de preaviso de la fecha del recordatorio. Un desplazamiento configurable determina con cuánta anticipación se genera el aviso. Las cláusulas expresadas en días hábiles no se convierten automáticamente a días calendario.

El worker utiliza el mismo bloqueo del contrato y una restricción de unicidad en PostgreSQL para mantener una sola alerta lógica, incluso ante ejecuciones repetidas o concurrentes. La identidad de publicación se conserva durante los reintentos y los fallos quedan visibles.

Esta garantía tiene un límite concreto: una alerta única en la base de datos no garantiza una única recepción externa. El servicio de webhooks maneja los reintentos de transporte y el receptor necesita deduplicar. Sin configurar el servicio, el worker crea alertas lógicas, pero no las envía.

Verificación documentada#

El repositorio incluye cobertura automatizada de revisión por API, migraciones, límites transaccionales, aritmética de fechas e idempotencia del worker. También documenta comprobaciones de arranque y reinicio con persistencia de la base de datos y los PDF originales, y una recepción HTTP firmada después de provocar un fallo del receptor y reintentar.

Dos ejecuciones de carga procesaron 1.000 PDF generados cada una, con dos cargas concurrentes, sin errores de ingesta y a un ritmo de 201–210 PDF por minuto. Estas cifras corresponden a documentos de prueba de una a cinco páginas: miden ese escenario de ingesta, no la precisión de extracción sobre contratos reales.

La evidencia de aceptación, el recorrido de ejecución y las mediciones de carga permiten revisar el alcance de esas verificaciones.

Alcance y aprendizajes#

El proyecto implementa un flujo local de API y revisión. OCR, una interfaz dedicada, autenticación multiusuario y cobertura amplia de lenguaje contractual quedan fuera del alcance implementado. La identidad del revisor es declarada, el historial no tiene paginación y los límites del parser por proceso no constituyen un presupuesto global de concurrencia.

El aprendizaje principal es separar las garantías: extraer no equivale a confirmar, confirmar no equivale a enviar y persistir una alerta no equivale a entregarla una sola vez. Modelar esas fronteras permite conservar evidencia, corregir decisiones y recuperar fallos sin ocultar las limitaciones del sistema.

El código y la documentación están disponibles en el repositorio de Contract Renewal.