{
  "name": "02 - Photo OCR Handler",
  "nodes": [
    {
      "parameters": {
        "updates": [
          "message"
        ]
      },
      "id": "telegram-trigger-photo",
      "name": "Telegram Photo Trigger",
      "type": "n8n-nodes-base.telegramTrigger",
      "typeVersion": 1,
      "position": [
        250,
        300
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json.message.chat.id}}",
              "value2": "={{$env.ALLOWED_CHAT_ID}}"
            }
          ]
        }
      },
      "id": "check-chat-id-photo",
      "name": "Check Chat ID",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        450,
        300
      ]
    },
    {
      "parameters": {
        "chatId": "={{$json.message.chat.id}}",
        "text": "\ud83d\udcf8 Foto\u011fraf i\u015fleniyor..."
      },
      "id": "processing-message",
      "name": "Send Processing Message",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        650,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "get",
        "fileId": "={{$json.message.photo[$json.message.photo.length - 1].file_id}}"
      },
      "id": "get-photo",
      "name": "Get Photo File",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        850,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{$env.TESSERACT_API_URL}}/ocr",
        "options": {
          "timeout": 30000
        },
        "sendBinaryData": true,
        "binaryPropertyName": "data"
      },
      "id": "call-tesseract",
      "name": "Call Tesseract OCR",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        1050,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "const ocrText = $input.first().json.text || '';\nreturn { json: { ocrText: ocrText.trim() } };"
      },
      "id": "extract-text",
      "name": "Extract OCR Text",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1250,
        200
      ]
    },
    {
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json.ocrText}}",
              "operation": "isNotEmpty"
            }
          ]
        }
      },
      "id": "check-ocr-success",
      "name": "Check OCR Success",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        1450,
        200
      ]
    },
    {
      "parameters": {
        "chatId": "={{$node[\"Telegram Photo Trigger\"].json.message.chat.id}}",
        "text": "\u274c Foto\u011fraftan metin \u00e7\u0131kar\u0131lamad\u0131. L\u00fctfen daha net bir foto\u011fraf g\u00f6nderin veya manuel olarak giri\u015f yap\u0131n."
      },
      "id": "ocr-fail-message",
      "name": "Send OCR Fail Message",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        1650,
        300
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "filePath": "/prompts/finance_parser.txt"
      },
      "id": "read-prompt-photo",
      "name": "Read Prompt",
      "type": "n8n-nodes-base.readBinaryFile",
      "typeVersion": 1,
      "position": [
        1650,
        100
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{$env.OLLAMA_BASE_URL}}/api/generate",
        "options": {
          "timeout": 30000
        },
        "bodyParameters": {
          "parameters": [
            {
              "name": "model",
              "value": "llama3.1"
            },
            {
              "name": "prompt",
              "value": "={{$node[\"Read Prompt\"].json.data}}\\n\\nOCR \u00c7\u0131kt\u0131s\u0131: {{$node[\"Extract OCR Text\"].json.ocrText}}\\n\\nSadece JSON d\u00f6nd\u00fcr, ba\u015fka a\u00e7\u0131klama yapma."
            },
            {
              "name": "stream",
              "value": false
            }
          ]
        }
      },
      "id": "call-ollama-photo",
      "name": "Call Ollama LLM",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 3,
      "position": [
        1850,
        100
      ]
    },
    {
      "parameters": {
        "jsCode": "const response = $input.first().json.response;\nconst parsedData = JSON.parse(response);\n\n// Generate fingerprint\nconst crypto = require('crypto');\nconst fingerprintString = `${parsedData.date}_${parsedData.amount}_${parsedData.description}`;\nconst fingerprint = crypto.createHash('sha256').update(fingerprintString).digest('hex');\n\nparsedData.fingerprint = fingerprint;\nparsedData.telegram_message_id = $('Telegram Photo Trigger').first().json.message.message_id;\nparsedData.raw_input = $('Extract OCR Text').first().json.ocrText;\nparsedData.source = 'photo';\n\nreturn { json: parsedData };"
      },
      "id": "parse-response-photo",
      "name": "Parse LLM Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2050,
        100
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT id FROM {{$json.type}}s WHERE fingerprint = '{{$json.fingerprint}}' LIMIT 1"
      },
      "id": "check-duplicate-photo",
      "name": "Check Duplicate",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        2250,
        100
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "number": [
            {
              "value1": "={{$json.length}}",
              "operation": "equal",
              "value2": 0
            }
          ]
        }
      },
      "id": "is-not-duplicate-photo",
      "name": "Is Not Duplicate",
      "type": "n8n-nodes-base.if",
      "typeVersion": 1,
      "position": [
        2450,
        100
      ]
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO {{$node[\"Parse LLM Response\"].json.type}}s (telegram_message_id, date, amount, currency, category, subcategory, bank, payment_method, source_name, description, fingerprint, confidence_score, source, raw_input, asset_type, asset_name, transaction_type, quantity, unit_price) VALUES ({{$node[\"Parse LLM Response\"].json.telegram_message_id}}, '{{$node[\"Parse LLM Response\"].json.date}}', {{$node[\"Parse LLM Response\"].json.amount}}, '{{$node[\"Parse LLM Response\"].json.currency}}', '{{$node[\"Parse LLM Response\"].json.category}}', '{{$node[\"Parse LLM Response\"].json.subcategory}}', '{{$node[\"Parse LLM Response\"].json.bank}}', '{{$node[\"Parse LLM Response\"].json.payment_method}}', '{{$node[\"Parse LLM Response\"].json.source_name}}', '{{$node[\"Parse LLM Response\"].json.description}}', '{{$node[\"Parse LLM Response\"].json.fingerprint}}', {{$node[\"Parse LLM Response\"].json.confidence}}, '{{$node[\"Parse LLM Response\"].json.source}}', '{{$node[\"Parse LLM Response\"].json.raw_input}}', '{{$node[\"Parse LLM Response\"].json.asset_type}}', '{{$node[\"Parse LLM Response\"].json.asset_name}}', '{{$node[\"Parse LLM Response\"].json.transaction_type}}', {{$node[\"Parse LLM Response\"].json.quantity}}, {{$node[\"Parse LLM Response\"].json.unit_price}}) RETURNING id"
      },
      "id": "insert-db-photo",
      "name": "Insert to Database",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        2650,
        100
      ],
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{$node[\"Telegram Photo Trigger\"].json.message.chat.id}}",
        "text": "\u2705 Foto\u011fraftan kay\u0131t eklendi!\\n\\n\ud83d\udcca T\u00fcr: {{$node[\"Parse LLM Response\"].json.type}}\\n\ud83d\udcb0 Tutar: {{$node[\"Parse LLM Response\"].json.amount}} {{$node[\"Parse LLM Response\"].json.currency}}\\n\ud83d\udcc1 Kategori: {{$node[\"Parse LLM Response\"].json.category}}\\n\ud83d\udcdd A\u00e7\u0131klama: {{$node[\"Parse LLM Response\"].json.description}}\\n\ud83d\udcc5 Tarih: {{$node[\"Parse LLM Response\"].json.date}}"
      },
      "id": "send-success-photo",
      "name": "Send Success Message",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        2850,
        100
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "chatId": "={{$node[\"Telegram Photo Trigger\"].json.message.chat.id}}",
        "text": "\u26a0\ufe0f Bu kay\u0131t zaten mevcut! Tekrar eklenmedi."
      },
      "id": "send-duplicate-photo",
      "name": "Send Duplicate Message",
      "type": "n8n-nodes-base.telegram",
      "typeVersion": 1,
      "position": [
        2650,
        200
      ],
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "Telegram Photo Trigger": {
      "main": [
        [
          {
            "node": "Check Chat ID",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Chat ID": {
      "main": [
        [
          {
            "node": "Send Processing Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Processing Message": {
      "main": [
        [
          {
            "node": "Get Photo File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Photo File": {
      "main": [
        [
          {
            "node": "Call Tesseract OCR",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call Tesseract OCR": {
      "main": [
        [
          {
            "node": "Extract OCR Text",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract OCR Text": {
      "main": [
        [
          {
            "node": "Check OCR Success",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check OCR Success": {
      "main": [
        [
          {
            "node": "Read Prompt",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send OCR Fail Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Prompt": {
      "main": [
        [
          {
            "node": "Call Ollama LLM",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Call Ollama LLM": {
      "main": [
        [
          {
            "node": "Parse LLM Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse LLM Response": {
      "main": [
        [
          {
            "node": "Check Duplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Duplicate": {
      "main": [
        [
          {
            "node": "Is Not Duplicate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Not Duplicate": {
      "main": [
        [
          {
            "node": "Insert to Database",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Duplicate Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert to Database": {
      "main": [
        [
          {
            "node": "Send Success Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 1,
  "updatedAt": "2026-02-07T23:34:27.213Z",
  "versionId": "1"
}