feat(n8n): financial-brief.json workflow for CEO OS automation
This commit is contained in:
parent
299ffaeb95
commit
9629b4e794
1 changed files with 264 additions and 0 deletions
264
n8n-workflows/financial-brief.json
Normal file
264
n8n-workflows/financial-brief.json
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
{
|
||||
"name": "CEO OS — Financial Weekly Brief",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "n4-trigger",
|
||||
"name": "Every Friday 17:00",
|
||||
"type": "n8n-nodes-base.scheduleTrigger",
|
||||
"typeVersion": 1,
|
||||
"position": [
|
||||
0,
|
||||
300
|
||||
],
|
||||
"parameters": {
|
||||
"rule": {
|
||||
"interval": [
|
||||
{
|
||||
"field": "cronExpression",
|
||||
"expression": "0 17 * * 5"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "n4-vars",
|
||||
"name": "Config",
|
||||
"type": "n8n-nodes-base.set",
|
||||
"typeVersion": 3,
|
||||
"position": [
|
||||
220,
|
||||
300
|
||||
],
|
||||
"parameters": {
|
||||
"mode": "manual",
|
||||
"assignments": {
|
||||
"assignments": [
|
||||
{
|
||||
"id": "d1",
|
||||
"name": "api",
|
||||
"value": "={{$env['CEO_OS_API_URL'] ?? 'https://boardmind.dev/api'}}",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"id": "d2",
|
||||
"name": "tenantId",
|
||||
"value": "={{$env['CEO_OS_TENANT_ID']}}",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"id": "d3",
|
||||
"name": "serviceKey",
|
||||
"value": "={{$env['CEO_OS_SERVICE_KEY']}}",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "n4-contracts",
|
||||
"name": "Get Contracts",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4,
|
||||
"position": [
|
||||
440,
|
||||
200
|
||||
],
|
||||
"parameters": {
|
||||
"url": "={{$json.api}}/v1/contracts?tenantId={{$json.tenantId}}",
|
||||
"method": "GET",
|
||||
"sendHeaders": true,
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "X-Service-Key",
|
||||
"value": "={{$json.serviceKey}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "n4-obs",
|
||||
"name": "Get Expense Observations",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4,
|
||||
"position": [
|
||||
440,
|
||||
400
|
||||
],
|
||||
"parameters": {
|
||||
"url": "={{$('Config').item.json.api}}/v1/observations?tenantId={{$('Config').item.json.tenantId}}&subjectType=expense",
|
||||
"method": "GET",
|
||||
"sendHeaders": true,
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "X-Service-Key",
|
||||
"value": "={{$('Config').item.json.serviceKey}}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "n4-build",
|
||||
"name": "Build Financial Context",
|
||||
"type": "n8n-nodes-base.code",
|
||||
"typeVersion": 2,
|
||||
"position": [
|
||||
680,
|
||||
300
|
||||
],
|
||||
"parameters": {
|
||||
"jsCode": "const cfg = $('Config').item.json;\nconst contracts = $('Get Contracts').all().map(i => i.json);\nconst expenses = $('Get Expense Observations').all().map(i => i.json);\n\nconst now = Date.now();\nconst monthAgo = now - 30 * 86400000;\n\nconst activeContracts = contracts.filter(c => c.status === 'signed' || c.status === 'active');\nconst totalRevenue = activeContracts.reduce((s, c) => s + (parseFloat(c.value) || 0), 0);\n\nconst monthlyExpenses = expenses.filter(e => new Date(e.observedAt || e.createdAt).getTime() > monthAgo);\nconst totalExpenses = monthlyExpenses.reduce((s, e) => s + (parseFloat(e.value) || 0), 0);\n\nconst prompt = [\n `Generează un brief financiar săptămânal. Vineri, ${new Date().toLocaleDateString('ro-RO')}.`,\n '',\n `## Date financiare:`,\n `- Contracte active: ${activeContracts.length} → Total valoare: ${totalRevenue.toLocaleString('ro-RO')} EUR`,\n `- Cheltuieli luna curentă: ${totalExpenses.toLocaleString('ro-RO')} EUR (${monthlyExpenses.length} tranzacții)`,\n `- Sold net estimat: ${(totalRevenue - totalExpenses).toLocaleString('ro-RO')} EUR`,\n '',\n 'Structurează în: 💰 Situație actuală, 📈 Tendință, ⚠️ Atenție la, ✅ Recomandate. Max 200 cuvinte.',\n].join('\\n');\n\nreturn [{ json: {\n prompt, totalRevenue, totalExpenses,\n api: cfg.api, tenantId: cfg.tenantId, serviceKey: cfg.serviceKey,\n}}];"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "n4-ai",
|
||||
"name": "Generate Financial Brief",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4,
|
||||
"position": [
|
||||
900,
|
||||
300
|
||||
],
|
||||
"parameters": {
|
||||
"url": "={{$json.api}}/v1/ai/ask",
|
||||
"method": "POST",
|
||||
"sendHeaders": true,
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "X-Service-Key",
|
||||
"value": "={{$json.serviceKey}}"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "={\"messages\": [{\"role\": \"user\", \"content\": {{JSON.stringify($json.prompt)}}}], \"context\": \"{\\\"financialBrief\\\": true}\"}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "n4-save",
|
||||
"name": "Save Financial Brief",
|
||||
"type": "n8n-nodes-base.httpRequest",
|
||||
"typeVersion": 4,
|
||||
"position": [
|
||||
1120,
|
||||
300
|
||||
],
|
||||
"parameters": {
|
||||
"url": "={{$('Build Financial Context').item.json.api}}/v1/observations",
|
||||
"method": "POST",
|
||||
"sendHeaders": true,
|
||||
"headerParameters": {
|
||||
"parameters": [
|
||||
{
|
||||
"name": "X-Service-Key",
|
||||
"value": "={{$('Build Financial Context').item.json.serviceKey}}"
|
||||
},
|
||||
{
|
||||
"name": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
]
|
||||
},
|
||||
"sendBody": true,
|
||||
"specifyBody": "json",
|
||||
"jsonBody": "={\"tenantId\": \"{{$('Build Financial Context').item.json.tenantId}}\", \"metric\": \"financial-brief\", \"value\": {{JSON.stringify($json.reply)}}, \"unit\": \"{{$('Build Financial Context').item.json.totalRevenue}} EUR\", \"subjectType\": \"finance\", \"confidence\": 0.95}"
|
||||
}
|
||||
}
|
||||
],
|
||||
"connections": {
|
||||
"Every Friday 17:00": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Config",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Config": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Get Contracts",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
},
|
||||
{
|
||||
"node": "Get Expense Observations",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Contracts": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Build Financial Context",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Get Expense Observations": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Build Financial Context",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Build Financial Context": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Generate Financial Brief",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
},
|
||||
"Generate Financial Brief": {
|
||||
"main": [
|
||||
[
|
||||
{
|
||||
"node": "Save Financial Brief",
|
||||
"type": "main",
|
||||
"index": 0
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
},
|
||||
"active": false,
|
||||
"settings": {
|
||||
"executionOrder": "v1"
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "ceo-os"
|
||||
},
|
||||
{
|
||||
"name": "finance"
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in a new issue