{
  "meta": {
    "instanceId": "608063c199ef9befaee7d009cae64cabedc72960a786e69676f755ea2cde6bfa",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "1c7353fe-71c5-4856-91b5-c7ce0603cbf3",
      "name": "README",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        157456,
        94896
      ],
      "parameters": {
        "width": 900,
        "height": 3392,
        "content": "# Invoice Budget Tracker\n\nAuto-categorize business invoices and track spending vs budget with AI alerts.\n\n## Quick Start Guide\n\n## 1. Setup Google Drive\n### 1.1 Create Google OAuth credentials\n- https://docs.n8n.io/integrations/builtin/credentials/google/\n\n### 1.2 Folder structure:\n- `/Invoices/` - configure GetFiles node to watch this folder\n- `/Invoices/2026-01/` - auto-created monthly subfolders\n- Failed files get `[REVIEW] - ` prefix (stay in folder)\n- Duplicates get `[DUPLICATE] - ` prefix (stay in folder)\n\n### 1.3 Setup Google Drive OAuth credentials:\n- DownloadInvoice\n- GetFiles\n- RenameFile\n- SearchMonthFolder\n- CreateMonthFolder\n- MoveToMonth\n- RenameToReview\n- RenameAsDuplicate\n\n## 2. Setup Telegram\n### 2.1 Create Telegram Bot\n- https://blog.n8n.io/create-telegram-bot/\n\n### 2.2 Setup Telegram Credentials:\n- BudgetTrigger\n- AlertMessage\n- ErrorAlert\n- SuccessLog\n- DuplicateLog\n- BudgetReply\n- WelcomeMessage\n- NotAuthorizedMessage\n- WeeklySummaryMessage\n- MonthlySummaryMessage\n\n## 3. Setup OpenRouter\n### 3.1 Create API Key\n- https://docs.n8n.io/integrations/builtin/credentials/openrouter/\n\n### 3.2 Setup AI Credentials:\n- Gpt4oCategorizer\n- Gpt4oBudgetAgent\n\n## 4. Setup Ainoflow\n### 4.1 Create API Key\n- https://www.ainoflow.io/signup\n\n### 4.2 Setup HTTP Bearer Credentials:\n- OcrExtract\n- CheckInvoiceExists\n- SaveInvoice\n- GetBudgets\n- GetSummary\n- SaveSummary\n- GetWeeklySummary\n- GetMonthlySummary\n- GetAppSettings (×3 nodes)\n- GetAppConfig2\n- SaveAppSettings\n- ForEachCategory\n- ForEachCategoryItem\n- DeleteItem\n\n### 4.3 Setup MCP Bearer Credentials:\n- JsonStorageMcp\n\n## 5. First Time Setup (REQUIRED)\n⚠️ You MUST send /start before using any other commands!\n\n1. Send `/start` to your Telegram bot\n2. Bot registers your chat_id and settings\n3. Only you can use this bot instance\n4. All other commands require /start first\n\n## 6. How to use\n\n### 6.1. Invoice Processing\n- Drop invoice PDF/image to watched folder\n- Workflow runs hourly (HourlyTrigger)\n- Automatic OCR extraction via Ainoflow\n- AI categorization (Software, Marketing, etc.)\n- Budget alerts when category ≥80%\n- File renamed: `[date] - Vendor (amount).ext`\n- Moved to monthly folder\n\n### 6.2. Telegram Notifications\n- ✅ Success: vendor, amount, category, file path\n- 📋 Duplicate: filename renamed with [DUPLICATE] prefix\n- ⚠️ Error: filename renamed with [REVIEW] prefix\n- 🔔 Budget Alert: category at ≥80%\n\n### 6.3. Budget Management (Telegram)\n- \"Set budget Software 500\" - set budget\n- \"Show budgets\" - list all budgets\n- \"Budget status\" - show spent vs budget\n- \"Remove Travel budget\" - delete budget\n\n### 6.4. Scheduled Reports\n- **Weekly** (Fridays): Current month progress\n- **Monthly** (10th): Previous month summary\n\n## 7. Customization\n\n### Categories (Budget Agent section):\nEdit **SetDefaults** node → `allowed_categories`\nThen re-register bot (/start) to apply changes\n\n### Processing (Invoice Processing section):\nEdit **WorkflowConfig** node:\n- `alert_threshold` - budget alert % (default: 80)\n- `review_prefix` - failed files prefix\n- `duplicate_prefix` - duplicate files prefix\n\n## 8. Data Reset\n⚠️ Deletes ALL invoice data from Ainoflow Storage!\n\n1. Click ManualResetTrigger → Test Workflow\n2. Approve deletion when prompted\n3. All invoice-* categories will be removed\n\n## 9. Need help?\nContact: https://ainovasystems.com/"
      },
      "typeVersion": 1
    },
    {
      "id": "77376161-4a33-4f2a-92bd-febc5d521630",
      "name": "Budget Agent",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158384,
        96528
      ],
      "parameters": {
        "color": 5,
        "width": 3092,
        "height": 676,
        "content": "## 2. Budget Management AI Agent\nTelegram-based budget configuration via AI Agent + MCP Storage"
      },
      "typeVersion": 1
    },
    {
      "id": "bb80a7e2-993f-450a-9cbe-7f2fbf9208b7",
      "name": "Weekly Summary",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158384,
        97232
      ],
      "parameters": {
        "color": 5,
        "width": 1660,
        "height": 428,
        "content": "## 3. Weekly Budget Check\nWeekly check on current month's budget progress (every Friday)"
      },
      "typeVersion": 1
    },
    {
      "id": "40784f04-0883-487c-8774-aabcd1727f50",
      "name": "DownloadInvoice",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        160112,
        95248
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('LoopInput').item.json.id }}"
        },
        "options": {},
        "operation": "download"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Lx8EZLOwmZuUPE9f",
          "name": "GoogleOAuth"
        }
      },
      "executeOnce": false,
      "typeVersion": 3
    },
    {
      "id": "f032ae09-11e3-499c-9d8c-b68713247533",
      "name": "CheckInvoiceExists",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        158672,
        96096
      ],
      "parameters": {
        "url": "=https://api.ainoflow.io/api/v1/storage/json/{{ $('StorageInput').item.json.storage_category }}/{{ $('StorageInput').item.json.input_file_hash }}",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "allowEmpty",
              "value": "true"
            }
          ]
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "1335f683-10ca-40c2-aa06-34475db9a604",
      "name": "IfNewInvoice",
      "type": "n8n-nodes-base.if",
      "position": [
        158880,
        96096
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "check-empty",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ Object.keys($json).length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "3b95acab-3f78-4e0e-9826-526276eae440",
      "name": "OcrExtract",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        160336,
        95152
      ],
      "parameters": {
        "url": "https://api.ainoflow.io/api/v1/convert/submit-file",
        "method": "POST",
        "options": {},
        "sendBody": true,
        "contentType": "multipart-form-data",
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "languages",
              "value": "en,de,pt"
            },
            {
              "name": "outputs",
              "value": "text"
            },
            {
              "name": "response",
              "value": "direct"
            },
            {
              "name": "file",
              "parameterType": "formBinaryData",
              "inputDataFieldName": "data"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "3e1df0bc-78c4-4c45-b687-c68fba448845",
      "name": "IfOcrSuccess",
      "type": "n8n-nodes-base.if",
      "position": [
        160928,
        95248
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "check-ocr-success",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.invoice_ocr_text }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "e040e1b9-d74b-4427-aa5a-8d23ace1da24",
      "name": "GetBudgets",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        161312,
        95168
      ],
      "parameters": {
        "url": "https://api.ainoflow.io/api/v1/storage/json/invoice-config/budgets",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "allowEmpty",
              "value": "true"
            }
          ]
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "2af3851b-e42b-4397-9108-aa6637eaf058",
      "name": "Gpt4oCategorizer",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        161712,
        95536
      ],
      "parameters": {
        "model": "openai/gpt-4o",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "id": "qbnEUslOR5kCNftL",
          "name": "Openrouter"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "613ec53d-c9d5-4dc7-9455-ec4544fc2baf",
      "name": "SaveInvoice",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        159152,
        96000
      ],
      "parameters": {
        "url": "=https://api.ainoflow.io/api/v1/storage/json/{{ $('StorageInput').item.json.storage_category }}/{{ $('StorageInput').item.json.input_file_hash }}",
        "method": "PUT",
        "options": {},
        "jsonBody": "={\n  \"vendor\": {{ JSON.stringify($('AICategorizer').item.json.output.vendor) }},\n  \"vendor_normalized\": {{ JSON.stringify($('AICategorizer').item.json.output.vendor_normalized || $('AICategorizer').item.json.output.vendor) }},\n  \"amount\": {{ $('AICategorizer').item.json.output.amount }},\n  \"currency\": \"{{ $('AICategorizer').item.json.output.currency }}\",\n  \"date\": \"{{ $('AICategorizer').item.json.output.date }}\",\n  \"invoice_number\": \"{{ $('AICategorizer').item.json.output.invoice_number || '' }}\",\n  \"category\": \"{{ $('AICategorizer').item.json.output.category }}\",\n  \"file_id\": \"{{ $('StorageInput').item.json.input_file_id }}\",\n  \"processed_at\": \"{{ $now.toISO() }}\"\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "b06d1994-4670-4e12-a45d-e4e087cb6160",
      "name": "GetSummary",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        159376,
        96000
      ],
      "parameters": {
        "url": "=https://api.ainoflow.io/api/v1/storage/json/invoice-summary-{{ $('AICategorizer').item.json.output.date.substring(0, 7) }}/totals",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "allowEmpty",
              "value": "true"
            }
          ]
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "d894c7fd-da95-4c47-b3fc-01760ff54e1a",
      "name": "SaveSummary",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        160048,
        96000
      ],
      "parameters": {
        "url": "=https://api.ainoflow.io/api/v1/storage/json/{{ $('SummaryInput').item.json.summary_category }}/totals",
        "method": "PUT",
        "options": {},
        "jsonBody": "={{ JSON.stringify($('SummaryInput').item.json.summary) }}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "c4aa4e6f-14a5-4f08-a5cf-7b0a77570dc7",
      "name": "IfNeedsAlert",
      "type": "n8n-nodes-base.if",
      "position": [
        160288,
        96000
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "check-alert-needed",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $('SummaryInput').item.json.needs_alert }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2cffc820-7e18-41b2-8a13-0b0479b4f8a7",
      "name": "AlertMessage",
      "type": "n8n-nodes-base.telegram",
      "position": [
        160512,
        95984
      ],
      "webhookId": "3864f591-c866-4eea-aed1-91d19a2b9a0e",
      "parameters": {
        "text": "=⚠️ *Budget Alert*\n\n*{{ $('SummaryInput').item.json.invoice.category }}* is {{ $('SummaryInput').item.json.budget_status.pct }}% of monthly budget\n\n📅 *Period:* {{ $('StorageInput').item.json.invoice_month }}\n\nSpent: €{{ $('SummaryInput').item.json.budget_status.spent }}\nBudget: €{{ $('SummaryInput').item.json.budget_status.budget }}\n\n*Latest invoice:*\n{{ $('SummaryInput').item.json.invoice.vendor_normalized || $('SummaryInput').item.json.invoice.vendor }}: €{{ $('SummaryInput').item.json.invoice.amount }}\nDate: {{ $('SummaryInput').item.json.invoice.date }}\n\n[View invoice](https://drive.google.com/file/d/{{ $('SummaryInput').item.json.file_info.input_file_id }}/view)",
        "chatId": "={{ $('WorkflowConfig').item.json.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "96484f33-8cea-4495-a297-39de4d2c871f",
      "name": "RenameFile",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        160288,
        96304
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('SummaryInput').item.json.file_info.input_file_id }}"
        },
        "options": {},
        "operation": "update",
        "newUpdatedFileName": "={{ $('SummaryInput').item.json.file_info.new_filename }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Lx8EZLOwmZuUPE9f",
          "name": "GoogleOAuth"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "f56074bc-60e2-4d47-aa80-579d0f855cec",
      "name": "SearchMonthFolder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        160608,
        96304
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "id",
            "value": "={{ $('SummaryInput').item.json.file_info.input_folder_id }}"
          },
          "whatToSearch": "folders"
        },
        "options": {},
        "resource": "fileFolder",
        "queryString": "={{ $('SummaryInput').item.json.file_info.month_folder }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Lx8EZLOwmZuUPE9f",
          "name": "GoogleOAuth"
        }
      },
      "typeVersion": 3,
      "alwaysOutputData": true
    },
    {
      "id": "354e6a3e-d173-4133-a199-05364605905f",
      "name": "IfFolderExists",
      "type": "n8n-nodes-base.if",
      "position": [
        160832,
        96304
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "folder-exists-condition",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6301903e-1e50-48c3-8ba1-2e7f15c6306e",
      "name": "CreateMonthFolder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        161056,
        96304
      ],
      "parameters": {
        "name": "={{ $('SummaryInput').item.json.file_info.month_folder }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('SummaryInput').item.json.file_info.input_folder_id }}"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Lx8EZLOwmZuUPE9f",
          "name": "GoogleOAuth"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "eae48e84-547e-4bc5-865d-e0cfd700b0a3",
      "name": "MoveToMonth",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        161520,
        96000
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('SummaryInput').item.json.file_info.input_file_id }}"
        },
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('ResultFolder').item.json.target_folder_id }}"
        },
        "operation": "move"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Lx8EZLOwmZuUPE9f",
          "name": "GoogleOAuth"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "8e1a79e1-a557-40d2-ac08-9653d42cd915",
      "name": "SuccessLog",
      "type": "n8n-nodes-base.telegram",
      "position": [
        161856,
        96000
      ],
      "webhookId": "success-log-webhook",
      "parameters": {
        "text": "=✅ {{ $('SummaryInput').item.json.invoice.vendor_normalized || $('SummaryInput').item.json.invoice.vendor }} €{{ $('SummaryInput').item.json.invoice.amount }} ({{ $('SummaryInput').item.json.invoice.category }})\n📁 {{ $('SummaryInput').item.json.file_info.month_folder }}/{{ $('SummaryInput').item.json.file_info.new_filename }}",
        "chatId": "={{ $('WorkflowConfig').item.json.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a2963aae-e11d-4db6-83ee-80e8f0ec15ca",
      "name": "ErrorAlert",
      "type": "n8n-nodes-base.telegram",
      "position": [
        161440,
        95568
      ],
      "webhookId": "dffa753e-bc6c-4a6d-b67b-4e3fbd7460e2",
      "parameters": {
        "text": "=⚠️ *Invoice Processing Failed*\n\nFile: {{ $('InputFile').item.json.input_file_filename }}\n\nRenamed with [REVIEW] prefix for manual processing. {{ $('IfInvalidContent').item.json.output.skip_reason }}.\n\n[View file](https://drive.google.com/file/d/{{ $('InputFile').item.json.input_file_id }}/view)",
        "chatId": "={{ $('WorkflowConfig').item.json.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "8a87dce0-e94e-4a3a-9def-4fa381223f0c",
      "name": "BudgetTrigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        158496,
        96752
      ],
      "webhookId": "budget-trigger-webhook",
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {
          "download": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "97e829f9-d398-42a4-a3c7-3b6cacd022e7",
      "name": "IfFirstRun",
      "type": "n8n-nodes-base.if",
      "position": [
        158912,
        96752
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-first-run",
              "operator": {
                "type": "number",
                "operation": "notExists",
                "singleValue": true
              },
              "leftValue": "={{ $('GetAppSettings1').item.json.chat_id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "428a2867-8c88-40d5-af32-b9665517e0a3",
      "name": "SaveAppSettings",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        160064,
        96736
      ],
      "parameters": {
        "url": "https://api.ainoflow.io/api/v1/storage/json/invoice-config/settings",
        "method": "PUT",
        "options": {},
        "sendBody": true,
        "authentication": "genericCredentialType",
        "bodyParameters": {
          "parameters": [
            {
              "name": "chat_id",
              "value": "={{ $('BudgetTrigger').item.json.message.chat.id }}"
            },
            {
              "name": "registered_at",
              "value": "={{ $now.toISO() }}"
            },
            {
              "name": "allowed_categories",
              "value": "={{ $('SetDefaults').item.json.allowed_categories }}"
            }
          ]
        },
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "8556410e-40fb-4f4a-b834-4f62c3482dfe",
      "name": "NotAuthorizedMessage",
      "type": "n8n-nodes-base.telegram",
      "position": [
        159152,
        96992
      ],
      "webhookId": "5836604e-1466-43d8-9371-352284177f83",
      "parameters": {
        "text": "🚫 *Access Denied*\n\nThis bot is already registered to another user.\n\nEach bot instance is personal and can only be used by its owner.",
        "chatId": "={{ $('BudgetTrigger').item.json.message.chat.id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "96afc98b-ef1f-480c-9822-b489d16b87f8",
      "name": "BudgetInput",
      "type": "n8n-nodes-base.set",
      "position": [
        159712,
        96976
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "text",
              "name": "text",
              "type": "string",
              "value": "={{ $('BudgetTrigger').item.json.message.text }}"
            },
            {
              "id": "chat-id",
              "name": "chat_id",
              "type": "string",
              "value": "={{ $('BudgetTrigger').item.json.message.chat.id }}"
            },
            {
              "id": "allowed-categories",
              "name": "allowed_categories",
              "type": "string",
              "value": "={{ $('GetAppSettings1').item.json.allowed_categories }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "89cde197-55f3-4565-8af9-f5d18ecd22e9",
      "name": "Gpt4oBudgetAgent",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        160336,
        96976
      ],
      "parameters": {
        "model": "openai/gpt-4o",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "id": "qbnEUslOR5kCNftL",
          "name": "Openrouter"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c46112d3-ad52-434a-afd8-dc71687b383d",
      "name": "JsonStorageMcp",
      "type": "@n8n/n8n-nodes-langchain.mcpClientTool",
      "position": [
        160592,
        96976
      ],
      "parameters": {
        "options": {},
        "endpointUrl": "https://mcp.ainoflow.io/mcp/v1/storage/json",
        "authentication": "bearerAuth",
        "serverTransport": "httpStreamable"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "c0d1ffda-7dd0-46c9-9d4f-e31e65e3ed9f",
      "name": "Calculator",
      "type": "@n8n/n8n-nodes-langchain.toolCalculator",
      "position": [
        160720,
        96976
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "aa17d101-b7d9-4b3d-b728-d855b1b02f10",
      "name": "Think",
      "type": "@n8n/n8n-nodes-langchain.toolThink",
      "position": [
        160848,
        96976
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "fafdaefb-bb22-47d9-ac99-12744332dec4",
      "name": "BudgetMemory",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        160464,
        96976
      ],
      "parameters": {
        "sessionKey": "=budget_agent_{{ $('BudgetInput').item.json.chat_id }}",
        "sessionIdType": "customKey"
      },
      "typeVersion": 1.3
    },
    {
      "id": "900133bf-182c-4d10-96b5-5ab6320efbd0",
      "name": "BudgetReply",
      "type": "n8n-nodes-base.telegram",
      "position": [
        161152,
        96752
      ],
      "webhookId": "ce36b3af-907e-4875-98b7-27483e085c4e",
      "parameters": {
        "text": "={{ $('BudgetAgent').item.json.output }}",
        "chatId": "={{ $('BudgetInput').item.json.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4903afe0-b865-4047-9b21-eefe49efb61a",
      "name": "WelcomeMessage",
      "type": "n8n-nodes-base.telegram",
      "position": [
        159856,
        96736
      ],
      "webhookId": "589feaa3-6c42-4d6d-9f7d-bb744b62a7cb",
      "parameters": {
        "text": "=👋 *Invoice Budget Tracker*\n\nI help you manage expense budgets.\n\n*Commands:*\n• \"Set budget Software 500\" - set monthly budget\n• \"Show budgets\" - list all budgets\n• \"Budget status\" - show spent vs budget\n• \"Remove Travel budget\" - delete budget\n\nInvoices are processed automatically from Google Drive.\n\nThe available *categories* for setting budgets are:\n{{ $json.allowed_categories.split(\",\").map(x=>\"• \" + x.trim()).join('\\n') }}",
        "chatId": "={{ $('BudgetTrigger').item.json.message.chat.id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "593f57b9-c89c-4ccc-b5d2-acb9a2c1b70c",
      "name": "WeeklyTrigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        158464,
        97440
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                5
              ],
              "triggerAtHour": 17
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "694e0916-8ee8-4c50-b17b-0cab3cec3884",
      "name": "GetWeeklySummary",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        158912,
        97440
      ],
      "parameters": {
        "url": "=https://api.ainoflow.io/api/v1/storage/json/invoice-summary-{{ $now.format('yyyy-MM') }}/totals",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "allowEmpty",
              "value": "true"
            }
          ]
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "32266bbd-88a8-4d66-85e6-7121fe9d19bf",
      "name": "IfHasData",
      "type": "n8n-nodes-base.if",
      "position": [
        159136,
        97440
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-data",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $('GetWeeklySummary').item.json.invoice_count }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "db67740e-04d4-4b20-b1c1-1cb437c1a6cd",
      "name": "CalcWeeklySummary",
      "type": "n8n-nodes-base.code",
      "position": [
        159360,
        97440
      ],
      "parameters": {
        "jsCode": "// Calculate weekly summary data - only calculations, no formatting\nconst summary = $input.first().json;\n\nconst total_pct = summary.total_budget > 0 \n  ? Math.round((summary.total_spent / summary.total_budget) * 100) \n  : 0;\n\n// Return structured data only\nreturn {\n  json: {\n    period: summary.period,\n    total_spent: summary.total_spent,\n    total_budget: summary.total_budget,\n    total_pct: total_pct,\n    invoice_count: summary.invoice_count,\n    categories: Object.entries(summary.categories || {}).map(([name, data]) => ({\n      name: name,\n      spent: data.spent,\n      budget: data.budget,\n      pct: data.pct\n    })),\n    insights: (summary.insights || []).slice(-3),\n    anomalies: (summary.anomalies || []).slice(-3).map(a => ({\n      vendor: a.vendor,\n      reason: a.reason\n    }))\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "6b536150-f447-4743-a09b-2472b3b0b85f",
      "name": "BuildWeeklyMessage",
      "type": "n8n-nodes-base.set",
      "position": [
        159584,
        97440
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "weekly-message",
              "name": "message",
              "type": "string",
              "value": "=📊 *Weekly Budget Check*\n📅 Month: {{ $json.period }}\n\n*Monthly Progress by Category:*\n\n{{ $json.categories.map(c => (c.pct >= 100 ? '🔴' : c.pct >= 80 ? '🟡' : '🟢') + ' ' + c.name + ': €' + c.spent + '/' + c.budget + ' (' + c.pct + '%)').join('\\n') }}\n\n*Monthly Total:* €{{ $json.total_spent }}{{ $json.total_budget > 0 ? ' / €' + $json.total_budget + ' (' + $json.total_pct + '%)' : '' }}\n*Invoices this month:* {{ $json.invoice_count }}\n{{ $json.insights.length > 0 ? '\\n*Recent Insights:*\\n' + $json.insights.map(i => '• ' + i).join('\\n') : '' }}\n{{ $json.anomalies.length > 0 ? '\\n⚠️ *Anomalies:*\\n' + $json.anomalies.map(a => '• ' + a.vendor + ': ' + a.reason).join('\\n') : '' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "319e9bd1-eac9-4d4a-9a01-3a86030cc6af",
      "name": "WeeklySummaryMessage",
      "type": "n8n-nodes-base.telegram",
      "position": [
        159808,
        97440
      ],
      "webhookId": "68563bc1-0d74-4e0d-bca6-abc19b6bc3b0",
      "parameters": {
        "text": "={{ $json.message }}",
        "chatId": "={{ $('GetAppSettings2').item.json.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "425607ec-05e3-4be8-9849-4bd7968fac20",
      "name": "Crypto",
      "type": "n8n-nodes-base.crypto",
      "position": [
        160336,
        95344
      ],
      "parameters": {
        "type": "SHA256",
        "binaryData": true,
        "dataPropertyName": "input_file_hash"
      },
      "typeVersion": 1
    },
    {
      "id": "56e13a30-186e-4aad-91e0-009bbb63ba54",
      "name": "WorkflowConfig",
      "type": "n8n-nodes-base.set",
      "position": [
        159616,
        95312
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "config-chat-id",
              "name": "chat_id",
              "type": "string",
              "value": "={{ $('GetAppSettings').item.json.chat_id }}"
            },
            {
              "id": "config-inbox-folder",
              "name": "input_folder_id",
              "type": "string",
              "value": "={{ $('LoopInput').item.json.parents[0] }}"
            },
            {
              "id": "config-alert-threshold",
              "name": "alert_threshold",
              "type": "number",
              "value": 80
            },
            {
              "id": "config-categories",
              "name": "allowed_categories",
              "type": "string",
              "value": "={{ $('GetAppSettings').item.json.allowed_categories || 'Other' }}"
            },
            {
              "id": "config-default-currency",
              "name": "default_currency",
              "type": "string",
              "value": "EUR"
            },
            {
              "id": "config-review-folder",
              "name": "review_prefix",
              "type": "string",
              "value": "[REVIEW] - "
            },
            {
              "id": "eb58fdfa-4fc1-4299-97ef-925bad40d6d0",
              "name": "duplicate_prefix",
              "type": "string",
              "value": "[DUPLICATE] - "
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "23640908-7387-4ac4-bc7d-652c1cc662f1",
      "name": "ResultFolder",
      "type": "n8n-nodes-base.set",
      "position": [
        161296,
        96000
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "cdf192b6-4deb-453b-939b-f5c4e2e518bc",
              "name": "=target_folder_id",
              "type": "string",
              "value": "={{ $json.id }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e578be06-4922-4b47-a810-07e45dc69759",
      "name": "RenameToReview",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        161184,
        95568
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('InputFile').item.json.input_file_id }}"
        },
        "options": {},
        "operation": "update",
        "newUpdatedFileName": "={{ $('WorkflowConfig').item.json.review_prefix }}{{ $('InputFile').item.json.input_file_filename }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Lx8EZLOwmZuUPE9f",
          "name": "GoogleOAuth"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "e73828e5-98ba-40e4-b7fc-01d621577063",
      "name": "DuplicateLog",
      "type": "n8n-nodes-base.telegram",
      "position": [
        159376,
        96320
      ],
      "webhookId": "duplicate-log-webhook",
      "parameters": {
        "text": "=🚫 *Duplicate:* {{ $('InputFile').item.json.input_file_filename }}\n🔗 Existing invoice: {{ $('StorageInput').item.json.invoice_month }}/{{ $('StorageInput').item.json.input_file_hash.substring(0, 8) }}",
        "chatId": "={{ $('WorkflowConfig').item.json.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "38778ce2-2a0d-4fe1-956a-92c3bbf0e428",
      "name": "IfNotForReviewOrDuplicate",
      "type": "n8n-nodes-base.if",
      "position": [
        159840,
        95312
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "615b643d-199d-416a-8656-c2e67290256f",
              "operator": {
                "type": "string",
                "operation": "notStartsWith"
              },
              "leftValue": "={{ $('LoopInput').item.json.name }}",
              "rightValue": "={{ $('WorkflowConfig').item.json.review_prefix }}"
            },
            {
              "id": "b4952369-ff83-44c0-bc49-c81f360b1122",
              "operator": {
                "type": "string",
                "operation": "notStartsWith"
              },
              "leftValue": "={{ $('LoopInput').item.json.name }}",
              "rightValue": "={{ $('WorkflowConfig').item.json.duplicate_prefix }}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "edbd6079-9253-4031-ab54-66ca7db69c08",
      "name": "GetFiles",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        159152,
        95312
      ],
      "parameters": {
        "filter": {
          "folderId": {
            "__rl": true,
            "mode": "list",
            "value": "1YuASChwxTDENnfcwfvrA_WFUJxmu2CNo",
            "cachedResultUrl": "https://drive.google.com/drive/folders/1YuASChwxTDENnfcwfvrA_WFUJxmu2CNo",
            "cachedResultName": "Invoice Budget Tracker"
          }
        },
        "options": {
          "fields": [
            "*"
          ]
        },
        "resource": "fileFolder",
        "queryString": "*.pdf"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Lx8EZLOwmZuUPE9f",
          "name": "GoogleOAuth"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "541e0e09-a215-4d5c-8b77-15143cf3caa0",
      "name": "LoopInput",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        159376,
        95312
      ],
      "parameters": {
        "options": {}
      },
      "executeOnce": false,
      "typeVersion": 3
    },
    {
      "id": "9fc45e3f-0d8e-4c1f-9f39-e200a8d793a4",
      "name": "HourlyTrigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        158480,
        95312
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 8-21 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a1c99368-bfd1-440f-8d21-ce78ed8b8cc0",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        160752,
        95248
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineAll"
      },
      "typeVersion": 3.2
    },
    {
      "id": "101debc3-625d-4927-8806-d2fae41b02c4",
      "name": "OcrOutput",
      "type": "n8n-nodes-base.set",
      "position": [
        160560,
        95152
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8d70886e-0a42-4607-a0b5-483bb49a4676",
              "name": "invoice_ocr_text",
              "type": "string",
              "value": "={{ $('OcrExtract').item.json.content?.[0]?.text }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "d064a5b7-bcae-49cd-8668-21648bfb745a",
      "name": "InputFile",
      "type": "n8n-nodes-base.set",
      "position": [
        160560,
        95344
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "drive-file-id",
              "name": "input_file_id",
              "type": "string",
              "value": "={{ $('LoopInput').item.json.id }}"
            },
            {
              "id": "file-hash",
              "name": "input_file_hash",
              "type": "string",
              "value": "={{ $('Crypto').item.json.input_file_hash }}"
            },
            {
              "id": "original-filename",
              "name": "input_file_filename",
              "type": "string",
              "value": "={{ $('DownloadInvoice').item.binary.data.fileName ?? 'invoice.pdf' }}"
            },
            {
              "id": "file-extension",
              "name": "input_file_extension",
              "type": "string",
              "value": "={{ ($('DownloadInvoice').item.binary.data.fileName).split('.').pop() || 'pdf' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ae090e45-8510-4efd-9fba-3afcd79998a0",
      "name": "ProcessingInput",
      "type": "n8n-nodes-base.set",
      "position": [
        161680,
        95168
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ocr-text",
              "name": "ocr_text",
              "type": "string",
              "value": "={{ $('OcrExtract').item.json.content[0].text }}"
            },
            {
              "id": "allowed-categories",
              "name": "allowed_categories",
              "type": "string",
              "value": "={{ $('WorkflowConfig').item.json.allowed_categories }}"
            },
            {
              "id": "budgets-context",
              "name": "budgets_context",
              "type": "string",
              "value": "={{ Object.entries($('GetBudgets').item.json.budgets || {}).map(([k,v]) => k + ': ' + v.monthly + ' ' + (v.currency || 'EUR') + '/month').join('\\n') || 'No budgets set' }}"
            },
            {
              "id": "e100c199-e78c-4ea0-8fd9-143d067447b5",
              "name": "input_folder_id",
              "type": "string",
              "value": "={{ $('WorkflowConfig').item.json.input_folder_id }}"
            },
            {
              "id": "file-hash",
              "name": "input_file_hash",
              "type": "string",
              "value": "={{ $('InputFile').item.json.input_file_hash }}"
            },
            {
              "id": "drive-file-id",
              "name": "input_file_id",
              "type": "string",
              "value": "={{ $('InputFile').item.json.input_file_id }}"
            },
            {
              "id": "original-filename",
              "name": "input_file_filename",
              "type": "string",
              "value": "={{ $('InputFile').item.json.input_file_filename }}"
            },
            {
              "id": "file-extension",
              "name": "input_file_extension",
              "type": "string",
              "value": "={{ $('InputFile').item.json.input_file_extension }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "ce72a80a-2f2c-41fa-9d25-57f2cadbd8b4",
      "name": "StorageInput",
      "type": "n8n-nodes-base.set",
      "position": [
        158464,
        96096
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "storage-category",
              "name": "storage_category",
              "type": "string",
              "value": "=invoice-data-{{ $('AICategorizer').item.json.output.date.substring(0, 7) }}"
            },
            {
              "id": "invoice-month",
              "name": "invoice_month",
              "type": "string",
              "value": "={{ $('AICategorizer').item.json.output.date.substring(0, 7) }}"
            },
            {
              "id": "input-file-hash",
              "name": "input_file_hash",
              "type": "string",
              "value": "={{ $('InputFile').item.json.input_file_hash }}"
            },
            {
              "id": "input-file-id",
              "name": "input_file_id",
              "type": "string",
              "value": "={{ $('InputFile').item.json.input_file_id }}"
            },
            {
              "id": "input-file-filename",
              "name": "input_file_filename",
              "type": "string",
              "value": "={{ $('InputFile').item.json.input_file_filename }}"
            },
            {
              "id": "input-file-extension",
              "name": "input_file_extension",
              "type": "string",
              "value": "={{ $('InputFile').item.json.input_file_extension }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "b9229f35-4a2b-4332-9c09-7435d3485107",
      "name": "Monthly Summary",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160064,
        97232
      ],
      "parameters": {
        "color": 5,
        "width": 1420,
        "height": 1052,
        "content": "## 4. Monthly Summary\nScheduled report generation on 10th of each month"
      },
      "typeVersion": 1
    },
    {
      "id": "986b3dbf-cd37-472f-b233-bafc89b0bcf7",
      "name": "MonthlyTrigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        160144,
        97424
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "months",
              "triggerAtHour": 9,
              "triggerAtDayOfMonth": 10
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "647185b5-2ced-4257-8d1e-0787cf4bebc4",
      "name": "MonthlySummaryMessage",
      "type": "n8n-nodes-base.telegram",
      "position": [
        160912,
        97424
      ],
      "webhookId": "monthly-summary-webhook",
      "parameters": {
        "text": "={{ $json.message ?? $json.error }}",
        "chatId": "={{ $('GetAppConfig2').item.json.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "6f88e46e-c38b-4851-b761-0f416921dfd6",
      "name": "IfHasMonthlyData1",
      "type": "n8n-nodes-base.if",
      "position": [
        160816,
        97808
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-monthly-data",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $('GetMonthlySummary').item.json.invoice_count }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "b87f2e29-e7ef-4745-8dd2-8ad0b85017ad",
      "name": "CalcMonthlySummary",
      "type": "n8n-nodes-base.code",
      "position": [
        161040,
        97712
      ],
      "parameters": {
        "jsCode": "// Calculate monthly summary data - only calculations, no formatting\nconst summary = $input.first().json;\nconst period = summary.period || $now.minus({months: 1}).format('yyyy-MM');\n\nconst total_pct = summary.total_budget > 0 \n  ? Math.round((summary.total_spent / summary.total_budget) * 100) \n  : 0;\n\n// Sort categories by spent (descending)\nconst categories = Object.entries(summary.categories || {})\n  .sort((a, b) => b[1].spent - a[1].spent)\n  .map(([name, data]) => ({\n    name: name,\n    spent: (data.spent || 0).toFixed(2),\n    budget: data.budget || 0,\n    pct: data.pct,\n    bar_filled: Math.min(10, Math.round(data.pct / 10)),\n    bar_empty: Math.max(0, 10 - Math.round(data.pct / 10))\n  }));\n\nreturn {\n  json: {\n    period: period,\n    total_spent: (summary.total_spent || 0).toFixed(2),\n    total_budget: summary.total_budget || 0,\n    total_pct: total_pct,\n    invoice_count: summary.invoice_count || 0,\n    categories: categories,\n    insights: (summary.insights || []).slice(-5),\n    anomalies: (summary.anomalies || []).slice(-3).map(a => ({\n      vendor: a.vendor,\n      reason: a.reason\n    })),\n    over_budget: categories.filter(c => c.pct >= 100).map(c => c.name),\n    near_budget: categories.filter(c => c.pct >= 80 && c.pct < 100).map(c => c.name)\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "6f6a13e1-f4dc-4f10-8563-abf5e695d60a",
      "name": "BuildMonthlyMessage",
      "type": "n8n-nodes-base.set",
      "position": [
        161264,
        97712
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "monthly-message",
              "name": "message",
              "type": "string",
              "value": "=📅 *Monthly Report - {{ $json.period }}*\n\n*Overview:*\n• Total Spent: €{{ $json.total_spent }}\n{{ $json.total_budget > 0 ? '• Budget Used: ' + $json.total_pct + '% of €' + $json.total_budget + '\\n' : '' }}• Invoices Processed: {{ $json.invoice_count }}\n\n*By Category:*\n\n{{ $json.categories.map(c => (c.pct >= 100 ? '🔴' : c.pct >= 80 ? '🟡' : '🟢') + ' *' + c.name + '*\\n   ' + '█'.repeat(c.bar_filled) + '░'.repeat(c.bar_empty) + ' ' + c.pct + '%\\n   €' + c.spent + ' / €' + c.budget).join('\\n\\n') }}\n{{ $json.insights.length > 0 ? '\\n*Key Insights:*\\n' + $json.insights.map(i => '• ' + i).join('\\n') : '' }}\n{{ $json.anomalies.length > 0 ? '\\n⚠️ *Anomalies Detected: ' + $json.anomalies.length + '*\\n' + $json.anomalies.map(a => '• ' + a.vendor + ': ' + a.reason).join('\\n') : '' }}\n{{ $json.over_budget.length > 0 ? '\\n🔴 *Over Budget:* ' + $json.over_budget.join(', ') : '' }}\n{{ $json.near_budget.length > 0 ? '\\n🟡 *Near Budget:* ' + $json.near_budget.join(', ') : '' }}"
            },
            {
              "id": "monthly-period",
              "name": "period",
              "type": "string",
              "value": "={{ $json.period }}"
            },
            {
              "id": "monthly-total",
              "name": "total_spent",
              "type": "string",
              "value": "={{ $json.total_spent }}"
            },
            {
              "id": "monthly-count",
              "name": "invoice_count",
              "type": "number",
              "value": "={{ $json.invoice_count }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "81f5c1a9-3da1-4188-adcf-ad968a87ee52",
      "name": "WorkflowInput",
      "type": "n8n-nodes-base.set",
      "position": [
        160368,
        97808
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "b4674f58-0a8a-4063-abf8-7e6e0392d038",
              "name": "year",
              "type": "number",
              "value": "={{ $json.year ?? $now.format(\"yyyy\") }}"
            },
            {
              "id": "1256f875-5c4d-42ec-8c91-c963ef3f26aa",
              "name": "month",
              "type": "number",
              "value": "={{ $json.month ?? $now.format(\"M\") }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c9d350c1-7fc1-4980-a412-8a8dff4dcdc3",
      "name": "GetMonthlySummaryTrigger",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        160144,
        97808
      ],
      "parameters": {
        "workflowInputs": {
          "values": [
            {
              "name": "year",
              "type": "number"
            },
            {
              "name": "month",
              "type": "number"
            }
          ]
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "b04313c1-249d-4ce6-b88f-d258cf2eb83c",
      "name": "MonthlySummary",
      "type": "@n8n/n8n-nodes-langchain.toolWorkflow",
      "position": [
        160976,
        96976
      ],
      "parameters": {
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $workflow.id }}",
          "cachedResultUrl": "/workflow/=%7B%7B%20$workflow.id%20%7D%7D"
        },
        "description": "Use this tool to get monthly summary.",
        "workflowInputs": {
          "value": {
            "year": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('year', `Provide year, number (e.g. 2026)`, 'number') }}",
            "month": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('month', `Provide month, number (e.g. 10)`, 'number') }}"
          },
          "schema": [
            {
              "id": "year",
              "type": "number",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "year",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "month",
              "type": "number",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "month",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "58b67b0a-3c3d-4dea-806a-5c373490f08c",
      "name": "GetMonthlySummary",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        160592,
        97808
      ],
      "parameters": {
        "url": "=https://api.ainoflow.io/api/v1/storage/json/invoice-summary-{{ new Date($json.year, $json.month - 1, 1).toISOString().slice(0,7) }}/totals",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "allowEmpty",
              "value": "true"
            }
          ]
        }
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "2b71f7d0-fe8c-4077-8271-2d0569215841",
      "name": "GetMonthlySummaryText",
      "type": "n8n-nodes-base.executeWorkflow",
      "position": [
        160592,
        97424
      ],
      "parameters": {
        "options": {},
        "workflowId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $workflow.id }}",
          "cachedResultUrl": "/workflow/=%7B%7B%20$workflow.id%20%7D%7D"
        },
        "workflowInputs": {
          "value": {
            "year": "={{ $now.minus({months: 1}).format('yyyy').toNumber() }}",
            "month": "={{ $now.minus({months: 1}).format('M').toNumber() }}"
          },
          "schema": [
            {
              "id": "year",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "year",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "month",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "month",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "2971c307-2b46-433a-8a28-9a752ef0fa87",
      "name": "CalcSummary",
      "type": "n8n-nodes-base.code",
      "position": [
        159600,
        96000
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Calculate summary update - only summary mutations\nconst invoice = $('AICategorizer').item.json.output;\nconst budgets = $('GetBudgets').item.json.budgets || {};\nconst existingSummary = $input.item.json;\n\nconst period = invoice.date.substring(0, 7);\nconst allowedCategories = $('WorkflowConfig').item.json.allowed_categories.split(', ');\nconst category = allowedCategories.includes(invoice.category) ? invoice.category : 'Other';\nconst amount = invoice.amount;\n\n// Initialize or clone summary\nlet summary = Object.keys(existingSummary).length > 0 \n  ? JSON.parse(JSON.stringify(existingSummary))\n  : {\n      period: period,\n      categories: {},\n      total_spent: 0,\n      total_budget: 0,\n      invoice_count: 0,\n      insights: [],\n      anomalies: []\n    };\n\n// Update category\nif (!summary.categories[category]) {\n  summary.categories[category] = {\n    spent: 0,\n    budget: budgets[category]?.monthly || 0,\n    pct: 0\n  };\n}\nsummary.categories[category].spent = Math.round((summary.categories[category].spent + amount) * 100) / 100;\nif (summary.categories[category].budget > 0) {\n  summary.categories[category].pct = Math.round(\n    (summary.categories[category].spent / summary.categories[category].budget) * 100\n  );\n}\n\n// Update totals\nsummary.total_spent = Math.round((summary.total_spent + amount) * 100) / 100;\nsummary.invoice_count += 1;\nsummary.total_budget = Object.values(budgets).reduce((sum, b) => sum + (b.monthly || 0), 0);\n\n// Add insight (keep last 10)\nif (invoice.insight) {\n  summary.insights = [...summary.insights, invoice.insight].slice(-10);\n}\n\n// Add anomaly if detected\nif (invoice.anomaly_detected) {\n  summary.anomalies.push({\n    vendor: invoice.vendor_normalized || invoice.vendor,\n    reason: invoice.anomaly_reason,\n    severity: 'medium',\n    date: invoice.date\n  });\n}\n\nreturn {\n  json: {\n    summary: summary,\n    summary_category: 'invoice-summary-' + period,\n    invoice: invoice,\n    budget_status: summary.categories[category]\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "e7f87a8a-9724-4fe2-b7ba-043df5c44542",
      "name": "SummaryInput",
      "type": "n8n-nodes-base.set",
      "position": [
        159824,
        96000
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "output-summary",
              "name": "summary",
              "type": "object",
              "value": "={{ $json.summary }}"
            },
            {
              "id": "output-summary-category",
              "name": "summary_category",
              "type": "string",
              "value": "={{ $json.summary_category }}"
            },
            {
              "id": "output-invoice",
              "name": "invoice",
              "type": "object",
              "value": "={{ $json.invoice }}"
            },
            {
              "id": "output-needs-alert",
              "name": "needs_alert",
              "type": "boolean",
              "value": "={{ $json.invoice.budget_warning || ($json.budget_status.budget > 0 && $json.budget_status.pct >= 80) }}"
            },
            {
              "id": "output-budget-status",
              "name": "budget_status",
              "type": "object",
              "value": "={{ $json.budget_status }}"
            },
            {
              "id": "output-file-info",
              "name": "file_info",
              "type": "object",
              "value": "={{ { input_folder_id: $('WorkflowConfig').item.json.input_folder_id, input_file_id: $('StorageInput').item.json.input_file_id, new_filename: '[' + $json.invoice.date + '] - ' + ($json.invoice.vendor_normalized || $json.invoice.vendor) + ' (' + ($json.invoice.invoice_number ? $json.invoice.invoice_number + ', ' : '') + $json.invoice.amount + ' ' + $json.invoice.currency + ').' + $('StorageInput').item.json.input_file_extension, month_folder: $('StorageInput').item.json.invoice_month } }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "130593ac-8c99-4b8c-b365-81bb1d124be6",
      "name": "IfAuthorized",
      "type": "n8n-nodes-base.if",
      "position": [
        158912,
        96976
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "is-authorized",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $('BudgetTrigger').item.json.message.chat.id }}",
              "rightValue": "={{ $json.chat_id ?? null }}"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "0bc1dd6c-1f9d-4a48-be17-f7ccac7035b9",
      "name": "GetAppConfig2",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        160368,
        97424
      ],
      "parameters": {
        "url": "https://api.ainoflow.io/api/v1/storage/json/invoice-config/settings",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "a410987e-c7ad-4726-b834-a56e8adfea82",
      "name": "ErrorOutput",
      "type": "n8n-nodes-base.set",
      "position": [
        161040,
        97904
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "708b9260-cb4e-47ef-ba4b-03a1307d5bee",
              "name": "error",
              "type": "string",
              "value": "=Monthly summary does not exist for selected month ({{ new Date($('WorkflowInput').item.json.year, $('WorkflowInput').item.json.month - 1, 1).toISOString().slice(0,7) }})"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "1fdbbaa6-70d5-48cd-b09e-4a50e6f845be",
      "name": "ManualResetTrigger",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        158464,
        97904
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "832ce7c3-0d67-408d-8aa4-84a65fa44fad",
      "name": "ForEachCategory",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        159424,
        97888
      ],
      "parameters": {
        "url": "https://api.ainoflow.io/api/v1/storage/json",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "9f45a2ac-c67a-4c7c-ab92-752f8e4285f2",
      "name": "DeleteItem",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        159696,
        98096
      ],
      "parameters": {
        "url": "=https://api.ainoflow.io/api/v1/storage/json/{{ $json.category }}/{{ $json.key }}",
        "method": "DELETE",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "ccee79a6-2fa5-447c-a711-b46cb55eaff5",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        158416,
        97776
      ],
      "parameters": {
        "color": 7,
        "width": 1584,
        "height": 464,
        "content": "## Cleanup / Reset\nThis is **MANUAL** trigger to full data cleanup. **Warning - this will DELETE ALL DATA** stored in your **Ainoflow** account"
      },
      "typeVersion": 1
    },
    {
      "id": "afd9800b-cc16-46b6-aee2-165aa010c2a8",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158416,
        95168
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 304,
        "content": "## Scheduled Trigger"
      },
      "typeVersion": 1
    },
    {
      "id": "b7e850ad-de62-469e-a536-43cdeff53018",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158624,
        95168
      ],
      "parameters": {
        "color": 2,
        "width": 464,
        "height": 304,
        "content": "## Ensure Tool Configuration Exists\nBefore starting processing, we should have a Telegram bot successfully configured and linked to the workflow via the `/start` message."
      },
      "typeVersion": 1
    },
    {
      "id": "cf649ee2-81e7-4280-aa9a-8c8ad5c920b7",
      "name": "GetAppSettings",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        158704,
        95312
      ],
      "parameters": {
        "url": "https://api.ainoflow.io/api/v1/storage/json/invoice-config/settings",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "8b9b5220-2d22-4799-8f1a-59108a660c76",
      "name": "GetAppSettings1",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueRegularOutput",
      "position": [
        158720,
        96752
      ],
      "parameters": {
        "url": "https://api.ainoflow.io/api/v1/storage/json/invoice-config/settings",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": true
    },
    {
      "id": "1a8389a1-32e0-438c-879e-625a1e55d2e0",
      "name": "GetAppSettings2",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        158688,
        97440
      ],
      "parameters": {
        "url": "https://api.ainoflow.io/api/v1/storage/json/invoice-config/settings",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "3516a16f-4c10-42ee-934d-c73a1afa1516",
      "name": "IfRegistrationExists",
      "type": "n8n-nodes-base.if",
      "position": [
        158928,
        95312
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "has-chat-id",
              "operator": {
                "type": "number",
                "operation": "exists",
                "singleValue": true
              },
              "leftValue": "={{ $json.chat_id }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c8104c27-cf1c-4342-8eb2-6f76b04f5cc0",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        159088,
        95168
      ],
      "parameters": {
        "color": 2,
        "width": 464,
        "height": 304,
        "content": "## Loop over unprocessed files\n- Get all files in folder, iterate one by one\n- Make sure you have selected right (inbox) directory here\n"
      },
      "typeVersion": 1
    },
    {
      "id": "0ca2c565-ac22-4ac1-bd9e-677ce62a45ae",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158432,
        96640
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 320,
        "content": "## Chat Trigger"
      },
      "typeVersion": 1
    },
    {
      "id": "ac805847-4685-4f0d-b1aa-29ef044a52e8",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158640,
        96640
      ],
      "parameters": {
        "color": 2,
        "width": 928,
        "height": 528,
        "content": "## Ensure Bot Privacy\nOn first use, the bot stores the user ID and locks access to that user. Any other user will receive an “unauthorized” message.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "187ac6c2-1ed5-449c-844b-d6141c56c9ef",
      "name": "IfStartMessage",
      "type": "n8n-nodes-base.if",
      "position": [
        159392,
        96864
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "not-start-command",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('BudgetTrigger').item.json.message.text }}",
              "rightValue": "/start"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "59e48c58-68ae-443b-bb1b-1c718b5c0742",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        159568,
        96640
      ],
      "parameters": {
        "color": 4,
        "width": 720,
        "height": 256,
        "content": "## Add processing started message\nNotify user about processing start (with message ... )"
      },
      "typeVersion": 1
    },
    {
      "id": "09f8c8f5-157a-40f5-9233-828e516832b3",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        159568,
        96896
      ],
      "parameters": {
        "color": 2,
        "width": 720,
        "height": 272,
        "content": "## Build Agent Input\n"
      },
      "typeVersion": 1
    },
    {
      "id": "72de16dc-c2bd-4277-aff8-a2ee95eae8fa",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        160288,
        96640
      ],
      "parameters": {
        "color": 6,
        "width": 800,
        "height": 528,
        "content": "## Budget Agent Processing\n- answer to user message\n- ensure budget is set as expected"
      },
      "typeVersion": 1
    },
    {
      "id": "4bae5be7-e65e-4b9c-b22a-e72a011c616f",
      "name": "BudgetAgent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        160560,
        96752
      ],
      "parameters": {
        "text": "={{ $('BudgetInput').item.json.text }}",
        "options": {
          "systemMessage": "=# Budget Manager for Invoice Budget Tracker\n\nYou manage budget configuration via Ainoflow Storage MCP.\n\n## Available MCP Tools\n\nJsonStorageMcp:\n- storage_json_get(category, key) - retrieve data\n- storage_json_upsert(category, key, data) - create/update data\n\n## Storage Structure\n\nCategory: \"invoice-config\"\nKey: \"budgets\"\n\n## Allowed Categories\n{{ $('BudgetInput').item.json.allowed_categories }}\n\n## Budget Schema\n```json\n{\n  \"budgets\": {\n    \"Software\": { \"monthly\": 500, \"currency\": \"EUR\" },\n    \"Marketing\": { \"monthly\": 1000, \"currency\": \"EUR\" }\n  },\n  \"alert_threshold\": 0.8\n}\n```\n\n## Operations\n\n### List Categories\nUser: \"What are categories?\" or \"Show categories\"\nDO NOT call storage - just return the Allowed Categories list above.\nFormat: \"📋 *Available Categories:*\\n• Software\\n• Marketing\\n...etc\"\n\n### Set Budget\nUser: \"Set budget Software 500\"\n1. storage_json_get(\"invoice-config\", \"budgets\")\n2. Add/update: budgets.Software = { monthly: 500, currency: \"EUR\" }\n3. storage_json_upsert(\"invoice-config\", \"budgets\", updated_data)\n4. Respond: \"✅ Budget set: Software - €500/month\"\n\n### List Budgets\nUser: \"Show budgets\"\n1. storage_json_get(\"invoice-config\", \"budgets\")\n2. Format as list with totals\n3. Use Calculator for total\n\n### Budget Status\nUser: \"Budget status\"\n1. storage_json_get(\"invoice-config\", \"budgets\")\n2. Get current month: {{ $now.format('yyyy-MM') }}\n3. storage_json_get(\"invoice-summary-{{ $now.format('yyyy-MM') }}\", \"totals\")\n4. Compare spent vs budget per category\n5. Show % and remaining\n\n### Delete Budget\nUser: \"Remove Travel budget\"\n1. storage_json_get(\"invoice-config\", \"budgets\")\n2. Delete budgets.Travel\n3. storage_json_upsert(\"invoice-config\", \"budgets\", updated_data)\n4. Confirm deletion\n\n## Rules\n- Default currency: EUR\n- Validate category from allowed list\n- Use Calculator for totals and percentages\n- Keep responses concise\n- Use *bold* (single asterisk) for amounts\n\nCurrent date: {{ $now.toISO() }}\nCurrent month: {{ $now.format('yyyy-MM') }}\n"
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "99e32992-9780-494e-9c64-99154722e57e",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        161088,
        96640
      ],
      "parameters": {
        "color": 4,
        "width": 288,
        "height": 528,
        "content": "## Result / Reply Message\nSends reply to the user"
      },
      "typeVersion": 1
    },
    {
      "id": "3ce0b558-2b8a-4c70-8fcc-b5ccfdc22452",
      "name": "Budget Agent1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158384,
        94896
      ],
      "parameters": {
        "color": 5,
        "width": 4068,
        "height": 868,
        "content": "## 1.1 Document Processing Loop / Data Extraction (Scheduled)\n"
      },
      "typeVersion": 1
    },
    {
      "id": "111e0912-7e9c-461d-a494-95a36a752492",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        159552,
        95168
      ],
      "parameters": {
        "color": 2,
        "width": 464,
        "height": 304,
        "content": "## Get Config and Validate Input File\n- Document not marked for manual review\n- Document not marked as duplicate\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c33f4996-4c7e-41e0-aca0-9e07754ee77d",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160016,
        95072
      ],
      "parameters": {
        "color": 2,
        "width": 1088,
        "height": 432,
        "content": "## Get Document Content\n- Downloads file\n- Extract text from file\n- Calculate file hash\n"
      },
      "typeVersion": 1
    },
    {
      "id": "d7b453c3-d836-4b2e-846a-607235d74b89",
      "name": "Sticky Note11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        161104,
        95072
      ],
      "parameters": {
        "color": 2,
        "width": 528,
        "height": 288,
        "content": "## Load Budget Data\n- Budget json loaded from config storage"
      },
      "typeVersion": 1
    },
    {
      "id": "2a06727f-aa5f-46e8-a4a9-6676a71cccd3",
      "name": "Sticky Note14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        161104,
        95360
      ],
      "parameters": {
        "color": 3,
        "width": 528,
        "height": 368,
        "content": "## Require manual review\n- If OCR / text extraction failed\n- If categorizer identified invalid content\n"
      },
      "typeVersion": 1
    },
    {
      "id": "3ea2ad97-17ba-4007-9ee9-ef42032c1a49",
      "name": "IfInvalidContent",
      "type": "n8n-nodes-base.if",
      "position": [
        160880,
        95536
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "74663490-59c4-4ebe-9716-ccba0dbb6498",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              },
              "leftValue": "={{ $json.output.is_invoice }}",
              "rightValue": false
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "485da58e-1815-44c3-afb9-4f1e46f1a9d8",
      "name": "Sticky Note15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        161632,
        95072
      ],
      "parameters": {
        "color": 2,
        "width": 688,
        "height": 656,
        "content": "## Extract Invoice Data"
      },
      "typeVersion": 1
    },
    {
      "id": "84d1b344-f5b1-4057-979b-0dd5f6936960",
      "name": "Budget Agent2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158384,
        95840
      ],
      "parameters": {
        "color": 5,
        "width": 4068,
        "height": 660,
        "content": "## 1.2 Document Processing Loop / Invoice Processing\n"
      },
      "typeVersion": 1
    },
    {
      "id": "59bbb7aa-83e1-487a-bb38-6be826e4c6ba",
      "name": "RenameAsDuplicate",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        159152,
        96320
      ],
      "parameters": {
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('InputFile').item.json.input_file_id }}"
        },
        "options": {},
        "operation": "update",
        "newUpdatedFileName": "={{ $('WorkflowConfig').item.json.duplicate_prefix }}{{ $('InputFile').item.json.input_file_filename }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "id": "Lx8EZLOwmZuUPE9f",
          "name": "GoogleOAuth"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "352a4f6f-dab1-4106-8d75-766b52fee649",
      "name": "Sticky Note16",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        159088,
        96192
      ],
      "parameters": {
        "color": 4,
        "width": 512,
        "height": 288,
        "content": "## Handle Duplicate Invoice\n- Rename as duplicate (for manual processing) \n- Notify user about duplicate"
      },
      "typeVersion": 1
    },
    {
      "id": "6b92e2a6-3292-4736-9f72-22b0e57d2108",
      "name": "Sticky Note17",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158592,
        96000
      ],
      "parameters": {
        "color": 2,
        "width": 496,
        "height": 304,
        "content": "## Duplicate Check\n"
      },
      "typeVersion": 1
    },
    {
      "id": "13111eac-ce49-47e5-bf07-3b85f33620c0",
      "name": "Sticky Note18",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        159088,
        95904
      ],
      "parameters": {
        "color": 2,
        "width": 208,
        "height": 288,
        "content": "## Save Record\n"
      },
      "typeVersion": 1
    },
    {
      "id": "5b1fede8-d5e9-48e0-84ea-51bf4b12987c",
      "name": "Sticky Note19",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        159296,
        95904
      ],
      "parameters": {
        "color": 2,
        "width": 928,
        "height": 288,
        "content": "## Update Summary\n"
      },
      "typeVersion": 1
    },
    {
      "id": "73c0db71-0705-48b6-b9a5-0451c73923f8",
      "name": "Sticky Note20",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160224,
        95904
      ],
      "parameters": {
        "color": 4,
        "width": 448,
        "height": 288,
        "content": "## Budget Alerts\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ac1d07f5-e557-44fd-b807-bcd6ef4cc75f",
      "name": "Sticky Note21",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160224,
        96192
      ],
      "parameters": {
        "color": 4,
        "width": 304,
        "height": 288,
        "content": "## Rename Document\n- Use invoice details to build new document name\n"
      },
      "typeVersion": 1
    },
    {
      "id": "9fe4053f-a90b-42db-a135-4e923452680d",
      "name": "Sticky Note22",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160528,
        96192
      ],
      "parameters": {
        "color": 2,
        "width": 736,
        "height": 288,
        "content": "## Ensure Month Folder Exists\n"
      },
      "typeVersion": 1
    },
    {
      "id": "71e6d8f0-5460-4d67-a48b-9c8ec76d6e09",
      "name": "Sticky Note23",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        161200,
        95904
      ],
      "parameters": {
        "color": 4,
        "width": 560,
        "height": 288,
        "content": "## Move Document to Month Folder\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ee1122c7-62b4-42b7-b5f3-9eb2402d2f90",
      "name": "Sticky Note25",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        161760,
        95904
      ],
      "parameters": {
        "color": 4,
        "width": 336,
        "height": 288,
        "content": "## Success Notification\n- Send message to user with invoice details\n"
      },
      "typeVersion": 1
    },
    {
      "id": "777c19d2-d3da-41ba-91a7-558f17412212",
      "name": "Sticky Note24",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158416,
        97344
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 288,
        "content": "## Weekly Trigger"
      },
      "typeVersion": 1
    },
    {
      "id": "1b659b80-e5ed-41ee-a848-be729baf5907",
      "name": "Sticky Note26",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158624,
        97344
      ],
      "parameters": {
        "color": 2,
        "width": 912,
        "height": 288,
        "content": "## Get Weekly Summary\n- Do not proceed if summary does not exist yet\n"
      },
      "typeVersion": 1
    },
    {
      "id": "bcdd3131-8093-4d10-ac03-696b72b7575d",
      "name": "Sticky Note27",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        159536,
        97344
      ],
      "parameters": {
        "color": 4,
        "width": 464,
        "height": 288,
        "content": "## Send Weekly Notification"
      },
      "typeVersion": 1
    },
    {
      "id": "b08ebd23-e906-460a-9ec5-6116f70ac2db",
      "name": "Sticky Note28",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160096,
        97328
      ],
      "parameters": {
        "color": 7,
        "width": 208,
        "height": 288,
        "content": "## Monthly Trigger"
      },
      "typeVersion": 1
    },
    {
      "id": "9513d252-3a58-4468-bd07-db807d054995",
      "name": "Sticky Note29",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160304,
        97328
      ],
      "parameters": {
        "color": 2,
        "width": 464,
        "height": 288,
        "content": "## Get Monthly Summary\n- Do not proceed if summary does not exist yet\n"
      },
      "typeVersion": 1
    },
    {
      "id": "54f09973-ad72-4177-9c67-8ecd665005a7",
      "name": "Sticky Note30",
      "type": "n8n-nodes-base.stickyNote",
      "disabled": true,
      "position": [
        160768,
        97328
      ],
      "parameters": {
        "color": 4,
        "width": 448,
        "height": 288,
        "content": "## Send Monthly Notification"
      },
      "typeVersion": 1
    },
    {
      "id": "32d50423-9e8a-4d07-ac65-a824967d593f",
      "name": "Sticky Note31",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        160096,
        97664
      ],
      "parameters": {
        "color": 2,
        "width": 1344,
        "height": 416,
        "content": "## Monthly Summary Calculation Logic\n- Respond with summary or error message\n- Uses subworkflow (workflow with same id)\n"
      },
      "typeVersion": 1
    },
    {
      "id": "bf54a221-ed26-4ce4-aeec-625df8fac3bd",
      "name": "Monthly Summary1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        158384,
        97680
      ],
      "parameters": {
        "color": 3,
        "width": 1660,
        "height": 604,
        "content": "## 5. Data Reset\n- Removes all account / project data"
      },
      "typeVersion": 1
    },
    {
      "id": "57a2e9b1-2d98-4b43-bbc0-546021395645",
      "name": "GetAppSettings3",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        158688,
        97904
      ],
      "parameters": {
        "url": "https://api.ainoflow.io/api/v1/storage/json/invoice-config/settings",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "668e46fa-dc01-452a-8948-ac682eb6d9c7",
      "name": "ApproveRemove",
      "type": "n8n-nodes-base.telegram",
      "position": [
        158912,
        97904
      ],
      "webhookId": "68563bc1-0d74-4e0d-bca6-abc19b6bc3b0",
      "parameters": {
        "chatId": "={{ $json.chat_id }}",
        "message": "⚠️ Approve data removal!",
        "options": {
          "limitWaitTime": {
            "values": {
              "resumeUnit": "minutes"
            }
          },
          "appendAttribution": false
        },
        "operation": "sendAndWait",
        "approvalOptions": {
          "values": {
            "approvalType": "double"
          }
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e754429a-d6cf-4d1e-a3d8-85287930f2a0",
      "name": "IfApproved",
      "type": "n8n-nodes-base.if",
      "position": [
        159120,
        97904
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7cb6d41c-1bf0-4a57-8431-9221eeba6caa",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.data.approved }}",
              "rightValue": false
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "5a0d78b8-8cab-46ed-befa-92f0e2441012",
      "name": "FirstRunOnlyStart",
      "type": "n8n-nodes-base.if",
      "position": [
        159152,
        96736
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "not-start-command",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('BudgetTrigger').item.json.message.text }}",
              "rightValue": "/start"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "cd18db5e-df54-4717-aaa3-bc5d5a289a1a",
      "name": "ForEachCategoryItem",
      "type": "n8n-nodes-base.httpRequest",
      "onError": "continueErrorOutput",
      "position": [
        159408,
        98112
      ],
      "parameters": {
        "url": "=https://api.ainoflow.io/api/v1/storage/json/{{ $json.category }}",
        "options": {},
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "id": "CdhQVxeD79PpCCOL",
          "name": "Ainoflow"
        }
      },
      "typeVersion": 4.2,
      "alwaysOutputData": false
    },
    {
      "id": "ac0992a0-7d3e-443d-9bfb-b4612d863f8d",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        159696,
        97872
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2b759fe9-1fee-4e1e-9531-a92e8996a1ca",
              "operator": {
                "type": "string",
                "operation": "startsWith"
              },
              "leftValue": "={{ $json.category }}",
              "rightValue": "invoice-"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "2f593874-03d0-4b5a-880a-a07ba313f377",
      "name": "SetDefaults",
      "type": "n8n-nodes-base.set",
      "position": [
        159632,
        96736
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c1513003-f08b-4bc2-9f89-c08b16af1314",
              "name": "allowed_categories",
              "type": "string",
              "value": "Software, Marketing, Travel, Office, Professional Services, Infrastructure, Vehicle, Other"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a2f9b5b7-efff-4d9b-934f-78c9e6a3e55e",
      "name": "Think1",
      "type": "@n8n/n8n-nodes-langchain.toolThink",
      "position": [
        161856,
        95536
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "bc49cb02-4592-457f-9972-bd4f05ace201",
      "name": "AICategorizer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        161936,
        95296
      ],
      "parameters": {
        "text": "=Filename: {{ $('ProcessingInput').item.json.input_file_filename }}\nFile Content: \n{{ $('ProcessingInput').item.json.ocr_text }}",
        "options": {
          "systemMessage": "=# Invoice Analyzer\n\nAnalyze documents and extract invoice data as JSON.\n\n## Step 1: Document Type Check\n\nFIRST determine if this document records a business expense that should be tracked.\n\n**NOT an invoice (skip):**\n- Contract or Agreement (no payment amount)\n- Delivery act / Acceptance act\n- PPA (Purchase/Payment Agreement without amount)\n- Quote / Estimate (not yet paid)\n- Bank statement\n- Report or Statement (summary without specific transaction)\n- **Multiple invoices in one file** (different vendors, dates, or invoice numbers)\n\n**IS an invoice for expense tracking — process normally:**\n- Any document showing: vendor + amount paid + date = INVOICE\n- Invoice marked as \"PAID\", \"SETTLED\", or already paid\n- Invoice marked as \"informational\", \"not for payment\", \"copy\", or \"for your records\"\n- Proforma invoice (with amount)\n- Travel booking confirmation (airline, hotel, car rental)\n- E-ticket or itinerary showing payment amount\n- Receipt with vendor name, amount, and date\n\n**Key rule:** If document shows money was paid or charged, it's an invoice for expense tracking. Ignore disclaimers like \"informational only\" or \"not for payment\".\n\nIf NOT a single invoice → return:\n```json\n{\n  \"is_invoice\": false,\n  \"document_type\": \"Delivery Act\",\n  \"skip_reason\": \"This is a delivery document, not an invoice\"\n}\n```\n\n## Step 2: Extract Data (only if invoice)\n\n### Available Categories\n{{ $('ProcessingInput').item.json.allowed_categories }}\n\n### Current Budget Status\n{{ $('ProcessingInput').item.json.budgets_context }}\n\n### Extraction Tasks\n1. Extract: vendor, amount, currency, date, invoice_number\n2. Normalize vendor name (e.g., 'Amazon Web Services EMEA SARL' → 'AWS')\n3. Categorize based on SERVICE PROVIDED:\n   - READ invoice line items and descriptions\n   - UNDERSTAND what was purchased\n   - MATCH service type to category\n4. Detect anomalies (unusual amount for vendor type)\n\n## Step 3: Review Before Output\n\nBefore returning, verify:\n- Is AMOUNT the invoice total? (not subtotal, not asset value, not tax only)\n- Is VENDOR the company name? (not address, not bank details)\n- Is CATEGORY based on service provided? (not vendor name guess)\n- Does it make business sense?\n\n## Output JSON Schema\n\n### If valid invoice:\n```json\n{\n  \"is_invoice\": true,\n  \"vendor\": \"Original Company Name from Invoice\",\n  \"vendor_normalized\": \"Short Name\",\n  \"amount\": 123.45,\n  \"currency\": \"EUR\",\n  \"date\": \"YYYY-MM-DD\",\n  \"invoice_number\": \"INV-123\",\n  \"category\": \"Software\",\n  \"subcategory\": \"Cloud Services\",\n  \"confidence\": 0.95,\n  \"budget_warning\": false,\n  \"anomaly_detected\": false,\n  \"anomaly_reason\": \"\",\n  \"insight\": \"Monthly cloud hosting subscription\"\n}\n```\n\n### If NOT an invoice:\n```json\n{\n  \"is_invoice\": false,\n  \"document_type\": \"Contract\",\n  \"skip_reason\": \"This is a purchase agreement, not an invoice\"\n}\n```\n\n## Rules\n- Default currency: EUR if unclear\n- Date format: YYYY-MM-DD\n- invoice_number: empty string if not found\n- confidence: 0.0-1.0, be conservative\n- If document is not invoice: is_invoice = false\n- Always provide insight for valid invoices\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3.1
    },
    {
      "id": "069cf08b-44ff-4db9-a7ef-099ba6a1ec16",
      "name": "StructuredOutputParser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        162016,
        95536
      ],
      "parameters": {
        "autoFix": true,
        "schemaType": "manual",
        "inputSchema": "{\n  \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n  \"title\": \"DocumentClassificationResult\",\n  \"type\": \"object\",\n  \"required\": [\"is_invoice\"],\n  \"properties\": {\n    \"is_invoice\": {\n      \"type\": \"boolean\"\n    }\n  },\n  \"allOf\": [\n    {\n      \"if\": {\n        \"properties\": { \"is_invoice\": { \"const\": true } },\n        \"required\": [\"is_invoice\"]\n      },\n      \"then\": {\n        \"required\": [\n          \"vendor\",\n          \"vendor_normalized\",\n          \"amount\",\n          \"currency\",\n          \"date\",\n          \"invoice_number\",\n          \"category\",\n          \"confidence\"\n        ],\n        \"properties\": {\n          \"vendor\": { \"type\": \"string\" },\n          \"vendor_normalized\": { \"type\": \"string\" },\n          \"amount\": { \"type\": \"number\" },\n          \"currency\": { \"type\": \"string\", \"minLength\": 3, \"maxLength\": 3 },\n          \"date\": { \"type\": \"string\", \"format\": \"date\" },\n          \"invoice_number\": { \"type\": \"string\" },\n          \"category\": { \"type\": \"string\" },\n          \"subcategory\": { \"type\": \"string\" },\n          \"confidence\": { \"type\": \"number\", \"minimum\": 0, \"maximum\": 1 },\n          \"budget_warning\": { \"type\": \"boolean\" },\n          \"anomaly_detected\": { \"type\": \"boolean\" },\n          \"anomaly_reason\": { \"type\": \"string\" },\n          \"insight\": { \"type\": \"string\" }\n        },\n        \"additionalProperties\": false\n      }\n    },\n    {\n      \"if\": {\n        \"properties\": { \"is_invoice\": { \"const\": false } },\n        \"required\": [\"is_invoice\"]\n      },\n      \"then\": {\n        \"required\": [\"document_type\", \"skip_reason\"],\n        \"properties\": {\n          \"document_type\": { \"type\": \"string\" },\n          \"skip_reason\": { \"type\": \"string\" }\n        },\n        \"additionalProperties\": false\n      }\n    }\n  ]\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "8313adbf-f2b6-4d43-9c08-da69491f3828",
      "name": "RestartMessage",
      "type": "n8n-nodes-base.telegram",
      "position": [
        159120,
        98096
      ],
      "webhookId": "68563bc1-0d74-4e0d-bca6-abc19b6bc3b0",
      "parameters": {
        "text": "=Data reset completed. Initialize workflow with /start command.",
        "chatId": "={{ $('GetAppSettings3').item.json.chat_id }}",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "id": "wyKnjaYmdKSyCmE1",
          "name": "InvoiceBudgetTracker"
        }
      },
      "typeVersion": 1.2
    }
  ],
  "pinData": {},
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "ForEachCategoryItem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge": {
      "main": [
        [
          {
            "node": "IfOcrSuccess",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Think": {
      "ai_tool": [
        [
          {
            "node": "BudgetAgent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Crypto": {
      "main": [
        [
          {
            "node": "InputFile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Think1": {
      "ai_tool": [
        [
          {
            "node": "AICategorizer",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "GetFiles": {
      "main": [
        [
          {
            "node": "LoopInput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfHasData": {
      "main": [
        [
          {
            "node": "CalcWeeklySummary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "InputFile": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "LoopInput": {
      "main": [
        [],
        [
          {
            "node": "LoopInput",
            "type": "main",
            "index": 0
          },
          {
            "node": "WorkflowConfig",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OcrOutput": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculator": {
      "ai_tool": [
        [
          {
            "node": "BudgetAgent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "GetBudgets": {
      "main": [
        [
          {
            "node": "ProcessingInput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetSummary": {
      "main": [
        [
          {
            "node": "CalcSummary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfApproved": {
      "main": [
        [
          {
            "node": "ForEachCategory",
            "type": "main",
            "index": 0
          },
          {
            "node": "RestartMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfFirstRun": {
      "main": [
        [
          {
            "node": "FirstRunOnlyStart",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "IfAuthorized",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OcrExtract": {
      "main": [
        [
          {
            "node": "OcrOutput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RenameFile": {
      "main": [
        [
          {
            "node": "SearchMonthFolder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BudgetAgent": {
      "main": [
        [
          {
            "node": "BudgetReply",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BudgetInput": {
      "main": [
        [
          {
            "node": "BudgetAgent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CalcSummary": {
      "main": [
        [
          {
            "node": "SummaryInput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "MoveToMonth": {
      "main": [
        [
          {
            "node": "SuccessLog",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SaveInvoice": {
      "main": [
        [
          {
            "node": "GetSummary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SaveSummary": {
      "main": [
        [
          {
            "node": "IfNeedsAlert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SetDefaults": {
      "main": [
        [
          {
            "node": "WelcomeMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BudgetMemory": {
      "ai_memory": [
        [
          {
            "node": "BudgetAgent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "IfAuthorized": {
      "main": [
        [
          {
            "node": "IfStartMessage",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "NotAuthorizedMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfNeedsAlert": {
      "main": [
        [
          {
            "node": "AlertMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfNewInvoice": {
      "main": [
        [
          {
            "node": "SaveInvoice",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "RenameAsDuplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfOcrSuccess": {
      "main": [
        [
          {
            "node": "GetBudgets",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "RenameToReview",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ResultFolder": {
      "main": [
        [
          {
            "node": "MoveToMonth",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "StorageInput": {
      "main": [
        [
          {
            "node": "CheckInvoiceExists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SummaryInput": {
      "main": [
        [
          {
            "node": "SaveSummary",
            "type": "main",
            "index": 0
          },
          {
            "node": "RenameFile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AICategorizer": {
      "main": [
        [
          {
            "node": "IfInvalidContent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ApproveRemove": {
      "main": [
        [
          {
            "node": "IfApproved",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BudgetTrigger": {
      "main": [
        [
          {
            "node": "GetAppSettings1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetAppConfig2": {
      "main": [
        [
          {
            "node": "GetMonthlySummaryText",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HourlyTrigger": {
      "main": [
        [
          {
            "node": "GetAppSettings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WeeklyTrigger": {
      "main": [
        [
          {
            "node": "GetAppSettings2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WorkflowInput": {
      "main": [
        [
          {
            "node": "GetMonthlySummary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetAppSettings": {
      "main": [
        [
          {
            "node": "IfRegistrationExists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfFolderExists": {
      "main": [
        [
          {
            "node": "ResultFolder",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "CreateMonthFolder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfStartMessage": {
      "main": [
        [
          {
            "node": "SetDefaults",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "BudgetInput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "JsonStorageMcp": {
      "ai_tool": [
        [
          {
            "node": "BudgetAgent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "MonthlySummary": {
      "ai_tool": [
        [
          {
            "node": "BudgetAgent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "MonthlyTrigger": {
      "main": [
        [
          {
            "node": "GetAppConfig2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RenameToReview": {
      "main": [
        [
          {
            "node": "ErrorAlert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WelcomeMessage": {
      "main": [
        [
          {
            "node": "SaveAppSettings",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "WorkflowConfig": {
      "main": [
        [
          {
            "node": "IfNotForReviewOrDuplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DownloadInvoice": {
      "main": [
        [
          {
            "node": "OcrExtract",
            "type": "main",
            "index": 0
          },
          {
            "node": "Crypto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ForEachCategory": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetAppSettings1": {
      "main": [
        [
          {
            "node": "IfFirstRun",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetAppSettings2": {
      "main": [
        [
          {
            "node": "GetWeeklySummary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetAppSettings3": {
      "main": [
        [
          {
            "node": "ApproveRemove",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ProcessingInput": {
      "main": [
        [
          {
            "node": "AICategorizer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetWeeklySummary": {
      "main": [
        [
          {
            "node": "IfHasData",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gpt4oBudgetAgent": {
      "ai_languageModel": [
        [
          {
            "node": "BudgetAgent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Gpt4oCategorizer": {
      "ai_languageModel": [
        [
          {
            "node": "AICategorizer",
            "type": "ai_languageModel",
            "index": 0
          },
          {
            "node": "StructuredOutputParser",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "IfInvalidContent": {
      "main": [
        [
          {
            "node": "RenameToReview",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "StorageInput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CalcWeeklySummary": {
      "main": [
        [
          {
            "node": "BuildWeeklyMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CreateMonthFolder": {
      "main": [
        [
          {
            "node": "ResultFolder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "FirstRunOnlyStart": {
      "main": [
        [
          {
            "node": "IfStartMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetMonthlySummary": {
      "main": [
        [
          {
            "node": "IfHasMonthlyData1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfHasMonthlyData1": {
      "main": [
        [
          {
            "node": "CalcMonthlySummary",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ErrorOutput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "RenameAsDuplicate": {
      "main": [
        [
          {
            "node": "DuplicateLog",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "SearchMonthFolder": {
      "main": [
        [
          {
            "node": "IfFolderExists",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "BuildWeeklyMessage": {
      "main": [
        [
          {
            "node": "WeeklySummaryMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CalcMonthlySummary": {
      "main": [
        [
          {
            "node": "BuildMonthlyMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "CheckInvoiceExists": {
      "main": [
        [
          {
            "node": "IfNewInvoice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ManualResetTrigger": {
      "main": [
        [
          {
            "node": "GetAppSettings3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ForEachCategoryItem": {
      "main": [
        [
          {
            "node": "DeleteItem",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfRegistrationExists": {
      "main": [
        [
          {
            "node": "GetFiles",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "GetMonthlySummaryText": {
      "main": [
        [
          {
            "node": "MonthlySummaryMessage",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "StructuredOutputParser": {
      "ai_outputParser": [
        [
          {
            "node": "AICategorizer",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "GetMonthlySummaryTrigger": {
      "main": [
        [
          {
            "node": "WorkflowInput",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IfNotForReviewOrDuplicate": {
      "main": [
        [
          {
            "node": "DownloadInvoice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}