{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "cb31bbea-fa34-4d6f-a752-9624ea163f80",
      "name": "Filter: Is Image Message?",
      "type": "n8n-nodes-base.if",
      "position": [
        -528,
        1024
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "id-1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.body.events[0].message.type }}",
              "rightValue": "image"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "2a7ce988-1076-4338-82b2-acbae2208c8b",
      "name": "Download LINE Image File",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -320,
        1024
      ],
      "parameters": {
        "url": "=https://api-data.line.me/v2/bot/message/{{ $json.body.events[0].message.id }}/content",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "5618729f-5be5-4a4d-82d8-69e709e20715",
      "name": "AI Agent: Extract Receipt Data",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -128,
        1024
      ],
      "parameters": {
        "text": "Analyze this receipt image and extract the data.",
        "options": {
          "systemMessage": "You are a professional accounting assistant. Extract the 'date' (YYYY/MM/DD), 'store', 'amount' (number only), and 'category' from the receipt. Category must be one of: [Food, Daily Needs, Transport, Entertainment, Others]."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 3
    },
    {
      "id": "0fea44d5-2360-4e2a-a5d0-3cf50593d224",
      "name": "OpenAI Model: OCR",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -224,
        1232
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "c0db1579-f7ef-42c2-a46f-4870a66b7623",
      "name": "Output Parser: Structured Data",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -32,
        1232
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"date\": \"2023/10/25\",\n  \"store\": \"Store Name\",\n  \"amount\": 1250,\n  \"category\": \"Food\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "e232a100-9f1b-496d-a2f2-f1a140dd293b",
      "name": "Google Sheets: Check Duplicate",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        176,
        1024
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5,
      "alwaysOutputData": true
    },
    {
      "id": "81b28408-649a-46c1-9bd5-1ac8b1c82a8c",
      "name": "Filter: Duplicate Found?",
      "type": "n8n-nodes-base.if",
      "position": [
        384,
        1024
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "id-1",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.row_number }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "3f2eae67-374c-485f-bd24-703fbf498a00",
      "name": "LINE: Notify Duplicate",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        576,
        928
      ],
      "parameters": {
        "url": "https://api.line.me/v2/bot/message/reply",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"replyToken\": \"{{ $('LINE Webhook1').item.json.body.events[0].replyToken }}\",\n  \"messages\": [\n    {\n      \"type\": \"text\",\n      \"text\": \"\u26a0\ufe0f This receipt is already registered.\\n({{ $('AI Agent: Extract Receipt Data').first().json.output.date }} / {{ $('AI Agent: Extract Receipt Data').first().json.output.amount }} JPY)\"\n    }\n  ]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "21d276d8-1356-4096-8e00-43a60a404fcc",
      "name": "Prepare Image Data",
      "type": "n8n-nodes-base.set",
      "position": [
        576,
        1120
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "7f0d26d6-709f-497e-8884-7c7625649414",
              "name": "data",
              "type": "binary",
              "value": "={{ $('Download LINE Image File').item.binary.data }}"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "5800aea2-5722-419d-8746-26a7a11e28cb",
      "name": "Google Drive: Save Proof",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        768,
        1120
      ],
      "parameters": {
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_FOLDER_ID"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "5e683814-7094-458d-aad3-745ab07dd6ff",
      "name": "Google Sheets: Add Row",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        944,
        1120
      ],
      "parameters": {
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "e9026ee0-e859-403e-8e85-6dc532aa47cd",
      "name": "Google Sheets: Fetch History",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1120,
        1120
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "b72b3741-08b7-406d-b5a8-ae63768a3daf",
      "name": "Calculate Monthly Totals",
      "type": "n8n-nodes-base.code",
      "position": [
        1296,
        1120
      ],
      "parameters": {
        "jsCode": "const today = new Date();\nconst currentMonth = today.getMonth();\nconst currentYear = today.getFullYear();\n\nlet totalThisMonth = 0;\nconst current = $('AI Agent: Extract Receipt Data').item.json.output;\n\nfor (const item of $input.all()) {\n  const row = item.json;\n  if (!row['Date']) continue;\n  const d = new Date(row['Date'].replace(/\\//g, '-'));\n  if (d.getMonth() === currentMonth && d.getFullYear() === currentYear) {\n    totalThisMonth += Number(row['Amount'] || 0);\n  }\n}\n\nreturn {\n  header: \"\u2705 Entry Successful\",\n  monthlyTotal: totalThisMonth,\n  store: current.store,\n  amount: current.amount\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "902800ce-018f-4a12-ab4c-55f19be1650f",
      "name": "AI Agent: Business Advice",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1504,
        1120
      ],
      "parameters": {
        "text": "=Current: {{ $json.amount }} JPY at {{ $json.store }}. Total this month: {{ $json.monthlyTotal }} JPY. Provide one brief financial advice.",
        "options": {
          "systemMessage": "You are a professional business consultant. Provide one sharp, short advice based on the user's spending data."
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "6e0490c0-383f-4321-8e28-8c68092c3943",
      "name": "LINE: Final Confirmation",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1776,
        1120
      ],
      "parameters": {
        "url": "https://api.line.me/v2/bot/message/reply",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"replyToken\": \"{{ $('LINE Webhook1').item.json.body.events[0].replyToken }}\",\n  \"messages\": [\n    {\n      \"type\": \"text\",\n      \"text\": \"{{ $('Calculate Monthly Totals').item.json.header }}\\n---\\nMonthly Total: {{ $('Calculate Monthly Totals').item.json.monthlyTotal.toLocaleString() }} JPY\\n\\n\ud83d\udca1 AI Advice:\\n{{ $json.output }}\"\n    }\n  ]\n}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "d3bf7889-ad4e-41e9-ab8b-152c2f8c7413",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -752,
        960
      ],
      "parameters": {
        "color": 7,
        "width": 840,
        "height": 400,
        "content": "### Phase 1: Ingestion & OCR"
      },
      "typeVersion": 1
    },
    {
      "id": "37dad164-391b-4a34-879c-c1bdfe4e278c",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        144,
        960
      ],
      "parameters": {
        "color": 7,
        "width": 450,
        "height": 400,
        "content": "### Phase 2: Security"
      },
      "typeVersion": 1
    },
    {
      "id": "0e0b7c70-a482-476f-bc8e-5fddb91a2472",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        960
      ],
      "parameters": {
        "color": 7,
        "width": 1280,
        "height": 400,
        "content": "### Phase 3: Storage & Intelligence"
      },
      "typeVersion": 1
    },
    {
      "id": "d0436ca8-ca3f-468e-8ac5-a6d9d9c9c993",
      "name": "OpenAI Model: Advice",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        1504,
        1328
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "00d589dc-95e3-4047-8455-e43483a51cd1",
      "name": "LINE Webhook1",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -736,
        1024
      ],
      "parameters": {
        "path": "line-receipt-tracker",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "2978171d-45f7-4290-8352-9deb03542e5b",
      "name": "Workflow Documentation1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1024,
        448
      ],
      "parameters": {
        "width": 646,
        "height": 483,
        "content": "## \ud83d\ude80 Manage expenses with AI insights through LINE\n\n### ## How it works\nThis workflow automates the tedious task of manual expense entry via LINE.\n1. **Capture**: The user sends a photo of a receipt to the LINE Bot.\n2. **AI OCR**: OpenAI processes the image to extract the date, store name, amount, and category.\n3. **Validation**: The system checks Google Sheets to prevent duplicate entries based on date and amount.\n4. **Storage**: Receipt images are archived in Google Drive, and structured data is logged into Google Sheets.\n5. **Financial Advice**: AI analyzes your monthly spending and provides a personalized business insight.\n\n### ## Setup steps\n1. **LINE**: Set up a Messaging API Channel and obtain the Channel Access Token.\n2. **Google Sheets**: Prepare a sheet with columns: `Date`, `Amount`, `Store`, `Category`.\n3. **Google Drive**: Create a folder for receipt images and copy its ID into the Drive node.\n4. **Credentials**: Set up OpenAI, LINE, and Google OAuth credentials in n8n.\n5. **Configuration**: Replace placeholder IDs in the Google Sheets, Google Drive, and HTTP Request nodes."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "LINE Webhook1": {
      "main": [
        [
          {
            "node": "Filter: Is Image Message?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Model: OCR": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent: Extract Receipt Data",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Image Data": {
      "main": [
        [
          {
            "node": "Google Drive: Save Proof",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Model: Advice": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent: Business Advice",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets: Add Row": {
      "main": [
        [
          {
            "node": "Google Sheets: Fetch History",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Monthly Totals": {
      "main": [
        [
          {
            "node": "AI Agent: Business Advice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download LINE Image File": {
      "main": [
        [
          {
            "node": "AI Agent: Extract Receipt Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter: Duplicate Found?": {
      "main": [
        [
          {
            "node": "LINE: Notify Duplicate",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Prepare Image Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Drive: Save Proof": {
      "main": [
        [
          {
            "node": "Google Sheets: Add Row",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent: Business Advice": {
      "main": [
        [
          {
            "node": "LINE: Final Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter: Is Image Message?": {
      "main": [
        [
          {
            "node": "Download LINE Image File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets: Fetch History": {
      "main": [
        [
          {
            "node": "Calculate Monthly Totals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent: Extract Receipt Data": {
      "main": [
        [
          {
            "node": "Google Sheets: Check Duplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Sheets: Check Duplicate": {
      "main": [
        [
          {
            "node": "Filter: Duplicate Found?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Output Parser: Structured Data": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent: Extract Receipt Data",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    }
  }
}