AutomationFlowsAI & RAG › Forecast Inventory and Auto-generate Reorders with Google Sheets, Gpt-4o…

Forecast Inventory and Auto-generate Reorders with Google Sheets, Gpt-4o…

Original n8n title: Forecast Inventory and Auto-generate Reorders with Google Sheets, Gpt-4o Mini and Slack

ByRedowan Ahmed Farhan @redowanfarhan on n8n.io

How it works

Event trigger★★★★☆ complexityAI-powered19 nodesGoogle SheetsAgentOpenAI ChatSlack
AI & RAG Trigger: Event Nodes: 19 Complexity: ★★★★☆ AI nodes: yes Added:

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

This workflow follows the Agent → Google Sheets 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
{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "3d0920f4-1405-48d3-b439-4154d6d27926",
      "name": "When clicking 'Execute workflow'",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -384,
        432
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "2a500a15-dd6e-4840-9136-3b96109f25f6",
      "name": "Combine Forecast and AI Output",
      "type": "n8n-nodes-base.code",
      "position": [
        880,
        416
      ],
      "parameters": {
        "jsCode": "const forecast = $('Build Forecast Dataset').first().json;\nconst aiOutput = $('Demand Forecast Agent').first().json.output || '';\n\nreturn [{\n  json: {\n    report_date: forecast.report_date,\n    total_products: forecast.total_products,\n    critical_count: forecast.critical_count,\n    low_stock_count: forecast.low_stock_count,\n    reorder_count: forecast.reorder_count,\n    ok_count: forecast.ok_count,\n    critical_items: forecast.critical_items,\n    low_stock_items: forecast.low_stock_items,\n    reorder_items: forecast.reorder_items,\n    all_products: forecast.all_products,\n    summary_text: forecast.summary_text,\n    ai_output: aiOutput,\n    has_critical: forecast.critical_count > 0\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "1af1c39b-3d42-454c-820d-96b410504c33",
      "name": "Set Forecast Configuration",
      "type": "n8n-nodes-base.set",
      "position": [
        -160,
        432
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "lookback_days",
              "type": "number",
              "value": 90
            },
            {
              "id": "2",
              "name": "forecast_days",
              "type": "number",
              "value": 30
            },
            {
              "id": "3",
              "name": "low_stock_threshold_days",
              "type": "number",
              "value": 14
            },
            {
              "id": "4",
              "name": "critical_stock_threshold_days",
              "type": "number",
              "value": 7
            },
            {
              "id": "5",
              "name": "report_date",
              "type": "string",
              "value": "={{ $now.format(\"yyyy-MM-dd\") }}"
            },
            {
              "id": "6",
              "name": "spreadsheet_id",
              "type": "string",
              "value": "1we-2q1E6iVC3Jum9_zycLN3WVndlt6TcHk-zee8GtTU"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6b77e18f-6683-4f05-98f7-30d3c04d3f86",
      "name": "Fetch Sales History",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        64,
        336
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Sales_History"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Forecast Configuration').first().json.spreadsheet_id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "9564dfcd-613f-4ac2-84df-4a318c56defd",
      "name": "Fetch Current Inventory",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        64,
        528
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Current_Inventory"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Forecast Configuration').first().json.spreadsheet_id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "eb825449-d2a4-4916-beae-4ed884f7df3d",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        272,
        416
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "aae6a52b-3104-411c-85f3-8d904b989368",
      "name": "Build Forecast Dataset",
      "type": "n8n-nodes-base.code",
      "position": [
        416,
        416
      ],
      "parameters": {
        "jsCode": "const salesItems = $('Fetch Sales History').all();\nconst inventoryItems = $('Fetch Current Inventory').all();\nconst config = $('Set Forecast Configuration').first().json;\n\nconst salesByProduct = {};\nfor (const item of salesItems) {\n  const s = item.json;\n  const pid = s.product_id || s.SKU || s.sku;\n  if (!pid) continue;\n  if (!salesByProduct[pid]) salesByProduct[pid] = { sales_data: [], total_units: 0 };\n  const units = parseFloat(s.units_sold || s.quantity || s.qty || 0);\n  salesByProduct[pid].sales_data.push({ date: s.date, units });\n  salesByProduct[pid].total_units += units;\n}\n\nconst inventoryProducts = [];\nfor (const item of inventoryItems) {\n  const inv = item.json;\n  const pid = inv.product_id || inv.SKU || inv.sku;\n  if (!pid) continue;\n\n  const salesData = salesByProduct[pid] || { sales_data: [], total_units: 0 };\n  const avgDailySales = salesData.total_units / (config.lookback_days || 90);\n  const currentStock = parseFloat(inv.current_stock || inv.quantity || 0);\n  const leadTime = parseFloat(inv.lead_time_days || 7);\n  const reorderPoint = parseFloat(inv.reorder_point || (avgDailySales * leadTime * 1.5));\n  const daysOfStock = avgDailySales > 0 ? Math.floor(currentStock / avgDailySales) : 999;\n  const projectedStockout = avgDailySales > 0 ? new Date(Date.now() + daysOfStock * 86400000).toISOString().split('T')[0] : 'N/A';\n  const reorderQty = Math.ceil(avgDailySales * (config.forecast_days || 30) * 1.2);\n\n  let status = 'OK';\n  if (daysOfStock <= config.critical_stock_threshold_days) status = 'CRITICAL';\n  else if (daysOfStock <= config.low_stock_threshold_days) status = 'LOW';\n  else if (currentStock <= reorderPoint) status = 'REORDER';\n\n  inventoryProducts.push({\n    product_id: pid,\n    product_name: inv.product_name || inv.name || pid,\n    current_stock: currentStock,\n    avg_daily_sales: Math.round(avgDailySales * 100) / 100,\n    days_of_stock: daysOfStock,\n    projected_stockout_date: projectedStockout,\n    reorder_quantity: reorderQty,\n    reorder_point: Math.round(reorderPoint),\n    lead_time_days: leadTime,\n    unit_cost: parseFloat(inv.unit_cost || 0),\n    supplier: inv.supplier || 'Unknown',\n    status,\n    sales_30d: Math.round(avgDailySales * 30),\n    sales_90d: salesData.total_units\n  });\n}\n\ninventoryProducts.sort((a, b) => a.days_of_stock - b.days_of_stock);\n\nconst critical = inventoryProducts.filter(p => p.status === 'CRITICAL');\nconst lowStock = inventoryProducts.filter(p => p.status === 'LOW');\nconst reorderNeeded = inventoryProducts.filter(p => p.status === 'REORDER');\n\nreturn [{\n  json: {\n    report_date: config.report_date,\n    total_products: inventoryProducts.length,\n    critical_count: critical.length,\n    low_stock_count: lowStock.length,\n    reorder_count: reorderNeeded.length,\n    ok_count: inventoryProducts.filter(p => p.status === 'OK').length,\n    critical_items: critical,\n    low_stock_items: lowStock,\n    reorder_items: reorderNeeded,\n    all_products: inventoryProducts,\n    summary_text: inventoryProducts.slice(0, 20).map(p =>\n      p.product_id + ' | ' + p.product_name + ' | Stock: ' + p.current_stock +\n      ' | Days: ' + p.days_of_stock + ' | AvgDaily: ' + p.avg_daily_sales +\n      ' | Stockout: ' + p.projected_stockout_date + ' | ' + p.status\n    ).join('\\n')\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "b288a667-baeb-4214-a410-8d2036211fdc",
      "name": "Demand Forecast Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        592,
        416
      ],
      "parameters": {
        "text": "=You are an expert supply chain analyst. Analyze this inventory snapshot and produce a demand forecast briefing.\n\nREPORT DATE: {{ $json.report_date }}\nTOTAL PRODUCTS: {{ $json.total_products }}\nCRITICAL (< 7 days): {{ $json.critical_count }}\nLOW STOCK (< 14 days): {{ $json.low_stock_count }}\nNEEDS REORDER: {{ $json.reorder_count }}\n\nINVENTORY DATA:\n{{ $json.summary_text }}\n\nCRITICAL ITEMS:\n{{ JSON.stringify($json.critical_items || []) }}\n\nProduce a report in markdown:\n\n# Daily Inventory & Demand Forecast\n## {{ $json.report_date }}\n\n### CRITICAL ALERTS (Immediate Action)\n[Each critical item: product, days remaining, recommended order qty]\n\n### Reorder Recommendations (Next 7 Days)\n[Prioritized list with quantities]\n\n### Demand Trend Analysis\n[Unusual patterns, seasonality signals, anomalies]\n\n### 30-Day Forecast\n[Overall inventory health projection]\n\n### Cost Impact\n[Estimated cost of recommended reorders]\n\n### Supply Chain Risk Flags\n[Concentration risks, single-supplier dependencies]\n\nBe specific with numbers, prioritize by business impact.",
        "options": {
          "systemMessage": "You are an expert supply chain analyst. Provide data-driven inventory recommendations that minimize stockouts while optimizing working capital."
        },
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "11e92896-dcec-4a88-a79b-ba47f1caddca",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        592,
        656
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {},
      "typeVersion": 1.3
    },
    {
      "id": "3d06a0e4-7fda-42f1-8f7b-634f4a1ba175",
      "name": "Critical Stock Exists?",
      "type": "n8n-nodes-base.if",
      "position": [
        1104,
        448
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "1",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.has_critical }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "612ad727-1322-40a9-8c38-e27a1c4f2e94",
      "name": "Send a message",
      "type": "n8n-nodes-base.slack",
      "position": [
        1328,
        320
      ],
      "parameters": {
        "text": "=*CRITICAL INVENTORY ALERT*  Date: {{ $json.report_date }} Critical Items (less than 7 days stock): {{ $json.critical_count }} Low Stock Items: {{ $json.low_stock_count }} Needs Reorder: {{ $json.reorder_count }}  *Critical Products:* {{ ($json.critical_items || []).map(p => '\u2022 ' + p.product_name + ' (' + p.product_id + ') - ' + p.days_of_stock + ' days left - Reorder ' + p.reorder_quantity + ' units from ' + p.supplier).join('\\n') }}  *AI Forecast Summary:* {{ ($json.ai_output || '').substring(0, 500) }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C0ASJMR4MMJ",
          "cachedResultName": "sales-team"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "454af903-aa55-4470-89d2-41990fc783c6",
      "name": "Write Forecast to Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1552,
        416
      ],
      "parameters": {
        "columns": {
          "value": {
            "AI Analysis": "={{ $json.summary_text }}",
            "Report Date": "={{ $json.report_date }}",
            "Reorder Count": "={{ $json.reorder_count }}",
            "Critical Count": "={{ $json.critical_count }}",
            "Total Products": "={{ $json.total_products }}",
            "Low Stock Count": "={{ $json.low_stock_count }}"
          },
          "schema": [
            {
              "id": "Report Date",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Report Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Total Products",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Total Products",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Critical Count",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Critical Count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Low Stock Count",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Low Stock Count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Reorder Count",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Reorder Count",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "AI Analysis",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "AI Analysis",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 919236352,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1we-2q1E6iVC3Jum9_zycLN3WVndlt6TcHk-zee8GtTU/edit#gid=919236352",
          "cachedResultName": "Forcast_Analysis"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Set Forecast Configuration').first().json.spreadsheet_id }}"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "45dfc131-e4c7-4b96-884d-fbc8e310cb54",
      "name": "Generate Purchase Orders",
      "type": "n8n-nodes-base.code",
      "position": [
        1552,
        592
      ],
      "parameters": {
        "jsCode": "const forecastData = $('Build Forecast Dataset').first().json;\nconst itemsToReorder = [\n  ...(forecastData.critical_items || []),\n  ...(forecastData.low_stock_items || []),\n  ...(forecastData.reorder_items || [])\n];\n\nconst seen = new Set();\nconst uniqueOrders = itemsToReorder.filter(item => {\n  if (seen.has(item.product_id)) return false;\n  seen.add(item.product_id);\n  return true;\n});\n\nconst purchaseOrders = uniqueOrders.map(item => ({\n  po_number: 'PO-' + item.product_id + '-' + new Date().toISOString().split('T')[0].replace(/-/g,''),\n  product_id: item.product_id,\n  product_name: item.product_name,\n  supplier: item.supplier,\n  order_quantity: item.reorder_quantity,\n  unit_cost: item.unit_cost,\n  total_cost: Math.round(item.reorder_quantity * item.unit_cost * 100) / 100,\n  priority: item.status,\n  days_of_stock: item.days_of_stock,\n  projected_stockout: item.projected_stockout_date,\n  created_date: forecastData.report_date,\n  status: 'PENDING_APPROVAL'\n}));\n\nconst totalCost = purchaseOrders.reduce((sum, po) => sum + po.total_cost, 0);\nreturn [{\n  json: {\n    purchase_orders: purchaseOrders,\n    po_count: purchaseOrders.length,\n    total_reorder_cost: Math.round(totalCost * 100) / 100,\n    report_date: forecastData.report_date\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "604a503d-5c60-48ea-bf23-d279758dbed6",
      "name": "Log Forecast Completion",
      "type": "n8n-nodes-base.set",
      "position": [
        1760,
        496
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "1",
              "name": "status",
              "type": "string",
              "value": "completed"
            },
            {
              "id": "2",
              "name": "report_date",
              "type": "string",
              "value": "={{ $('Build Forecast Dataset').first().json.report_date }}"
            },
            {
              "id": "3",
              "name": "products_analyzed",
              "type": "number",
              "value": "={{ $('Build Forecast Dataset').first().json.total_products }}"
            },
            {
              "id": "4",
              "name": "critical_alerts",
              "type": "number",
              "value": "={{ $('Build Forecast Dataset').first().json.critical_count }}"
            },
            {
              "id": "7",
              "name": "completed_at",
              "type": "string",
              "value": "={{ $now.toISO() }}"
            },
            {
              "id": "bd3c635e-1fc1-4ecc-97d3-61056e8a8c6d",
              "name": "pos_generated",
              "type": "string",
              "value": "=={{ $json.po_count !== undefined ? $json.po_count : 'N/A' }}"
            },
            {
              "id": "9d78838a-e618-4e5c-9969-1c269e1f6ab4",
              "name": "total_reorder_value",
              "type": "string",
              "value": "=={{ $json.total_reorder_cost !== undefined ? $json.total_reorder_cost : 'N/A' }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "99920140-c6a2-4a4a-9afb-0a17db66dcfa",
      "name": "Main Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1040,
        48
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 1260,
        "content": "## \ud83d\udce6 Inventory Forecasting & Auto Reorder Pipeline\n\nAutomatically analyzes sales history and current stock levels to forecast demand, flag critical shortages, generate purchase orders, and alert the team \u2014 all in one daily run.\n\n**Perfect for:** Operations managers, supply chain teams, and inventory analysts who need to eliminate manual reorder decisions and prevent stockouts.\n\n---\n\n## How it works\n\n1. **When clicking 'Execute workflow'** \u2014 Manually triggers the full inventory pipeline run.\n2. **Set Forecast Configuration** \u2014 Defines lookback period (90 days), forecast horizon (30 days), stock threshold limits, and the source Google Sheets spreadsheet ID.\n3. **Fetch Sales History** \u2014 Reads the Sales_History sheet to retrieve historical units sold per product.\n4. **Fetch Current Inventory** \u2014 Reads the Current_Inventory sheet to retrieve live stock levels, lead times, and supplier details.\n5. **Merge** \u2014 Combines the parallel sales and inventory data streams into a single dataset.\n6. **Build Forecast Dataset** \u2014 Calculates average daily sales, days of stock remaining, projected stockout dates, reorder points, and assigns each product a status (CRITICAL, LOW, REORDER, or OK).\n7. **Demand Forecast Agent** \u2014 Sends the inventory snapshot to an AI agent (GPT-4o mini) to generate a structured demand forecast report with risk flags and cost impact analysis.\n8. **OpenAI Chat Model** \u2014 Provides the GPT-4o mini language model to power the Demand Forecast Agent.\n9. **Combine Forecast and AI Output** \u2014 Merges the structured forecast dataset with the AI-generated narrative report into a single output object.\n10. **Critical Stock Exists?** \u2014 Checks if any products have fewer than 7 days of stock remaining and branches the flow accordingly.\n11. **Send a message** \u2014 *(Critical path only)* Posts a critical inventory alert to the Slack #sales-team channel listing affected products, days remaining, and reorder quantities.\n12. **Generate Purchase Orders** \u2014 Creates structured purchase order records for all CRITICAL, LOW, and REORDER items with PO numbers, quantities, costs, and supplier details.\n13. **Write Forecast to Sheet** \u2014 Appends the daily forecast summary row to the Forecast_Analysis Google Sheet.\n14. **Log Forecast Completion** \u2014 Records the final run metadata including products analyzed, critical alert count, POs generated, and total reorder value.\n\n---\n\n## Setup (~10 minutes)\n\n1. **Google Sheets OAuth2** \u2014 Connect your Google account in the *Fetch Sales History*, *Fetch Current Inventory*, and *Write Forecast to Sheet* nodes.\n2. **Spreadsheet ID** \u2014 Update the `spreadsheet_id` value in *Set Forecast Configuration* to match your Google Sheet.\n3. **Sheet tab names** \u2014 Ensure your spreadsheet has tabs named `Sales_History`, `Current_Inventory`, and `Forcast_Analysis` with matching column headers.\n4. **OpenAI API** \u2014 Add your OpenAI API key in the *OpenAI Chat Model* node.\n5. **Slack OAuth2** \u2014 Connect your Slack workspace in the *Send a message* node.\n6. **Slack channel** \u2014 Update the channel ID in *Send a message* to your preferred alert channel.\n> Stock thresholds (critical: 7 days, low: 14 days) and the 90-day lookback window can be adjusted in **Set Forecast Configuration** without touching any other node."
      },
      "typeVersion": 1
    },
    {
      "id": "42795950-423c-44bf-a4a3-7c34013e0294",
      "name": "Section 1: Trigger & Data Intake",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -432,
        192
      ],
      "parameters": {
        "color": 5,
        "width": 716,
        "height": 556,
        "content": "## 1\ufe0f\u20e3 Trigger & Data Intake\n\nThe **When clicking 'Execute workflow'** node starts the pipeline on demand. **Set Forecast Configuration** defines all key parameters including the lookback window, forecast horizon, stock alert thresholds, and the Google Sheets source ID. **Fetch Sales History** and **Fetch Current Inventory** then pull data from their respective sheet tabs in parallel before **Merge** combines both streams into a unified dataset ready for analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "2509e58c-e635-4a65-a88f-faff05a67475",
      "name": "Section 2: AI Forecasting",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        304,
        208
      ],
      "parameters": {
        "color": 3,
        "width": 776,
        "height": 544,
        "content": "## 2\ufe0f\u20e3 AI Demand Forecasting\n\n**Build Forecast Dataset** processes the merged data to calculate days of stock remaining, average daily sales velocity, projected stockout dates, and reorder quantities for every product \u2014 assigning each a CRITICAL, LOW, REORDER, or OK status. The **Demand Forecast Agent**, powered by the **OpenAI Chat Model** (GPT-4o mini), then receives the full snapshot and generates a structured markdown report covering critical alerts, reorder priorities, trend analysis, 30-day projections, and supply chain risk flags. **Combine Forecast and AI Output** merges the structured dataset with the AI narrative into a single payload for downstream routing."
      },
      "typeVersion": 1
    },
    {
      "id": "86baa62c-ae2a-4dc1-bc38-6f0491b8f189",
      "name": "Section 3: Alerts & Purchase Orders",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1104,
        64
      ],
      "parameters": {
        "color": 6,
        "width": 408,
        "height": 680,
        "content": "## 3\ufe0f\u20e3 Alerts & Purchase Orders\n\n**Critical Stock Exists?** evaluates whether any product has entered the critical threshold (under 7 days of stock) and branches the flow. When critical items are detected, **Send a message** fires an immediate formatted alert to the Slack #sales-team channel listing each affected product with days remaining and recommended order quantities. In parallel, **Generate Purchase Orders** builds structured PO records for all items flagged as CRITICAL, LOW, or REORDER, assigning each a unique PO number, supplier, order quantity, and estimated total cost."
      },
      "typeVersion": 1
    },
    {
      "id": "37949701-a3f4-41bd-9cf3-697951dd3df8",
      "name": "Section 4: Output & Logging",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1536,
        160
      ],
      "parameters": {
        "color": 4,
        "width": 520,
        "height": 584,
        "content": "## 4\ufe0f\u20e3 Output & Logging\n\n**Write Forecast to Sheet** appends a daily summary row to the Forecast_Analysis tab in Google Sheets, capturing report date, product counts by status, and the full AI analysis text for historical tracking. **Log Forecast Completion** finalizes the run by assembling a completion record that includes the number of products analyzed, critical alert count, purchase orders generated, and total estimated reorder value."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Build Forecast Dataset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send a message": {
      "main": [
        [
          {
            "node": "Write Forecast to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Demand Forecast Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Sales History": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Demand Forecast Agent": {
      "main": [
        [
          {
            "node": "Combine Forecast and AI Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Forecast Dataset": {
      "main": [
        [
          {
            "node": "Demand Forecast Agent",
            "type": "main",
            "index": 0
          },
          {
            "node": "Generate Purchase Orders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Critical Stock Exists?": {
      "main": [
        [
          {
            "node": "Send a message",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Write Forecast to Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Current Inventory": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Write Forecast to Sheet": {
      "main": [
        [
          {
            "node": "Log Forecast Completion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Purchase Orders": {
      "main": [
        [
          {
            "node": "Log Forecast Completion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Forecast Configuration": {
      "main": [
        [
          {
            "node": "Fetch Sales History",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Current Inventory",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Combine Forecast and AI Output": {
      "main": [
        [
          {
            "node": "Critical Stock Exists?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When clicking 'Execute workflow'": {
      "main": [
        [
          {
            "node": "Set Forecast Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

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

How it works

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

More AI & RAG workflows → · Browse all categories →

Related workflows

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

AI & RAG

Stop manually sending follow-ups. This workflow automates your entire cold email outreach with AI-powered personalization, smart scheduling, and automatic reply detection.

OpenAI Chat, Gmail Tool, Google Sheets +5
AI & RAG

This workflow streamlines academic assessment through a multi-agent AI system that interprets rubrics, grades submissions, checks for plagiarism, performs quality moderation, generates feedback, and e

HTTP Request, Agent, OpenAI Chat +3
AI & RAG

This workflow automates invoice processing directly from your email inbox.

Gmail Trigger, HTTP Request, Agent +5
AI & RAG

[](https://www.youtube.com/watch?v=MD1krFvVKdU) Automatically extract, evaluate, and shortlist multiple resumes against a selected job description using GPT-4. This smart, scalable n8n workflow helps

Form Trigger, Output Parser Structured, OpenAI Chat +6
AI & RAG

Streamline Facebook Messenger inbox management with an AI-powered categorization and response system. 💬⚙️ This workflow automatically classifies new messages as Lead, Query, or Spam using GPT-4, route

Error Trigger, Slack, Facebook Graph Api +5