# Validación de Dependencias: MGN-015, MGN-016, MGN-017, MGN-018 **Fecha:** 2025-12-05 **Estado:** REQUIERE ADAPTACIONES **Revisión:** v1.0 ## Resumen Ejecutivo Se realizó un análisis exhaustivo de las dependencias entre los módulos nuevos/modificados (MGN-015 a MGN-018) y los módulos existentes (MGN-001 a MGN-014). Se identificaron **dependencias faltantes críticas**, **impactos no contemplados**, y **adaptaciones necesarias**. ### Veredicto General | Módulo | Estado | Dependencias Faltantes | Impactos No Contemplados | |--------|--------|------------------------|--------------------------| | MGN-015 | ⚠️ Requiere ajustes | MGN-014, MGN-004 | 3 críticos | | MGN-016 | ⚠️ Requiere ajustes | MGN-014 | 4 altos | | MGN-017 | ⚠️ Requiere ajustes | MGN-014 | 3 altos | | MGN-018 | ⚠️ Requiere ajustes | MGN-014 | 4 altos | --- ## 1. Dependencias Faltantes Críticas ### 1.1 Todos los módulos → MGN-014 (Mensajería y Notificaciones) **Problema:** Ninguno de los módulos nuevos declara dependencia con MGN-014, pero TODOS requieren: - Auditoría de cambios (Tracking automático) - Notificaciones de eventos - Sistema de mensajes internos **Módulos Afectados:** ``` MGN-015 (Billing) → Notificar cambios de suscripción, facturas MGN-016 (Pagos) → Confirmar pagos, alertar fallas MGN-017 (WhatsApp) → Logging de mensajes, escalaciones MGN-018 (AI Agents) → Historial de conversaciones, feedback ``` **Acción Requerida:** Agregar `MGN-014` como dependencia en todos los READMEs. --- ### 1.2 MGN-015 → MGN-004 (Financiero) **Problema:** MGN-015 genera facturas de suscripción pero no tiene integración para generar asientos contables. **Impacto:** - Ingresos por suscripción no se registran en contabilidad - No hay conciliación entre facturación SaaS y libro mayor - Imposible cerrar mes contable correctamente **Acción Requerida:** ```sql -- Agregar a MGN-015 esquema de integración con MGN-004 CREATE TABLE billing.accounting_mappings ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), event_type VARCHAR(50) NOT NULL, -- subscription_payment, refund, credit debit_account_id UUID REFERENCES financial.accounts(id), credit_account_id UUID REFERENCES financial.accounts(id), created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP ); ``` --- ### 1.3 MGN-016 → MGN-004 (Financiero) **Problema:** Los pagos procesados por MercadoPago/Clip deben generar asientos contables automáticos. **Impacto:** - Pagos recibidos no se reflejan en contabilidad - Comisiones de procesadores no se registran - Conciliación bancaria imposible **Acción Requerida:** Crear webhook interno que dispare asientos: ```typescript // Al confirmar pago en MGN-016 async function onPaymentConfirmed(payment: PaymentTransaction) { await createAccountingEntry({ journal: 'bank', entries: [ { account: 'bank_account', debit: payment.net_amount }, { account: 'payment_fees', debit: payment.fee_amount }, { account: 'accounts_receivable', credit: payment.amount } ], reference: payment.id, date: payment.approved_at }); } ``` --- ## 2. Interdependencia Circular: MGN-017 ↔ MGN-018 ### Problema Identificado ``` MGN-017 (WhatsApp) └─ RF-005 (Chatbot) necesita MGN-018 (AI Agents) MGN-018 (AI Agents) └─ Necesita MGN-017 como canal de comunicación ``` ### Riesgo - Ciclo de dependencia que complica el orden de implementación - ¿Quién se implementa primero? ### Solución: Arquitectura en Capas ``` ┌─────────────────────────────────────────────────────────────┐ │ CAPA DE APLICACIÓN │ │ ┌─────────────────────────────────────────────────────────┐│ │ │ MGN-017-005 (Chatbot) = Orquestador de flujos ││ │ │ - Usa MGN-017 para enviar/recibir mensajes ││ │ │ - Usa MGN-018 para respuestas inteligentes ││ │ └─────────────────────────────────────────────────────────┘│ ├─────────────────────────────────────────────────────────────┤ │ CAPA DE SERVICIOS │ │ ┌────────────────────┐ ┌────────────────────┐ │ │ │ MGN-017 (WhatsApp) │ │ MGN-018 (AI Core) │ │ │ │ - Conexión API │ │ - LLM Processing │ │ │ │ - Mensajería │ │ - Knowledge Base │ │ │ │ - Templates │ │ - Tools │ │ │ └────────────────────┘ └────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` **Orden de Implementación:** 1. MGN-017 RF-001 a RF-004 (infraestructura WhatsApp) - NO requiere MGN-018 2. MGN-018 RF-001 a RF-006 (infraestructura AI) - NO requiere MGN-017 3. MGN-017 RF-005 (Chatbot) - Integra ambos módulos --- ## 3. Impactos en Módulos Existentes ### 3.1 Impacto en MGN-001 (Autenticación/Multi-Tenant) **Cambios Requeridos:** | Entidad | Cambio | Razón | |---------|--------|-------| | `core_tenants.tenants` | Agregar `subscription_status` | Bloquear acceso si suscripción vencida | | `core_rbac.roles` | Nuevos roles | `billing_admin`, `ai_admin`, `messaging_admin` | | `core_rbac.permissions` | Nuevos permisos | `billing:*`, `ai:*`, `whatsapp:*`, `payments:*` | **SQL Requerido:** ```sql -- Agregar campo de estado de suscripción para control de acceso ALTER TABLE core_tenants.tenants ADD COLUMN IF NOT EXISTS subscription_status VARCHAR(20) DEFAULT 'trial'; -- Nuevos roles INSERT INTO core_rbac.roles (code, name, description, is_system) VALUES ('billing_admin', 'Administrador de Facturación', 'Gestiona planes y suscripciones', true), ('ai_admin', 'Administrador de IA', 'Configura agentes y knowledge bases', true), ('messaging_admin', 'Administrador de Mensajería', 'Gestiona WhatsApp y chatbots', true), ('payments_admin', 'Administrador de Pagos', 'Configura terminales y procesa pagos', true) ON CONFLICT (code) DO NOTHING; ``` --- ### 3.2 Impacto en MGN-003 (Catálogos) **Cambios Requeridos:** | Entidad | Cambio | Razón | |---------|--------|-------| | `catalogs.contacts` | Agregar `whatsapp_number` | MGN-017 necesita identificar contactos | | `catalogs.contacts` | Agregar `whatsapp_opt_in` | Cumplimiento legal para marketing | | `catalogs.payment_methods` | Agregar tipos | `mercadopago`, `clip`, `stripe_terminal` | **SQL Requerido:** ```sql -- Campos para WhatsApp en contactos ALTER TABLE catalogs.contacts ADD COLUMN IF NOT EXISTS whatsapp_number VARCHAR(20), ADD COLUMN IF NOT EXISTS whatsapp_opt_in BOOLEAN DEFAULT false, ADD COLUMN IF NOT EXISTS whatsapp_opt_in_date TIMESTAMPTZ; CREATE INDEX IF NOT EXISTS idx_contacts_whatsapp ON catalogs.contacts(whatsapp_number) WHERE whatsapp_number IS NOT NULL; -- Validación de formato ALTER TABLE catalogs.contacts ADD CONSTRAINT chk_whatsapp_format CHECK (whatsapp_number IS NULL OR whatsapp_number ~ '^\+[1-9][0-9]{6,14}$'); ``` --- ### 3.3 Impacto en MGN-007 (Ventas) **Cambios Requeridos:** | Entidad | Cambio | Razón | |---------|--------|-------| | `sales.orders` | Agregar `payment_status` | Rastrear estado de pago de MGN-016 | | `sales.orders` | Agregar `payment_transaction_id` | Referencia a transacción | | Workflow | Nuevo estado | `awaiting_payment` antes de `confirmed` | **SQL Requerido:** ```sql -- Campos para integración con MGN-016 ALTER TABLE sales.orders ADD COLUMN IF NOT EXISTS payment_status VARCHAR(20) DEFAULT 'pending', ADD COLUMN IF NOT EXISTS payment_transaction_id UUID, ADD COLUMN IF NOT EXISTS paid_at TIMESTAMPTZ; -- Actualizar constraint de estados ALTER TABLE sales.orders DROP CONSTRAINT IF EXISTS chk_order_status; ALTER TABLE sales.orders ADD CONSTRAINT chk_order_status CHECK (status IN ('draft', 'sent', 'awaiting_payment', 'confirmed', 'done', 'cancelled')); ``` --- ### 3.4 Impacto en MGN-009 (CRM) **Cambios Requeridos:** | Entidad | Cambio | Razón | |---------|--------|-------| | `crm.leads` | Agregar `whatsapp_conversation_id` | Vincular con MGN-017 | | `crm.leads` | Agregar `source_channel` | Identificar origen (whatsapp, web, etc.) | | `crm.leads` | Agregar `ai_score` | Lead scoring de MGN-018 | **SQL Requerido:** ```sql -- Campos para integración con WhatsApp y AI ALTER TABLE crm.leads ADD COLUMN IF NOT EXISTS whatsapp_conversation_id UUID, ADD COLUMN IF NOT EXISTS source_channel VARCHAR(50) DEFAULT 'manual', ADD COLUMN IF NOT EXISTS ai_score DECIMAL(5,2), ADD COLUMN IF NOT EXISTS ai_score_updated_at TIMESTAMPTZ; -- Índice para búsqueda por conversación CREATE INDEX IF NOT EXISTS idx_leads_whatsapp_conv ON crm.leads(whatsapp_conversation_id) WHERE whatsapp_conversation_id IS NOT NULL; ``` --- ## 4. Feature Flags Centralizados ### Problema Cada módulo nuevo define sus propios feature flags en `subscription_plans.features`, pero no hay una forma centralizada de consultarlos. ### Solución: Función Auxiliar ```sql -- Crear en schema billing CREATE OR REPLACE FUNCTION billing.has_feature( p_tenant_id UUID, p_feature_name VARCHAR ) RETURNS BOOLEAN AS $$ DECLARE v_features JSONB; BEGIN SELECT sp.features INTO v_features FROM billing.subscriptions bs JOIN billing.subscription_plans sp ON bs.plan_id = sp.id WHERE bs.tenant_id = p_tenant_id AND bs.status = 'active' ORDER BY bs.created_at DESC LIMIT 1; IF v_features IS NULL THEN RETURN false; END IF; RETURN COALESCE((v_features->>p_feature_name)::boolean, false); END; $$ LANGUAGE plpgsql STABLE; -- Función para obtener límite numérico CREATE OR REPLACE FUNCTION billing.get_feature_limit( p_tenant_id UUID, p_feature_name VARCHAR ) RETURNS INTEGER AS $$ DECLARE v_features JSONB; BEGIN SELECT sp.features INTO v_features FROM billing.subscriptions bs JOIN billing.subscription_plans sp ON bs.plan_id = sp.id WHERE bs.tenant_id = p_tenant_id AND bs.status = 'active' ORDER BY bs.created_at DESC LIMIT 1; IF v_features IS NULL THEN RETURN 0; END IF; RETURN COALESCE((v_features->>p_feature_name)::integer, 0); END; $$ LANGUAGE plpgsql STABLE; ``` ### Uso en Módulos ```typescript // En cualquier módulo que necesite verificar feature async function checkFeatureEnabled(tenantId: string, feature: string): Promise { const result = await db.query( 'SELECT billing.has_feature($1, $2) as enabled', [tenantId, feature] ); return result.rows[0].enabled; } // Ejemplo en MGN-018 const canUseAI = await checkFeatureEnabled(tenantId, 'ai_agents_enabled'); const tokenLimit = await db.query( 'SELECT billing.get_feature_limit($1, $2) as limit', [tenantId, 'ai_monthly_token_limit'] ); ``` --- ## 5. Matriz de Features por Plan ### Features que deben definirse en planes ```json { "starter": { "max_users": 5, "max_companies": 1, "mercadopago_enabled": false, "clip_enabled": false, "stripe_enabled": false, "whatsapp_enabled": false, "whatsapp_chatbot": false, "whatsapp_marketing": false, "whatsapp_max_accounts": 0, "ai_agents_enabled": false, "ai_max_agents": 0, "ai_kb_max_documents": 0, "ai_monthly_token_limit": 0 }, "professional": { "max_users": 25, "max_companies": 3, "mercadopago_enabled": true, "clip_enabled": true, "stripe_enabled": false, "whatsapp_enabled": true, "whatsapp_chatbot": true, "whatsapp_marketing": false, "whatsapp_max_accounts": 1, "ai_agents_enabled": true, "ai_max_agents": 3, "ai_kb_max_documents": 100, "ai_monthly_token_limit": 500000 }, "enterprise": { "max_users": -1, "max_companies": -1, "mercadopago_enabled": true, "clip_enabled": true, "stripe_enabled": true, "whatsapp_enabled": true, "whatsapp_chatbot": true, "whatsapp_marketing": true, "whatsapp_max_accounts": 10, "ai_agents_enabled": true, "ai_max_agents": -1, "ai_kb_max_documents": 500, "ai_monthly_token_limit": 5000000, "ai_custom_tools": true } } ``` --- ## 6. Webhooks de Integración Requeridos ### Eventos que deben propagarse entre módulos ```typescript // Eventos de MGN-015 (Billing) type BillingEvents = { 'subscription.created': { tenant_id: string; plan_id: string; }; 'subscription.upgraded': { tenant_id: string; old_plan: string; new_plan: string; }; 'subscription.downgraded': { tenant_id: string; old_plan: string; new_plan: string; }; 'subscription.canceled': { tenant_id: string; reason: string; }; 'subscription.payment_failed': { tenant_id: string; invoice_id: string; }; 'invoice.paid': { tenant_id: string; invoice_id: string; amount: number; }; }; // Eventos de MGN-016 (Pagos) type PaymentEvents = { 'payment.approved': { tenant_id: string; order_id: string; amount: number; }; 'payment.declined': { tenant_id: string; order_id: string; reason: string; }; 'payment.refunded': { tenant_id: string; transaction_id: string; amount: number; }; 'terminal.connected': { tenant_id: string; terminal_id: string; }; 'terminal.disconnected': { tenant_id: string; terminal_id: string; }; }; // Eventos de MGN-017 (WhatsApp) type WhatsAppEvents = { 'message.received': { tenant_id: string; conversation_id: string; from: string; }; 'message.sent': { tenant_id: string; conversation_id: string; to: string; }; 'conversation.escalated': { tenant_id: string; conversation_id: string; reason: string; }; 'quality.warning': { tenant_id: string; account_id: string; rating: string; }; }; // Eventos de MGN-018 (AI Agents) type AIAgentEvents = { 'conversation.started': { tenant_id: string; agent_id: string; channel: string; }; 'conversation.completed': { tenant_id: string; conversation_id: string; resolved: boolean; }; 'tokens.threshold_reached': { tenant_id: string; usage_percent: number; }; 'tokens.limit_exceeded': { tenant_id: string; }; 'feedback.received': { tenant_id: string; conversation_id: string; rating: number; }; }; ``` ### Sistema de Eventos Centralizado ```sql -- Tabla de eventos del sistema (para debugging y auditoría) CREATE TABLE IF NOT EXISTS system.event_log ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID, event_type VARCHAR(100) NOT NULL, source_module VARCHAR(20) NOT NULL, payload JSONB NOT NULL, processed BOOLEAN DEFAULT false, processed_at TIMESTAMPTZ, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_events_tenant ON system.event_log(tenant_id); CREATE INDEX idx_events_type ON system.event_log(event_type); CREATE INDEX idx_events_unprocessed ON system.event_log(processed) WHERE processed = false; ``` --- ## 7. Plan de Implementación de Adaptaciones ### Fase 1: Preparación de Infraestructura (Semana 1) | Tarea | Prioridad | Esfuerzo | |-------|-----------|----------| | Crear funciones `has_feature()` y `get_feature_limit()` | CRÍTICA | 2h | | Crear tabla `system.event_log` | CRÍTICA | 1h | | Actualizar roles en MGN-001 | ALTA | 4h | | Agregar campos en MGN-003 (contacts) | ALTA | 2h | ### Fase 2: Integración MGN-015 ↔ MGN-004 (Semana 2) | Tarea | Prioridad | Esfuerzo | |-------|-----------|----------| | Crear `billing.accounting_mappings` | CRÍTICA | 4h | | Implementar auto-generación de asientos | CRÍTICA | 8h | | Crear job de conciliación diaria | ALTA | 4h | ### Fase 3: Integración MGN-016 ↔ MGN-007 ↔ MGN-004 (Semana 3) | Tarea | Prioridad | Esfuerzo | |-------|-----------|----------| | Agregar campos en MGN-007 (orders) | ALTA | 2h | | Webhook `payment.approved` → actualizar orden | CRÍTICA | 4h | | Auto-generar asientos de pagos | CRÍTICA | 8h | | Reconciliador de comisiones | MEDIA | 4h | ### Fase 4: Integración MGN-017 ↔ MGN-009 (Semana 4) | Tarea | Prioridad | Esfuerzo | |-------|-----------|----------| | Agregar campos en MGN-009 (leads) | ALTA | 2h | | Auto-crear leads desde WhatsApp | ALTA | 8h | | Vincular conversaciones a leads | ALTA | 4h | ### Fase 5: Integración MGN-018 ↔ MGN-015 (Semana 5) | Tarea | Prioridad | Esfuerzo | |-------|-----------|----------| | Implementar control de tokens | CRÍTICA | 8h | | Alertas de consumo | ALTA | 4h | | Rate limiting por tenant | ALTA | 4h | --- ## 8. Riesgos y Mitigaciones | Riesgo | Probabilidad | Impacto | Mitigación | |--------|--------------|---------|------------| | Feature flags no sincronizados | ALTA | CRÍTICO | Función centralizada + cache | | Ciclo de dependencia 017↔018 | MEDIA | ALTO | Arquitectura en capas | | Fallo en webhook de pago | MEDIA | CRÍTICO | Dead letter queue + retry | | Exceso de tokens en AI | ALTA | ALTO | Rate limiting estricto | | Datos sensibles en logs | MEDIA | CRÍTICO | PII masking automático | | Asientos contables incorrectos | BAJA | CRÍTICO | Validación + rollback | --- ## 9. Checklist de Validación Pre-Implementación ### MGN-015 (Billing) - [ ] Agregar dependencia con MGN-014 en README - [ ] Agregar dependencia con MGN-004 en README - [ ] Crear `billing.has_feature()` function - [ ] Definir eventos de suscripción - [ ] Mapear cuentas contables ### MGN-016 (Pagos) - [ ] Agregar dependencia con MGN-014 en README - [ ] Definir estados de pago en MGN-007 - [ ] Crear webhooks de integración - [ ] Mapear asientos de pagos y comisiones ### MGN-017 (WhatsApp) - [ ] Agregar dependencia con MGN-014 en README - [ ] Agregar campos en MGN-003 (contacts) - [ ] Agregar campos en MGN-009 (leads) - [ ] Definir templates de notificación para MGN-007 ### MGN-018 (AI Agents) - [ ] Agregar dependencia con MGN-014 en README - [ ] Implementar control de tokens en MGN-015 - [ ] Definir tools para MGN-007 y MGN-009 - [ ] Implementar rate limiting --- ## 10. Conclusión Las modificaciones a los módulos MGN-015, MGN-016, MGN-017 y MGN-018 **pueden implementarse** pero requieren las adaptaciones documentadas en este análisis. Las principales áreas de atención son: 1. **Dependencia faltante con MGN-014** en todos los módulos nuevos 2. **Integración contable** entre MGN-015/MGN-016 y MGN-004 3. **Control centralizado de features** mediante funciones auxiliares 4. **Interdependencia 017↔018** resuelta con arquitectura en capas 5. **Campos adicionales** en MGN-003, MGN-007 y MGN-009 Implementando estas adaptaciones, el sistema quedará correctamente integrado y sin impactos inesperados.