{
  "id": "aDRgA0zAqjUD2yvU",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Smart Restaurant Order & Suggestion System with Gemini AI and Telegram",
  "tags": [],
  "nodes": [
    {
      "id": "4492f7c4-0f63-4cc9-9772-b1d8194dd2fb",
      "name": "New Order Trigger (Form)",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -880,
        360
      ],
      "parameters": {
        "options": {},
        "formTitle": "Oneclick Restaurant Order - Table number 1",
        "formFields": {
          "values": [
            {
              "fieldLabel": "Please enter your name",
              "placeholder": "John doe",
              "requiredField": true
            },
            {
              "fieldType": "number",
              "fieldLabel": "Please enter your phone number",
              "placeholder": "123456789"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Tandoori Chicken  -  250 Rupees"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Biryani - 200 Rupees"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Masala Dosa - 150 Rupees"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Idli vada - 100 Rupees"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Dal Tadka - 150 Rupees"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Steam Rice - 100 Rupees"
            },
            {
              "fieldLabel": "Paratha - 30 Rupees"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Paneer butter masal - 250 Rupees"
            },
            {
              "fieldType": "number",
              "fieldLabel": "Fix Thali - 150 Rupees"
            }
          ]
        },
        "formDescription": "Please add your dish quantity and submit to place your order"
      },
      "typeVersion": 2.2
    },
    {
      "id": "1e2209ba-20d6-4d2a-9f03-6a62b3c98f4e",
      "name": "Extract & Format Order Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -660,
        360
      ],
      "parameters": {
        "jsCode": "const input = $input.all();\nconst formData = input[0].json;\n\nconst name = formData[\"Please enter your name\"];\nconst mobile = String(formData[\"Please enter your phone number\"]);\n\nfunction generateCustomerId() {\n  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n  let id = '';\n  for (let i = 0; i < 6; i++) {\n    id += chars.charAt(Math.floor(Math.random() * chars.length));\n  }\n  return `CUST-${id}`;\n}\n\nconst customerId = generateCustomerId();\n\nconst dishes = Object.entries(formData)\n  .map(([key, value]) => {\n    const match = key.match(/^(.*)\\s*-\\s*(\\d+)\\s*Rupees$/);\n    if (!match) return null;\n    const rawQty = Number(value);\n    if (isNaN(rawQty) || rawQty < 1) return null;  // only >1\n    const unitPrice = Number(match[2]);\n    return {\n      dishName: match[1].trim(),\n      quantity: rawQty,\n      unitPrice,\n      totalPrice: rawQty * unitPrice\n    };\n  })\n  .filter(item => item !== null);\n\nreturn [\n  {\n    json: {\n      customerId,\n      name,\n      mobile,\n      dishes,\n    },\n  },\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "fc25b5bf-717a-40b9-9cf3-69bd12c3fc52",
      "name": "Save Customer Info",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -440,
        360
      ],
      "parameters": {
        "columns": {
          "value": {
            "Customer id": "={{ $json.customerId }}",
            "Customer name": "={{ $json.name }}",
            "costomer mobile number": "={{ $json.mobile }}"
          },
          "schema": [
            {
              "id": "Customer id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Customer id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Customer name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Customer name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "costomer mobile number",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "costomer mobile number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI/edit#gid=0",
          "cachedResultName": "customer details"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI/edit?usp=drivesdk",
          "cachedResultName": "restaurant order placement "
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "844defa5-d868-4397-a52e-9a165932aba0",
      "name": "Save Dish Info",
      "type": "n8n-nodes-base.code",
      "position": [
        -220,
        360
      ],
      "parameters": {
        "jsCode": "// Input comes from the previous node\nconst data = $('Extract & Format Order Data').first().json.dishes;\n\nreturn data;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c5d5435a-2d99-48f0-b5c2-48531fb12670",
      "name": "Prepare Dish Details for AI",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        0,
        360
      ],
      "parameters": {
        "columns": {
          "value": {
            "dish name": "={{ $json.dishName }}",
            "Customer id": "={{ $('Extract & Format Order Data').item.json.customerId }}",
            "actual price": "={{ $json.totalPrice }}",
            "dish quantity": "={{ $json.quantity }}",
            "per unit price": "={{ $json.unitPrice }}"
          },
          "schema": [
            {
              "id": "Customer id",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Customer id",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "dish name",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "dish name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "dish quantity",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "dish quantity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "per unit price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "per unit price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "actual price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "actual price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1326050181,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI/edit#gid=1326050181",
          "cachedResultName": "customer order details"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1QztyOVgP8vIAQGLeBNErIHqJ77fq4vDRVD1DvHJdGaI/edit?usp=drivesdk",
          "cachedResultName": "restaurant order placement "
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.6
    },
    {
      "id": "560536c7-a876-4418-9ad7-f4d3461d85f3",
      "name": "Clean Data for AI Input",
      "type": "n8n-nodes-base.code",
      "position": [
        220,
        360
      ],
      "parameters": {
        "jsCode": "// Fetch all incoming items\nconst items = $input.all();\n\n// Extract the raw row data (each item.json is one row)\nconst rawRows = items.map(item => item.json);\n\n// Bundle everything into a single field\nconst payload = { rows: rawRows };\n\n// Return a single output item whose json contains your full dataset\nreturn [{ json: { data: payload } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "c0a4ab92-9ae3-45ca-806c-f4e1e5e396cc",
      "name": "Gemini AI Dish Suggestion Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        440,
        360
      ],
      "parameters": {
        "text": "={{ $json.data }}",
        "options": {
          "systemMessage": "You are a friendly AI assistant for a restaurant, designed to suggest dishes that customers might enjoy based on their recent order. \n\nWe will provide you with structured JSON input representing a customer\u2019s previous order, for example:\n\nYou are a friendly AI assistant for a restaurant, designed to suggest dishes that customers might enjoy based on their recent order. \n\nWe will provide you with structured JSON input representing a customer\u2019s previous order, for example:\n\n{\n  \"customerId\": \"CUST-1D0RWH\",\n  \"name\": \"ajay\",\n  \"mobile\": \"9898989898\",\n  \"dishes\": [\n    { \"dishName\": \"Tandoori Chicken\", \"quantity\": 1, \"unitPrice\": 250, \"totalPrice\": 250 },\n    { \"dishName\": \"Masala Dosa\",       \"quantity\": 1, \"unitPrice\": 150, \"totalPrice\": 150 },\n    { \"dishName\": \"Idli vada\",         \"quantity\": 1, \"unitPrice\": 100, \"totalPrice\": 100 },\n    { \"dishName\": \"Dal Tadka\",         \"quantity\": 1, \"unitPrice\": 150, \"totalPrice\": 150 },\n    { \"dishName\": \"Paratha\",           \"quantity\": 2, \"unitPrice\": 30,  \"totalPrice\": 60 },\n    { \"dishName\": \"Paneer butter masal\",\"quantity\":1, \"unitPrice\": 250,\"totalPrice\":250 }\n  ]\n}\n\nYour job:\n1. Analyze the dishes\u2014look at cuisine types, flavors, categories, and quantities.\n2. Recommend **3\u20135 other dishes** likely to appeal to this customer, explaining *why* (e.g., complementary flavors, similar cuisines, balancing variety).\n3. Output JSON with:\n   - `suggestions`: an array of objects each with `dishName` and `reason`\n\n**Important formatting rules:**\n- Output must be strictly valid JSON (no extra text).\n- Follow this structure exactly:\n\n\nYour job:\n1. Analyze the dishes\u2014look at cuisine types, flavors, categories, and quantities.\n2. Recommend **3\u20135 other dishes** likely to appeal to this customer, explaining *why* (e.g., complementary flavors, similar cuisines, balancing variety).\n3. Output JSON with:\n   - `suggestions`: an array of objects each with `dishName` and `reason`\n\n**Important formatting rules:**\n- Output must be strictly valid JSON (no extra text).\n- Follow this structure exactly:"
        },
        "promptType": "define"
      },
      "typeVersion": 1.9
    },
    {
      "id": "d80e5505-1f6d-4904-b497-b62530f284e2",
      "name": "Format AI Suggestions for Telegram",
      "type": "n8n-nodes-base.code",
      "position": [
        816,
        360
      ],
      "parameters": {
        "jsCode": "// Step 1: Fetch the raw output from the AI Agent node\nconst aiResponse = $node[\"Gemini AI Dish Suggestion Agent\"].json.output; // Update \"AI Agent\" to your node name\n\n// Step 2: Strip Markdown fences if present\nconst markdownPattern = /^```json\\s*([\\s\\S]*)\\s*```$/;\nconst cleaned = aiResponse.replace(markdownPattern, \"$1\");\n\n// Step 3: Parse JSON safely\nlet parsed;\ntry {\n  parsed = JSON.parse(cleaned);\n} catch (err) {\n  throw new Error(`Failed to parse AI response JSON: ${err.message}`);\n}\n\n// Step 4: Return each suggestion as its own item (n8n format)\nreturn parsed.suggestions.map(s => ({\n  json: {\n    customerId: parsed.customerId,\n    ...s\n  }\n}));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c902fee2-f89a-42c8-92ea-4bced23561b7",
      "name": "Send Suggestions via Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1036,
        360
      ],
      "parameters": {
        "text": "={{ $json.dishName }}\n\n{{ $json.reason }}",
        "chatId": "newchatid",
        "additionalFields": {}
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "068d712a-eddc-4021-8c3f-b601e767af92",
      "name": "Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        468,
        580
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-2.5-pro"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "29206de4-5ee1-44e0-9e48-6440f390a981",
      "name": "Think Tool",
      "type": "@n8n/n8n-nodes-langchain.toolThink",
      "position": [
        588,
        580
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "9f542a6c-37d5-4acb-a27d-64c1043e7b2e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -910,
        0
      ],
      "parameters": {
        "color": 5,
        "width": 160,
        "height": 520,
        "content": "Triggered when a customer submits their dish order form."
      },
      "typeVersion": 1
    },
    {
      "id": "4d847217-066e-4323-afbd-03fe71074cc3",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -470,
        0
      ],
      "parameters": {
        "color": 4,
        "width": 160,
        "height": 520,
        "content": "Adds customer details to the Google Sheet.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "63dd550d-71bd-4599-858d-6c1336bd4aed",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -30,
        0
      ],
      "parameters": {
        "color": 5,
        "width": 160,
        "height": 520,
        "content": "Gathers final dish data to send to the AI agent.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a954f2da-409f-4a5e-b31e-70ffd34ff718",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        190,
        0
      ],
      "parameters": {
        "width": 160,
        "height": 520,
        "content": "Reformats the data to improve AI understanding."
      },
      "typeVersion": 1
    },
    {
      "id": "f85f9bc1-c82a-475d-bfd5-5e1cc68b67c3",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        786,
        0
      ],
      "parameters": {
        "color": 4,
        "width": 160,
        "height": 520,
        "content": "Converts Gemini output into Telegram-friendly message format."
      },
      "typeVersion": 1
    },
    {
      "id": "7ba85c44-5f48-482b-b385-81f819290c54",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1006,
        0
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 520,
        "content": "Sends dish suggestions directly to the customer."
      },
      "typeVersion": 1
    },
    {
      "id": "7e499f3f-1037-4d71-a40a-45669b4ac16c",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -250,
        0
      ],
      "parameters": {
        "color": 3,
        "width": 160,
        "height": 520,
        "content": "Stores ordered dish quantities and types to a separate sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "587a6136-fc12-4c0a-8fb1-a3b06026cb11",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        440,
        0
      ],
      "parameters": {
        "color": 6,
        "width": 260,
        "height": 520,
        "content": "Uses Gemini AI to recommend related dishes or offers."
      },
      "typeVersion": 1
    },
    {
      "id": "5f0d16a4-be36-4a56-8b4e-05093cfeaa68",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -690,
        0
      ],
      "parameters": {
        "width": 160,
        "height": 520,
        "content": "Formats incoming form fields for further processing."
      },
      "typeVersion": 1
    },
    {
      "id": "286198a1-70dc-4d08-babf-dc24b127bf72",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -360,
        -540
      ],
      "parameters": {
        "color": 2,
        "width": 800,
        "height": 320,
        "content": "### This workflow helps automate restaurant order processing and customer engagement by:\n\n- Saving Time: Automatically records customer and dish data without manual entry.\n\n- Personalizing Experience: AI suggests relevant dishes or combos to upsell or enhance the order.\n\n- Centralized Tracking: All order data is logged into Google Sheets for real-time access and analytics.\n\n- Instant Outreach: Sends dish suggestions directly to customers via Telegram within seconds.\n\n- Scalability: Easily handles multiple orders with AI-driven intelligence\u2014ideal for growing restaurants.\n\n"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "3910b529-9989-490f-ba6d-ed97e80f157a",
  "connections": {
    "Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Gemini AI Dish Suggestion Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Think Tool": {
      "ai_tool": [
        [
          {
            "node": "Gemini AI Dish Suggestion Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Save Dish Info": {
      "main": [
        [
          {
            "node": "Prepare Dish Details for AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Save Customer Info": {
      "main": [
        [
          {
            "node": "Save Dish Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Clean Data for AI Input": {
      "main": [
        [
          {
            "node": "Gemini AI Dish Suggestion Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "New Order Trigger (Form)": {
      "main": [
        [
          {
            "node": "Extract & Format Order Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract & Format Order Data": {
      "main": [
        [
          {
            "node": "Save Customer Info",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Dish Details for AI": {
      "main": [
        [
          {
            "node": "Clean Data for AI Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Gemini AI Dish Suggestion Agent": {
      "main": [
        [
          {
            "node": "Format AI Suggestions for Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format AI Suggestions for Telegram": {
      "main": [
        [
          {
            "node": "Send Suggestions via Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}