19 KiB
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:
-- 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:
// 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:
- MGN-017 RF-001 a RF-004 (infraestructura WhatsApp) - NO requiere MGN-018
- MGN-018 RF-001 a RF-006 (infraestructura AI) - NO requiere MGN-017
- 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:
-- 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:
-- 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:
-- 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:
-- 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
-- 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
// En cualquier módulo que necesite verificar feature
async function checkFeatureEnabled(tenantId: string, feature: string): Promise<boolean> {
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
{
"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
// 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
-- 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:
- Dependencia faltante con MGN-014 en todos los módulos nuevos
- Integración contable entre MGN-015/MGN-016 y MGN-004
- Control centralizado de features mediante funciones auxiliares
- Interdependencia 017↔018 resuelta con arquitectura en capas
- Campos adicionales en MGN-003, MGN-007 y MGN-009
Implementando estas adaptaciones, el sistema quedará correctamente integrado y sin impactos inesperados.