AutomationFlowsSlack & Telegram › Forecast Inventory and Route Purchase Orders with Google Sheets, Openai,…

Forecast Inventory and Route Purchase Orders with Google Sheets, Openai,…

Original n8n title: Forecast Inventory and Route Purchase Orders with Google Sheets, Openai, Telegram, Slack, and Gmail

ByRahul Joshi @rahul08 on n8n.io

This workflow runs daily to forecast SKU demand from Google Sheets data, drafts purchase-order justifications with OpenAI, routes critical and warning items for Telegram review and Slack alerts, logs decisions back to Google Sheets, and sends an HTML digest and supplier emails…

Event trigger★★★★★ complexityAI-powered38 nodesError TriggerSlackGoogle SheetsTelegramGmailOpenAITelegram Trigger
Slack & Telegram Trigger: Event Nodes: 38 Complexity: ★★★★★ AI nodes: yes Added:
Forecast Inventory and Route Purchase Orders with Google Sheets, Openai,… — n8n workflow card showing Error Trigger, Slack, Google Sheets integration

This workflow corresponds to n8n.io template #17683 — we link there as the canonical source.

This workflow follows the Error Trigger → Gmail recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "O9PxBJETNUXHxX4H",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Inventory Forecasting & Smart Purchase Order Automation System",
  "tags": [],
  "nodes": [
    {
      "id": "4e194e41-cf3c-479b-9914-69e96d3c31b7",
      "name": "Section \u2013 Error Handling",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2080,
        8064
      ],
      "parameters": {
        "color": 7,
        "width": 652,
        "height": 456,
        "content": "## \u26a0\ufe0f Error Handling\nA workflow-level error trigger catches any node failure and posts an alert to Slack. Replace `YOUR_SLACK_CHANNEL_ID` with your ops or alerts channel before going live."
      },
      "typeVersion": 1
    },
    {
      "id": "2cb54dfe-2f07-42b4-8184-6a59a6f38eb6",
      "name": "On Workflow Error",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        2224,
        8288
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "bbe87660-d1f0-422b-996c-a3d9096d0452",
      "name": "Slack \u2013 Post Workflow Error Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        2496,
        8288
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f *AI Crisis Management Agent Error*\n\n*Workflow:* {{ $workflow.name }}\n*Failed Node:* {{ $execution.lastNodeExecuted }}\n*Time:* {{ $now.format('MMM D, YYYY \u2013 HH:mm') }}\n*Execution ID:* {{ $execution.id }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_CHANNEL_ID",
          "cachedResultName": "your-alerts-channel"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.3
    },
    {
      "id": "798192c1-ea39-41df-b0f1-66e2469f2612",
      "name": "\ud83d\udccc Overview \u2013 How This Workflow Works",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        5376
      ],
      "parameters": {
        "color": 2,
        "width": 920,
        "height": 648,
        "content": "## \ud83d\udce6 AI Inventory Forecasting & Smart Purchase Order Automation\n\n### How it works\nEvery morning, the workflow reads four data sources from Google Sheets \u2014 sales history, current inventory levels, vendor directory, and existing purchase orders \u2014 and runs a demand forecast in code. Each SKU is assessed against reorder points and classified as Critical (stockout imminent), Warning (running low), or Watch (monitor). Critical items get an AI-drafted PO sent for Telegram approval and a Slack alert; Warning items generate a draft with a lighter Telegram ping; Watch items are logged only. After sending, a daily HTML digest email summarises all actions taken. A second Telegram trigger handles the approval callback \u2014 approve or reject \u2014 which emails the PO to the supplier and confirms back to the requester.\n\n### Setup steps\n1. Connect **Google Sheets OAuth2** and create a sheet with tabs: `Sales History`, `Inventory`, `Vendors`, `Purchase Orders`. Replace `YOUR_GOOGLE_SHEET_ID` in every Sheets node.\n2. Connect **OpenAI API** to both PO draft generation nodes.\n3. Connect **Gmail OAuth2** and update `procurement@yourcompany.com` in the digest and supplier email nodes.\n4. Connect **Telegram Bot API** and replace `YOUR_TELEGRAM_CHAT_ID` in all Telegram nodes.\n5. Connect **Slack OAuth2** and replace `YOUR_SLACK_CHANNEL_ID` in the critical alert and error nodes.\n6. Activate the daily schedule trigger and the Telegram approval callback trigger."
      },
      "typeVersion": 1
    },
    {
      "id": "d788e0af-1719-4d1c-aeb0-336247a424d0",
      "name": "Section \u2013 Daily Trigger & Data Fetch",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        5920
      ],
      "parameters": {
        "color": 7,
        "width": 1236,
        "height": 1132,
        "content": "## \u23f0 Daily Trigger & Multi-Source Data Fetch\nFires once a day. Reads sales history, current stock levels, vendor info, and open POs from four separate sheets in parallel, then merges them into a unified dataset before forecasting begins."
      },
      "typeVersion": 1
    },
    {
      "id": "13921a94-5522-41d5-bbf7-60f6160f107d",
      "name": "Section \u2013 Demand Forecast & Severity Classification",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3120,
        5968
      ],
      "parameters": {
        "color": 7,
        "width": 772,
        "height": 732,
        "content": "## \ud83d\udcca Demand Forecast & Severity Classification\nCalculates a rolling demand forecast per SKU based on sales velocity. Compares each SKU's current stock against its reorder point, then classifies as Critical, Warning, or Watch. SKUs with no action needed are filtered out."
      },
      "typeVersion": 1
    },
    {
      "id": "c4ac1c27-7307-4174-9f93-b0a509b9a53f",
      "name": "Section \u2013 AI PO Drafting & Severity Routing",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4016,
        5888
      ],
      "parameters": {
        "color": 7,
        "width": 1160,
        "height": 988,
        "content": "## \ud83e\udd16 AI PO Drafting & Severity-Based Routing\nCritical and Warning SKUs each get an AI-generated purchase order draft from GPT-4o-mini. Critical POs trigger a Telegram approval request and a Slack alert; Warning POs send a lighter Telegram ping. Watch SKUs are logged without any outbound message."
      },
      "typeVersion": 1
    },
    {
      "id": "71efc726-f06d-4581-b237-33e40783932c",
      "name": "Section \u2013 Daily Digest Email",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3312,
        6752
      ],
      "parameters": {
        "color": 7,
        "width": 660,
        "height": 412,
        "content": "## \ud83d\udce7 Daily Digest Email\nBuilds an HTML summary of all inventory actions taken during the run \u2014 critical alerts, warnings, and watch items \u2014 and emails it to the procurement team via Gmail."
      },
      "typeVersion": 1
    },
    {
      "id": "8b9596d2-a26d-42ea-a12b-cd34a62fe152",
      "name": "Section \u2013 Telegram Approval Callback",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2352,
        7232
      ],
      "parameters": {
        "color": 7,
        "width": 2048,
        "height": 732,
        "content": "## \u2705 Telegram Approval Callback\nListens for the procurement manager's Telegram reply (`approve` or `reject`). Approve emails the PO to the supplier and confirms on Telegram. Reject logs the decision and notifies the requester. The PO row is updated either way."
      },
      "typeVersion": 1
    },
    {
      "id": "16083758-6f73-45b5-a918-5029fbc10d2c",
      "name": "\ud83d\udd11 Credentials & Security",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4544,
        7808
      ],
      "parameters": {
        "color": 3,
        "width": 484,
        "height": 384,
        "content": "## \ud83d\udd11 Credentials Required\n- **Google Sheets OAuth2** \u2014 4 data tabs + Purchase Orders log\n- **OpenAI API** \u2014 Critical + Warning PO drafting nodes\n- **Gmail OAuth2** \u2014 daily digest + supplier PO email\n- **Telegram Bot API** \u2014 approval requests + callbacks + confirmations\n- **Slack OAuth2** \u2014 critical stock alert + error alerts\n\nNever hardcode sheet IDs, emails, or chat IDs in shared templates."
      },
      "typeVersion": 1
    },
    {
      "id": "3e1df18d-2b04-4861-87ed-2d8e72405fa6",
      "name": "Schedule Trigger (Daily)",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1984,
        6480
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 6
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a8a29e68-fdb6-4517-ab82-f7d01e3ba67c",
      "name": "Get Sales History",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2352,
        6176
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1965792427,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1965792427",
          "cachedResultName": "Sales History"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "32c66024-8c22-4676-b84e-fd08704c6d98",
      "name": "Get Inventory Levels",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2368,
        6384
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1402664148,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1402664148",
          "cachedResultName": "Inventory"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "530e89d1-10c8-4e54-9bf2-9df4d10d2fc4",
      "name": "Get Vendor Directory",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2368,
        6608
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1667168001,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1667168001",
          "cachedResultName": "Vendors"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "bf725f3a-3d2c-457c-8f11-1c088aff1ce7",
      "name": "Get Existing Purchase Orders",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2368,
        6800
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1835691874,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1835691874",
          "cachedResultName": "Purchase Orders"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "a8426892-2d81-400b-8938-6d849c7f08f4",
      "name": "Calculate Demand Forecast",
      "type": "n8n-nodes-base.code",
      "position": [
        3168,
        6480
      ],
      "parameters": {
        "jsCode": "const salesRows = $('Get Sales History').all().map(i => i.json);\nconst inventoryRows = $('Get Inventory Levels').all().map(i => i.json);\nconst vendorRows = $('Get Vendor Directory').all().map(i => i.json);\nconst existingPORows = $('Get Existing Purchase Orders').all().map(i => i.json);\n\nconst LOOKBACK_DAYS = 30;\nconst TREND_WINDOW_DAYS = 7;\nconst PENDING_LOOKBACK_DAYS = 7;\nconst now = new Date();\nconst cutoff30 = new Date(now.getTime() - LOOKBACK_DAYS * 24 * 60 * 60 * 1000);\nconst cutoff7 = new Date(now.getTime() - TREND_WINDOW_DAYS * 24 * 60 * 60 * 1000);\nconst pendingCutoff = new Date(now.getTime() - PENDING_LOOKBACK_DAYS * 24 * 60 * 60 * 1000);\n\nconst demand30BySku = {};\nconst demand7BySku = {};\nfor (const row of salesRows) {\n  const sku = String(row.SKU || row.sku || '').trim();\n  if (!sku) continue;\n  const rowDate = new Date(row.Date || row.date);\n  if (isNaN(rowDate.getTime())) continue;\n  const units = Number(row.UnitsSold || row.unitsSold || row.units_sold || 0);\n  if (rowDate >= cutoff30) demand30BySku[sku] = (demand30BySku[sku] || 0) + units;\n  if (rowDate >= cutoff7) demand7BySku[sku] = (demand7BySku[sku] || 0) + units;\n}\n\nconst vendorBySku = {};\nfor (const v of vendorRows) {\n  const sku = String(v.SKU || v.sku || '').trim();\n  if (!sku) continue;\n  vendorBySku[sku] = {\n    supplierName: v.SupplierName || v.supplierName || '',\n    supplierEmail: v.SupplierEmail || v.supplierEmail || '',\n    moq: Number(v.MOQ || v.moq || 0)\n  };\n}\n\nconst openStatuses = ['Draft', 'Pending Approval', 'Approved'];\nconst pendingSkus = new Set();\nfor (const po of existingPORows) {\n  const sku = String(po.SKU || po.sku || '').trim();\n  const status = String(po.Status || po.status || '').trim();\n  const ts = new Date(po.Timestamp || po.timestamp);\n  if (sku && openStatuses.includes(status) && !isNaN(ts.getTime()) && ts >= pendingCutoff) {\n    pendingSkus.add(sku);\n  }\n}\n\nconst results = [];\n\nfor (const inv of inventoryRows) {\n  const sku = String(inv.SKU || inv.sku || '').trim();\n  if (!sku) continue;\n\n  const productName = inv.ProductName || inv.productName || '';\n  const currentStock = Number(inv.CurrentStock || inv.currentStock || 0);\n  const leadTimeDays = Number(inv.LeadTimeDays || inv.leadTimeDays || 7);\n  const reorderThresholdDays = Number(inv.ReorderThresholdDays || inv.reorderThresholdDays || 7);\n  const safetyStock = Number(inv.SafetyStock || inv.safetyStock || 0);\n  const unitCost = Number(inv.UnitCost || inv.unitCost || 0);\n\n  const totalUnitsSold30 = demand30BySku[sku] || 0;\n  const totalUnitsSold7 = demand7BySku[sku] || 0;\n  const avgDailyDemand = totalUnitsSold30 / LOOKBACK_DAYS;\n  const avgDailyDemand7 = totalUnitsSold7 / TREND_WINDOW_DAYS;\n  const trendUp = avgDailyDemand > 0 && avgDailyDemand7 > avgDailyDemand * 1.2;\n\n  const daysOfStockRemaining = avgDailyDemand > 0\n    ? Math.round((currentStock / avgDailyDemand) * 10) / 10\n    : null;\n\n  const vendor = vendorBySku[sku] || { supplierName: '', supplierEmail: '', moq: 0 };\n  const alreadyPending = pendingSkus.has(sku);\n\n  let severity = 'OK';\n  if (!alreadyPending && daysOfStockRemaining !== null) {\n    if (daysOfStockRemaining <= 3) severity = 'Critical';\n    else if (daysOfStockRemaining <= reorderThresholdDays) severity = 'Warning';\n    else if (trendUp && daysOfStockRemaining <= reorderThresholdDays * 1.5) severity = 'Watch';\n  }\n\n  let recommendedQty = 0;\n  if (severity === 'Critical' || severity === 'Warning') {\n    const targetStock = (avgDailyDemand * (leadTimeDays + reorderThresholdDays)) + safetyStock;\n    recommendedQty = Math.max(0, Math.ceil(targetStock - currentStock));\n    if (vendor.moq > 0 && recommendedQty > 0 && recommendedQty < vendor.moq) {\n      recommendedQty = vendor.moq;\n    }\n  }\n\n  const poId = severity !== 'OK' ? `${sku}-${Date.now()}` : '';\n\n  results.push({\n    json: {\n      sku,\n      productName,\n      currentStock,\n      avgDailyDemand: Math.round(avgDailyDemand * 100) / 100,\n      avgDailyDemand7: Math.round(avgDailyDemand7 * 100) / 100,\n      trendUp,\n      daysOfStockRemaining,\n      leadTimeDays,\n      reorderThresholdDays,\n      safetyStock,\n      unitCost,\n      recommendedQty,\n      estimatedCost: Math.round(recommendedQty * unitCost * 100) / 100,\n      severity,\n      alreadyPending,\n      poId,\n      supplierName: vendor.supplierName,\n      supplierEmail: vendor.supplierEmail,\n      moq: vendor.moq\n    }\n  });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "43791c38-f751-45f1-a437-7296f0acc478",
      "name": "IF - Actionable",
      "type": "n8n-nodes-base.if",
      "position": [
        3504,
        6384
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-actionable",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{$json.severity}}",
              "rightValue": "OK"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "78664c40-3a0f-4670-b3de-96db17c0daee",
      "name": "Switch - Severity Routing",
      "type": "n8n-nodes-base.switch",
      "position": [
        3776,
        6352
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "sev-critical",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{$json.severity}}",
                    "rightValue": "Critical"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "sev-warning",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{$json.severity}}",
                    "rightValue": "Warning"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "sev-watch",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{$json.severity}}",
                    "rightValue": "Watch"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "d17f3a25-f975-4e30-a603-7d95d55a9fed",
      "name": "Log Purchase Order - Critical",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4688,
        6208
      ],
      "parameters": {
        "columns": {
          "value": {
            "SKU": "={{$('Switch - Severity Routing1').item.json.sku}}",
            "POId": "={{$('Switch - Severity Routing1').item.json.poId}}",
            "Status": "Pending Approval",
            "POReason": "={{$json.message.content}}",
            "Severity": "={{$('Switch - Severity Routing1').item.json.severity}}",
            "Timestamp": "={{$now.toISO()}}",
            "ProductName": "={{$('Switch - Severity Routing1').item.json.productName}}",
            "CurrentStock": "={{$('Switch - Severity Routing1').item.json.currentStock}}",
            "SupplierName": "={{$('Switch - Severity Routing1').item.json.supplierName}}",
            "EstimatedCost": "={{$('Switch - Severity Routing1').item.json.estimatedCost}}",
            "SupplierEmail": "={{$('Switch - Severity Routing1').item.json.supplierEmail}}",
            "RecommendedQty": "={{$('Switch - Severity Routing1').item.json.recommendedQty}}"
          },
          "schema": [
            {
              "id": "POId",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "POId",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SKU",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SKU",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ProductName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ProductName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CurrentStock",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "CurrentStock",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RecommendedQty",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "RecommendedQty",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "EstimatedCost",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "EstimatedCost",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Severity",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Severity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "POReason",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "POReason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SupplierName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierEmail",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SupplierEmail",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1835691874,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1835691874",
          "cachedResultName": "Purchase Orders"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "808a4e9d-9d3d-4e2c-82fd-14e6aa861d7d",
      "name": "Send Telegram Approval Request",
      "type": "n8n-nodes-base.telegram",
      "position": [
        4928,
        6096
      ],
      "parameters": {
        "text": "=\ud83d\udea8 *CRITICAL Reorder \u2014 Approval Needed*\n\n*SKU:* {{$json.SKU}}\n*Product:* {{$json.ProductName}}\n*Current Stock:* {{$json.CurrentStock}} units\n*Recommended Qty:* {{$json.RecommendedQty}}\n*Estimated Cost:* {{$json.EstimatedCost}}\n*Supplier:* {{$json.SupplierName}}\n\n\ud83d\udcdd {{$json.POReason}}\n\nTap Approve to email the supplier automatically.",
        "chatId": "YOUR_TELEGRAM_CHAT_ID",
        "replyMarkup": "inlineKeyboard",
        "inlineKeyboard": {
          "rows": [
            {
              "row": {
                "buttons": [
                  {
                    "text": "\u2705 Approve",
                    "additionalFields": {
                      "callback_data": "=approve_{{$json.POId}}"
                    }
                  },
                  {
                    "text": "\u274c Reject",
                    "additionalFields": {
                      "callback_data": "=reject_{{$json.POId}}"
                    }
                  }
                ]
              }
            }
          ]
        },
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "0b25eda2-7d7d-457a-b08e-c92009762e42",
      "name": "Send Slack Critical Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        4928,
        6304
      ],
      "parameters": {
        "text": "=\ud83d\udea8 CRITICAL stockout risk: {{$json.SKU}} ({{$json.ProductName}}) \u2014 {{$json.CurrentStock}} units left, reorder {{$json.RecommendedQty}} pending Telegram approval.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_CHANNEL_ID",
          "cachedResultName": "your-alerts-channel"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.2
    },
    {
      "id": "615bbccf-2d91-42d4-a00d-2d9e6e8b6569",
      "name": "Log Purchase Order - Warning",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4656,
        6528
      ],
      "parameters": {
        "columns": {
          "value": {
            "SKU": "={{$('Switch - Severity Routing1').item.json.sku}}",
            "POId": "={{$('Switch - Severity Routing1').item.json.poId}}",
            "Status": "Draft",
            "POReason": "={{$json.message.content}}",
            "Severity": "={{$('Switch - Severity Routing1').item.json.severity}}",
            "Timestamp": "={{$now.toISO()}}",
            "ProductName": "={{$('Switch - Severity Routing1').item.json.productName}}",
            "CurrentStock": "={{$('Switch - Severity Routing1').item.json.currentStock}}",
            "SupplierName": "={{$('Switch - Severity Routing1').item.json.supplierName}}",
            "EstimatedCost": "={{$('Switch - Severity Routing1').item.json.estimatedCost}}",
            "SupplierEmail": "={{$('Switch - Severity Routing1').item.json.supplierEmail}}",
            "RecommendedQty": "={{$('Switch - Severity Routing1').item.json.recommendedQty}}"
          },
          "schema": [
            {
              "id": "POId",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "POId",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SKU",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SKU",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ProductName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ProductName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CurrentStock",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "CurrentStock",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RecommendedQty",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "RecommendedQty",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "EstimatedCost",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "EstimatedCost",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Severity",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Severity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "POReason",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "POReason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SupplierName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierEmail",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SupplierEmail",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1835691874,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1835691874",
          "cachedResultName": "Purchase Orders"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "f046dc99-da08-4b11-9381-3f94625454ee",
      "name": "Send Telegram Alert - Warning",
      "type": "n8n-nodes-base.telegram",
      "position": [
        4896,
        6528
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f *Reorder Recommended (Draft logged)*\n\n*SKU:* {{$json.SKU}}\n*Product:* {{$json.ProductName}}\n*Current Stock:* {{$json.CurrentStock}} units\n*Recommended Qty:* {{$json.RecommendedQty}}\n*Estimated Cost:* {{$json.EstimatedCost}}\n\n\ud83d\udcdd {{$json.POReason}}",
        "chatId": "YOUR_TELEGRAM_CHAT_ID",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "d4ef66f7-5b6d-4c83-82ad-db038ed8baf6",
      "name": "Log Purchase Order - Watch",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        4256,
        6672
      ],
      "parameters": {
        "columns": {
          "value": {
            "SKU": "={{$json.sku}}",
            "POId": "={{$json.poId}}",
            "Status": "Watch",
            "POReason": "Demand trending up \u2014 monitoring, no reorder triggered yet.",
            "Severity": "Watch",
            "Timestamp": "={{$now.toISO()}}",
            "ProductName": "={{$json.productName}}",
            "CurrentStock": "={{$json.currentStock}}",
            "SupplierName": "={{$json.supplierName}}",
            "EstimatedCost": 0,
            "SupplierEmail": "={{$json.supplierEmail}}",
            "RecommendedQty": 0
          },
          "schema": [
            {
              "id": "POId",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "POId",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SKU",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SKU",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ProductName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ProductName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CurrentStock",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "CurrentStock",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RecommendedQty",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "RecommendedQty",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "EstimatedCost",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "EstimatedCost",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Severity",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Severity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "POReason",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "POReason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SupplierName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierEmail",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "SupplierEmail",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1835691874,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1835691874",
          "cachedResultName": "Purchase Orders"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "d7476eff-4f8a-49c0-a0a0-a91054312d92",
      "name": "Build Daily Digest HTML",
      "type": "n8n-nodes-base.code",
      "position": [
        3536,
        6960
      ],
      "parameters": {
        "jsCode": "const items = $input.all().map(i => i.json);\nconst critical = items.filter(i => i.severity === 'Critical');\nconst warning = items.filter(i => i.severity === 'Warning');\nconst watch = items.filter(i => i.severity === 'Watch');\nconst ok = items.filter(i => i.severity === 'OK');\n\nfunction rows(list) {\n  return list.map(i => `<tr><td>${i.sku}</td><td>${i.productName}</td><td>${i.currentStock}</td><td>${i.daysOfStockRemaining ?? '-'}</td><td>${i.recommendedQty}</td><td>${i.estimatedCost}</td></tr>`).join('');\n}\n\nconst html = `\n<h2>\ud83d\udce6 InvenOS AI \u2014 Daily Inventory Digest</h2>\n<p>${critical.length} Critical, ${warning.length} Warning, ${watch.length} Watch, ${ok.length} OK</p>\n<h3 style=\"color:#c0392b\">Critical</h3>\n<table border=\"1\" cellpadding=\"6\" style=\"border-collapse:collapse\"><tr><th>SKU</th><th>Product</th><th>Stock</th><th>Days Left</th><th>Reorder Qty</th><th>Est. Cost</th></tr>${rows(critical)}</table>\n<h3 style=\"color:#e67e22\">Warning</h3>\n<table border=\"1\" cellpadding=\"6\" style=\"border-collapse:collapse\"><tr><th>SKU</th><th>Product</th><th>Stock</th><th>Days Left</th><th>Reorder Qty</th><th>Est. Cost</th></tr>${rows(warning)}</table>\n<h3 style=\"color:#f1c40f\">Watch</h3>\n<table border=\"1\" cellpadding=\"6\" style=\"border-collapse:collapse\"><tr><th>SKU</th><th>Product</th><th>Stock</th><th>Days Left</th><th>Reorder Qty</th><th>Est. Cost</th></tr>${rows(watch)}</table>\n`;\n\nreturn [{ json: { html, criticalCount: critical.length, warningCount: warning.length, watchCount: watch.length } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "caae8415-57ed-4782-8420-e5e3364d68c2",
      "name": "Send Daily Digest Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3776,
        6960
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "={{$json.html}}",
        "options": {},
        "subject": "=InvenOS AI \u2014 Daily Inventory Digest {{$now.format('yyyy-MM-dd')}}"
      },
      "typeVersion": 2.1
    },
    {
      "id": "550e64d5-55c5-4b8d-93bb-e1a5cdb37645",
      "name": "Generate PO Draft (AI) - Warning1",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        4240,
        6512
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Write a short, professional purchase order justification (3-4 sentences max) for this routine reorder. Be specific with the numbers, don't invent data.\n\nSKU: {{$json.sku}}\nProduct: {{$json.productName}}\nCurrent Stock: {{$json.currentStock}} units\nDays of Stock Remaining: {{$json.daysOfStockRemaining}}\nAverage Daily Demand: {{$json.avgDailyDemand}} units/day\nLead Time: {{$json.leadTimeDays}} days\nRecommended Reorder Qty: {{$json.recommendedQty}} units\nEstimated Cost: {{$json.estimatedCost}}\n\nReturn only the justification text, no headers."
            }
          ]
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "2b5dcd97-ca76-4cf0-8cb1-5f19bf5ca33b",
      "name": "Generate PO Draft (AI) - Critical1",
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "position": [
        4224,
        6208
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Write a short, professional purchase order justification (3-4 sentences max) for this CRITICAL stockout risk. Be specific with the numbers, don't invent data.\n\nSKU: {{$json.sku}}\nProduct: {{$json.productName}}\nCurrent Stock: {{$json.currentStock}} units\nDays of Stock Remaining: {{$json.daysOfStockRemaining}}\nAverage Daily Demand: {{$json.avgDailyDemand}} units/day\nLead Time: {{$json.leadTimeDays}} days\nRecommended Reorder Qty: {{$json.recommendedQty}} units\nEstimated Cost: {{$json.estimatedCost}}\n\nReturn only the justification text, no headers."
            }
          ]
        }
      },
      "typeVersion": 1.8
    },
    {
      "id": "b2f2c2e6-ec0d-4330-b0e9-e61e095fab92",
      "name": "Merge1",
      "type": "n8n-nodes-base.merge",
      "position": [
        2864,
        6448
      ],
      "parameters": {
        "numberInputs": 4
      },
      "typeVersion": 3.2
    },
    {
      "id": "a2008412-4397-43ac-9c56-94d7ab68015d",
      "name": "Get PO Details1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3600,
        7376
      ],
      "parameters": {
        "options": {},
        "filtersUI": {
          "values": [
            {
              "lookupValue": "={{$json.POId}}",
              "lookupColumn": "POId"
            }
          ]
        },
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1835691874,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1835691874",
          "cachedResultName": "Purchase Orders"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "5311ac7f-0f5b-4e2e-bf2e-cb728fbe3495",
      "name": "Telegram Trigger (Approval Callback)1",
      "type": "n8n-nodes-base.telegramTrigger",
      "position": [
        2464,
        7632
      ],
      "parameters": {
        "updates": [
          "callback_query"
        ],
        "additionalFields": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "9a829940-6d60-4569-ba18-acb1c5d3455e",
      "name": "Parse Approval Callback1",
      "type": "n8n-nodes-base.code",
      "position": [
        2704,
        7632
      ],
      "parameters": {
        "jsCode": "const cq = $json.callback_query || {};\nconst data = cq.data || '';\nconst [action, poId] = data.split('_');\nreturn [{\n  json: {\n    action,\n    poId,\n    chatId: cq.message?.chat?.id,\n    messageId: cq.message?.message_id\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "acbd5ab4-b932-4e57-bd66-74fa551d46ff",
      "name": "Switch - Approve or Reject1",
      "type": "n8n-nodes-base.switch",
      "position": [
        2944,
        7632
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "act-approve",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{$json.action}}",
                    "rightValue": "approve"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 1,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "act-reject",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{$json.action}}",
                    "rightValue": "reject"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "40b87f6e-13a9-4ef6-b9c3-02e28d296c4c",
      "name": "Update PO Status - Approved1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3360,
        7376
      ],
      "parameters": {
        "columns": {
          "value": {
            "POId": "={{$json.poId}}",
            "Status": "Approved",
            "row_number": 0
          },
          "schema": [
            {
              "id": "POId",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "POId",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SKU",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "SKU",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ProductName",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "ProductName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CurrentStock",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "CurrentStock",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RecommendedQty",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "RecommendedQty",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "EstimatedCost",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "EstimatedCost",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Severity",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Severity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "POReason",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "POReason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierName",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "SupplierName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierEmail",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "SupplierEmail",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "POId"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1835691874,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1835691874",
          "cachedResultName": "Purchase Orders"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "a3578153-56d6-457d-b1ff-606d00a85075",
      "name": "Update PO Status - Rejected1",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        3328,
        7728
      ],
      "parameters": {
        "columns": {
          "value": {
            "POId": "={{$json.poId}}",
            "Status": "Rejected",
            "row_number": 0
          },
          "schema": [
            {
              "id": "POId",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "POId",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Timestamp",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SKU",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "SKU",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ProductName",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "ProductName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "CurrentStock",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "CurrentStock",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "RecommendedQty",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "RecommendedQty",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "EstimatedCost",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "EstimatedCost",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Severity",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Severity",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "POReason",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "POReason",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierName",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "SupplierName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "SupplierEmail",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "SupplierEmail",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "POId"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 1835691874,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit#gid=1835691874",
          "cachedResultName": "Purchase Orders"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/YOUR_GOOGLE_SHEET_ID/edit?usp=drivesdk",
          "cachedResultName": "Inventory Management Sheet"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "da18ae8e-82d1-4480-8882-af3d37b6f636",
      "name": "Send PO Email to Supplier1",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3840,
        7376
      ],
      "parameters": {
        "sendTo": "=procurement@yourcompany.com",
        "message": "=Hi {{$json.SupplierName}},\n\nPlease process a purchase order for the following:\n\nSKU: {{$json.SKU}}\nProduct: {{$json.ProductName}}\nQuantity: {{$json.RecommendedQty}}\nEstimated Cost: {{$json.EstimatedCost}}\n\nThanks,\nTechdome Procurement",
        "options": {},
        "subject": "=Purchase Order Request \u2014 {{$json.SKU}} ({{$json.ProductName}})"
      },
      "typeVersion": 2.1
    },
    {
      "id": "d996646b-52db-4995-b932-be7fa279bade",
      "name": "Send Telegram Confirmation - Approved1",
      "type": "n8n-nodes-base.telegram",
      "position": [
        4080,
        7376
      ],
      "parameters": {
        "text": "=\u2705 Approved \u2014 PO for {{$('Get PO Details1').item.json.SKU}} has been emailed to {{$('Get PO Details1').item.json.SupplierName}}.",
        "chatId": "YOUR_TELEGRAM_CHAT_ID",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1397f5d0-3f14-480c-a118-ba43e486c746",
      "name": "Send Telegram Confirmation - Rejected1",
      "type": "n8n-nodes-base.telegram",
      "position": [
        3568,
        7728
      ],
      "parameters": {
        "text": "=\u274c Rejected \u2014 no PO was sent for POId {{$json.POId}}.",
        "chatId": "YOUR_TELEGRAM_CHAT_ID",
        "additionalFields": {
          "parse_mode": "Markdown"
        }
      },
      "typeVersion": 1.2
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "cebcc6f8-900c-42ca-bf5d-6c4a40dc610b",
  "nodeGroups": [],
  "connections": {
    "Merge1": {
      "main": [
        [
          {
            "node": "Calculate Demand Forecast",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get PO Details1": {
      "main": [
        [
          {
            "node": "Send PO Email to Supplier1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Actionable": {
      "main": [
        [
          {
            "node": "Switch - Severity Routing",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Sales History": {
      "main": [
        [
          {
            "node": "Merge1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On Workflow Error": {
      "main": [
        [
          {
            "node": "Slack \u2013 Post Workflow Error Alert",
            "type": "main",
   

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow runs daily to forecast SKU demand from Google Sheets data, drafts purchase-order justifications with OpenAI, routes critical and warning items for Telegram review and Slack alerts, logs decisions back to Google Sheets, and sends an HTML digest and supplier emails…

Source: https://n8n.io/workflows/17683/ — original creator credit. Request a take-down →

More Slack & Telegram workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Slack & Telegram

This workflow handles customer order complaints submitted via Telegram by looking up order details in Google Sheets, using OpenAI to classify message sentiment, and routing each case to auto-approval,

Telegram Trigger, Google Sheets, Telegram +3
Slack & Telegram

This workflow handles COD order confirmation and abandoned-cart recovery by combining webhooks, Google Sheets logging, OpenAI message generation, and Telegram messaging with inline buttons, plus Slack

Telegram Trigger, Google Sheets, Telegram +3
Slack & Telegram

This workflow runs a Telegram restaurant ordering flow that uses OpenAI to parse orders and suggest an upsell, sends a Razorpay payment link, confirms paid orders via a Razorpay webhook, logs orders a

Telegram Trigger, OpenAI, Telegram +3
Slack & Telegram

This workflow handles legal client intake via Telegram, uses OpenAI (gpt-4o-mini) to classify the case and send a matching document checklist, logs cases in Google Sheets, schedules a consultation in

Telegram Trigger, OpenAI, Telegram +4
Slack & Telegram

This workflow runs daily at 8am to detect meaningful changes in competitor pricing, Google search ranking, revenue anomalies, and customer churn using Google Sheets, SerpApi, and OpenAI, then sends a

Error Trigger, Slack, OpenAI +4