Facture d'eau

Intermédiaire

Ceci est unMiscellaneous, Multimodal AIworkflow d'automatisation du domainecontenant 15 nœuds.Utilise principalement des nœuds comme Set, Code, Switch, Telegram, GoogleSheets. Automatiser le calcul des factures d'eau avec Telegram, Gemini AI et Google Sheets

Prérequis
  • Token Bot Telegram
  • Informations d'identification Google Sheets API
  • Clé API Google Gemini
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "id": "3dPhcViLijZ5zBah",
  "meta": {
    "instanceId": "f357e038067887a62c03e581da0f98dfa8010dcc02f1fa97f81df592773a1c40",
    "templateCredsSetupCompleted": true
  },
  "name": "TagihanAir",
  "tags": [],
  "nodes": [
    {
      "id": "0251a048-cd44-464c-8094-89a9baff4695",
      "name": "Déclencheur Telegram",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        -2688,
        -240
      ],
      "webhookId": "665df113-870a-4b73-832c-075ca8e3caa2",
      "parameters": {
        "updates": [
          "message"
        ],
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "9da0ef32-0aae-47d4-ad66-ddeb8ff60e07",
      "name": "Redirect Message Types",
      "type": "n8n-nodes-base.switch",
      "position": [
        -2384,
        -256
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Image Message",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "05b30af4-967b-4824-abdc-84a8292ac0e5",
                    "operator": {
                      "type": "object",
                      "operation": "exists",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.message.photo[0] }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra",
          "renameFallbackOutput": "Text Message"
        }
      },
      "typeVersion": 3.2
    },
    {
      "id": "22e0a88e-aa48-46f2-896a-99473313fe34",
      "name": "Get a file",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -1936,
        -240
      ],
      "webhookId": "4b59179c-2b2a-47fa-9a06-cfe9a8be8db7",
      "parameters": {
        "fileId": "={{ $json.message.photo[3].file_id }}",
        "resource": "file",
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "40406678-0fce-4f9a-9335-69e3600c84e8",
      "name": "Image Explainer",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        -1488,
        -64
      ],
      "parameters": {
        "text": "=Ambil angka didalam kotak m³\nCaption : {{ $('Telegram Trigger').item.json.message.caption }}",
        "messages": {
          "messageValues": [
            {
              "type": "HumanMessagePromptTemplate",
              "messageType": "imageBinary"
            }
          ]
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.4
    },
    {
      "id": "0d24bce4-067b-40af-bb51-b6ca5c0a9ae3",
      "name": "Modèle de chat Google Gemini",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        -1536,
        192
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "edfc1d10-e1b8-460c-b850-7eb4d1b5f30f",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        -1344,
        144
      ],
      "parameters": {
        "jsonSchemaExample": "{\n\t\"m3\": \"00000\",\n    \"caption\": \"Nama\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "8faed6ed-cabf-4ed2-a6bd-164ee72e1483",
      "name": "Get row(s) in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1136,
        -64
      ],
      "parameters": {
        "options": {
          "dataLocationOnSheet": {
            "values": {
              "rangeDefinition": "detectAutomatically"
            }
          }
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kbzli64xlywauDLgVVfc2FC4CHqnjzc3f9EU0kkvfIQ/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1kbzli64xlywauDLgVVfc2FC4CHqnjzc3f9EU0kkvfIQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kbzli64xlywauDLgVVfc2FC4CHqnjzc3f9EU0kkvfIQ/edit?usp=drivesdk",
          "cachedResultName": "Tagihan Air"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "da0f78a6-3146-4e15-911f-61f3f6a073e2",
      "name": "Append row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -256,
        -64
      ],
      "parameters": {
        "columns": {
          "value": {
            "Nama": "={{ $json.Nama }}",
            "Beban": "={{ $json.Beban }}",
            "Harga/m³": "={{ $json['Harga/m³'] }}",
            "Total Bayar": "={{ $json['Total Bayar'] }}",
            "Jumlah Bayar": "={{ $json['Jumlah Bayar'] }}",
            "Tanggal Input": "={{ $json.tanggalF }}",
            "Volume Saat Ini": "={{ $json['Volume Saat ini'] }}",
            "Volume Sebelumnya": "={{ $json['Volume Sebelumnya'] }}"
          },
          "schema": [
            {
              "id": "Nama",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Nama",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Volume Sebelumnya",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Volume Sebelumnya",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Volume Saat Ini",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Volume Saat Ini",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Harga/m³",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Harga/m³",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Jumlah Bayar",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Jumlah Bayar",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Beban",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Beban",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Total Bayar",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Total Bayar",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Tanggal Input",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Tanggal Input",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "useAppend": true
        },
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kbzli64xlywauDLgVVfc2FC4CHqnjzc3f9EU0kkvfIQ/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1kbzli64xlywauDLgVVfc2FC4CHqnjzc3f9EU0kkvfIQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1kbzli64xlywauDLgVVfc2FC4CHqnjzc3f9EU0kkvfIQ/edit?usp=drivesdk",
          "cachedResultName": "Tagihan Air"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "c58a7b4d-b780-4167-be6e-5f91cee2eb72",
      "name": "Note adhésive",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2016,
        32
      ],
      "parameters": {
        "width": 400,
        "height": 624,
        "content": "## 1. Create Google Sheet\nRows :\n- Nama\t\n- Volume Sebelumnya\t\n- Volume Saat Ini\t\n- Harga/m³\t\n- Jumlah Bayar\t\n- Beban\t\n- Total Bayar\t\n- Tanggal Input\n\n## 2. Create Telegram Bot\n- Open Telegram and search for @BotFather.\n- Use the command /newbot and follow the instructions (choose a name and username).\n- BotFather will give you a token.\n- Copy the token and paste it into your n8n (or automation platform) credentials.\n\n## 3. Create Your Gemini API Integration\n- Go to Google AI Studio.\n- Generate an API key for Gemini.\n- Paste the Gemini API key into your credentials."
      },
      "typeVersion": 1
    },
    {
      "id": "efe8f266-d509-4372-a98d-082af2f5d2c1",
      "name": "Note adhésive1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1136,
        336
      ],
      "parameters": {
        "color": 4,
        "width": 544,
        "height": 272,
        "content": "## Short Explanation of the Water Bill BOT\nEach resident sends a picture of the water meter along with a caption that includes their name to the chatbot.\nThe BOT automatically calculates the difference in volume between the previous and current payment.\nExample calculation:\nPrevious Volume: 535\nCurrent Volume: 545\nDifference: 10 m³\nIf the price per 1 m³ is Rp3,000, then 10 × 3,000 = Rp30,000\nAdditional mandatory fee (fixed charge): Rp3,000\nTotal = Rp33,000\n\n"
      },
      "typeVersion": 1
    },
    {
      "id": "ad11f386-8b9c-4e06-921b-bb8cd54fb5f4",
      "name": "Find Latest Row",
      "type": "n8n-nodes-base.code",
      "position": [
        -928,
        -64
      ],
      "parameters": {
        "jsCode": "const data = items.map(item => item.json);\n\nconst maxRowItem = data.reduce((max, current) => {\n  return current.row_number > max.row_number ? current : max;\n}, data[0]);\n\nreturn [\n  {\n    json: maxRowItem\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "ac746257-cbf5-40be-85de-7262071f643b",
      "name": "Format Bill Message",
      "type": "n8n-nodes-base.code",
      "position": [
        -64,
        -64
      ],
      "parameters": {
        "jsCode": "const current = $json;\nconst previous = $('Calculate Bill').item.json;\nconst previousInfo = $('Find Latest Row').item.json;\nconst user = $('Prepare Data for Sheet').item.json.user;\nconst nama = $('Prepare Data for Sheet').item.json.Nama;\n\nfunction formatRupiah(angka) {\n  return angka.toString().replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.');\n}\n\nfunction removeLeadingZeros(str) {\n  return str.toString().replace(/^0+/, '');\n}\n\nconst volPrevlong = Number(previous['Volume Sebelumnya']);\nconst volPrev = Number(current['Volume Sebelumnya']);\nconst volumeSelisihlalu = Math.abs(volPrevlong - volPrev);\nconst volNowRaw = current['Volume Saat Ini'];\nconst volNow = Number(volNowRaw);\nconst volumeSelisih = Math.abs(volNow - volPrev);\n\nconst volNowDisplay = removeLeadingZeros(volNowRaw);\n\nconst totalBayarNow = formatRupiah(current['Total Bayar']);\nconst totalBayarPrev = formatRupiah(previousInfo['Total Bayar']);\n\nreturn [\n  {\n    json: {\n      user,\n      nama,\n      tanggal_sebelumnya: previousInfo['Tanggal Input'],\n      tanggal_sekarang: current['Tanggal Input'],\n      vol_sebelumnyalagi: volPrevlong,\n      vol_sebelumnya: volPrev,\n      vol_saat_ini: volNowDisplay,\n      volume_selisihlalu: volumeSelisihlalu,\n      volume_selisih: volumeSelisih,\n      total_bayar_sekarang: `Rp${totalBayarNow}`,\n      total_bayar_sebelumnya: `Rp${totalBayarPrev}`\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "f68c7969-bdf0-4d70-a7e3-96894db6c2d8",
      "name": "Send Bill to Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        144,
        -64
      ],
      "webhookId": "d1f3b592-bfaa-4095-b613-46e52ecc754a",
      "parameters": {
        "text": "=Hallo Kak {{ $('Prepare Data for Sheet').item.json.user }}, \nberikut tagihan untuk Bapak/Ibu {{ $('Prepare Data for Sheet').item.json.Nama }}\n-----------------------------\n\n<b>Tagihan Sebelumnya</b>\n\n<b>{{ $json.tanggal_sebelumnya }}</b>\nVolume : {{ $('Calculate Bill').item.json['Volume Sebelumnya'] }} ➤ {{ $('Calculate Bill').item.json['Volume Saat Ini'] }} = {{ $json.volume_selisihlalu }}m³\nTotal Bayar : {{ $json.total_bayar_sebelumnya }}\nStatus : Lunas\n\n-----------------------------\n\n<b>Tagihan Saat Ini</b>\n\n<b>{{ $json.tanggal_sekarang }}</b>\nVolume : {{ $json.vol_sebelumnya }} ➤ {{ $json.vol_saat_ini }} = {{ $json.volume_selisih }}m³\nTotal Bayar : {{ $json.total_bayar_sekarang }}\nStatus : Pending\n\n<b>Silakan lakukan pembayaran melalui QRIS <a href=\"https://miftahrahmat.com\">disini</a> ( Bendahara RT )</b>\n",
        "chatId": "={{ $('Prepare Data for Sheet').item.json.chat_id }}",
        "additionalFields": {
          "parse_mode": "HTML",
          "appendAttribution": false,
          "reply_to_message_id": "={{ $('Prepare Data for Sheet').item.json.mess_id }}"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "e29bafb4-47de-4220-bf11-bb2c882be340",
      "name": "Prepare Data for Sheet",
      "type": "n8n-nodes-base.set",
      "position": [
        -512,
        -64
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d66900d4-cb6a-4bca-bca2-99c94f70d7e7",
              "name": "Volume Sebelumnya",
              "type": "number",
              "value": "={{ $json['Volume Saat Ini'] }}"
            },
            {
              "id": "4a2b3dda-e6ac-43b1-a8d4-3e8e6e49f443",
              "name": "Volume Saat ini",
              "type": "string",
              "value": "={{ $json.VolumeSaatini }}"
            },
            {
              "id": "888a80f9-effe-479b-9fcf-dea623bd5cb1",
              "name": "Nama",
              "type": "string",
              "value": "={{ $json.caption }}"
            },
            {
              "id": "73834b6e-1daf-494d-adc2-074178c77e0d",
              "name": "tanggalF",
              "type": "string",
              "value": "={{ $json.tanggalF }}"
            },
            {
              "id": "32823266-a5d3-42a2-9279-fbf989c2f763",
              "name": "Tanggal bayar sebelumnya",
              "type": "string",
              "value": "={{ $json['Tanggal Input'] }}"
            },
            {
              "id": "432c4403-74f5-46d4-9527-46d0b4fee725",
              "name": "Volume",
              "type": "number",
              "value": "={{ $json.Volume }}"
            },
            {
              "id": "40551b2e-d541-4cac-a7b9-0a7175f04467",
              "name": "Jumlah Bayar",
              "type": "number",
              "value": "={{ $json['Jumlah Bayar'] }}"
            },
            {
              "id": "20b5be6f-0e70-49db-95fb-db04f5bf6b69",
              "name": "Beban",
              "type": "number",
              "value": "={{ $json.Beban }}"
            },
            {
              "id": "a62d41b0-6f00-4ac3-b3a0-b5d558d8cee1",
              "name": "Total Bayar",
              "type": "number",
              "value": "={{ $json['Total Bayar'] }}"
            },
            {
              "id": "04aaabba-14fd-4232-97cc-c406bf127a53",
              "name": "Harga/m³",
              "type": "number",
              "value": "={{ $json['Harga/m³'] }}"
            },
            {
              "id": "f6738814-fd06-4e20-a727-6de499dac851",
              "name": "user",
              "type": "string",
              "value": "={{ $json.user }}"
            },
            {
              "id": "b3643859-3815-4a7b-82e0-87a7504ec190",
              "name": "chat_id",
              "type": "number",
              "value": "={{ $json.chat_id }}"
            },
            {
              "id": "bcd99fe0-0322-4a25-9453-017bc620a4ef",
              "name": "mess_id",
              "type": "number",
              "value": "={{ $json.mess_id }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "e24e6599-1475-478b-a83e-a026e6a8aca6",
      "name": "Calculate Bill",
      "type": "n8n-nodes-base.code",
      "position": [
        -720,
        -64
      ],
      "parameters": {
        "jsCode": "const item = $json;\n\nconst volumeSebelumnya = Number(item[\"Volume Saat Ini\"] || 0);\nconst volumeSekarang = String($('Image Explainer').first().json.output.m3).padStart(5, \"0\");\nconst hargaPerM3 = Number(item[\"Harga/m³\"] || 0);\nconst beban = Number(item[\"Beban\"] || 0);\nconst nama = item[\"Nama\"] || \"\";\n\nconst volume = volumeSekarang - volumeSebelumnya;\nconst jumlahBayar = volume * hargaPerM3;\nconst totalBayar = jumlahBayar + beban;\n\nconst inputDate = $now;\n\nconst dateObj = new Date(inputDate);\n\nconst hari = ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'];\nconst bulan = ['Januari', 'Februari', 'Maret', 'April', 'Mei', 'Juni', 'Juli', 'Agustus', 'September', 'Oktober', 'November', 'Desember'];\n\nconst namaHari = hari[dateObj.getDay()];\nconst tanggal = dateObj.getDate();\nconst namaBulan = bulan[dateObj.getMonth()];\nconst tahun = dateObj.getFullYear();\n\nconst formatted = `${namaHari}, ${tanggal} ${namaBulan} ${tahun}`;\n\nreturn [{\n  json: {\n    ...item,\n    VolumeSaatini: volumeSekarang,\n    Volume: volume,\n    \"Jumlah Bayar\": jumlahBayar,\n    \"Total Bayar\": totalBayar,\n    caption: nama,\n    tanggalF: formatted,\n    mess_id: $('Telegram Trigger').first().json.message.message_id,\n    chat_id: $('Telegram Trigger').first().json.message.chat.id,\n    user: $('Telegram Trigger').first().json.message.from.first_name\n  }\n}];"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "8fb90ae0-c3bb-4b63-976b-4faef238f2ba",
  "connections": {
    "22e0a88e-aa48-46f2-896a-99473313fe34": {
      "main": [
        [
          {
            "node": "40406678-0fce-4f9a-9335-69e3600c84e8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e24e6599-1475-478b-a83e-a026e6a8aca6": {
      "main": [
        [
          {
            "node": "e29bafb4-47de-4220-bf11-bb2c882be340",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ad11f386-8b9c-4e06-921b-bb8cd54fb5f4": {
      "main": [
        [
          {
            "node": "e24e6599-1475-478b-a83e-a026e6a8aca6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "40406678-0fce-4f9a-9335-69e3600c84e8": {
      "main": [
        [
          {
            "node": "8faed6ed-cabf-4ed2-a6bd-164ee72e1483",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Telegram Trigger": {
      "main": [
        [
          {
            "node": "9da0ef32-0aae-47d4-ad66-ddeb8ff60e07",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "da0f78a6-3146-4e15-911f-61f3f6a073e2": {
      "main": [
        [
          {
            "node": "ac746257-cbf5-40be-85de-7262071f643b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ac746257-cbf5-40be-85de-7262071f643b": {
      "main": [
        [
          {
            "node": "f68c7969-bdf0-4d70-a7e3-96894db6c2d8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "8faed6ed-cabf-4ed2-a6bd-164ee72e1483": {
      "main": [
        [
          {
            "node": "ad11f386-8b9c-4e06-921b-bb8cd54fb5f4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e29bafb4-47de-4220-bf11-bb2c882be340": {
      "main": [
        [
          {
            "node": "da0f78a6-3146-4e15-911f-61f3f6a073e2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9da0ef32-0aae-47d4-ad66-ddeb8ff60e07": {
      "main": [
        [
          {
            "node": "22e0a88e-aa48-46f2-896a-99473313fe34",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "40406678-0fce-4f9a-9335-69e3600c84e8",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "edfc1d10-e1b8-460c-b850-7eb4d1b5f30f": {
      "ai_outputParser": [
        [
          {
            "node": "40406678-0fce-4f9a-9335-69e3600c84e8",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Intermédiaire - Divers, IA Multimodale

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Intermédiaire
Nombre de nœuds15
Catégorie2
Types de nœuds10
Description de la difficulté

Adapté aux utilisateurs expérimentés, avec des workflows de complexité moyenne contenant 6-15 nœuds

Auteur
Miftah Rahmat

Miftah Rahmat

@miftahr

I’m an automation enthusiast specializing in n8n workflow design and integration.

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34