Workflow automatisé d'approbation et de remboursement des dépenses multi-niveaux

Avancé

Ceci est uncontenant 21 nœuds.Utilise principalement des nœuds comme If, Set, Code, Gmail, Slack. Traitement automatisé des approubations et remboursements de frais multi-niveaux avec JotForm, Slack et Google Sheets

Prérequis
  • Compte Google et informations d'identification Gmail API
  • Token Bot Slack ou URL Webhook
  • Informations d'identification Google Sheets API

Catégorie

-
Aperçu du workflow
Visualisation des connexions entre les nœuds, avec support du zoom et du déplacement
Exporter le workflow
Copiez la configuration JSON suivante dans n8n pour importer et utiliser ce workflow
{
  "meta": {
    "instanceId": "277842713620d9f5554de3b1518b865a152c8c4db680008bd8aec536fc18b4a8",
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "2eb6d9f2-7f9d-453f-a548-cf2660f7248c",
      "name": "Déclencheur JotForm",
      "type": "n8n-nodes-base.jotFormTrigger",
      "position": [
        -1120,
        -16
      ],
      "webhookId": "expense-submission",
      "parameters": {
        "form": "252860582136459"
      },
      "credentials": {
        "jotFormApi": {
          "id": "W7O1b225FpOwkwDT",
          "name": "JotForm account-Deepanshi"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "0798c2b1-7ed5-45ce-a26c-2e8f7ada6a43",
      "name": "Analyser les données du formulaire",
      "type": "n8n-nodes-base.code",
      "position": [
        -864,
        -16
      ],
      "parameters": {
        "jsCode": "// Parse form data and prepare for processing\nconst formData = $input.first().json;\n\nreturn {\n  json: {\n    submissionId: formData.submissionID || Date.now().toString(),\n    employeeName: formData.employeeName || formData.q3_employeeName,\n    employeeEmail: formData.employeeEmail || formData.q4_employeeEmail,\n    employeeId: formData.employeeId || formData.q5_employeeId,\n    amount: parseFloat(formData.amount || formData.q6_amount),\n    category: formData.category || formData.q7_category,\n    merchant: formData.merchant || formData.q8_merchant,\n    date: formData.date || formData.q9_date,\n    description: formData.description || formData.q10_description,\n    receiptUrl: formData.receiptUrl || formData.q11_receipt,\n    submittedAt: new Date().toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "df2085e9-dc08-4f25-a99e-009e2340b47c",
      "name": "Valider la politique",
      "type": "n8n-nodes-base.code",
      "position": [
        -672,
        -16
      ],
      "parameters": {
        "jsCode": "// Company policy rules and validation\nconst data = $input.first().json;\n\nconst policy = {\n  maxAmounts: {\n    meals: 75,\n    travel: 500,\n    office_supplies: 200,\n    software: 1000,\n    entertainment: 150,\n    other: 100\n  },\n  approvedCategories: ['meals', 'travel', 'office_supplies', 'software', 'entertainment'],\n  autoApproveThreshold: 100,\n  managerApprovalThreshold: 500\n};\n\nconst amount = data.amount;\nconst category = data.category;\n\nlet policyViolations = [];\nlet requiresApproval = 'auto';\n\nif (!policy.approvedCategories.includes(category)) {\n  policyViolations.push('Category not approved');\n}\n\nif (policy.maxAmounts[category] && amount > policy.maxAmounts[category]) {\n  policyViolations.push('Amount exceeds category limit');\n}\n\nif (amount < policy.autoApproveThreshold && policyViolations.length === 0) {\n  requiresApproval = 'auto';\n} else if (amount >= policy.autoApproveThreshold && amount < policy.managerApprovalThreshold) {\n  requiresApproval = 'manager';\n} else if (amount >= policy.managerApprovalThreshold) {\n  requiresApproval = 'director';\n}\n\nreturn {\n  json: {\n    ...data,\n    policyViolations: policyViolations,\n    isCompliant: policyViolations.length === 0,\n    requiresApproval: requiresApproval,\n    status: 'pending'\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "4ac52b34-7a64-49f5-b368-43d8b99bcab3",
      "name": "Vérifier les violations",
      "type": "n8n-nodes-base.if",
      "position": [
        -464,
        -16
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition1",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ $json.policyViolations.length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "9d132c2f-7f99-4b36-b543-27131702460c",
      "name": "Définir le rejet",
      "type": "n8n-nodes-base.set",
      "position": [
        -272,
        144
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "status",
              "name": "status",
              "type": "string",
              "value": "rejected"
            },
            {
              "id": "rejectionReason",
              "name": "rejectionReason",
              "type": "string",
              "value": "=Policy violations: {{ $json.policyViolations.join(', ') }}"
            }
          ]
        }
      },
      "typeVersion": 3.3
    },
    {
      "id": "47566677-5342-4b26-9974-793526a59bd9",
      "name": "Router automatiquement",
      "type": "n8n-nodes-base.if",
      "position": [
        -272,
        -176
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.requiresApproval }}",
              "rightValue": "auto"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "c0b971bc-a5ce-48b6-978c-54ae02112505",
      "name": "Approuver automatiquement",
      "type": "n8n-nodes-base.set",
      "position": [
        -64,
        -272
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "status",
              "name": "status",
              "type": "string",
              "value": "approved"
            },
            {
              "id": "approvedBy",
              "name": "approvedBy",
              "type": "string",
              "value": "System (Auto-Approved)"
            },
            {
              "id": "approvedAt",
              "name": "approvedAt",
              "type": "string",
              "value": "={{ new Date().toISOString() }}"
            }
          ]
        }
      },
      "typeVersion": 3.3
    },
    {
      "id": "eef387ab-bee8-4570-8cca-26ccbd30abeb",
      "name": "Router vers le manager",
      "type": "n8n-nodes-base.if",
      "position": [
        -64,
        -80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.requiresApproval }}",
              "rightValue": "manager"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "74152681-2cf6-4e76-aabb-87ae00a86048",
      "name": "Manager Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        144,
        -224
      ],
      "webhookId": "61c90b37-cd59-4332-b0c6-0f8f15004d43",
      "parameters": {
        "text": "=New Expense Approval Required\nEmployee: {{ $json.employeeName }}\nAmount: ${{ $json.amount }}\nCategory: {{ $json.category }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C01234567"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "piPcLxWbLrndcGhp",
          "name": "Slack account - Deepanshi"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e05fba8b-60e5-4438-9f7a-cd828bace8b8",
      "name": "Directeur Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        144,
        -16
      ],
      "webhookId": "eba016eb-5ad8-4d29-822e-9038e73a0733",
      "parameters": {
        "text": "=High-Value Expense - Director Approval\nEmployee: {{ $json.employeeName }}\nAmount: ${{ $json.amount }}\nCategory: {{ $json.category }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C98765432"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "id": "piPcLxWbLrndcGhp",
          "name": "Slack account - Deepanshi"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "b7a58104-fc21-485a-8c93-edb1dc253b2b",
      "name": "Enregistrer dans Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        336,
        -64
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [
            "submissionId"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "id": "Kz2DdSp11rxqwlFt",
          "name": "Google Sheets account - Deepanshi"
        }
      },
      "typeVersion": 4.4
    },
    {
      "id": "1af29bbe-b3ee-42ee-91a9-388b70659c48",
      "name": "Est approuvé",
      "type": "n8n-nodes-base.if",
      "position": [
        544,
        -64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "approved"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "0e8c5d12-fee3-4c7d-bc16-77a79e39befe",
      "name": "E-mail de rejet",
      "type": "n8n-nodes-base.gmail",
      "position": [
        752,
        0
      ],
      "webhookId": "fe2cb3ee-3c0f-4429-ac5c-9482a923f808",
      "parameters": {
        "sendTo": "={{ $json.employeeEmail }}",
        "message": "=Hi, Your expense for {{ $json.amount}} has been rejected as it did not matches with the company's validation policy.",
        "options": {},
        "subject": "=Expense Rejected - ${{ $json.amount }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "PIMDNhXNj8Zyiz3G",
          "name": "Gmail account - Deepanshi"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "1b5d88c6-fe8f-4984-9e9e-19789ba76c60",
      "name": "Approuvé",
      "type": "n8n-nodes-base.gmail",
      "position": [
        752,
        -192
      ],
      "webhookId": "fe2cb3ee-3c0f-4429-ac5c-9482a923f808",
      "parameters": {
        "sendTo": "={{ $json.employeeEmail }}",
        "message": "Hi, Your expense for {{ $json.Amount }} has been approved",
        "options": {},
        "subject": "=Expense Approved - ${{ $json.amount }}"
      },
      "credentials": {
        "gmailOAuth2": {
          "id": "PIMDNhXNj8Zyiz3G",
          "name": "Gmail account - Deepanshi"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "6382a19b-08de-4466-9013-696d5ffac4db",
      "name": "Note adhésive",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        -208
      ],
      "parameters": {
        "height": 432,
        "content": "📩 Trigger: New Expense Submission\nCaptures employee expense details \nand receipt upload from JotForm.\nCreate your form for free on [JotForm using this link](https://www.jotform.com/?partner=mediajade) \n"
      },
      "typeVersion": 1
    },
    {
      "id": "5b890f09-277e-41e6-9628-dd6907b14e5f",
      "name": "Note adhésive1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -912,
        -160
      ],
      "parameters": {
        "width": 192,
        "content": "🧾 Parse & Normalize Data\nExtracts key fields (name, email, amount, \ncategory, merchant, receipt URL) \nfor further processing.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "fe3ea799-b6f3-48f4-bbc4-96623e1e8256",
      "name": "Note adhésive2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        112
      ],
      "parameters": {
        "width": 208,
        "height": 192,
        "content": "⚙️ Policy Validation\nChecks compliance against company rules:\n- Allowed categories\n- Max amount limits\n- Auto/Manager/Director approval routing\n"
      },
      "typeVersion": 1
    },
    {
      "id": "11112b1f-af67-4c7c-86cc-b4ccfe83a249",
      "name": "Note adhésive3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -512,
        -160
      ],
      "parameters": {
        "width": 176,
        "content": "🚫 Compliance Check\nIf violations exist → reject\nElse → continue for approval routing\n"
      },
      "typeVersion": 1
    },
    {
      "id": "054e826f-590f-4de0-8ccd-d299d2f6e044",
      "name": "Note adhésive4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -288,
        -368
      ],
      "parameters": {
        "width": 576,
        "height": 496,
        "content": "⚡ Routing Decision\nDetermines if expense should be:\n- Auto-approved\n- Sent for manager approval\n- Sent for director approval\n"
      },
      "typeVersion": 1
    },
    {
      "id": "6ebce30b-f8d7-4bf2-bdf3-6f33b8363a55",
      "name": "Note adhésive5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        320,
        -224
      ],
      "parameters": {
        "width": 208,
        "height": 384,
        "content": "📊 Audit Logging\nAppends expense status, \napprover details, and decision \nto Google Sheets for tracking.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f5e44753-7705-41e1-bdac-0158deea26ab",
      "name": "Note adhésive6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        544,
        -384
      ],
      "parameters": {
        "width": 384,
        "height": 576,
        "content": "🔍 Approval Check\nBranches workflow to send \napproval or rejection emails \nbased on final status.\n"
      },
      "typeVersion": 1
    }
  ],
  "pinData": {},
  "connections": {
    "47566677-5342-4b26-9974-793526a59bd9": {
      "main": [
        [
          {
            "node": "c0b971bc-a5ce-48b6-978c-54ae02112505",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "eef387ab-bee8-4570-8cca-26ccbd30abeb",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "1af29bbe-b3ee-42ee-91a9-388b70659c48": {
      "main": [
        [
          {
            "node": "1b5d88c6-fe8f-4984-9e9e-19789ba76c60",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "0e8c5d12-fee3-4c7d-bc16-77a79e39befe",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "c0b971bc-a5ce-48b6-978c-54ae02112505": {
      "main": [
        [
          {
            "node": "b7a58104-fc21-485a-8c93-edb1dc253b2b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "b7a58104-fc21-485a-8c93-edb1dc253b2b": {
      "main": [
        [
          {
            "node": "1af29bbe-b3ee-42ee-91a9-388b70659c48",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "eef387ab-bee8-4570-8cca-26ccbd30abeb": {
      "main": [
        [
          {
            "node": "74152681-2cf6-4e76-aabb-87ae00a86048",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "e05fba8b-60e5-4438-9f7a-cd828bace8b8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9d132c2f-7f99-4b36-b543-27131702460c": {
      "main": [
        [
          {
            "node": "b7a58104-fc21-485a-8c93-edb1dc253b2b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "74152681-2cf6-4e76-aabb-87ae00a86048": {
      "main": [
        [
          {
            "node": "b7a58104-fc21-485a-8c93-edb1dc253b2b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e05fba8b-60e5-4438-9f7a-cd828bace8b8": {
      "main": [
        [
          {
            "node": "b7a58104-fc21-485a-8c93-edb1dc253b2b",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2eb6d9f2-7f9d-453f-a548-cf2660f7248c": {
      "main": [
        [
          {
            "node": "0798c2b1-7ed5-45ce-a26c-2e8f7ada6a43",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "0798c2b1-7ed5-45ce-a26c-2e8f7ada6a43": {
      "main": [
        [
          {
            "node": "df2085e9-dc08-4f25-a99e-009e2340b47c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "df2085e9-dc08-4f25-a99e-009e2340b47c": {
      "main": [
        [
          {
            "node": "4ac52b34-7a64-49f5-b368-43d8b99bcab3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "4ac52b34-7a64-49f5-b368-43d8b99bcab3": {
      "main": [
        [
          {
            "node": "47566677-5342-4b26-9974-793526a59bd9",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "9d132c2f-7f99-4b36-b543-27131702460c",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}
Foire aux questions

Comment utiliser ce workflow ?

Copiez le code de configuration JSON ci-dessus, créez un nouveau workflow dans votre instance n8n et sélectionnez "Importer depuis le JSON", collez la configuration et modifiez les paramètres d'authentification selon vos besoins.

Dans quelles scénarios ce workflow est-il adapté ?

Avancé

Est-ce payant ?

Ce workflow est entièrement gratuit et peut être utilisé directement. Veuillez noter que les services tiers utilisés dans le workflow (comme l'API OpenAI) peuvent nécessiter un paiement de votre part.

Informations sur le workflow
Niveau de difficulté
Avancé
Nombre de nœuds21
Catégorie-
Types de nœuds8
Description de la difficulté

Adapté aux utilisateurs avancés, avec des workflows complexes contenant 16+ nœuds

Auteur
Jitesh Dugar

Jitesh Dugar

@jiteshdugar

AI Automation Specialist - OpenAI, CRM & Automation Expert with a solid understanding of various tools that include Zapier, Make, Zoho CRM, Hubspot, Google Sheets, Airtable, Pipedrive, Google Analytics, and more.

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34