Files
smb-online/n8n/renewal-reminder.json
T
mivanchenko 1e6c46e9f0 Phase 3: add renewal-reminder workflow
Daily 08:00 schedule → read Clients → flag active clients whose
renewal_date is due (14/7/3/1/0 days out or overdue) → Telegram
summary → log to Activity Log. Quiet on days with nothing due.
Verified end-to-end via CLI run against a seeded due client.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 14:42:29 +02:00

210 lines
6.1 KiB
JSON

{
"name": "SMB \u00b7 Renewal Reminder",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "cronExpression",
"expression": "0 8 * * *"
}
]
}
},
"id": "41b1500b-ece3-44ea-b192-363a998c1247",
"name": "Daily 08:00",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
240,
300
]
},
{
"parameters": {
"authentication": "serviceAccount",
"resource": "sheet",
"operation": "read",
"documentId": {
"__rl": true,
"value": "1raMSWRZw_JfHlWqOb3LbhaQ6LWx0VGblxIV4Z2pSzp8",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "470934735",
"mode": "list",
"cachedResultName": "Clients"
},
"options": {}
},
"id": "f06a60af-dff1-415d-aca6-fef0367f3553",
"name": "Read Clients",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
460,
300
],
"credentials": {
"googleApi": {
"id": "45TWPyl1wVk2Vxdm",
"name": "SMB Google (service account)"
}
}
},
{
"parameters": {
"jsCode": "\nconst rows = $input.all().map(i=>i.json);\nconst today=new Date();\nconst t0=Date.UTC(today.getUTCFullYear(),today.getUTCMonth(),today.getUTCDate());\nfunction parseDate(v){\n if(v==null||v==='') return null;\n const s=String(v).trim();\n if(/^\\d+(\\.\\d+)?$/.test(s)){ return Date.UTC(1899,11,30)+Number(s)*86400000; }\n const m=s.match(/^(\\d{4})-(\\d{2})-(\\d{2})/);\n if(m) return Date.UTC(+m[1],+m[2]-1,+m[3]);\n const d=Date.parse(s); return isNaN(d)?null:d;\n}\nconst offsets=[14,7,3,1,0];\nconst due=[];\nfor(const r of rows){\n const status=String(r.status||'').toLowerCase();\n if(status!=='active') continue;\n const rd=parseDate(r.renewal_date);\n if(rd==null) continue;\n const days=Math.round((rd-t0)/86400000);\n if(days<0 || offsets.includes(days)){\n due.push({client_id:r.client_id, business:r.business_name, renewal_date:r.renewal_date,\n days, fee:r.monthly_fee_eur, cycle:r.billing_cycle});\n }\n}\nif(due.length===0) return [];\ndue.sort((a,b)=>a.days-b.days);\nconst line=d=>`\u2022 ${d.business||d.client_id} \u2014 ${d.days<0?('\u00dcBERF\u00c4LLIG seit '+(-d.days)+'T'):(d.days===0?'heute':('in '+d.days+'T'))} (${d.renewal_date}${d.fee?(', '+d.fee+'\u20ac/'+(d.cycle||'')):''})`;\nconst summary='\ud83d\udd14 Anstehende Verl\u00e4ngerungen ('+due.length+')\\n'+due.map(line).join('\\n');\nreturn [{json:{count:due.length, summary, due}}];\n"
},
"id": "9f3e4ca9-0d87-4d1c-9f5e-abdf5f9f77dd",
"name": "Find due renewals",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
680,
300
]
},
{
"parameters": {
"resource": "message",
"operation": "sendMessage",
"chatId": "5499280257",
"text": "={{ $json.summary }}",
"additionalFields": {
"appendAttribution": false
}
},
"id": "807748ee-311e-4b18-bae1-ae339068a04f",
"name": "Notify Telegram",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.2,
"position": [
900,
300
],
"credentials": {
"telegramApi": {
"id": "d9s4Ec5ocEH8FAxh",
"name": "SMB Telegram (leads bot)"
}
}
},
{
"parameters": {
"jsCode": "const r=$('Find due renewals').first().json;\nconst now=new Date().toISOString().replace('T',' ').slice(0,16);\nreturn [{json:{ts:now, workflow:'renewal-reminder', client_id:'',\n action:'renewals due: '+r.count,\n detail:r.due.map(d=>d.client_id+'('+d.days+'T)').join(', '), result:'ok'}}];"
},
"id": "c6a1792f-1866-4b1a-aa74-e1f346d80a97",
"name": "Build activity",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1120,
300
]
},
{
"parameters": {
"authentication": "serviceAccount",
"resource": "sheet",
"operation": "append",
"documentId": {
"__rl": true,
"value": "1raMSWRZw_JfHlWqOb3LbhaQ6LWx0VGblxIV4Z2pSzp8",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "170940481",
"mode": "list",
"cachedResultName": "Activity Log"
},
"columns": {
"mappingMode": "autoMapInputData",
"value": {},
"matchingColumns": [],
"schema": []
},
"options": {}
},
"id": "55978962-489b-4740-a242-7470f08087b6",
"name": "Append to Activity Log",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
1340,
300
],
"credentials": {
"googleApi": {
"id": "45TWPyl1wVk2Vxdm",
"name": "SMB Google (service account)"
}
}
}
],
"connections": {
"Daily 08:00": {
"main": [
[
{
"node": "Read Clients",
"type": "main",
"index": 0
}
]
]
},
"Read Clients": {
"main": [
[
{
"node": "Find due renewals",
"type": "main",
"index": 0
}
]
]
},
"Find due renewals": {
"main": [
[
{
"node": "Notify Telegram",
"type": "main",
"index": 0
}
]
]
},
"Notify Telegram": {
"main": [
[
{
"node": "Build activity",
"type": "main",
"index": 0
}
]
]
},
"Build activity": {
"main": [
[
{
"node": "Append to Activity Log",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"callerPolicy": "workflowsFromSameOwner",
"availableInMCP": false
}
}