{
  "name": "Asset Warranty Expiry Guardian — Never Miss A Warranty Or Renewal Deadline Again (Sheets → Gmail → Todoist → Slack)",
  "nodes": [
    {
      "id": "8e504d88-7104-41ed-85ed-1e1e24822dbf",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -400,
        64
      ],
      "parameters": {
        "width": 520,
        "height": 800,
        "content": "## Asset Warranty Expiry Guardian\n\nLaptops, monitors, machines, licenses — every one of them has a warranty that quietly expires. This workflow reads your **asset register from Google Sheets** every morning, computes each item's warranty deadline and routes it through an escalation ladder:\n\n- **30 days left** → email the asset owner to decide: extend, replace or let it lapse. For assets worth ≥ 2000, an LLM also drafts a **vendor negotiation email** (saved as Gmail draft)\n- **7 days left** → urgent Slack alert + a Todoist task with a due date\n- **Already expired** → the register is updated to `warranty expired` so reports stay honest\n\n### 🔧 Setup\n1. Create a sheet with headers: `asset, owner_email, purchase_date, warranty_months, vendor, value, status`.\n2. Connect **Google Sheets**, **Gmail**, **OpenAI**, **Slack** and **Todoist** credentials.\n3. Select the sheet in **Read Asset Register** and **Mark As Expired**.\n4. Adjust the high-value threshold (2000) in **High-Value Asset?**.\n5. Activate — runs daily at **08:30**.\n\n### 💡 Why it's useful\nA single missed warranty claim on one broken laptop usually costs more than a year of running this workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "859e2780-a9cc-4384-bad1-e96f6dc01fc0",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        560,
        320
      ],
      "parameters": {
        "color": 4,
        "width": 660,
        "height": 460,
        "content": "### 1️⃣ Compute deadlines\nExpiry date = purchase date + warranty months. Each asset gets `daysLeft` and is routed by urgency."
      },
      "typeVersion": 1
    },
    {
      "id": "9fbe5ffc-53cd-423a-a85c-6a0c25ec49b7",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        320
      ],
      "parameters": {
        "color": 5,
        "width": 640,
        "height": 868,
        "content": "### 2️⃣ Escalation ladder\n 30 days: owner decides ·  7 days: Slack + Todoist task · 💀 expired: register updated."
      },
      "typeVersion": 1
    },
    {
      "id": "db790013-e7bc-40ba-b9fb-f44249a46bbc",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1984,
        720
      ],
      "parameters": {
        "color": 6,
        "width": 700,
        "height": 460,
        "content": "### 3️⃣ High-value negotiation\nFor expensive assets, the LLM drafts a warranty-extension negotiation email to the vendor — saved as a Gmail draft for you to review and send."
      },
      "typeVersion": 1
    },
    {
      "id": "3c937028-161a-43f5-9ca4-8c2f8bc3305a",
      "name": "Every Day 08:30",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        176,
        608
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8,
              "triggerAtMinute": 30
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "abb2a8a3-4e0a-4feb-974f-fc646f745003",
      "name": "Read Asset Register",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        400,
        608
      ],
      "parameters": {
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "fd69bf11-9571-4394-9c1a-0ad6aaf2ecd3",
      "name": "Compute Days Left",
      "type": "n8n-nodes-base.code",
      "position": [
        704,
        608
      ],
      "parameters": {
        "jsCode": "// Expiry date = purchase_date + warranty_months; compute days left for each asset\nconst today = new Date();\ntoday.setHours(0, 0, 0, 0);\n\nreturn $input.all()\n  .map(item => {\n    const row = item.json;\n    const purchase = new Date(row.purchase_date);\n    const months = Number(row.warranty_months) || 0;\n    const expiry = new Date(purchase);\n    expiry.setMonth(expiry.getMonth() + months);\n    const daysLeft = Math.floor((expiry - today) / 864e5);\n\n    return {\n      json: {\n        ...row,\n        value: Number(row.value) || 0,\n        expiryDate: expiry.toISOString().slice(0, 10),\n        daysLeft: isNaN(daysLeft) ? null : daysLeft\n      }\n    };\n  })\n  .filter(item => item.json.daysLeft !== null && item.json.status !== 'warranty expired');"
      },
      "typeVersion": 2
    },
    {
      "id": "08b53c61-6a6b-4f3a-8a88-fa0df72104f5",
      "name": "Route By Urgency",
      "type": "n8n-nodes-base.switch",
      "position": [
        992,
        592
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "Expired",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "sw-1",
                    "operator": {
                      "type": "number",
                      "operation": "lt"
                    },
                    "leftValue": "={{ $json.daysLeft }}",
                    "rightValue": 0
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "7 Days",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "sw-2",
                    "operator": {
                      "type": "number",
                      "operation": "lte"
                    },
                    "leftValue": "={{ $json.daysLeft }}",
                    "rightValue": 7
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "30 Days",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "loose"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "sw-3",
                    "operator": {
                      "type": "number",
                      "operation": "lte"
                    },
                    "leftValue": "={{ $json.daysLeft }}",
                    "rightValue": 30
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.2
    },
    {
      "id": "b00a67eb-2955-45f4-86fc-58547d3d646d",
      "name": "Mark As Expired",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1392,
        448
      ],
      "parameters": {
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": ""
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 4.5
    },
    {
      "id": "4f5a8992-dc78-4ddb-80b9-8710bf54b3a4",
      "name": "Urgent Slack Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        1392,
        608
      ],
      "parameters": {
        "text": "=*Warranty expires in {{ $json.daysLeft }} day(s)!*\n\n• Asset: *{{ $json.asset }}* (value: {{ $json.value }})\n• Vendor: {{ $json.vendor }}\n• Expiry: {{ $json.expiryDate }}\n• Owner: {{ $json.owner_email }}\n\nLast chance to file claims or extend — a Todoist task with the deadline was just created.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "name",
          "value": "#it-assets"
        },
        "otherOptions": {}
      },
      "typeVersion": 2.3
    },
    {
      "id": "b65a4819-01d3-4a90-8383-1d373c9c6b98",
      "name": "Create Deadline Task",
      "type": "n8n-nodes-base.todoist",
      "position": [
        1616,
        608
      ],
      "parameters": {
        "content": "=Warranty deadline: {{ $json.asset }} ({{ $json.vendor }}) expires {{ $json.expiryDate }}",
        "options": {
          "description": "=Check the asset's condition NOW and file any warranty claims before {{ $json.expiryDate }}. Owner: {{ $json.owner_email }} — value: {{ $json.value }}.",
          "dueDateTime": "={{ $json.expiryDate }}"
        },
        "project": {
          "__rl": true,
          "mode": "list",
          "value": ""
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "8692b4cd-e178-45c6-9d79-6b00bac5ada5",
      "name": "Owner Decision Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1392,
        880
      ],
      "parameters": {
        "sendTo": "={{ $json.owner_email }}",
        "message": "=Hi,\n\nThe warranty for an asset you own expires in <b>{{ $json.daysLeft }} days</b>:\n\n<ul><li>Asset: <b>{{ $json.asset }}</b></li><li>Vendor: {{ $json.vendor }}</li><li>Expiry: {{ $json.expiryDate }}</li><li>Book value: {{ $json.value }}</li></ul>\n\nPlease decide this week and reply with one of:\n<b>EXTEND</b> (we'll contact the vendor) · <b>REPLACE</b> (we'll start procurement) · <b>LAPSE</b> (asset is fine to run without warranty)\n\nThanks!\nAsset Guardian 🤖",
        "options": {},
        "subject": "=Warranty for \"{{ $json.asset }}\" ends {{ $json.expiryDate }} — decision needed"
      },
      "typeVersion": 2.1
    },
    {
      "id": "c31ddc22-c633-4a1f-9e5c-7eacd7fb4a3d",
      "name": "High-Value Asset?",
      "type": "n8n-nodes-base.if",
      "position": [
        1600,
        880
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "if-1",
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $json.value }}",
              "rightValue": 2000
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8e44343e-9f64-4867-8e2f-a35d749ccf78",
      "name": "Draft Negotiation Email",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        2048,
        864
      ],
      "parameters": {
        "text": "=Draft a warranty-extension negotiation email to a vendor.\n\nContext:\n- Asset: {{ $json.asset }}\n- Vendor: {{ $json.vendor }}\n- Current warranty ends: {{ $json.expiryDate }}\n- Asset book value: {{ $json.value }}\n\nRules:\n- Max 160 words, plain text, professional but warm\n- Ask for an extension quote AND mention we're comparing against replacing the asset (real leverage, no bluffing)\n- Ask for multi-year pricing options\n- Leave [NAME] placeholders for the sender's signature\n\nReturn only the email body.",
        "messages": {
          "messageValues": [
            {
              "message": "You are a procurement specialist who writes short, effective vendor negotiation emails."
            }
          ]
        },
        "promptType": "define"
      },
      "typeVersion": 1.5
    },
    {
      "id": "90ba795b-8e0d-49cf-a82e-cbf3293a256a",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2048,
        1024
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "b704de61-1d40-4dfb-8c72-53481345e24b",
      "name": "Save Negotiation Draft",
      "type": "n8n-nodes-base.gmail",
      "position": [
        2384,
        864
      ],
      "parameters": {
        "message": "={{ $json.text }}",
        "options": {},
        "subject": "=Warranty extension inquiry — {{ $('High-Value Asset?').item.json.asset }}",
        "resource": "draft"
      },
      "typeVersion": 2.1
    }
  ],
  "connections": {
    "Every Day 08:30": {
      "main": [
        [
          {
            "node": "Read Asset Register",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route By Urgency": {
      "main": [
        [
          {
            "node": "Mark As Expired",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Urgent Slack Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Owner Decision Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compute Days Left": {
      "main": [
        [
          {
            "node": "Route By Urgency",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "High-Value Asset?": {
      "main": [
        [
          {
            "node": "Draft Negotiation Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Draft Negotiation Email",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Urgent Slack Alert": {
      "main": [
        [
          {
            "node": "Create Deadline Task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Read Asset Register": {
      "main": [
        [
          {
            "node": "Compute Days Left",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Owner Decision Email": {
      "main": [
        [
          {
            "node": "High-Value Asset?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Draft Negotiation Email": {
      "main": [
        [
          {
            "node": "Save Negotiation Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "active": false
}
