{
  "name": "容量規劃與趨勢分析",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8 1 * *"
            }
          ]
        }
      },
      "id": "schedule",
      "name": "每月 1 日 08:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [240, 300]
    },
    {
      "parameters": {
        "url": "https://mo.wooo.work/api/system/db/stats",
        "options": { "timeout": 30000 }
      },
      "id": "uat-db-stats",
      "name": "UAT DB 統計",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [460, 200],
      "continueOnFail": true
    },
    {
      "parameters": {
        "url": "https://momo.wooo.work/api/system/db/stats",
        "options": { "timeout": 30000 }
      },
      "id": "gcp-db-stats",
      "name": "GCP DB 統計",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [460, 400],
      "continueOnFail": true
    },
    {
      "parameters": {
        "mode": "combine",
        "combineBy": "combineAll",
        "options": {}
      },
      "id": "merge",
      "name": "合併結果",
      "type": "n8n-nodes-base.merge",
      "typeVersion": 3,
      "position": [680, 300]
    },
    {
      "parameters": {
        "jsCode": "const results = $input.all();\nconst now = new Date();\nconst monthKey = now.toISOString().slice(0, 7);\n\n// 從 static data 讀取歷史數據\nconst history = $getWorkflowStaticData('global');\nif (!history.monthly) {\n  history.monthly = [];\n}\n\nconst uatStats = results[0]?.json || {};\nconst gcpStats = results[1]?.json || {};\n\n// 記錄本月數據\nhistory.monthly.push({\n  month: monthKey,\n  uat: {\n    dbSize: uatStats.database_size_mb || 0,\n    connections: uatStats.connection_count || 0,\n    tableCount: uatStats.table_count || 0\n  },\n  gcp: {\n    dbSize: gcpStats.database_size_mb || 0,\n    connections: gcpStats.connection_count || 0,\n    tableCount: gcpStats.table_count || 0\n  }\n});\n\n// 保留最近 12 個月\nif (history.monthly.length > 12) {\n  history.monthly.shift();\n}\n\n// 計算成長趨勢\nconst monthsData = history.monthly;\nlet uatGrowthRate = 0;\nlet gcpGrowthRate = 0;\nlet uatPrediction = 0;\nlet gcpPrediction = 0;\n\nif (monthsData.length >= 2) {\n  const lastMonth = monthsData[monthsData.length - 2];\n  const thisMonth = monthsData[monthsData.length - 1];\n  \n  if (lastMonth.uat.dbSize > 0) {\n    uatGrowthRate = ((thisMonth.uat.dbSize - lastMonth.uat.dbSize) / lastMonth.uat.dbSize * 100).toFixed(1);\n    // 預測 6 個月後的大小\n    uatPrediction = (thisMonth.uat.dbSize * Math.pow(1 + parseFloat(uatGrowthRate) / 100, 6)).toFixed(0);\n  }\n  \n  if (lastMonth.gcp.dbSize > 0) {\n    gcpGrowthRate = ((thisMonth.gcp.dbSize - lastMonth.gcp.dbSize) / lastMonth.gcp.dbSize * 100).toFixed(1);\n    gcpPrediction = (thisMonth.gcp.dbSize * Math.pow(1 + parseFloat(gcpGrowthRate) / 100, 6)).toFixed(0);\n  }\n}\n\n// 容量警告閾值\nconst DB_SIZE_WARNING = 8000; // 8GB\nconst DB_SIZE_CRITICAL = 9000; // 9GB\n\nconst uatWarning = (uatStats.database_size_mb || 0) > DB_SIZE_WARNING;\nconst gcpWarning = (gcpStats.database_size_mb || 0) > DB_SIZE_WARNING;\nconst uatPredictionWarning = parseFloat(uatPrediction) > DB_SIZE_CRITICAL;\nconst gcpPredictionWarning = parseFloat(gcpPrediction) > DB_SIZE_CRITICAL;\n\nreturn [{\n  json: {\n    uat: {\n      currentSize: (uatStats.database_size_mb || 0) + ' MB',\n      growthRate: uatGrowthRate + '%',\n      prediction6m: uatPrediction + ' MB',\n      warning: uatWarning,\n      predictionWarning: uatPredictionWarning\n    },\n    gcp: {\n      currentSize: (gcpStats.database_size_mb || 0) + ' MB',\n      growthRate: gcpGrowthRate + '%',\n      prediction6m: gcpPrediction + ' MB',\n      warning: gcpWarning,\n      predictionWarning: gcpPredictionWarning\n    },\n    historyMonths: monthsData.length,\n    hasWarning: uatWarning || gcpWarning || uatPredictionWarning || gcpPredictionWarning\n  }\n}];"
      },
      "id": "analyze",
      "name": "分析趨勢",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [900, 300]
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst now = new Date().toLocaleString('zh-TW', { timeZone: 'Asia/Taipei' });\n\nlet message = `📈 <b>每月容量規劃報告</b>\\n\\n`;\n\nmessage += `<b>🟦 UAT 環境</b>\\n`;\nmessage += `├ 目前大小: ${data.uat.currentSize}\\n`;\nmessage += `├ 月成長率: ${data.uat.growthRate}\\n`;\nmessage += `├ 6 個月預測: ${data.uat.prediction6m}\\n`;\nif (data.uat.warning) {\n  message += `└ ⚠️ 警告：接近容量上限\\n`;\n} else if (data.uat.predictionWarning) {\n  message += `└ ⚠️ 預測：6 個月內可能超過容量\\n`;\n} else {\n  message += `└ ✅ 容量正常\\n`;\n}\n\nmessage += `\\n<b>🟥 GCP 環境</b>\\n`;\nmessage += `├ 目前大小: ${data.gcp.currentSize}\\n`;\nmessage += `├ 月成長率: ${data.gcp.growthRate}\\n`;\nmessage += `├ 6 個月預測: ${data.gcp.prediction6m}\\n`;\nif (data.gcp.warning) {\n  message += `└ ⚠️ 警告：接近容量上限\\n`;\n} else if (data.gcp.predictionWarning) {\n  message += `└ ⚠️ 預測：6 個月內可能超過容量\\n`;\n} else {\n  message += `└ ✅ 容量正常\\n`;\n}\n\nmessage += `\\n📊 歷史數據: ${data.historyMonths} 個月\\n`;\nmessage += `⏰ 報告時間: ${now}`;\n\nreturn [{ json: { message } }];"
      },
      "id": "format-report",
      "name": "格式化報告",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [1120, 300]
    },
    {
      "parameters": {
        "url": "https://api.telegram.org/bot8075645931:AAH-EGKMo8ZC4QJs-Nc1_0s92xHrGdQvdpg/sendMessage",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"chat_id\": \"5619078117\",\n  \"parse_mode\": \"HTML\",\n  \"text\": \"{{ $json.message }}\"\n}",
        "options": {}
      },
      "id": "telegram",
      "name": "發送報告",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [1340, 300]
    }
  ],
  "connections": {
    "每月 1 日 08:00": {
      "main": [
        [
          { "node": "UAT DB 統計", "type": "main", "index": 0 },
          { "node": "GCP DB 統計", "type": "main", "index": 0 }
        ]
      ]
    },
    "UAT DB 統計": {
      "main": [
        [{ "node": "合併結果", "type": "main", "index": 0 }]
      ]
    },
    "GCP DB 統計": {
      "main": [
        [{ "node": "合併結果", "type": "main", "index": 1 }]
      ]
    },
    "合併結果": {
      "main": [
        [{ "node": "分析趨勢", "type": "main", "index": 0 }]
      ]
    },
    "分析趨勢": {
      "main": [
        [{ "node": "格式化報告", "type": "main", "index": 0 }]
      ]
    },
    "格式化報告": {
      "main": [
        [{ "node": "發送報告", "type": "main", "index": 0 }]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 0,
  "updatedAt": "2026-02-07T17:00:00.000Z",
  "versionId": "1"
}
