23 KiB
Seguimiento de Impuestos GLM
Aplicación interna que centraliza el calendario tributario regional de GomezLee Marketing y automatiza el envío de recordatorios por correo y WhatsApp.
INFORMACIÓN GENERAL
| Campo | Detalle |
|---|---|
| Proyecto | Seguimiento de Impuestos GLM |
| Área | Administración |
| Estado | Listo para producción |
| Developer principal | Isaac Aracena |
| IT Manager | Luis Matos |
| Fecha de inicio | 2026-07-24 |
| Fecha de cierre | 2026-07-27 |
OBJETIVO
Problema que resuelve
El seguimiento de las obligaciones tributarias de los diferentes países de GLM se realizaba mediante calendarios y archivos separados. Esto dificultaba consultar las fechas límite, identificar a los responsables y garantizar que los avisos fueran enviados a tiempo.
Además, agregar o cambiar destinatarios requería modificar manualmente los flujos de automatización.
Solución implementada
Seguimiento de Impuestos GLM centraliza en una sola aplicación:
- El calendario tributario regional.
- Las obligaciones de Nómina y Administración.
- Los países y fechas límite.
- Los contactos responsables.
- Los canales habilitados para cada contacto.
- El historial de notificaciones enviadas.
La aplicación permite administrar obligaciones y contactos desde una interfaz web. Un flujo de n8n consulta diariamente la información almacenada en Supabase y envía los recordatorios correspondientes por Gmail y WhatsApp.
Usuarios y beneficiarios
- Equipo de Administración.
- Equipo de Nómina.
- Responsables tributarios de cada país.
- Contactos regionales.
- Dirección de Recursos Humanos.
- Equipo de IT de GomezLee Marketing.
ARQUITECTURA
Diagrama general
Usuario autorizado
|
v
Frontend React + Vite
|
+------> Supabase Auth
|
+------> Supabase PostgreSQL
|
v
Obligaciones y contactos
|
v
n8n — Ejecución 8:00 AM
|
v
RPC tax_due_reminders
|
+--------+--------+
| |
v v
Gmail HTML WhatsApp
| |
+--------+--------+
|
v
tax_notification_log
Stack tecnológico
| Componente | Tecnología | Propósito |
|---|---|---|
| Frontend | React 19 | Interfaz de usuario |
| Lenguaje | TypeScript | Tipado y lógica de la aplicación |
| Bundler | Vite | Desarrollo y compilación |
| Estilos | Tailwind CSS | Diseño visual |
| Autenticación | Supabase Auth + Google OAuth | Control de acceso |
| Base de datos | Supabase / PostgreSQL | Obligaciones, países, contactos y bitácora |
| API de datos | Supabase REST / PostgREST | Comunicación entre frontend, n8n y base de datos |
| Automatización | n8n | Orquestación de recordatorios |
| Correo | Gmail OAuth | Envío de correos HTML |
| Mensajería | WhatsApp GLM | Envío de avisos por WhatsApp |
| Hosting | EasyPanel / servidor GLM | Despliegue de la aplicación y servicios |
Integraciones externas
| Sistema | Tipo de integración | Datos que fluyen |
|---|---|---|
| Supabase Auth | Google OAuth | Inicio de sesión y sesión del usuario |
| Supabase REST | API REST / RPC | Obligaciones, contactos, países y notificaciones |
| n8n | Webhook y Schedule Trigger | Ejecución manual, diaria y notificación de cambios |
| Gmail | OAuth | Correos de recordatorio |
| WhatsApp GLM | API REST | Mensajes de recordatorio |
| Google Workspace | OAuth | Identidad corporativa de los usuarios |
REGLAS DE NEGOCIO
Regla de recordatorios
La fórmula principal es:
Miércoles estrictamente anterior y el mismo día de la fecha límite.
Ejemplos:
| Fecha límite | Primer aviso | Segundo aviso |
|---|---|---|
| Lunes | Miércoles anterior | Lunes |
| Martes | Miércoles anterior | Martes |
| Miércoles | Miércoles de la semana anterior | Miércoles |
| Jueves | Miércoles anterior | Jueves |
| Viernes | Miércoles anterior | Viernes |
| Sábado | Miércoles anterior | Sábado |
| Domingo | Miércoles anterior | Domingo |
El miércoles calculado debe ser estrictamente anterior. Si la obligación vence un miércoles, el primer aviso corresponde al miércoles de la semana anterior.
Enrutamiento de contactos
- Los contactos de área Regional reciben todas las obligaciones de todos los países.
- Los contactos regionales de Nómina reciben las obligaciones de Nómina de todos los países.
- Los contactos regionales de Administración reciben las obligaciones administrativas de todos los países.
- Los contactos de un país específico reciben solamente las obligaciones de su país y categoría.
- Solo se utilizan contactos activos.
- El correo se envía únicamente cuando el canal de correo está habilitado.
- WhatsApp se envía únicamente cuando el canal de WhatsApp está habilitado.
- Los números deben guardarse con código internacional.
Obligaciones tributarias
- El país es obligatorio.
- Las únicas categorías disponibles son:
- Nómina.
- Administración.
- Una obligación puede editarse o eliminarse mientras no tenga avisos enviados.
- Después del primer correo o WhatsApp registrado, la obligación queda bloqueada.
- Las obligaciones bloqueadas permanecen disponibles en modo de solo lectura.
- Cuando un día tiene más de tres obligaciones, la opción Ver todos permite consultar la lista completa.
Prevención de duplicados
Cada notificación enviada se registra en tax_notification_log.
La combinación de obligación, contacto, canal y tipo de aviso evita que el mismo recordatorio sea enviado dos veces.
BASE DE DATOS
Tablas
La aplicación utiliza cinco tablas:
| Tabla | Propósito |
|---|---|
tax_calendar_access |
Correos autorizados para ingresar |
tax_countries |
Catálogo de países |
tax_obligations |
Obligaciones y eventos tributarios |
tax_contacts |
Contactos responsables y canales habilitados |
tax_notification_log |
Bitácora de correos y WhatsApp enviados |
Funciones principales
| Función | Propósito |
|---|---|
has_tax_calendar_access |
Valida si el correo puede utilizar la aplicación |
tax_previous_wednesday |
Calcula el miércoles estrictamente anterior |
tax_due_reminders |
Devuelve los recordatorios y destinatarios pendientes |
tax_record_notification |
Registra un envío exitoso |
tax_obligation_delivery_status |
Consulta si una obligación ya fue notificada |
tax_prevent_sent_obligation_changes |
Bloquea cambios después del primer aviso |
Instalación completa
Para una instalación nueva, ejecutar en Supabase:
supabase/Seguimiento-de-Impuestos-GLM.sql
El script incluye:
- Tablas.
- Índices.
- Triggers.
- Funciones RPC.
- Políticas RLS.
- Accesos iniciales.
- Países.
- Contactos.
- Obligaciones históricas de 2026.
- Prevención de notificaciones duplicadas.
Actualizaciones incrementales
Para bases que ya tenían una versión anterior:
supabase/actualizacion_eventos_bloqueados.sql
supabase/actualizacion_final_calendario_y_nomina.sql
No ejecutar actualizaciones incrementales si ya se utilizó el script completo más reciente.
CONFIGURACIÓN Y SETUP
Prerrequisitos
- Node.js instalado.
- npm instalado.
- Acceso al Supabase empresarial.
- Acceso a Google Cloud y Supabase Auth.
- Acceso a n8n.
- Credencial de Gmail configurada en n8n.
- Acceso a la API de WhatsApp de GLM.
- Acceso al hosting de EasyPanel.
- Correo autorizado para ingresar a la aplicación.
Variables del frontend
Copiar el archivo de ejemplo:
Copy-Item .env.example .env
Configurar:
VITE_SUPABASE_URL=https://dbit.digitalcompass.agency
VITE_SUPABASE_PUBLISHABLE_KEY=REEMPLAZAR_CON_LA_LLAVE_PUBLICA
VITE_TAX_WEBHOOK_URL=https://agenteit.digitalcompass.agency/webhook/seguimiento-impuestos
También puede utilizarse:
VITE_SUPABASE_ANON_KEY=REEMPLAZAR_CON_LA_ANON_KEY
Nunca colocar la llave service_role dentro del frontend.
Variables y credenciales de n8n
| Configuración | Descripción |
|---|---|
| Supabase URL | URL del Supabase empresarial |
| Supabase Service Role | Llave privada para ejecutar RPC y registrar envíos |
| Gmail Credential | Cuenta que envía los recordatorios |
| WhatsApp Base URL | Endpoint del servicio de WhatsApp |
| WhatsApp Instance | Instancia botsoporte |
| WhatsApp API Key | Credencial privada del servicio |
| GLM Tax App URL | https://home.digitalcompass.agency/ |
| GLM Logo URL | Logo público utilizado en el correo HTML |
Las llaves privadas deben administrarse en n8n o en el vault de credenciales de GLM.
Nunca commitear
.env, llaves privadas, tokens, contraseñas o credenciales reales al repositorio.
Supabase Auth
La URL autorizada para regresar a la aplicación después del login es:
https://home.digitalcompass.agency/
En el servicio de Supabase Auth debe agregarse:
ADDITIONAL_REDIRECT_URLS=https://home.digitalcompass.agency/
El callback de Google OAuth hacia Supabase permanece en:
https://dbit.digitalcompass.agency/auth/v1/callback
INSTALACIÓN LOCAL
1. Clonar el repositorio
git clone https://git.digitalcompass.agency/Isaac_Aracena/seguimiento-impuestos.git
cd seguimiento-impuestos
2. Instalar dependencias
npm install
3. Crear el archivo de entorno
Copy-Item .env.example .env
Editar .env con la configuración pública correspondiente.
4. Ejecutar en desarrollo
npm run dev
Aplicación local:
http://localhost:5173/
5. Validar el proyecto
npm run typecheck
npm run lint
npm run format:check
6. Generar el build
npm run build
7. Probar el build
npm run preview
DESPLIEGUE
La aplicación se publica directamente en la raíz del subdominio:
https://home.digitalcompass.agency/
La configuración de Vite utiliza:
base: "/"
Proceso general:
npm install
npm run build
El contenido generado en dist/ debe desplegarse en el servicio correspondiente de EasyPanel.
Después del despliegue:
- Abrir la aplicación.
- Iniciar sesión con Google.
- Confirmar que Supabase redirige a la raíz del subdominio.
- Verificar que carguen obligaciones, países y contactos.
- Crear un registro de prueba.
- Confirmar su almacenamiento en Supabase.
CONFIGURACIÓN DE N8N
Importar el archivo:
n8n/Seguimiento-de-Impuestos-GLM.json
Después de importarlo:
- Seleccionar la credencial en Gmail - Enviar recordatorio.
- Configurar la conexión privada con Supabase.
- Configurar el endpoint y la API key de WhatsApp.
- Verificar la zona horaria
America/Santo_Domingo. - Ejecutar una prueba manual.
- Confirmar el correo recibido.
- Confirmar el WhatsApp recibido.
- Verificar el registro en
tax_notification_log. - Activar el workflow.
CÓMO FUNCIONA
Flujo diario
- El Schedule Trigger inicia el workflow a las 8:00 a. m.
- n8n obtiene la fecha correspondiente a la ejecución.
- El nodo de Supabase llama la RPC
tax_due_reminders. - Supabase identifica las obligaciones que deben notificarse.
- Supabase cruza cada obligación con los contactos aplicables.
- n8n genera el correo HTML con el branding de GLM.
- n8n genera el mensaje de WhatsApp.
- Gmail envía los correos habilitados.
- La API de WhatsApp envía los mensajes habilitados.
- Cada envío exitoso se registra en Supabase.
- Los registros enviados quedan protegidos contra duplicados.
Cambios desde la aplicación
Cuando el usuario:
- Crea una obligación.
- Actualiza una obligación.
- Elimina una obligación.
- Crea un contacto.
- Actualiza un contacto.
- Desactiva un contacto.
La información se guarda directamente en Supabase.
El flujo de n8n consulta siempre la información vigente, por lo que no es necesario modificar manualmente el workflow cuando cambien los contactos.
Schedules y triggers
| Trigger | Frecuencia | Descripción |
|---|---|---|
| Schedule Trigger | Diario, 8:00 a. m. | Envía los recordatorios correspondientes |
| Manual Trigger | Bajo demanda | Permite realizar pruebas desde n8n |
Webhook seguimiento-impuestos |
Bajo demanda | Recibe acciones del frontend o ejecuciones controladas |
Prueba con una fecha específica
{
"action": "run_now",
"run_date": "2026-07-24"
}
TESTING
Casos de prueba mínimos
| Caso | Input | Resultado esperado | Estado |
|---|---|---|---|
| Login autorizado | Correo incluido en tax_calendar_access |
Acceso concedido | Validado |
| Login no autorizado | Correo no incluido | Acceso denegado | Validado |
| Crear obligación | Fecha, descripción, categoría y país | Registro visible en calendario | Validado |
| País vacío | Obligación sin país | Formulario no permite guardar | Validado |
| Categoría inválida | Valor diferente a Nómina o Administración | Registro rechazado | Validado |
| Editar sin aviso | Obligación sin notificaciones | Cambios permitidos | Validado |
| Editar con aviso | Obligación ya notificada | Modo de solo lectura | Validado |
| Eliminar sin aviso | Obligación sin notificaciones | Eliminación permitida | Validado |
| Eliminar con aviso | Obligación ya notificada | Eliminación bloqueada | Validado |
| Más de tres obligaciones | Día con cuatro o más registros | Opción Ver todos disponible | Validado |
| Contacto regional | Área Regional activa | Recibe todas las obligaciones | Validado |
| Contacto regional de Nómina | País Regional y área Nómina | Recibe Nómina de todos los países | Validado |
| Correo deshabilitado | email_enabled = false |
No se genera correo | Validado |
| WhatsApp deshabilitado | whatsapp_enabled = false |
No se genera WhatsApp | Validado |
| Aviso duplicado | Mismo contacto, obligación, canal y tipo | Segundo envío bloqueado | Validado |
| API de WhatsApp caída | Error HTTP | Ejecución registrada como fallida | Pendiente de prueba controlada |
| Gmail no disponible | Error de credencial o servicio | Nodo falla y queda visible en Executions | Pendiente de prueba controlada |
ERRORES CONOCIDOS Y TROUBLESHOOTING
| Error | Causa probable | Solución |
|---|---|---|
| El login vuelve a Supabase | Redirect URL incorrecta | Agregar https://home.digitalcompass.agency/ a ADDITIONAL_REDIRECT_URLS |
| Pantalla en blanco después del deploy | Base de Vite incorrecta | Confirmar base: "/" y reconstruir |
| 401 Unauthorized en Supabase | Llave incorrecta o expirada | Revisar la llave pública o service_role según el componente |
| No cargan obligaciones | Error en URL, RLS o sesión | Revisar consola del navegador y políticas RLS |
| No llegan correos | Credencial de Gmail no seleccionada | Abrir el nodo Gmail y seleccionar la credencial |
| No llega WhatsApp | API key, número o instancia incorrectos | Revisar encabezado apikey, instancia y código internacional |
| Recordatorio duplicado | Bitácora no registrada correctamente | Revisar los nodos Supabase - Registrar correo/WhatsApp |
| Obligación editable después del aviso | Trigger de protección no instalado | Ejecutar el script actualizado de Supabase |
| Contacto no recibe avisos | País, área, canal o estado incorrecto | Revisar el contacto desde la app |
| Webhook no responde | Workflow inactivo o URL incorrecta | Revisar activación y Production URL en n8n |
| Error al compilar | Dependencias incompletas | Eliminar node_modules, ejecutar npm install y reconstruir |
MONITOREO
n8n
Revisar periódicamente:
- Executions.
- Ejecuciones fallidas.
- Respuesta de Gmail.
- Respuesta de WhatsApp.
- Respuesta de los nodos de registro en Supabase.
Una ejecución normal debe finalizar sin nodos rojos y registrar cada canal enviado.
Supabase
Revisar:
- Nuevas obligaciones.
- Contactos activos.
- Estado de acceso de usuarios.
- Registros recientes en
tax_notification_log. - Duplicados o errores de datos.
- Obligaciones bloqueadas después del primer envío.
Resultado esperado
Cada día a las 8:00 a. m.:
- Se consultan las obligaciones pendientes.
- Se identifican los contactos aplicables.
- Se envían los canales habilitados.
- Se registra cada envío exitoso.
- No se repiten avisos ya enviados.
ESTRUCTURA DEL REPOSITORIO
seguimiento-impuestos/
|-- README.md
|-- AGENTS.md
|-- package.json
|-- package-lock.json
|-- vite.config.ts
|-- tsconfig.json
|-- eslint.config.js
|-- index.html
|-- .env.example
|-- .gitignore
|
|-- public/
| |-- favicon.ico
| |-- favicon-32.png
| |-- favicon-192.png
| └-- apple-touch-icon.png
|
|-- src/
| |-- App.tsx
| |-- TaxApp.tsx
| |-- main.tsx
| |-- styles.css
| |
| |-- assets/
| | └-- glm-logo.png
| |
| |-- auth/
| | └-- AuthGate.tsx
| |
| └-- lib/
| |-- supabase-auth.ts
| |-- supabase-data.ts
| └-- tax-utils.ts
|
|-- supabase/
| |-- README.md
| |-- Seguimiento-de-Impuestos-GLM.sql
| |-- seguimiento_impuestos_auth.sql
| |-- actualizacion_eventos_bloqueados.sql
| └-- actualizacion_final_calendario_y_nomina.sql
|
|-- n8n/
| |-- CONFIGURACION.md
| └-- Seguimiento-de-Impuestos-GLM.json
|
└-- dist/
└-- Build generado para producción
node_modules/, .env y demás archivos sensibles o generados no deben subirse al repositorio.
CHANGELOG
2026-07-27 — v1.0.0
- Aplicación preparada para producción.
- Migración del calendario histórico 2026 a Supabase.
- Login con Google y control de accesos.
- Gestión de obligaciones por país y categoría.
- Gestión dinámica de contactos.
- Filtros por país y nombre.
- Búsqueda en la vista Lista.
- Recordatorios por Gmail y WhatsApp.
- Correo HTML con identidad visual GLM.
- Prevención de envíos duplicados.
- Bloqueo de obligaciones después del primer aviso.
- Vista completa para días con más de tres obligaciones.
- Despliegue configurado en la raíz del subdominio.
- Flujo n8n con ejecución diaria a las 8:00 a. m.
2026-07-25 — v0.9.0
- Integración del frontend con Supabase.
- Creación de las tablas principales.
- Migración de obligaciones históricas.
- Creación del flujo inicial de n8n.
- Incorporación de contactos regionales y por país.
2026-07-24 — v0.1.0
- Limpieza del prototipo generado por Lovable.
- Eliminación de archivos y dependencias innecesarias.
- Estandarización del proyecto con React, Vite y TypeScript.
- Aplicación inicial del branding de GLM.
DECISIONS LOG
DEC-001 — Supabase como fuente única de datos
- Fecha: 2026-07-24
- Contexto: El prototipo almacenaba el calendario directamente en el frontend.
- Opciones consideradas: Mantener datos estáticos o migrarlos a Supabase.
- Decisión: Utilizar Supabase/PostgreSQL.
- Razón: Permite persistencia, administración multiusuario, integración con n8n y trazabilidad.
DEC-002 — Lógica determinística para las fechas
- Fecha: 2026-07-24
- Contexto: Se consideró utilizar Gemini para decidir cuándo enviar los avisos.
- Opciones consideradas: IA generativa o funciones de fechas en PostgreSQL.
- Decisión: Utilizar funciones determinísticas.
- Razón: La regla es exacta y no debe depender de interpretaciones probabilísticas.
DEC-003 — Contactos administrados desde la aplicación
- Fecha: 2026-07-25
- Contexto: Cada cambio de destinatario obligaba a editar n8n.
- Opciones consideradas: Contactos hardcodeados o contactos en Supabase.
- Decisión: Guardar contactos en
tax_contacts. - Razón: Los usuarios pueden mantener destinatarios sin modificar el workflow.
DEC-004 — Bloqueo después del primer envío
- Fecha: 2026-07-26
- Contexto: Modificar una obligación después de notificarla podía generar inconsistencias.
- Opciones consideradas: Permitir cambios siempre o bloquear después del envío.
- Decisión: Bloquear edición y eliminación después del primer aviso.
- Razón: Preserva la integridad del historial y evita discrepancias con mensajes ya enviados.
DEC-005 — Despliegue en subdominio
- Fecha: 2026-07-27
- Contexto: La app inicialmente utilizaba
/calendario-impuestos/como base. - Opciones consideradas: Ruta interna o subdominio independiente.
- Decisión: Publicar en
https://home.digitalcompass.agency/. - Razón: Simplifica navegación, OAuth, despliegue y mantenimiento.
CONTACTOS DEL PROYECTO
| Rol | Nombre | Contacto |
|---|---|---|
| Solicitante funcional | Ada | Pendiente de documentar |
| IT Manager | Luis Matos | lmatos@gomezleemarketing.com |
| Developer principal | Isaac Aracena | iaracena@gomezleemarketing.com |
| Contacto regional de Nómina | Mati Soto Valenzuela | msoto@gomezleemarketing.com |
| Contacto regional de Nómina | Iveth Herrera | iherrera@gomezleemarketing.com |
DEFINITION OF DONE
- Calendario histórico migrado a Supabase.
- Aplicación integrada con la base de datos.
- Login con Google implementado.
- Accesos administrables desde Supabase.
- Obligaciones administrables desde la aplicación.
- Contactos administrables desde la aplicación.
- País obligatorio.
- Categorías limitadas a Nómina y Administración.
- Filtros y búsquedas implementados.
- Regla del miércoles anterior implementada.
- Aviso del mismo día implementado.
- Correos HTML con branding GLM.
- Envíos por WhatsApp.
- Prevención de duplicados.
- Bloqueo después del primer aviso.
- Vista para días con más de tres obligaciones.
- Workflow exportado en
/n8n. - Scripts SQL almacenados en
/supabase. - Variables públicas documentadas en
.env.example. - Proyecto subido a Gitea.
- Manual de uso elaborado.
- Ejecutar monitoreo controlado durante los primeros días en producción.
- Registrar el enlace definitivo del board de Kan.bn.
- Documentar la aprobación funcional final.
SEGURIDAD
- No subir el archivo
.env. - No almacenar la llave
service_roleen React. - No publicar la API key de WhatsApp.
- No almacenar contraseñas o tokens en el README.
- Utilizar únicamente llaves públicas en variables
VITE_*. - Mantener RLS activo en las tablas.
- Restringir los accesos mediante
tax_calendar_access. - Revisar periódicamente los usuarios autorizados.
- Rotar credenciales cuando una persona deje de necesitar acceso.
DOCUMENTACIÓN ADICIONAL
AGENTS.md: reglas para agentes y asistentes de programación.supabase/README.md: instrucciones específicas de la base de datos.n8n/CONFIGURACION.md: configuración del workflow.supabase/Seguimiento-de-Impuestos-GLM.sql: instalación completa.n8n/Seguimiento-de-Impuestos-GLM.json: workflow importable.
Documento mantenido por el equipo GLM IT.