{
  "id": "YOUR_WORKFLOW_ID",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Master Expense Processor",
  "tags": [],
  "nodes": [
    {
      "id": "366d6b5d-97b0-4d2c-b616-c36dca573897",
      "name": "personal",
      "type": "n8n-nodes-base.if",
      "position": [
        240,
        -96
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "111765cf-cc89-4b22-b5f1-8d3dee67739e",
              "operator": {
                "type": "array",
                "operation": "contains",
                "rightType": "any"
              },
              "leftValue": "={{ $json[\"Expense Category\"] }}",
              "rightValue": "=Personal"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8988762e-61e3-4426-8925-5902c48d1e22",
      "name": "business",
      "type": "n8n-nodes-base.if",
      "position": [
        272,
        48
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "8e0cf8f8-568c-4528-8678-db1617658038",
              "operator": {
                "type": "array",
                "operation": "contains",
                "rightType": "any"
              },
              "leftValue": "={{ $json[\"Expense Category\"] }}",
              "rightValue": "Business"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "5f8454f2-66b5-4c8f-b9b4-39a109cb98dd",
      "name": "shared",
      "type": "n8n-nodes-base.if",
      "position": [
        320,
        192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a065d01d-eb83-484b-86bd-f300e1897f77",
              "operator": {
                "type": "array",
                "operation": "contains",
                "rightType": "any"
              },
              "leftValue": "={{ $json[\"Expense Category\"] }}",
              "rightValue": "Shared / Home"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a8312156-2ddd-4ea0-9a64-bc81ed415267",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -800,
        -48
      ],
      "parameters": {
        "options": {},
        "formTitle": "Expense Capture",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Expense Description"
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Expense Category",
              "multiselect": true,
              "fieldOptions": {
                "values": [
                  {
                    "option": "Personal"
                  },
                  {
                    "option": "Business"
                  },
                  {
                    "option": "Shared / Home"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Billing Period",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Current"
                  },
                  {
                    "option": "Retrospective"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Vendor Location",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Israel"
                  },
                  {
                    "option": "ROW"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldType": "file",
              "fieldLabel": "Receipt",
              "requiredField": true
            },
            {
              "fieldLabel": "Invoice"
            },
            {
              "fieldLabel": "Retro Expense Billing Period"
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "For biling period",
              "fieldOptions": {
                "values": [
                  {}
                ]
              }
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "16a28cb0-2922-43bf-bf96-400995beac6b",
      "name": "Extract from File",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -272,
        -288
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "Receipt"
      },
      "typeVersion": 1
    },
    {
      "id": "1b322926-6839-4476-b273-65ce9cf5df4f",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -32,
        -512
      ],
      "parameters": {
        "text": "={{ $json.text }}",
        "options": {
          "systemMessage": "You are a structured document interpretation assistant. Your task is to take the extracted answers from an OCR service applied to financial documents (invoices and receipts) and convert them into a structured JSON object following a strict schema.\n\nUse the extracted information from the document as your source.\n\nNormalize amounts to numbers (e.g. \"\u20aa1,234.00\" \u2192 1234.00), and use ISO 4217 codes for currencies (e.g., \"ILS\").\n\nNormalize country to ISO 3166-1 alpha-2 codes (e.g., \"Israel\" \u2192 IL).\n\nIf a value is not confidently found, return null.\n\nFor boolean fields (e.g., \"Was this paid with Paypal?\"), return true, false, or null.\n\nUse \"personal\" or \"business\" for expense type classification.\n\nFor the category fields:\n\nIf \"type\" is \"business\", select from the business categories list and leave the personal category as null.\n\nIf \"type\" is \"personal\", select from the personal list and leave the business category as null.\n\nProvide concise, clean, machine-readable JSON."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "c06903cc-294e-45c2-92b6-fea447ff5a1e",
      "name": "Google Gemini Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        240,
        -352
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "22e7e1dc-2196-4e20-8e09-f9340c3aa1e4",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        576,
        -448
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\n  \"total_amount\": 149.99,\n  \"currency\": \"ILS\",\n  \"billing_entity_name\": \"Example Company Ltd.\",\n  \"billing_entity_address\": \"City, Country\",\n  \"billing_entity_vat_id\": \"123456789\",\n  \"document_type\": \"invoice\",\n  \"document_number\": \"INV-2025-00123\",\n  \"document_date\": \"2025-07-31\",\n  \"due_date\": \"2025-08-15\",\n  \"payment_method\": \"credit_card\",\n  \"payment_method_last4\": \"1234\",\n  \"paid_with_paypal\": false,\n  \"line_items\": [\n    {\n      \"description\": \"API credits for document parsing\",\n      \"amount\": 149.99\n    }\n  ],\n  \"main_expenditure_description\": \"API credits for services\",\n  \"type\": \"business\",\n  \"business_category\": \"Cloud Services\",\n  \"personal_category\": null,\n  \"made_out_to_user\": false,\n  \"made_out_to_company\": true,\n  \"is_billing_entity_in_israel\": true,\n  \"billing_entity_country_code\": \"IL\"\n}\n"
      },
      "typeVersion": 1.3
    },
    {
      "id": "8326b498-8af3-43c6-a413-2238ce7dbb8a",
      "name": "Upload file",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        800,
        -368
      ],
      "parameters": {
        "name": "={{ $json.Receipt[0].filename }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.personal_drive_match.matched_month_folder_id }}"
        },
        "inputDataFieldName": "Receipt"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "2c12fae4-d316-40e1-8f56-5349314c92e6",
      "name": "Upload file1",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        976,
        -160
      ],
      "parameters": {
        "name": "={{ $json.Receipt[0].filename }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_BUSINESS_DRIVE_ID",
          "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_BUSINESS_DRIVE_ID",
          "cachedResultName": "Business Drive - Shared"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.matched_month_folder_id }}"
        },
        "inputDataFieldName": "Receipt"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "f576868c-7d35-4a36-94fd-f659ab415107",
      "name": "Code",
      "type": "n8n-nodes-base.code",
      "position": [
        560,
        -80
      ],
      "parameters": {
        "jsCode": "// Full CSV string including 2024\u20132026\nconst folderCSV = `\nyear,year_folder_id,month_number,month_name,month_folder_id\n2024,FOLDER_ID_PLACEHOLDER,01,January,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,02,February,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,03,March,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,04,April,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,05,May,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,06,June,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,07,July,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,08,August,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,09,September,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,10,October,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,11,November,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,12,December,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,01,January,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,02,February,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,03,March,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,04,April,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,05,May,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,06,June,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,07,July,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,08,August,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,09,September,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,10,October,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,11,November,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,12,December,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,01,January,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,02,February,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,03,March,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,04,April,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,05,May,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,06,June,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,07,July,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,08,August,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,09,September,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,10,October,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,11,November,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,12,December,FOLDER_ID_PLACEHOLDER\n`.trim();\n\n// Parse CSV into folder map\nconst folderMap = folderCSV\n  .split('\\n')\n  .slice(1)\n  .map(line => {\n    const [year, year_folder_id, month_number, month_name, month_folder_id] = line.split(',');\n    return { year, year_folder_id, month_number, month_name, month_folder_id };\n  });\n\nreturn items.map(item => {\n  const submittedAt = new Date(item.json.submittedAt);\n  const year = String(submittedAt.getUTCFullYear());\n  const month = String(submittedAt.getUTCMonth() + 1).padStart(2, '0');\n\n  const match = folderMap.find(entry => entry.year === year && entry.month_number === month);\n\n  if (!match) {\n    throw new Error(`No folder match found for year ${year}, month ${month}`);\n  }\n\n  return {\n    json: {\n      ...item.json,\n      matched_year: year,\n      matched_month: month,\n      matched_month_folder_id: match.month_folder_id,\n      matched_year_folder_id: match.year_folder_id\n    },\n    binary: item.binary || {}\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "ee42a0c0-c38b-48cc-a97d-fdd90d89e34c",
      "name": "Code1",
      "type": "n8n-nodes-base.code",
      "position": [
        464,
        -224
      ],
      "parameters": {
        "jsCode": "const folderCSV = `\nyear,year_folder_id,month_number,month_name,month_folder_id\n2024,FOLDER_ID_PLACEHOLDER,01,January,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,02,February,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,03,March,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,04,April,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,05,May,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,06,June,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,07,July,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,08,August,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,09,September,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,10,October,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,11,November,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,12,December,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,01,January,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,02,February,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,03,March,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,04,April,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,05,May,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,06,June,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,07,July,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,08,August,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,09,September,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,10,October,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,11,November,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,12,December,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,01,January,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,02,February,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,03,March,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,04,April,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,05,May,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,06,June,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,07,July,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,08,August,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,09,September,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,10,October,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,11,November,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,12,December,FOLDER_ID_PLACEHOLDER\n`.trim();\n\nconst folderMap = folderCSV\n  .split(\"\\n\")\n  .slice(1)\n  .map(line => {\n    const [year, year_folder_id, month_number, month_name, month_folder_id] = line.split(\",\");\n    return { year, year_folder_id, month_number, month_name, month_folder_id };\n  });\n\nreturn items.map(item => {\n  const submittedAt = new Date(item.json.submittedAt);\n  const year = String(submittedAt.getUTCFullYear());\n  const month = String(submittedAt.getUTCMonth() + 1).padStart(2, \"0\");\n\n  const match = folderMap.find(entry => entry.year === year && entry.month_number === month);\n\n  if (!match) {\n    throw new Error(`No folder match found for year ${year}, month ${month}`);\n  }\n\n  return {\n    json: {\n      ...item.json,\n      personal_drive_match: {\n        matched_year: year,\n        matched_month: month,\n        matched_year_folder_id: match.year_folder_id,\n        matched_month_folder_id: match.month_folder_id\n      }\n    },\n    binary: item.binary || {}\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "211b4848-5f68-4fcf-b925-a4d3da03443d",
      "name": "Code2",
      "type": "n8n-nodes-base.code",
      "position": [
        512,
        352
      ],
      "parameters": {
        "jsCode": "const sharedFolderCSV = `\nyear,year_folder_id,month_number,month_name,month_folder_id\n2024,FOLDER_ID_PLACEHOLDER,01,January,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,02,February,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,03,March,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,04,April,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,05,May,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,06,June,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,07,July,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,08,August,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,09,September,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,10,October,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,11,November,FOLDER_ID_PLACEHOLDER\n2024,FOLDER_ID_PLACEHOLDER,12,December,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,01,January,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,02,February,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,03,March,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,04,April,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,05,May,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,06,June,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,07,July,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,08,August,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,09,September,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,10,October,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,11,November,FOLDER_ID_PLACEHOLDER\n2025,FOLDER_ID_PLACEHOLDER,12,December,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,01,January,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,02,February,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,03,March,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,04,April,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,05,May,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,06,June,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,07,July,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,08,August,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,09,September,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,10,October,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,11,November,FOLDER_ID_PLACEHOLDER\n2026,FOLDER_ID_PLACEHOLDER,12,December,FOLDER_ID_PLACEHOLDER\n`.trim();\n\nconst folderMap = sharedFolderCSV\n  .split(\"\\n\")\n  .slice(1)\n  .map(line => {\n    const [year, year_folder_id, month_number, month_name, month_folder_id] = line.split(\",\");\n    return { year, year_folder_id, month_number, month_name, month_folder_id };\n  });\n\nreturn items.map(item => {\n  const submittedAt = new Date(item.json.submittedAt);\n  const year = String(submittedAt.getUTCFullYear());\n  const month = String(submittedAt.getUTCMonth() + 1).padStart(2, \"0\");\n\n  const match = folderMap.find(entry => entry.year === year && entry.month_number === month);\n\n  if (!match) {\n    throw new Error(`No shared folder match found for year ${year}, month ${month}`);\n  }\n\n  return {\n    json: {\n      ...item.json,\n      shared_drive_match: {\n        matched_year: year,\n        matched_month: month,\n        matched_year_folder_id: match.year_folder_id,\n        matched_month_folder_id: match.month_folder_id\n      }\n    },\n    binary: item.binary || {}\n  };\n});\n"
      },
      "typeVersion": 2
    },
    {
      "id": "ca1baad9-432a-4ccf-9060-620aec1205ad",
      "name": "Upload file2",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        784,
        288
      ],
      "parameters": {
        "name": "={{ $json.Receipt[0].filename }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SHARED_DRIVE_ID",
          "cachedResultUrl": "https://drive.google.com/drive/folders/YOUR_SHARED_DRIVE_ID",
          "cachedResultName": "Shared Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.shared_drive_match.matched_year_folder_id }}"
        },
        "inputDataFieldName": "Receipt"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "05133746-35a7-45f6-90da-a885f478615f",
      "name": "Merge2",
      "type": "n8n-nodes-base.merge",
      "position": [
        1024,
        176
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "combineBy": "combineByPosition"
      },
      "typeVersion": 3.2
    },
    {
      "id": "a7120d38-1440-488a-8c1c-c3c8556fcc15",
      "name": "Send a message",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1264,
        48
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\" />\n  <style>\n    body {\n      background-color: #f4f4f4;\n      font-family: Arial, sans-serif;\n      padding: 20px;\n      color: #333;\n    }\n    .container {\n      background-color: #ffffff;\n      border: 1px solid #dddddd;\n      max-width: 600px;\n      margin: auto;\n      padding: 20px;\n    }\n    h2 {\n      color: #2c3e50;\n      margin-top: 0;\n    }\n    table {\n      width: 100%;\n      border-collapse: collapse;\n      margin-top: 16px;\n    }\n    th, td {\n      padding: 8px;\n      border-bottom: 1px solid #eeeeee;\n      text-align: left;\n      vertical-align: top;\n    }\n    .footer {\n      margin-top: 24px;\n      font-size: 12px;\n      color: #888;\n    }\n    .drive-link {\n      display: inline-block;\n      margin-top: 20px;\n      padding: 10px 18px;\n      background-color: #ffffff;\n      color: #1a73e8;\n      border: 2px solid #1a73e8;\n      text-decoration: none;\n      border-radius: 4px;\n      font-weight: bold;\n    }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <h2>\ud83d\udccc New Household Expense Recorded</h2>\n    <p>Dear Users,</p>\n    <p>A new <strong>{{ $json.output.transaction_type }}</strong> household expense has been recorded. The details are as follows:</p>\n\n    <table>\n      <tr>\n        <th>Receipt Number</th>\n        <td>{{ $json.output.receipt_number }}</td>\n      </tr>\n      <tr>\n        <th>Date</th>\n        <td>{{ $json.output.transaction_date }}</td>\n      </tr>\n      <tr>\n        <th>Category</th>\n        <td>{{ $json.output.personal_category }}</td>\n      </tr>\n      <tr>\n        <th>Vendor</th>\n        <td>{{ $json.output.vendor_name }}</td>\n      </tr>\n      <tr>\n        <th>Vendor Address</th>\n        <td>{{ $json.output.vendor_address }}</td>\n      </tr>\n      <tr>\n        <th>Vendor Phone</th>\n        <td>{{ $json.output.vendor_phone_number }}</td>\n      </tr>\n      <tr>\n        <th>Payment Method</th>\n        <td>{{ $json.output.payment_method }}</td>\n      </tr>\n      <tr>\n        <th>Item(s)</th>\n        <td>\n          {{ $json.output.items[0].quantity }} \u00d7 {{ $json.output.items[0].description }} @ {{ $json.output.items[0].unit_price }} {{ $json.output.currency }}\n        </td>\n      </tr>\n      <tr>\n        <th>Tax</th>\n        <td>{{ $json.output.tax_amount }} {{ $json.output.currency }}</td>\n      </tr>\n      <tr>\n        <th>Total Amount</th>\n        <td><strong>{{ $json.output.total_amount }} {{ $json.output.currency }}</strong></td>\n      </tr>\n      <tr>\n        <th>Expense Owner</th>\n        <td>{{ $json.output.expense_owner }}</td>\n      </tr>\n      <tr>\n        <th>Owner Address</th>\n        <td>{{ $json.output.expense_owner_address }}</td>\n      </tr>\n    </table>\n\n    <a class=\"drive-link\" href=\"{{ $json.webViewLink }}\" target=\"_blank\">\n      \ud83d\udcce View Receipt in Google Drive\n    </a>\n\n    <div class=\"footer\">\n      This email was generated automatically by your household expense tracking system.\n    </div>\n  </div>\n</body>\n</html>\n",
        "options": {
          "senderName": "Apps",
          "appendAttribution": false,
          "replyToSenderOnly": false
        },
        "subject": "=New expense captured:  {{ $json.output.items[0].description }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "448844b5-d210-498d-8eb8-54ae8d7f9936",
      "name": "Send a message1",
      "type": "n8n-nodes-base.gmail",
      "position": [
        528,
        80
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "This is an expense for processing",
        "options": {
          "attachmentsUi": {
            "attachmentsBinary": [
              {
                "property": "Receipt"
              }
            ]
          }
        },
        "subject": "Expense"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e791c8b3-ee79-4db3-a4aa-a23067a4fa52",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        -112
      ],
      "parameters": {
        "width": 208,
        "height": 80,
        "content": "# Personal"
      },
      "typeVersion": 1
    },
    {
      "id": "4016b83c-025c-4e2b-b461-a5813e159ca9",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -224,
        48
      ],
      "parameters": {
        "width": 208,
        "height": 80,
        "content": "# Business"
      },
      "typeVersion": 1
    },
    {
      "id": "8e40fc28-58df-4f09-b478-fdb2b197ac34",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        208
      ],
      "parameters": {
        "width": 208,
        "height": 80,
        "content": "# Shared"
      },
      "typeVersion": 1
    },
    {
      "id": "b63b8504-4c44-4045-85ee-32c79c8519dc",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -560,
        -192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "5e5d048a-2c50-489b-a0f2-d3dd093746b6",
              "operator": {
                "type": "array",
                "operation": "contains",
                "rightType": "any"
              },
              "leftValue": "={{ $json[\"Expense Category\"] }}",
              "rightValue": "Shared / Home"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "3c457e36-04e4-445d-aaa7-fe5c0605d0ff",
      "name": "Upload a file",
      "type": "n8n-nodes-base.s3",
      "position": [
        960,
        0
      ],
      "parameters": {
        "fileName": "=expenses/2025/{{ $json.Receipt[0].filename }}",
        "operation": "upload",
        "bucketName": "business-expenses",
        "additionalFields": {},
        "binaryPropertyName": "Receipt"
      },
      "credentials": {
        "s3": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "be9c204f-77d8-45e4-b0e0-e9f7197b59a4",
      "name": "Upload a file1",
      "type": "n8n-nodes-base.s3",
      "position": [
        784,
        -240
      ],
      "parameters": {
        "fileName": "=receipts/2025/{{ $json.Receipt[0].filename }}",
        "operation": "upload",
        "bucketName": "personal-expenses",
        "additionalFields": {},
        "binaryPropertyName": "Receipt"
      },
      "credentials": {
        "s3": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "37419632-4f39-4d07-a679-28a4cef8deed",
      "name": "Upload a file2",
      "type": "n8n-nodes-base.s3",
      "position": [
        784,
        448
      ],
      "parameters": {
        "fileName": "=receipts/2025/{{ $json.Receipt[0].filename }}",
        "operation": "upload",
        "bucketName": "shared-expenses",
        "additionalFields": {},
        "binaryPropertyName": "Receipt"
      },
      "credentials": {
        "s3": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "b9f722de-3c6a-4429-9394-b12ad530f339",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Extract from File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code": {
      "main": [
        [
          {
            "node": "Upload file1",
            "type": "main",
            "index": 0
          },
          {
            "node": "Upload a file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code1": {
      "main": [
        [
          {
            "node": "Upload file",
            "type": "main",
            "index": 0
          },
          {
            "node": "Upload a file1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code2": {
      "main": [
        [
          {
            "node": "Upload file2",
            "type": "main",
            "index": 0
          },
          {
            "node": "Upload a file2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge2": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "shared": {
      "main": [
        [
          {
            "node": "Code2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Merge2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "business": {
      "main": [
        [
          {
            "node": "Code",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send a message1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "personal": {
      "main": [
        [
          {
            "node": "Code1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload file": {
      "main": [
        []
      ]
    },
    "Upload file1": {
      "main": [
        []
      ]
    },
    "Upload file2": {
      "main": [
        [
          {
            "node": "Merge2",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Extract from File": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "personal",
            "type": "main",
            "index": 0
          },
          {
            "node": "business",
            "type": "main",
            "index": 0
          },
          {
            "node": "shared",
            "type": "main",
            "index": 0
          },
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}