{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "5b494ae5-5c7b-4aeb-939c-033fad6d230a",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        19840,
        5152
      ],
      "parameters": {
        "color": 7,
        "width": 680,
        "height": 356,
        "content": "## Inventory Reorder Prediction\nVersion 1.0.0 \u2014 E-Commerce\n\nRuns daily, pulls all Shopify product variants with inventory levels, fetches orders from the last 7 days to compute sales velocity, then uses GPT-4o to predict stockout dates and determine whether to reorder. Reorder emails are sent to the supplier and all reorder decisions are logged to Google Sheets.\n\nFlow: Schedule => Fetch Products (Shopify) => Fetch Orders (Shopify) => Compute Sales Velocity (Code) => Predict Stockout Risk (AI Agent) => Should Reorder? (IF) => Send Reorder Email + Log to Sheets"
      },
      "typeVersion": 1
    },
    {
      "id": "d4559dd4-0805-41c3-8f7e-14039c1b9191",
      "name": "Prerequisites",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        19856,
        5520
      ],
      "parameters": {
        "color": 5,
        "width": 420,
        "height": 276,
        "content": "## Prerequisites\n- Shopify store with Admin API access (Custom App)\n- OpenAI API key (GPT-4o)\n- Gmail account for reorder notifications\n- Google Sheets for reorder log\n\nShopify setup: Admin => Apps and sales channels => Develop apps => Create an app => Enable read_products and read_orders API scopes => Install app => Copy Admin API access token."
      },
      "typeVersion": 1
    },
    {
      "id": "d4dbdfb5-d585-4502-9431-5c16ab689f55",
      "name": "Setup Required",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        20544,
        5328
      ],
      "parameters": {
        "color": 3,
        "width": 420,
        "height": 404,
        "content": "## Setup Required\n1. Fetch Products + Fetch Orders \u2014 connect 'Shopify Access Token API' credential\n2. OpenAI sub-node \u2014 connect OpenAI credential\n3. Send Reorder Email \u2014 connect Gmail OAuth2 credential, update supplier@example.com to real address\n4. Log to Google Sheets \u2014 connect Google Sheets credential, replace YOUR_REORDER_LOG_SHEET_ID\n5. Adjust reorder threshold in the Should Reorder? IF node (default: should_reorder = true from AI)"
      },
      "typeVersion": 1
    },
    {
      "id": "188a9caf-38bf-4c4c-ba2f-af9566181e89",
      "name": "How It Works",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        19840,
        5824
      ],
      "parameters": {
        "color": 4,
        "width": 420,
        "height": 488,
        "content": "## How It Works\n1. Runs daily at 06:00 UTC via cron schedule\n2. Fetches all Shopify products and their variant inventory levels\n3. Fetches all orders from the past 7 days and sums units sold per variant\n4. Code node joins the two datasets to compute sales velocity (units/day) and estimated days until stockout\n5. AI Agent evaluates each variant's risk level and recommended reorder quantity\n6. IF should_reorder is true: sends email to supplier and logs to Google Sheets\n7. IF should_reorder is false: logs to Google Sheets with low risk status"
      },
      "typeVersion": 1
    },
    {
      "id": "c3e2e2b9-77bc-493f-a69d-d26fc789f0d9",
      "name": "Daily Inventory Check",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        20256,
        5936
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 6 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "5aa9c8f2-93f0-4e2e-ab51-7c4765f8e2c6",
      "name": "Fetch Products note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        20368,
        5792
      ],
      "parameters": {
        "width": 270,
        "height": 96,
        "content": "Pulls all product variants with current inventory_quantity from Shopify"
      },
      "typeVersion": 1
    },
    {
      "id": "1f8a64ed-475b-4589-a783-9ce974891dea",
      "name": "Fetch All Products",
      "type": "n8n-nodes-base.shopify",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        20416,
        5936
      ],
      "parameters": {
        "resource": "product",
        "operation": "getAll",
        "returnAll": true,
        "additionalFields": {}
      },
      "retryOnFail": true,
      "typeVersion": 1,
      "waitBetweenTries": 2000
    },
    {
      "id": "b795a9d5-1a42-4423-8e22-060b08c40f7c",
      "name": "Fetch Orders note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        20656,
        5792
      ],
      "parameters": {
        "width": 260,
        "height": 96,
        "content": "Fetches all orders from the last 7 days to calculate sales velocity"
      },
      "typeVersion": 1
    },
    {
      "id": "0825665e-ad08-4576-836e-baa074294a2d",
      "name": "Fetch Recent Orders",
      "type": "n8n-nodes-base.shopify",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        20672,
        5920
      ],
      "parameters": {
        "options": {
          "status": "any"
        },
        "operation": "getAll",
        "returnAll": true
      },
      "retryOnFail": true,
      "typeVersion": 1,
      "waitBetweenTries": 2000
    },
    {
      "id": "a805af61-e0d0-42d9-994a-7412ebed5155",
      "name": "Velocity note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        20928,
        5792
      ],
      "parameters": {
        "width": 238,
        "height": 96,
        "content": "Joins products + orders, computes velocity (units/day) and days until stockout per variant"
      },
      "typeVersion": 1
    },
    {
      "id": "44d9823e-3f64-4220-8a3f-fae0f242048c",
      "name": "Compute Sales Velocity",
      "type": "n8n-nodes-base.code",
      "position": [
        20944,
        5904
      ],
      "parameters": {
        "jsCode": "const orders = $('Fetch Recent Orders').all();\nconst salesMap = {};\nfor (const order of orders) {\n  for (const item of (order.json.line_items || [])) {\n    const vid = String(item.variant_id);\n    salesMap[vid] = (salesMap[vid] || 0) + (item.quantity || 0);\n  }\n}\nconst products = $('Fetch All Products').all();\nconst result = [];\nfor (const product of products) {\n  for (const variant of (product.json.variants || [])) {\n    const vid = String(variant.id);\n    const stock = variant.inventory_quantity || 0;\n    const sold7d = salesMap[vid] || 0;\n    const velocity = sold7d / 7;\n    const days_until_stockout = velocity > 0 ? Math.floor(stock / velocity) : 999;\n    result.push({ json: {\n      product_title:    product.json.title,\n      variant_id:       vid,\n      variant_title:    variant.title,\n      sku:              variant.sku || '',\n      stock,\n      sold_7d:          sold7d,\n      velocity_per_day: Math.round(velocity * 100) / 100,\n      days_until_stockout\n    }});\n  }\n}\nreturn result;"
      },
      "typeVersion": 2
    },
    {
      "id": "eabd760d-b5c7-4506-af34-a71c03a0a05d",
      "name": "Predict note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        21184,
        5792
      ],
      "parameters": {
        "width": 302,
        "height": 96,
        "content": "AI Agent assesses stockout risk and recommends reorder quantity with 30-day + 20% safety buffer"
      },
      "typeVersion": 1
    },
    {
      "id": "8127ab51-ad94-4f26-a48f-12d04ef81f59",
      "name": "Predict Stockout Risk",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        21216,
        5904
      ],
      "parameters": {
        "text": "=Analyse this Shopify product variant and determine reorder urgency.\n\nProduct: {{ $json.product_title }} \u2014 {{ $json.variant_title }}\nSKU: {{ $json.sku }}\nCurrent Stock: {{ $json.stock }} units\nSold in Last 7 Days: {{ $json.sold_7d }} units\nSales Velocity: {{ $json.velocity_per_day }} units/day\nEstimated Days Until Stockout: {{ $json.days_until_stockout }}\n\nAssess risk level, recommend a reorder quantity that covers 30 days of demand plus 20% safety stock, and decide whether an immediate reorder is needed.",
        "options": {
          "systemMessage": "=You are an inventory analyst for an e-commerce business. Assess stockout risk based on sales velocity and current stock. critical = stockout within 3 days, high = within 7 days, medium = 7-14 days, low = 14+ days. Recommend reorder quantities based on 30-day demand plus 20% safety buffer. If stock is 0 and velocity is 0, classify as low risk.",
          "returnIntermediateSteps": false
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.8
    },
    {
      "id": "9b30b060-c895-458a-942a-2160cb146bd5",
      "name": "OpenAI \u2014 Predict",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        21088,
        6144
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o"
        },
        "options": {
          "temperature": 0
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "acbb6299-063c-4fe8-b4d2-89f97ab63235",
      "name": "Stockout Risk Schema",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        21408,
        6128
      ],
      "parameters": {
        "schemaType": "manual",
        "inputSchema": "{\"type\":\"object\",\"properties\":{\"risk_level\":{\"type\":\"string\",\"enum\":[\"critical\",\"high\",\"medium\",\"low\"]},\"recommended_reorder_qty\":{\"type\":\"integer\"},\"reasoning\":{\"type\":\"string\"},\"should_reorder\":{\"type\":\"boolean\"}},\"required\":[\"risk_level\",\"recommended_reorder_qty\",\"reasoning\",\"should_reorder\"]}"
      },
      "typeVersion": 1.2
    },
    {
      "id": "7781da67-6c37-4b3c-b52b-84213d3e8050",
      "name": "Should Reorder note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        21504,
        5792
      ],
      "parameters": {
        "width": 255,
        "height": 96,
        "content": "Routes to email supplier (true) or skip to log only (false)"
      },
      "typeVersion": 1
    },
    {
      "id": "c9d3f410-9ba0-49ae-b11a-fc6eec70ff5d",
      "name": "Should Reorder?",
      "type": "n8n-nodes-base.if",
      "position": [
        21536,
        5904
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cond-reorder",
              "operator": {
                "type": "boolean",
                "operation": "equal"
              },
              "leftValue": "={{ $json.output.should_reorder }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "c6e17c0d-0253-44ff-aadf-978ae89a753f",
      "name": "Email note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        21776,
        5744
      ],
      "parameters": {
        "width": 255,
        "height": 60,
        "content": "Sends reorder request to supplier with full variant details"
      },
      "typeVersion": 1
    },
    {
      "id": "be5298cc-5a62-4e86-8cf8-641fceb8d2c5",
      "name": "Send Reorder Email",
      "type": "n8n-nodes-base.gmail",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        21808,
        5840
      ],
      "parameters": {
        "sendTo": "user@example.com",
        "message": "=<h2>Reorder Request</h2><table border='1' cellpadding='6' cellspacing='0' style='border-collapse:collapse'><tr><td><strong>Product</strong></td><td>{{ $('Compute Sales Velocity').item.json.product_title }} \u2014 {{ $('Compute Sales Velocity').item.json.variant_title }}</td></tr><tr><td><strong>SKU</strong></td><td>{{ $('Compute Sales Velocity').item.json.sku }}</td></tr><tr><td><strong>Current Stock</strong></td><td>{{ $('Compute Sales Velocity').item.json.stock }} units</td></tr><tr><td><strong>Sales Velocity</strong></td><td>{{ $('Compute Sales Velocity').item.json.velocity_per_day }} units/day</td></tr><tr><td><strong>Days Until Stockout</strong></td><td>{{ $('Compute Sales Velocity').item.json.days_until_stockout }}</td></tr><tr><td><strong>Risk Level</strong></td><td>{{ $json.output.risk_level.toUpperCase() }}</td></tr><tr><td><strong>Recommended Reorder Qty</strong></td><td>{{ $json.output.recommended_reorder_qty }} units</td></tr></table><p><em>{{ $json.output.reasoning }}</em></p><p>Please confirm receipt and expected delivery timeline.</p>",
        "options": {},
        "subject": "=Reorder Request \u2014 {{ $('Compute Sales Velocity').item.json.product_title }} (SKU: {{ $('Compute Sales Velocity').item.json.sku }})"
      },
      "retryOnFail": true,
      "typeVersion": 2.1,
      "waitBetweenTries": 2000
    },
    {
      "id": "3c432a16-5374-4310-a221-5724ded8150a",
      "name": "Log note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        22128,
        5776
      ],
      "parameters": {
        "width": 265,
        "height": 144,
        "content": "Logs all reorder decisions (triggered or skipped) to Google Sheets for tracking"
      },
      "typeVersion": 1
    },
    {
      "id": "eff4aab4-2149-4f6b-860f-1d63706fa714",
      "name": "Log to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "onError": "continueErrorOutput",
      "maxTries": 3,
      "position": [
        21840,
        6096
      ],
      "parameters": {
        "columns": {
          "value": {
            "SKU": "={{ $('Compute Sales Velocity').item.json.sku }}",
            "Stock": "={{ $('Compute Sales Velocity').item.json.stock }}",
            "Product": "={{ $('Compute Sales Velocity').item.json.product_title }}",
            "Sold 7d": "={{ $('Compute Sales Velocity').item.json.sold_7d }}",
            "Variant": "={{ $('Compute Sales Velocity').item.json.variant_title }}",
            "Reasoning": "={{ $('Predict Stockout Risk').item.json.output.reasoning }}",
            "Timestamp": "={{ DateTime.now().toISO() }}",
            "Risk Level": "={{ $('Predict Stockout Risk').item.json.output.risk_level }}",
            "Reorder Qty": "={{ $('Predict Stockout Risk').item.json.output.recommended_reorder_qty }}",
            "Velocity/day": "={{ $('Compute Sales Velocity').item.json.velocity_per_day }}",
            "Days to Stockout": "={{ $('Compute Sales Velocity').item.json.days_until_stockout }}",
            "Reorder Triggered": "={{ $('Predict Stockout Risk').item.json.output.should_reorder }}"
          },
          "mappingMode": "defineBelow"
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "name",
          "value": "Reorder Log"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "YOUR_REORDER_LOG_SHEET_ID"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.5,
      "waitBetweenTries": 2000
    }
  ],
  "connections": {
    "Should Reorder?": {
      "main": [
        [
          {
            "node": "Send Reorder Email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch All Products": {
      "main": [
        [
          {
            "node": "Fetch Recent Orders",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI \u2014 Predict": {
      "ai_languageModel": [
        [
          {
            "node": "Predict Stockout Risk",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Send Reorder Email": {
      "main": [
        [
          {
            "node": "Log to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Recent Orders": {
      "main": [
        [
          {
            "node": "Compute Sales Velocity",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Stockout Risk Schema": {
      "ai_outputParser": [
        [
          {
            "node": "Predict Stockout Risk",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Daily Inventory Check": {
      "main": [
        [
          {
            "node": "Fetch All Products",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Predict Stockout Risk": {
      "main": [
        [
          {
            "node": "Should Reorder?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compute Sales Velocity": {
      "main": [
        [
          {
            "node": "Predict Stockout Risk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}