semillero-special-hotel/n8n/settlement_calculation_workflow.json
gabogg 41fb0d0d75 feat: implement phase 5 settlements and i18n support
- Add English/Spanish translation system for UI pages
- Add bilingual AI audit notes using translation LLM chains in n8n
- Support zero-trust Docker routing to dev stack via internal hostnames
- Quiet down Next.js database query and middleware logging in test runs
2026-06-12 19:00:46 +00:00

503 lines
17 KiB
JSON

{
"name": "Settlement Calculation Workflow",
"nodes": [
{
"parameters": {
"httpMethod": "POST",
"path": "calculate-settlements",
"responseMode": "responseNode",
"options": {
"rawBody": false
}
},
"id": "Webhook-Node-1",
"name": "Webhook",
"type": "n8n-nodes-base.webhook",
"typeVersion": 1,
"position": [
100,
300
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ ($node[\"Webhook\"].json[\"headers\"][\"x-forwarded-uri\"] || \"\").includes(\"webhook-test\") || ($node[\"Webhook\"].json[\"headers\"][\"x-semillero-env\"] || \"\").includes(\"dev\") }}",
"value2": true
}
]
}
},
"id": "If-Node-1",
"name": "Is Test/Dev Mode?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
300,
300
]
},
{
"parameters": {
"values": {
"string": [
{
"name": "appUrl",
"value": "__APP_DEV_INTERNAL_URL__"
},
{
"name": "signature",
"value": "__N8N_WEBHOOK_SECRET_DEV__"
}
]
},
"options": {}
},
"id": "Set-Dev-Env",
"name": "Set Dev Environment",
"type": "n8n-nodes-base.set",
"typeVersion": 1,
"position": [
500,
200
]
},
{
"parameters": {
"values": {
"string": [
{
"name": "appUrl",
"value": "__APP_PROD_INTERNAL_URL__"
},
{
"name": "signature",
"value": "__N8N_WEBHOOK_SECRET__"
}
]
},
"options": {}
},
"id": "Set-Prod-Env",
"name": "Set Prod Environment",
"type": "n8n-nodes-base.set",
"typeVersion": 1,
"position": [
500,
400
]
},
{
"parameters": {
"method": "GET",
"url": "={{ $('Set Dev Environment').isExecuted ? $('Set Dev Environment').item.json.appUrl : $('Set Prod Environment').item.json.appUrl }}/api/n8n/fetch-calculation-data",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "x-n8n-signature",
"value": "={{ $('Set Dev Environment').isExecuted ? $('Set Dev Environment').item.json.signature : $('Set Prod Environment').item.json.signature }}"
}
]
},
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "period",
"value": "={{ $node[\"Webhook\"].json[\"body\"][\"period\"] }}"
}
]
},
"options": {}
},
"id": "Http-Request-Fetch",
"name": "Fetch Calculation Data",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
700,
300
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Set Dev Environment').isExecuted ? $('Set Dev Environment').item.json.appUrl : $('Set Prod Environment').item.json.appUrl }}/api/n8n/process-formula",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "x-n8n-signature",
"value": "={{ $('Set Dev Environment').isExecuted ? $('Set Dev Environment').item.json.signature : $('Set Prod Environment').item.json.signature }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"period\": \"{{ $node[\"Webhook\"].json[\"body\"][\"period\"] }}\",\n \"simulateOnly\": {{ $node[\"Webhook\"].json[\"body\"][\"simulateOnly\"] }},\n \"collaborators\": {{ JSON.stringify($node[\"Fetch Calculation Data\"].json[\"collaborators\"]) }},\n \"activePlans\": {{ JSON.stringify($node[\"Fetch Calculation Data\"].json[\"activePlans\"]) }},\n \"goals\": {{ JSON.stringify($node[\"Fetch Calculation Data\"].json[\"goals\"]) }},\n \"salesResults\": {{ JSON.stringify($node[\"Fetch Calculation Data\"].json[\"salesResults\"]) }},\n \"pastPeriods\": {{ JSON.stringify($node[\"Fetch Calculation Data\"].json[\"pastPeriods\"]) }},\n \"approvedPastSettlements\": {{ JSON.stringify($node[\"Fetch Calculation Data\"].json[\"approvedPastSettlements\"]) }},\n \"pastSalesResults\": {{ JSON.stringify($node[\"Fetch Calculation Data\"].json[\"pastSalesResults\"]) }},\n \"pastGoals\": {{ JSON.stringify($node[\"Fetch Calculation Data\"].json[\"pastGoals\"]) }}\n}",
"options": {}
},
"id": "Http-Request-Process",
"name": "Process Formula",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
900,
300
]
},
{
"parameters": {
"promptType": "define",
"text": "=Review the calculated settlements for compliance. For each item in the results array, evaluate the main settlement totals and adjustments. Return a JSON object with a \"results\" array matching the input structure, but adding the fields \"aiAudited\" (boolean) and \"aiAuditNotes\" (string or null).\nIf a collaborator's total payout is negative, set aiAudited to true and aiAuditNotes to \"Audit warning: Negative net payout detected due to clawback adjustments.\"\nIf a collaborator's total payout exceeds 10,000, set aiAudited to true and aiAuditNotes to \"Audit warning: High commission payout exceeding 10K threshold.\"\nOtherwise, set aiAudited to false and aiAuditNotes to null.\n\nInput calculations data:\n{{ JSON.stringify($node[\"Process Formula\"].json[\"results\"]) }}",
"hasOutputParser": true,
"needsFallback": true,
"options": {}
},
"id": "LLM-Chain-Audit",
"name": "LLM Chain: Compliance Audit",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.9,
"position": [
1100,
300
]
},
{
"parameters": {
"options": {}
},
"id": "DeepSeek-Model-Node-2",
"name": "Primary Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatDeepSeek",
"typeVersion": 1,
"position": [
950,
480
],
"credentials": {
"deepSeekApi": {
"id": "YbGKBhQ9rlUebE4F",
"name": "Semillero2_Primary_deepSeekApi"
}
}
},
{
"parameters": {
"options": {}
},
"id": "Google-Gemini-Model-Node-2",
"name": "Fallback Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
"typeVersion": 1,
"position": [
1100,
480
],
"credentials": {
"googlePalmApi": {
"id": "1Vz05qteUH9kLf7Z",
"name": "Google Gemini(PaLM) Api account"
}
}
},
{
"parameters": {
"jsonSchema": "{\n \"type\": \"object\",\n \"properties\": {\n \"results\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"main\": {\n \"type\": \"object\",\n \"properties\": {\n \"period\": { \"type\": \"string\" },\n \"planId\": { \"type\": \"number\" },\n \"userId\": { \"type\": \"number\" },\n \"salesAmount\": { \"type\": \"number\" },\n \"goalAmount\": { \"type\": \"number\" },\n \"achievementPercentage\": { \"type\": \"number\" },\n \"calculatedCommission\": { \"type\": \"number\" },\n \"calculatedBonus\": { \"type\": \"number\" },\n \"adjustmentAmount\": { \"type\": \"number\" },\n \"totalPayout\": { \"type\": \"number\" },\n \"status\": { \"type\": \"string\" },\n \"adjustmentNotes\": { \"type\": \"string\", \"nullable\": true }\n }\n },\n \"adjustments\": { \"type\": \"array\" },\n \"aiAudited\": { \"type\": \"boolean\" },\n \"aiAuditNotes\": { \"type\": \"string\", \"nullable\": true }\n }\n }\n }\n },\n \"required\": [\"results\"]\n}"
},
"id": "Structured-Output-Parser-Node-2",
"name": "Structured Output Parser",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"typeVersion": 1,
"position": [
1250,
480
]
},
{
"parameters": {
"promptType": "define",
"text": "=Translate the aiAuditNotes for each record in the results array into a localized JSON object containing \"en\" and \"es\" keys. If aiAuditNotes is NOT null and NOT empty, you MUST translate it to Spanish for the \"es\" key, and keep the original English value for the \"en\" key (both must be non-empty strings). Only if aiAuditNotes is null or empty, set both \"en\" and \"es\" to null.\n\nInput calculation results:\n{{ JSON.stringify($node[\"LLM Chain: Compliance Audit\"].json[\"results\"]) }}",
"hasOutputParser": true,
"needsFallback": true,
"options": {}
},
"id": "LLM-Chain-Translation-2",
"name": "LLM Chain: Translation",
"type": "@n8n/n8n-nodes-langchain.chainLlm",
"typeVersion": 1.9,
"position": [
1300,
300
]
},
{
"parameters": {
"jsonSchema": "{\n \"type\": \"object\",\n \"properties\": {\n \"results\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"object\",\n \"properties\": {\n \"main\": {\n \"type\": \"object\",\n \"properties\": {\n \"period\": { \"type\": \"string\" },\n \"planId\": { \"type\": \"number\" },\n \"userId\": { \"type\": \"number\" },\n \"salesAmount\": { \"type\": \"number\" },\n \"goalAmount\": { \"type\": \"number\" },\n \"achievementPercentage\": { \"type\": \"number\" },\n \"calculatedCommission\": { \"type\": \"number\" },\n \"calculatedBonus\": { \"type\": \"number\" },\n \"adjustmentAmount\": { \"type\": \"number\" },\n \"totalPayout\": { \"type\": \"number\" },\n \"status\": { \"type\": \"string\" },\n \"adjustmentNotes\": { \"type\": \"string\", \"nullable\": true }\n }\n },\n \"adjustments\": { \"type\": \"array\" },\n \"aiAudited\": { \"type\": \"boolean\" },\n \"aiAuditNotes\": {\n \"type\": \"object\",\n \"properties\": {\n \"en\": { \"type\": \"string\", \"nullable\": true },\n \"es\": { \"type\": \"string\", \"nullable\": true }\n },\n \"required\": [\"en\", \"es\"]\n }\n }\n }\n }\n },\n \"required\": [\"results\"]\n}"
},
"id": "Structured-Output-Parser-Translation-2",
"name": "Structured Output Parser (Translation)",
"type": "@n8n/n8n-nodes-langchain.outputParserStructured",
"typeVersion": 1,
"position": [
1400,
480
]
},
{
"parameters": {
"conditions": {
"boolean": [
{
"value1": "={{ $node[\"Webhook\"].json[\"body\"][\"simulateOnly\"] }}",
"value2": true
}
]
}
},
"id": "If-Node-Simulation",
"name": "Is Simulation Only?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [
1500,
300
]
},
{
"parameters": {
"method": "POST",
"url": "={{ $('Set Dev Environment').isExecuted ? $('Set Dev Environment').item.json.appUrl : $('Set Prod Environment').item.json.appUrl }}/api/n8n/save-settlements",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "x-n8n-signature",
"value": "={{ $('Set Dev Environment').isExecuted ? $('Set Dev Environment').item.json.signature : $('Set Prod Environment').item.json.signature }}"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"period\": \"{{ $node[\"Webhook\"].json[\"body\"][\"period\"] }}\",\n \"simulateOnly\": false,\n \"results\": {{ JSON.stringify($node[\"LLM Chain: Translation\"].json[\"results\"]) }},\n \"uploaderId\": {{ $node[\"Webhook\"].json[\"body\"][\"uploaderId\"] || 1 }}\n}",
"options": {}
},
"id": "Http-Request-Save",
"name": "Save Settlements",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.1,
"position": [
1700,
400
]
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={\n \"success\": true,\n \"code\": \"SETTLEMENTS_CALCULATED\",\n \"metadata\": {\n \"count\": {{ $node[\"Process Formula\"].json[\"metadata\"][\"count\"] }},\n \"totalCommission\": {{ $node[\"Process Formula\"].json[\"metadata\"][\"totalCommission\"] }},\n \"totalAdjustment\": {{ $node[\"Process Formula\"].json[\"metadata\"][\"totalAdjustment\"] }}\n },\n \"simulated\": {{ JSON.stringify($node[\"LLM Chain: Translation\"].json[\"results\"]) }}\n}"
},
"id": "Respond-To-Webhook-Calculated",
"name": "Respond to Webhook (Calculated)",
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1,
"position": [
1900,
300
]
}
],
"connections": {
"Webhook": {
"main": [
[
{
"node": "Is Test/Dev Mode?",
"type": "main",
"index": 0
}
]
]
},
"Is Test/Dev Mode?": {
"main": [
[
{
"node": "Set Dev Environment",
"type": "main",
"index": 0
}
],
[
{
"node": "Set Prod Environment",
"type": "main",
"index": 0
}
]
]
},
"Set Dev Environment": {
"main": [
[
{
"node": "Fetch Calculation Data",
"type": "main",
"index": 0
}
]
]
},
"Set Prod Environment": {
"main": [
[
{
"node": "Fetch Calculation Data",
"type": "main",
"index": 0
}
]
]
},
"Fetch Calculation Data": {
"main": [
[
{
"node": "Process Formula",
"type": "main",
"index": 0
}
]
]
},
"Process Formula": {
"main": [
[
{
"node": "LLM Chain: Compliance Audit",
"type": "main",
"index": 0
}
]
]
},
"Primary Chat Model": {
"ai_languageModel": [
[
{
"node": "LLM Chain: Compliance Audit",
"type": "ai_languageModel",
"index": 0
},
{
"node": "LLM Chain: Translation",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Fallback Chat Model": {
"ai_languageModel": [
[
{
"node": "LLM Chain: Compliance Audit",
"type": "ai_languageModel",
"index": 1
},
{
"node": "LLM Chain: Translation",
"type": "ai_languageModel",
"index": 1
}
]
]
},
"Structured Output Parser": {
"outputParser": [
[
{
"node": "LLM Chain: Compliance Audit",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"Structured Output Parser (Translation)": {
"outputParser": [
[
{
"node": "LLM Chain: Translation",
"type": "ai_outputParser",
"index": 0
}
]
]
},
"LLM Chain: Compliance Audit": {
"main": [
[
{
"node": "LLM Chain: Translation",
"type": "main",
"index": 0
}
]
]
},
"LLM Chain: Translation": {
"main": [
[
{
"node": "Is Simulation Only?",
"type": "main",
"index": 0
}
]
]
},
"Is Simulation Only?": {
"main": [
[
{
"node": "Respond to Webhook (Calculated)",
"type": "main",
"index": 0
}
],
[
{
"node": "Save Settlements",
"type": "main",
"index": 0
}
]
]
},
"Save Settlements": {
"main": [
[
{
"node": "Respond to Webhook (Calculated)",
"type": "main",
"index": 0
}
]
]
}
},
"active": true,
"settings": {},
"id": "settlement-calculation-workflow"
}