AutomationFlowsSlack & Telegram › Send New Production Orders From Google Sheets to a Telegram Shop Floor Chat

Send New Production Orders From Google Sheets to a Telegram Shop Floor Chat

BySEVENEDGE @sevenedge on n8n.io

This workflow runs every 15 minutes to read a Google Sheets production order tracker, posts each unannounced order as a plain-text alert to a Telegram shop-floor chat, and then updates the sheet to mark those orders as announced so they are not sent twice. Runs on a 15-minute…

Cron / scheduled trigger★★★★☆ complexity10 nodesGoogle SheetsTelegram
Slack & Telegram Trigger: Cron / scheduled Nodes: 10 Complexity: ★★★★☆ Added:

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

This workflow follows the Google Sheets → Telegram 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": "OLdnJpiLK1YjAgSo",
  "name": "Production order tracker: Google Sheets to shop floor chat alerts",
  "tags": [
    {
      "id": "02ThXpPxieX6RXPt",
      "name": "Google Sheets",
      "createdAt": "2026-07-25T22:20:02.957Z",
      "updatedAt": "2026-07-25T22:20:02.957Z"
    },
    {
      "id": "6tLEpuPTZKvuhUfj",
      "name": "Manufacturing",
      "createdAt": "2026-07-25T22:20:02.983Z",
      "updatedAt": "2026-07-25T22:20:02.983Z"
    },
    {
      "id": "kUT2LehedzPpj79Q",
      "name": "Operations",
      "createdAt": "2026-07-25T22:20:02.924Z",
      "updatedAt": "2026-07-25T22:20:02.924Z"
    }
  ],
  "nodes": [
    {
      "id": "1d8f301e-3259-4a5c-acaa-8d89df3a5e42",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        816,
        192
      ],
      "parameters": {
        "width": 480,
        "height": 816,
        "content": "## Production order tracker: Google Sheets to shop floor chat alerts\n\n### How it works\n\nThis workflow monitors a Google Sheets production order tracker and alerts the shop floor chat about newly detected orders. It can be run manually or on a 15-minute schedule, reads the configured order columns, filters for unannounced orders, sends Telegram notifications, and then updates the sheet to prevent duplicate alerts.\n\n### Setup steps\n\n- Connect Google Sheets credentials and configure the production spreadsheet and sheet range in both Google Sheets nodes.\n- Connect Telegram bot credentials and set the target shop floor chat ID in the Telegram node.\n- Confirm the Settings node column names match the spreadsheet headers, including order ID, product, quantity, and due date.\n- Ensure the sheet includes a status or announced marker column that the filtering code and update node can use consistently.\n\n### Customization\n\nAdjust the schedule interval, Telegram message format, column mappings, or filtering logic to match different production tracking rules."
      },
      "typeVersion": 1
    },
    {
      "id": "f4a6f0b5-7764-4d2a-bc33-2dafcbb322f7",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1376,
        192
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 496,
        "content": "## Start and configure\n\nManual and scheduled triggers start the workflow, then the settings node defines the Google Sheets column names used to identify order details."
      },
      "typeVersion": 1
    },
    {
      "id": "c50056ba-1dc9-464d-a337-2c2fa578219b",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1824,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 432,
        "height": 320,
        "content": "## Read and filter orders\n\nThe workflow reads the production sheet and runs code to identify production orders that have not yet been announced to the shop floor."
      },
      "typeVersion": 1
    },
    {
      "id": "543cb9ab-0682-4fdd-9b05-83457be269f9",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2320,
        288
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 320,
        "content": "## Notify and mark orders\n\nNew orders are sent to the shop floor chat through Telegram, then the corresponding sheet rows are updated to mark them as announced."
      },
      "typeVersion": 1
    },
    {
      "id": "f1cc8530-9c18-419b-a6e4-8680d3558a15",
      "name": "Scheduled 15 Min Interval",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1440,
        528
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "minutes",
              "minutesInterval": 15
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "a8f4a98a-b679-43f6-a872-2d3b2b90e073",
      "name": "Set Order Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        1648,
        448
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0",
              "name": "colOrderId",
              "type": "string",
              "value": "Order"
            },
            {
              "id": "1",
              "name": "colProduct",
              "type": "string",
              "value": "Product"
            },
            {
              "id": "2",
              "name": "colQuantity",
              "type": "string",
              "value": "Quantity"
            },
            {
              "id": "3",
              "name": "colDueDate",
              "type": "string",
              "value": "Due date"
            },
            {
              "id": "4",
              "name": "colStation",
              "type": "string",
              "value": "Station"
            },
            {
              "id": "5",
              "name": "colPriority",
              "type": "string",
              "value": "Priority"
            },
            {
              "id": "6",
              "name": "colStatus",
              "type": "string",
              "value": "Announced"
            },
            {
              "id": "7",
              "name": "announcedValue",
              "type": "string",
              "value": "yes"
            },
            {
              "id": "8",
              "name": "urgentDays",
              "type": "string",
              "value": "2"
            },
            {
              "id": "9",
              "name": "maxPerRun",
              "type": "string",
              "value": "20"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "cc3f3681-55cc-45e8-8075-95d9f66bb828",
      "name": "Read Production Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Select your production spreadsheet and worksheet.",
      "position": [
        1872,
        448
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "4f671df5-9595-4cd9-a404-c84e2d8f7241",
      "name": "Identify New Orders",
      "type": "n8n-nodes-base.code",
      "position": [
        2112,
        448
      ],
      "parameters": {
        "jsCode": "// Pick up production orders that have not been announced to the shop floor yet,\n// and build one short message per order. Nothing here is company specific \u2014\n// change the column names in Settings, not this code.\nconst cfg = $('Set Order Fields').first().json;\n\nconst COL = {\n  id:       cfg.colOrderId   || 'Order',\n  product:  cfg.colProduct   || 'Product',\n  qty:      cfg.colQuantity  || 'Quantity',\n  due:      cfg.colDueDate   || 'Due date',\n  station:  cfg.colStation   || 'Station',\n  status:   cfg.colStatus    || 'Announced',\n  priority: cfg.colPriority  || 'Priority',\n};\nconst DONE = (cfg.announcedValue || 'yes').toLowerCase();\nconst MAX  = Number(cfg.maxPerRun || 20);\n\nconst rows = $input.all().map(i => i.json);\nconst pending = rows.filter(r => {\n  const flag = String(r[COL.status] ?? '').trim().toLowerCase();\n  const hasId = String(r[COL.id] ?? '').trim() !== '';\n  return hasId && flag !== DONE;\n});\n\nif (!pending.length) return [];\n\nfunction daysLeft(v) {\n  if (!v) return null;\n  const d = new Date(v);\n  if (isNaN(d)) return null;\n  return Math.ceil((d - new Date()) / 86400000);\n}\n\nconst out = [];\nfor (const r of pending.slice(0, MAX)) {\n  const left = daysLeft(r[COL.due]);\n  const urgent = left !== null && left <= Number(cfg.urgentDays || 2);\n\n  const lines = [];\n  lines.push((urgent ? '\ud83d\udd34 ' : '\ud83d\udd35 ') + 'ORDER ' + String(r[COL.id]));\n  if (r[COL.product])  lines.push('Product: ' + r[COL.product]);\n  if (r[COL.qty])      lines.push('Quantity: ' + r[COL.qty]);\n  if (r[COL.station])  lines.push('Station: ' + r[COL.station]);\n  if (r[COL.due])      lines.push('Due: ' + r[COL.due] + (left !== null ? '  (' + left + ' days)' : ''));\n  if (r[COL.priority]) lines.push('Priority: ' + r[COL.priority]);\n\n  out.push({ json: {\n    order_id: String(r[COL.id]),\n    row_number: r.row_number ?? null,\n    urgent,\n    days_left: left,\n    text: lines.join('\\n'),\n  }});\n}\n\n// Newest deadline first \u2014 the shop floor should see what burns, not what is alphabetically first.\nout.sort((a, b) => (a.json.days_left ?? 9999) - (b.json.days_left ?? 9999));\nreturn out;"
      },
      "typeVersion": 2
    },
    {
      "id": "0fbc2b16-993b-41f0-9220-f5a1e09d49d3",
      "name": "Alert Shop Floor via Telegram",
      "type": "n8n-nodes-base.telegram",
      "notes": "Swap this node for Slack, e-mail or any chat you already use \u2014 the message is plain text.",
      "onError": "continueRegularOutput",
      "position": [
        2368,
        448
      ],
      "parameters": {
        "text": "={{ $json.text }}",
        "additionalFields": {
          "disable_web_page_preview": true
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "da10a508-4099-4825-8a2f-b4cacecc09fe",
      "name": "Update Announcement Status in Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "notes": "Match on the order column and write the announcedValue into the Announced column.",
      "onError": "continueRegularOutput",
      "position": [
        2640,
        448
      ],
      "parameters": {
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.5
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "2826f3c5-c0cc-4e7f-91ed-b6341c13c743",
  "nodeGroups": [],
  "connections": {
    "Set Order Fields": {
      "main": [
        [
          {
            "node": "Read Production Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Identify New Orders": {
      "main": [
        [
          {
            "node": "Alert Shop Floor via Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Production Sheet": {
      "main": [
        [
          {
            "node": "Identify New Orders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Scheduled 15 Min Interval": {
      "main": [
        [
          {
            "node": "Set Order Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Alert Shop Floor via Telegram": {
      "main": [
        [
          {
            "node": "Update Announcement Status in Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Pro

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

About this workflow

This workflow runs every 15 minutes to read a Google Sheets production order tracker, posts each unannounced order as a plain-text alert to a Telegram shop-floor chat, and then updates the sheet to mark those orders as announced so they are not sent twice. Runs on a 15-minute…

Source: https://n8n.io/workflows/17508/ — 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

⚠️ Heads up: this is satire. The "Hell Yeah!" workflow is a parody of "automate your whole life with AI agents" grindset content. The API endpoints are fictional and the function nodes are illustrativ

HTTP Request, Salesforce, Telegram +4
Slack & Telegram

This workflow tracks a configurable crypto watchlist using the CoinGecko API, sends Telegram alerts when price, % change, or volume-spike conditions are met (with optional RSI filtering), optionally l

HTTP Request, Telegram, Google Sheets +1
Slack & Telegram

This workflow continuously monitors the Meta Ads Library for new creatives from a specific competitor pages, logs them into Google Sheets, and sends a concise Telegram notification with the number of

HTTP Request, Telegram, Google Sheets +1
Slack & Telegram

&gt; n8n, Binance API, Google Sheets, Slack, Telegram, Jira & Email

HTTP Request, Google Sheets, Slack +3
Slack & Telegram

This workflow is ideal for marketers, product managers, competitive intelligence teams, and anyone who needs to track changes on web pages — whether it's competitor pricing, job postings, policy updat

HTTP Request, Google Sheets, Telegram +1