diff --git a/n8n/renewal-reminder.json b/n8n/renewal-reminder.json new file mode 100644 index 0000000..74548bc --- /dev/null +++ b/n8n/renewal-reminder.json @@ -0,0 +1,210 @@ +{ + "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 + } +} \ No newline at end of file