# Plan de Trabajo — Módulo de Renovaciones y Contratos > Sistema completo de gestión de servicios, clientes, contratos y notificaciones automáticas de vencimiento. --- ## Índice 1. [Visión General](#1-visión-general) 2. [Arquitectura de Datos](#2-arquitectura-de-datos) 3. [Módulos del Sistema](#3-módulos-del-sistema) 4. [Flujo de Trabajo](#4-flujo-de-trabajo) 5. [Sistema de Notificaciones](#5-sistema-de-notificaciones) 6. [Plantillas de Correo](#6-plantillas-de-correo) 7. [Configuración SMTP](#7-configuración-smtp) 8. [Plan de Implementación por Fases](#8-plan-de-implementación-por-fases) 9. [Estructura de Archivos](#9-estructura-de-archivos) 10. [API Endpoints](#10-api-endpoints) --- ## 1. Visión General El módulo de **Renovaciones** permite a la empresa gestionar el ciclo de vida completo de sus servicios vendidos a clientes: creación de catálogo, asignación a clientes con fechas de vencimiento, envío automático y manual de correos de cobro/renovación, y configuración total de notificaciones programadas. ### Capacidades principales | Capacidad | Descripción | |-----------|-------------| | Catálogo de servicios | Crear servicios con precio, tipo (renovable/único), periodicidad | | Gestión de clientes | CRUD completo de clientes con datos de contacto | | Contratos / Asignaciones | Relacionar clientes con servicios, definir fechas de inicio y vencimiento | | Agrupación de correos | Si varios servicios vencen la misma fecha → un solo correo con el total | | Notificaciones programadas | Configurar N días antes del vencimiento, con cron interno | | Editor de plantillas | Editor visual con preview en tiempo real | | Configuración SMTP | Panel para cambiar servidor de correo sin reiniciar | --- ## 2. Arquitectura de Datos ### Modelo Entidad-Relación ``` clientes ─────────── contratos ─────────── servicios │ │ │ │ ├── fecha_inicio ├── tipo: renovable / unico │ ├── fecha_vencimiento ├── precio │ ├── estado ├── periodicidad (mensual/anual/etc) │ └── notas └── descripcion │ └── email, telefono, empresa, ... contratos ──── notificaciones_log ├── fecha_envio ├── tipo (aviso / vencimiento / recordatorio) └── estado (enviado / fallido / pendiente) smtp_config (tabla singleton) plantillas_correo notificacion_reglas (días antes, activo, plantilla_id) ``` ### Tablas SQL ```sql -- Servicios / Productos CREATE TABLE servicios ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, nombre TEXT NOT NULL, descripcion TEXT, precio NUMERIC(12,2) NOT NULL DEFAULT 0, moneda TEXT NOT NULL DEFAULT 'COP', tipo TEXT NOT NULL DEFAULT 'renovable', -- 'renovable' | 'unico' periodicidad TEXT, -- 'mensual' | 'trimestral' | 'semestral' | 'anual' | NULL activo BOOLEAN NOT NULL DEFAULT true ); -- Clientes CREATE TABLE clientes ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, nombre TEXT NOT NULL, empresa TEXT, email TEXT NOT NULL, email_cc TEXT, -- correos adicionales separados por coma telefono TEXT, documento TEXT, notas TEXT, activo BOOLEAN NOT NULL DEFAULT true ); -- Contratos / Asignaciones CREATE TABLE contratos ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, deleted_at TIMESTAMPTZ, cliente_id BIGINT NOT NULL REFERENCES clientes(id), servicio_id BIGINT NOT NULL REFERENCES servicios(id), fecha_inicio DATE NOT NULL, fecha_vencimiento DATE NOT NULL, precio_acordado NUMERIC(12,2), -- puede diferir del precio base estado TEXT NOT NULL DEFAULT 'activo', -- 'activo' | 'vencido' | 'cancelado' | 'renovado' auto_renovar BOOLEAN NOT NULL DEFAULT false, notas TEXT ); -- Reglas de notificación (configurable por días antes del vencimiento) CREATE TABLE notificacion_reglas ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, nombre TEXT NOT NULL, -- ej: "Aviso 30 días antes" dias_antes INT NOT NULL, -- ej: 30, 15, 7, 1 plantilla_id BIGINT REFERENCES plantillas_correo(id), activo BOOLEAN NOT NULL DEFAULT true, aplica_a TEXT NOT NULL DEFAULT 'todos' -- 'todos' | 'renovable' | 'unico' ); -- Plantillas de correo CREATE TABLE plantillas_correo ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, updated_at TIMESTAMPTZ, nombre TEXT NOT NULL, asunto TEXT NOT NULL, cuerpo_html TEXT NOT NULL, -- soporta variables: {{.ClienteNombre}}, {{.Servicios}}, {{.Total}}, etc. tipo TEXT NOT NULL DEFAULT 'renovacion' -- 'renovacion' | 'vencimiento' | 'pago' | 'personalizado' ); -- Log de notificaciones enviadas CREATE TABLE notificaciones_log ( id BIGSERIAL PRIMARY KEY, created_at TIMESTAMPTZ, cliente_id BIGINT REFERENCES clientes(id), regla_id BIGINT REFERENCES notificacion_reglas(id), contratos_ids TEXT, -- JSON array de IDs agrupados fecha_envio TIMESTAMPTZ, estado TEXT NOT NULL DEFAULT 'pendiente', -- 'enviado' | 'fallido' | 'pendiente' error_msg TEXT, asunto TEXT, preview_html TEXT -- copia del correo enviado ); -- Configuración SMTP (singleton, solo 1 fila activa) CREATE TABLE smtp_config ( id BIGSERIAL PRIMARY KEY, updated_at TIMESTAMPTZ, host TEXT NOT NULL, port INT NOT NULL DEFAULT 587, username TEXT NOT NULL, password TEXT NOT NULL, -- almacenado cifrado (AES-256) encryption TEXT NOT NULL DEFAULT 'tls', -- 'tls' | 'ssl' | 'none' from_address TEXT NOT NULL, from_name TEXT NOT NULL, activo BOOLEAN NOT NULL DEFAULT true ); ``` --- ## 3. Módulos del Sistema ### 3.1 Catálogo de Servicios (`/app/servicios`) **Funcionalidades:** - Listar servicios con filtro por tipo y estado - Crear/editar/eliminar servicio - Campos: nombre, descripción, precio, moneda, tipo (renovable | único), periodicidad - Badge visual diferenciando renovables de únicos - Indicador de cuántos contratos activos tiene cada servicio **Campos del formulario:** | Campo | Tipo | Requerido | Notas | |-------|------|-----------|-------| | Nombre | texto | ✅ | | | Descripción | textarea | ❌ | | | Precio | decimal | ✅ | | | Moneda | select | ✅ | COP / USD / EUR | | Tipo | radio | ✅ | Renovable / Único | | Periodicidad | select | si renovable | Mensual / Trimestral / Semestral / Anual | | Activo | toggle | ✅ | | --- ### 3.2 Clientes (`/app/clientes`) **Funcionalidades:** - CRUD completo de clientes - Vista detalle del cliente con todos sus contratos activos/vencidos - Historial de correos enviados al cliente - Múltiples emails CC por cliente **Campos del formulario:** | Campo | Tipo | Requerido | |-------|------|-----------| | Nombre completo | texto | ✅ | | Empresa / Razón social | texto | ❌ | | Email principal | email | ✅ | | Emails CC | texto (separados por coma) | ❌ | | Teléfono / WhatsApp | texto | ❌ | | Documento (NIT/CC) | texto | ❌ | | Notas internas | textarea | ❌ | | Activo | toggle | ✅ | --- ### 3.3 Contratos / Asignaciones (`/app/contratos`) **Vista principal:** - Tabla con columnas: Cliente, Servicio, Fecha inicio, Fecha vencimiento, Estado, Días restantes - Filtros: por cliente, por servicio, por estado, por rango de fechas - Indicador visual de urgencia (verde > 30 días, amarillo 1-30 días, rojo vencido) - Botón "Renovar" que crea un nuevo contrato a partir del vencido **Formulario de asignación:** | Campo | Tipo | Notas | |-------|------|-------| | Cliente | select buscable | autocompletado | | Servicio | select buscable | muestra precio base | | Fecha inicio | date | default: hoy | | Fecha vencimiento | date | calculada automáticamente según periodicidad | | Precio acordado | decimal | editable, pre-rellena con precio del servicio | | Auto-renovar | toggle | crea nuevo contrato automáticamente al vencer | | Notas | textarea | | **Vista detalle del contrato:** - Historial de renovaciones anteriores - Timeline de notificaciones enviadas - Botón "Enviar correo manual" - Botón "Renovar ahora" --- ### 3.4 Reglas de Notificación (`/app/notificaciones/reglas`) Permite configurar cuándo y qué correo enviar antes del vencimiento. **Ejemplos de reglas:** | Regla | Días antes | Plantilla | Aplica a | |-------|-----------|-----------|----------| | Aviso temprano | 30 | Plantilla "Renovación próxima" | Renovables | | Recordatorio | 7 | Plantilla "Vence en 7 días" | Todos | | Último aviso | 1 | Plantilla "Vence mañana" | Todos | | Vencido | 0 | Plantilla "Servicio vencido" | Todos | **Campos:** | Campo | Tipo | Notas | |-------|------|-------| | Nombre de la regla | texto | | | Días antes del vencimiento | número | 0 = día del vencimiento | | Plantilla de correo | select | | | Aplica a | select | Todos / Solo renovables / Solo únicos | | Activo | toggle | | --- ### 3.5 Plantillas de Correo (`/app/notificaciones/plantillas`) **Editor visual con:** - Editor de HTML (textarea con resaltado) - Panel de variables disponibles (click to insert) - Preview en tiempo real lado a lado - Envío de correo de prueba a email específico **Variables disponibles en plantillas:** ``` {{.ClienteNombre}} → Nombre del cliente {{.ClienteEmpresa}} → Empresa del cliente {{.Servicios}} → Tabla HTML de servicios (nombre, vencimiento, precio) {{.Total}} → Total en moneda local {{.FechaVencimiento}} → Fecha de vencimiento (la más próxima si hay varias) {{.DiasRestantes}} → Días que faltan para vencer {{.LinkPago}} → URL de pago (configurable) {{.EmpresaNombre}} → Nombre de la empresa (desde config) {{.FechaActual}} → Fecha de hoy ``` **Tipo de plantillas:** | Tipo | Uso | |------|-----| | `renovacion` | Aviso de renovación próxima | | `vencimiento` | El servicio está a punto de vencer / vencido | | `pago` | Confirmación o solicitud de pago | | `personalizado` | Uso libre / envío manual | --- ### 3.6 Historial de Envíos (`/app/notificaciones/historial`) - Tabla con todos los correos enviados - Filtro por cliente, fecha, estado (enviado/fallido) - Ver HTML del correo enviado (modal preview) - Reenviar correo fallido con un clic --- ### 3.7 Configuración SMTP (`/app/configuracion/smtp`) Panel para configurar el servidor de correo saliente sin tocar archivos. **Campos:** | Campo | Tipo | Default | |-------|------|---------| | Host SMTP | texto | smtp.gmail.com | | Puerto | número | 587 | | Usuario | email | | | Contraseña | password (cifrada) | | | Cifrado | select | TLS / SSL / Ninguno | | Nombre remitente | texto | U-site | | Email remitente | email | | - Botón **"Probar conexión"** — envía correo de prueba y muestra resultado - La config se guarda en BD (cifrada) y sobrescribe la del `config.yml` en runtime --- ## 4. Flujo de Trabajo ### Flujo de creación de un contrato ``` 1. Crear servicio en catálogo ↓ 2. Crear/seleccionar cliente ↓ 3. Crear contrato (asignar servicio + fechas + precio) ↓ 4. Sistema calcula automáticamente cuándo disparar notificaciones según reglas configuradas ↓ 5. Cron diario evalúa contratos y dispara correos agrupados ``` ### Lógica de agrupación de correos ``` Para cada cliente con contratos próximos a vencer: │ ├── mismo_dia = contratos donde fecha_vencimiento == misma fecha │ └── → UN solo correo con tabla de servicios + total sumado │ └── fechas_distintas = contratos con fechas diferentes └── → UN correo por cada fecha de vencimiento distinta ``` **Ejemplo práctico:** - Cliente "Empresa ABC" tiene: - Dominio → vence 15 mayo → correo independiente - Hosting + SSL → ambos vencen 15 mayo → **un solo correo con total combinado** - Mantenimiento → vence 30 mayo → correo independiente --- ## 5. Sistema de Notificaciones ### Arquitectura del Cron El sistema usa un **cron interno en Go** (librería `robfig/cron`) que se inicia al arrancar la aplicación. ```go // Se ejecuta diariamente a las 8:00 AM cron.AddFunc("0 8 * * *", jobs.ProcesarVencimientos) ``` ### Job: `ProcesarVencimientos` ``` 1. Obtener todas las reglas activas (ordenadas por dias_antes) 2. Para cada regla: a. Buscar contratos donde: - estado = 'activo' - fecha_vencimiento = HOY + dias_antes - NO exista ya un envío del mismo tipo en notificaciones_log b. Agrupar contratos encontrados por cliente + fecha_vencimiento c. Para cada grupo: - Renderizar plantilla con datos del grupo - Enviar correo (con CC si aplica) - Registrar en notificaciones_log 3. Si auto_renovar = true y estado = vencido: - Crear nuevo contrato con nueva fecha de vencimiento - Actualizar estado del anterior a 'renovado' ``` ### Estados de un contrato ``` activo ──────────── (cron notifica) ──────────── vence │ │ ├── renovado (si auto_renovar o manual) │ │ │ └── cancelado (manual) vencido ``` --- ## 6. Plantillas de Correo ### Variables en el cuerpo HTML El motor de plantillas usa `html/template` de Go (ya usado en el proyecto). ### Plantilla base sugerida — Renovación ```html
``` ### Preview en tiempo real - Frontend: Alpine.js + `