{
  "active": false,
  "activeVersion": null,
  "activeVersionId": null,
  "connections": {
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Fetch Transacciones ERP",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch P\u00e9rdidas Agua",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Transacciones ERP": {
      "main": [
        [
          {
            "node": "Merge Datasets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch P\u00e9rdidas Agua": {
      "main": [
        [
          {
            "node": "Merge Datasets",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Merge Datasets": {
      "main": [
        [
          {
            "node": "Calculate Financial Indicators",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Financial Indicators": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Data for AI": {
      "main": [
        [
          {
            "node": "AI Agent - Financial Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent - Financial Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent - Financial Analysis": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent - Financial Analysis",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "IF Requiere Alerta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Requiere Alerta": {
      "main": [
        [
          {
            "node": "Filter Critical Alerts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Critical Alerts": {
      "main": [
        [
          {
            "node": "Aggregate Alerts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate Alerts": {
      "main": [
        [
          {
            "node": "Generate HTML Report",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get Grafana Dashboard",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate HTML Report": {
      "main": [
        [
          {
            "node": "Send Alert Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Grafana Dashboard": {
      "main": [
        [
          {
            "node": "Update Grafana Dashboard",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save to Database": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Save to Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Format Data for AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "createdAt": "2025-11-21T00:04:20.960Z",
  "id": "cPCCC18A3ledR7z5",
  "isArchived": false,
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "ERM Financiero Consolidado",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 6 * * *"
            }
          ]
        }
      },
      "id": "31cc5dbb-1874-4601-bb7a-8ccc03f89d5a",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -2720,
        -80
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT f.id_filial, f.nombre, SUM(CASE WHEN t.tipo_transaccion = 'ingreso' THEN t.monto ELSE 0 END) AS ingresos, SUM(CASE WHEN t.tipo_transaccion = 'egreso' THEN t.monto ELSE 0 END) AS egresos FROM filiales f LEFT JOIN transacciones_erp t ON f.id_filial = t.id_filial AND DATE_TRUNC('month', t.fecha_transaccion) = DATE_TRUNC('month', CURRENT_DATE) GROUP BY f.id_filial, f.nombre",
        "options": {}
      },
      "id": "e1628df7-ed1a-4046-8f71-b77748750949",
      "name": "Fetch Transacciones ERP",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        -2496,
        -176
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT id_filial, volumen_producido_m3, volumen_facturado_m3, porcentaje_perdida, costo_estimado_perdida FROM perdidas_agua WHERE fecha_registro >= CURRENT_DATE - INTERVAL '30 days'",
        "options": {}
      },
      "id": "7d624ba7-4a09-4ea6-93cb-b2e7a9698394",
      "name": "Fetch P\u00e9rdidas Agua",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        -2496,
        16
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "combine",
        "fieldsToMatchString": "id_filial",
        "options": {}
      },
      "id": "19419444-cfdd-47bf-9e07-c643a0ec91bd",
      "name": "Merge Datasets",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [
        -2304,
        -64
      ]
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\n\nconst processed = items.map(item => {\n  const data = item.json;\n  \n  const utilidad_neta = (data.ingresos || 0) - (data.egresos || 0);\n  const margen_operativo = data.ingresos > 0 ? ((utilidad_neta / data.ingresos) * 100).toFixed(2) : 0;\n  const eficiencia_facturacion = data.volumen_producido_m3 > 0 ? ((data.volumen_facturado_m3 / data.volumen_producido_m3) * 100).toFixed(2) : 0;\n  const alerta_presupuesto = Math.abs(data.desviacion || 0) > (data.monto_presupuestado || 0) * 0.15 ? 'CR\u00cdTICO' : 'NORMAL';\n\n  return {\n    json: {\n      ...data,\n      utilidad_neta,\n      margen_operativo,\n      eficiencia_facturacion,\n      alerta_presupuesto,\n      fecha_calculo: new Date().toISOString().split('T')[0]\n    }\n  };\n});\n\nreturn processed;"
      },
      "id": "f63e60b8-b396-48a5-8b4c-7f897dc4b712",
      "name": "Calculate Financial Indicators",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -2064,
        -64
      ]
    },
    {
      "parameters": {
        "jsCode": "function formatJSON(arr) {\n  return JSON.stringify(arr, null, 2).replace(/\\\\\"/g, '\"');\n}\n\nconst unified = formatJSON($input.first().json.data);\n\nreturn [{ json: { unified } }];"
      },
      "id": "4cc18b97-8837-49ee-b964-27faf30ab2fc",
      "name": "Format Data for AI",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1344,
        -160
      ]
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "typeVersion": 1,
      "position": [
        -1120,
        -368
      ],
      "id": "40224a81-dbf1-47de-9774-525a11da377e",
      "name": "Google Gemini Chat Model",
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Eres un Analista Financiero Senior especializado en gesti\u00f3n de empresas de servicios p\u00fablicos de agua. Tu responsabilidad es evaluar la salud financiera y operativa de filiales y generar alertas tempranas sobre riesgos cr\u00edticos.\n\nAnaliza los siguientes indicadores financieros consolidados de las filiales de Aqualia:\n\n{{ JSON.stringify($json) }}\n\n### Criterios para clasificar como RIESGO FINANCIERO (requiere_alerta: true):\n\n* Margen operativo < 15% indica baja rentabilidad\n* P\u00e9rdida de agua > 35% representa ineficiencia cr\u00edtica\n* Desviaci\u00f3n presupuestal > 15% del monto presupuestado\n* Eficiencia de facturaci\u00f3n < 85%\n* Utilidad neta negativa por m\u00e1s de 2 meses consecutivos\n* Costo de agua perdida > 20% de los ingresos totales\n\n### Criterios para clasificar como OPERACI\u00d3N NORMAL (requiere_alerta: false):\n\n* Indicadores dentro de rangos aceptables\n* Variaciones explicables por estacionalidad\n* Tendencias positivas en eficiencia\n\n**Responde \u00daNICAMENTE con un array JSON v\u00e1lido. No incluyas texto antes ni despu\u00e9s.**\n\nEl formato exacto es:\n\n[\n  {\n    \"id_filial\": <number>,\n    \"nombre_filial\": \"<string>\",\n    \"requiere_alerta\": <true|false>,\n    \"nivel_riesgo\": \"<BAJO|MEDIO|ALTO|CR\u00cdTICO>\",\n    \"analisis_detallado\": \"<texto explicativo>\",\n    \"recomendaciones\": \"<acciones sugeridas>\"\n  }\n]",
        "hasOutputParser": true,
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3,
      "position": [
        -1120,
        -160
      ],
      "id": "ded82908-3fd1-413d-8e38-bb5191f6f354",
      "name": "AI Agent - Financial Analysis"
    },
    {
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"type\": \"array\",\n  \"items\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"id_filial\": { \"type\": \"number\" },\n      \"nombre_filial\": { \"type\": \"string\" },\n      \"requiere_alerta\": { \"type\": \"boolean\" },\n      \"nivel_riesgo\": { \"type\": \"string\" },\n      \"analisis_detallado\": { \"type\": \"string\" },\n      \"recomendaciones\": { \"type\": \"string\" }\n    },\n    \"required\": [\"id_filial\", \"nombre_filial\", \"requiere_alerta\", \"nivel_riesgo\", \"analisis_detallado\", \"recomendaciones\"],\n    \"additionalProperties\": false\n  }\n}"
      },
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "typeVersion": 1.3,
      "position": [
        -976,
        -368
      ],
      "id": "fecd1ebc-0dc8-4d5d-befb-98e8ce8a4a4b",
      "name": "Structured Output Parser"
    },
    {
      "parameters": {
        "fieldToSplitOut": "output",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        -704,
        -160
      ],
      "id": "0ee43343-1ae8-47f7-aa3b-f3ecb78e0200",
      "name": "Split Out"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 2
          },
          "conditions": [
            {
              "id": "25874bfc-d965-4a09-8e97-a9f45d9d0110",
              "leftValue": "={{ $json.requiere_alerta }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        -496,
        -160
      ],
      "id": "6d4eb638-261c-4292-a5d6-4bf27e9bc953",
      "name": "IF Requiere Alerta"
    },
    {
      "parameters": {
        "jsCode": "const items = $input.all();\n\nlet alertas = [];\n\nfor (const item of items) {\n    const data = item.json;\n\n    if (data.requiere_alerta === true) {\n        alertas.push({\n            id_filial: data.id_filial,\n            nombre_filial: data.nombre_filial,\n            nivel_riesgo: data.nivel_riesgo,\n            analisis_detallado: data.analisis_detallado,\n            recomendaciones: data.recomendaciones\n        });\n    }\n}\n\nreturn alertas.map(a => ({ json: a }));"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -288,
        -176
      ],
      "id": "bb41a2fa-ef53-4e8c-bcd5-cfedf6119dc1",
      "name": "Filter Critical Alerts"
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      },
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        -80,
        -176
      ],
      "id": "605bb882-00aa-40e6-90bf-33356519c3b2",
      "name": "Aggregate Alerts"
    },
    {
      "parameters": {
        "html": "=<html>\n  <body style=\"font-family: Arial, sans-serif; background-color:#f4f8fb; padding: 20px; color:#003049;\">\n    <div style=\"max-width: 800px; margin: auto; background: #ffffff; padding: 25px; border-radius: 8px; border: 1px solid #dce6ee;\">\n      \n      <h2 style=\"color:#005f99; margin-bottom: 10px; font-weight: 600;\">\n        Alerta Financiera - ERM\n      </h2>\n      \n      <p style=\"font-size: 15px; color:#003049; line-height: 1.5;\">\n        Se han detectado filiales con indicadores financieros cr\u00edticos que requieren atenci\u00f3n inmediata.\n      </p>\n\n      <div style=\"margin-top: 25px;\">\n        {{\n          $input.all().map(i => i.json.data).flat().map(item => `\n            <div style=\"\n              border-left: 4px solid ${\n                item.nivel_riesgo === 'CR\u00cdTICO' ? '#dc3545' :\n                item.nivel_riesgo === 'ALTO' ? '#fd7e14' :\n                item.nivel_riesgo === 'MEDIO' ? '#ffc107' : '#4bb3fd'\n              };\n              padding: 15px;\n              margin-bottom: 20px;\n              background: #f0f7fc;\n              border-radius: 6px;\n            \">\n              <strong style=\"font-size: 16px; color:#003049;\">\n                ${item.nombre_filial} (ID: ${item.id_filial})\n              </strong>\n              <p style=\"margin: 8px 0; font-size: 14px; color:#dc3545; font-weight: bold;\">\n                Nivel de Riesgo: ${item.nivel_riesgo}\n              </p>\n              <p style=\"margin: 8px 0; font-size: 14px; color:#003049;\">\n                <strong>An\u00e1lisis:</strong> ${item.analisis_detallado}\n              </p>\n              <p style=\"margin: 8px 0; font-size: 14px; color:#005f99;\">\n                <strong>Recomendaciones:</strong> ${item.recomendaciones}\n              </p>\n            </div>\n          `).join(\"\")\n        }}\n      </div>\n\n      <p style=\"margin-top: 30px; font-size: 13px; color:#6c7a86; text-align: center;\">\n        Este es un reporte autom\u00e1tico generado por el sistema ERM con an\u00e1lisis de IA.\n      </p>\n\n    </div>\n  </body>\n</html>"
      },
      "type": "n8n-nodes-base.html",
      "typeVersion": 1.2,
      "position": [
        128,
        -176
      ],
      "id": "d4ac0dc7-4dcf-4620-827b-d33492792710",
      "name": "Generate HTML Report"
    },
    {
      "parameters": {
        "fromEmail": "andresfelipecalderonramirez@gmail.com",
        "toEmail": "=andres.calderon-r@mail.escuelaing.edu.co, santiago.botero-g@mail.escuelaing.edu.co, ricardo.ayala-g@mail.escuelaing.edu.co, santiago.amaya-z@mail.escuelaing.edu.co, laura.perilla-q@mail.escuelaing.edu.co",
        "subject": "Alerta Financiera Cr\u00edtica - Aqualia",
        "html": "={{ $json.html }}",
        "options": {}
      },
      "type": "n8n-nodes-base.emailSend",
      "typeVersion": 2.1,
      "position": [
        336,
        -176
      ],
      "id": "1dfe28ac-da87-429e-835c-47ebd605cf14",
      "name": "Send Alert Email",
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "get",
        "dashboardUidOrUrl": "https://andrescalderonr.grafana.net/d/anzptgl/aquasense"
      },
      "type": "n8n-nodes-base.grafana",
      "typeVersion": 1,
      "position": [
        128,
        16
      ],
      "id": "347e7896-e61a-4c37-9334-e09edcdf11f3",
      "name": "Get Grafana Dashboard",
      "credentials": {
        "grafanaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://andrescalderonr.grafana.net/api/dashboards/db",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "grafanaApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"meta\": {{ JSON.stringify(Object.assign({}, $json.meta, { version: $json.meta.version - 1 })) }},\n  \"dashboard\": {{ JSON.stringify(Object.assign({}, $json.dashboard, { version: $json.dashboard.version - 1 })) }},\n  \"overwrite\": true\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        336,
        16
      ],
      "id": "60f5a4fb-ff20-4343-b15c-1bc1511be494",
      "name": "Update Grafana Dashboard",
      "credentials": {
        "grafanaApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "schema": {
          "__rl": true,
          "value": "public",
          "mode": "list"
        },
        "table": {
          "__rl": true,
          "value": "indicadores_financieros",
          "mode": "list"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "id_filial": "={{ $json.id_filial }}",
            "fecha_calculo": "={{ $json.fecha_calculo }}",
            "ingresos_totales": "={{ $json.ingresos }}",
            "egresos_totales": "={{ $json.egresos }}",
            "margen_operativo": "={{ $json.margen_operativo }}",
            "costo_agua_perdida": "={{ $json.costo_estimado_perdida }}",
            "eficiencia_facturacion": "={{ $json.eficiencia_facturacion }}",
            "roi_digitalizacion": 0
          },
          "matchingColumns": [
            "id_indicador"
          ],
          "schema": [
            {
              "id": "id_indicador",
              "displayName": "id_indicador",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "id_filial",
              "displayName": "id_filial",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "fecha_calculo",
              "displayName": "fecha_calculo",
              "required": true,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true
            },
            {
              "id": "ingresos_totales",
              "displayName": "ingresos_totales",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "egresos_totales",
              "displayName": "egresos_totales",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "margen_operativo",
              "displayName": "margen_operativo",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "costo_agua_perdida",
              "displayName": "costo_agua_perdida",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "eficiencia_facturacion",
              "displayName": "eficiencia_facturacion",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true
            },
            {
              "id": "roi_digitalizacion",
              "displayName": "roi_digitalizacion",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "number",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "created_at",
              "displayName": "created_at",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "dateTime",
              "canBeUsedToMatch": true,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "id": "5ea199e3-5bce-4b55-b822-478f1258b52b",
      "name": "Save to Database",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.5,
      "position": [
        -1584,
        16
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "options": {}
      },
      "type": "n8n-nodes-base.splitInBatches",
      "typeVersion": 3,
      "position": [
        -1792,
        -64
      ],
      "id": "f60c557f-2099-4b46-9edf-16a37f0e3563",
      "name": "Loop Over Items"
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      },
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        -1584,
        -160
      ],
      "id": "e88e8322-695f-4bf3-b1b0-2528daf7a729",
      "name": "Aggregate"
    }
  ],
  "settings": {
    "executionOrder": "v1"
  },
  "shared": [
    {
      "updatedAt": "2025-11-21T00:04:20.971Z",
      "createdAt": "2025-11-21T00:04:20.971Z",
      "role": "workflow:owner",
      "workflowId": "cPCCC18A3ledR7z5",
      "projectId": "xno20arzPonor2IK"
    }
  ],
  "staticData": null,
  "tags": [
    {
      "updatedAt": "2025-12-06T23:02:14.399Z",
      "createdAt": "2025-12-06T23:01:34.502Z",
      "id": "EOtNswDwaWouZBrL",
      "name": "ERM"
    }
  ],
  "triggerCount": 0,
  "updatedAt": "2025-12-15T06:02:09.681Z",
  "versionId": "ea16139f-a81b-4930-87b0-ebf1b940190e"
}