{
  "name": "Stale Deal Alert — HubSpot → Slack",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      },
      "id": "schedule-trigger",
      "name": "Daily 8am",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [0, 0]
    },
    {
      "parameters": {
        "method": "GET",
        "url": "https://api.hubapi.com/crm/v3/pipelines/deals",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "hubspotApi",
        "options": {}
      },
      "id": "fetch-stages",
      "name": "Fetch Stages",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [220, 0],
      "credentials": {
        "hubspotApi": {
          "id": "credential-id",
          "name": "HubSpot API"
        }
      }
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.hubapi.com/crm/v3/objects/deals/search",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "hubspotApi",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={\n  \"filterGroups\": [\n    {\n      \"filters\": [\n        {\n          \"propertyName\": \"hs_lastmodifieddate\",\n          \"operator\": \"LT\",\n          \"value\": \"\" + $now.minus({days: 14}).toMillis()\n        },\n        {\n          \"propertyName\": \"dealstage\",\n          \"operator\": \"NOT_IN\",\n          \"values\": [\"closedwon\", \"closedlost\"]\n        }\n      ]\n    }\n  ],\n  \"properties\": [\"dealname\", \"amount\", \"dealstage\", \"hubspot_owner_id\", \"hs_lastmodifieddate\"],\n  \"sorts\": [{\"propertyName\": \"hs_lastmodifieddate\", \"direction\": \"ASCENDING\"}],\n  \"limit\": 100\n}",
        "options": {}
      },
      "id": "search-stale-deals",
      "name": "Search Stale Deals",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [440, 0],
      "credentials": {
        "hubspotApi": {
          "id": "credential-id",
          "name": "HubSpot API"
        }
      }
    },
    {
      "parameters": {
        "mode": "runOnceForAllItems",
        "jsCode": "const deals = $('Search Stale Deals').first().json.results || [];\nconst pipelines = $('Fetch Stages').first().json.results;\n\nconst stageMap = {};\nfor (const p of pipelines) {\n  for (const s of p.stages) stageMap[s.id] = s.label;\n}\n\nconst byOwner = {};\nfor (const deal of deals) {\n  const props = deal.properties;\n  const ownerId = props.hubspot_owner_id || 'unassigned';\n  const daysStale = Math.round((Date.now() - new Date(props.hs_lastmodifieddate)) / 86400000);\n\n  if (!byOwner[ownerId]) byOwner[ownerId] = [];\n  byOwner[ownerId].push({\n    name: props.dealname,\n    amount: parseFloat(props.amount || '0'),\n    stage: stageMap[props.dealstage] || props.dealstage,\n    daysStale,\n    dealId: deal.id,\n  });\n}\n\nreturn Object.entries(byOwner).map(([ownerId, deals]) => ({\n  json: { ownerId, deals, dealCount: deals.length }\n}));"
      },
      "id": "group-by-owner",
      "name": "Group by Owner",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [660, 0]
    },
    {
      "parameters": {
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "sales-pipeline",
          "mode": "name"
        },
        "messageType": "block",
        "blocksUi": "={\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \":warning: *Stale Deals Alert*\\nYou have *\" + $json.dealCount + \"* deals with no activity for 14+ days:\\n\" + $json.deals.map(d => \"\\u2022 *\" + d.name + \"* \\u2014 \" + d.stage + \" \\u2014 \" + d.daysStale + \"d stale \\u2014 $\" + d.amount.toLocaleString()).join('\\n')\n      }\n    }\n  ]\n}",
        "otherOptions": {
          "unfurl_links": false
        }
      },
      "id": "post-to-slack",
      "name": "Post to Slack",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.3,
      "position": [880, 0],
      "credentials": {
        "slackApi": {
          "id": "credential-id",
          "name": "Slack API"
        }
      }
    }
  ],
  "connections": {
    "Daily 8am": {
      "main": [
        [
          {
            "node": "Fetch Stages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Stages": {
      "main": [
        [
          {
            "node": "Search Stale Deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search Stale Deals": {
      "main": [
        [
          {
            "node": "Group by Owner",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Group by Owner": {
      "main": [
        [
          {
            "node": "Post to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "pinData": {},
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 0,
  "active": false,
  "meta": {
    "instanceId": "",
    "templateId": "revi-stale-deal-alert"
  }
}
