Générer et envoyer des rappels pour des factures clients avec Jotform et Xero

Avancé

Ceci est uncontenant 39 nœuds.Utilise principalement des nœuds comme If, Set, Code, Xero, Switch. Générer des factures et envoyer des rappels pilotés par l'IA avec Jotform et Xero

Prérequis
  • Point de terminaison HTTP Webhook (généré automatiquement par n8n)
  • Clé API OpenAI

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
{
  "id": "Bk4bt3p0zi7Z9ETX",
  "meta": {
    "instanceId": "3549451ca835035557d5dc1c3d9e6ba924e7314534a74c901f66b91f9ef6023e",
    "templateCredsSetupCompleted": true
  },
  "name": "Generate Invoices and Send Reminders for Customers with Jotform and Xero",
  "tags": [],
  "nodes": [
    {
      "id": "d7858d88-bccd-4bbb-8de0-c7ba96d74263",
      "name": "Recevoir la soumission du formulaire",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -464,
        0
      ],
      "webhookId": "148f97af-2d29-4836-a910-2c77b7c33b26",
      "parameters": {
        "path": "148f97af-2d29-4836-a910-2c77b7c33b26",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 2.1
    },
    {
      "id": "267003ec-6e40-4a33-bacc-2244c8e43b64",
      "name": "Note adhésive",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 320,
        "content": "## Receive Submission\nReceives the product/service form submission from Jotform"
      },
      "typeVersion": 1
    },
    {
      "id": "8ee7dc1e-86bf-4bec-b8b6-7b97889eab6b",
      "name": "Note adhésive3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 288,
        "height": 320,
        "content": "## Create/Update Contact\nCreates or updates the contact"
      },
      "typeVersion": 1
    },
    {
      "id": "a14a8305-8c22-4213-9414-861019d3ae69",
      "name": "Note adhésive5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        400,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 320,
        "content": "## Create The Invoice\nCreates a new invoice for that contact"
      },
      "typeVersion": 1
    },
    {
      "id": "77f6b18b-004e-4e00-8de2-54194fdd9a47",
      "name": "Note adhésive7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1488,
        -400
      ],
      "parameters": {
        "width": 896,
        "height": 1200,
        "content": "## Generate Invoices and Send Reminders for Customers with Jotform and Xero\nThis workflow automates the entire process of receiving a product/service order, checking or creating a customer in **Xero**, generating an invoice, emailing it — all triggered by a form submission (via **Jotform**), and sending invoice reminders.\n\n## How It Works\n### 1- Receive Submission\n* Triggered when a user submits a form.\n* Collects data like customer details, selected product/service, etc.\n\n### 2- Create/Update The Customer\n* Creates/Updates the customer.\n\n### 3- Create The Invoice\n* Generates a new invoice for the customer using the item selected.\n\n### 4- Send The Invoice\n* Automatically sends the invoice via email to the customer.\n\n### 5- Store The Invoice In DB\n* Stores the needed invoice details in the DB.\n\n### 6- Send Reminders\n* Every day at 8 AM, the automation checks each invoice to decide whether to:\n    * send a reminder email,\n    * skip and send it later, or\n    * delete the invoice from the DB (if it's paid or all reminders have been sent).\n\n## Who Can Benefit from This Workflow?\n* **Freelancers**\n* **Service Providers**\n* **Consultants & Coaches**\n* **Small Businesses**\n* **E-commerce or Custom Product Sellers**\n\n## Requirements\n- Jotform webhook setup, more info [here](https://www.jotform.com/help/245-how-to-setup-a-webhook-with-jotform/)\n- Xero credentials, more info [here](https://docs.n8n.io/integrations/builtin/credentials/xero)\n- Make sure that products/services values in Jotform are exactly the same as your item `Code` in your Xero account\n- Email setup, update email nodes (`Send email` & `Send reminder email` & `Send reminders sent summary`)\n- Create data table with the following columns:\n    * invoiceId (string)\n    * remainingAmount (number)\n    * currency (string)\n    * remindersSent (number)\n    * lastSentAt (date time)\n- Update `Add reminders config` node so update the data table id and intervals in days (default is after 2 days, then after 3 days and finally after 5 days )\n- LLM model credentials"
      },
      "typeVersion": 1
    },
    {
      "id": "79c58923-f8c3-4054-93ca-c2de89ff7306",
      "name": "Note adhésive8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -240,
        -112
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 320,
        "content": "## Format Data\nFormats the data thus making it easier to be used in other nodes"
      },
      "typeVersion": 1
    },
    {
      "id": "e495d2d4-3f6d-482a-bb95-7a4dfdbd5dba",
      "name": "Formater les données",
      "type": "n8n-nodes-base.code",
      "position": [
        -160,
        0
      ],
      "parameters": {
        "jsCode": "function extractAddressData(text) {\n  const regex = /Street Address:\\s*([^<]+)<br>Street Address Line 2:\\s*([^<]+)<br>City:\\s*([^<]+)<br>State \\/ Province:\\s*([^<]+)<br>Postal \\/ Zip Code:\\s*([^<]+)<br>Country:\\s*([^<]+)<br>/;\n  const matches = text.match(regex);\n  \n  if (matches) {\n    return {\n      line1: matches[1].trim(),\n      line2: matches[2].trim(),\n      city: matches[3].trim(),\n      stateProvince: matches[4].trim(),\n      postalZipCode: matches[5].trim(),\n      country: matches[6].trim()\n    };\n  }\n  \n  return {\n    line1: null,\n    line2: null,\n    city: null,\n    stateProvince: null,\n    postalZipCode: null,\n    country: null\n  }\n}\n\nreturn {\n  address: extractAddressData($input.first().json.body.billingAddress),\n  customer: {\n    name: $input.first().json.body.name,\n    email: $input.first().json.body.email,\n    phone: $input.first().json.body.phone\n  },\n  item: {\n    name: $input.first().json.body.itemName\n  }\n}"
      },
      "typeVersion": 2
    },
    {
      "id": "9153a6f7-10d8-44f6-976b-b0abdaf5fd20",
      "name": "Créer/Mettre à jour le contact",
      "type": "n8n-nodes-base.xero",
      "position": [
        160,
        0
      ],
      "parameters": {
        "name": "={{ $json.customer.name }}",
        "resource": "contact",
        "organizationId": "bc9a44a6-eb14-4f81-b24c-ca676c506446",
        "additionalFields": {
          "phonesUi": {
            "phonesValues": [
              {
                "phoneType": "MOBILE",
                "phoneNumber": "={{ $json.customer.phone }}"
              }
            ]
          },
          "addressesUi": {
            "addressesValues": [
              {
                "city": "={{ $json.address.city }}",
                "type": "STREET",
                "line1": "={{ $json.address.line1 }}",
                "line2": "={{ $json.address.line2 }}",
                "region": "={{ $json.address.stateProvince }}",
                "country": "={{ $json.address.country }}",
                "postalCode": "={{ $json.address.postalZipCode }}"
              }
            ]
          },
          "emailAddress": "={{ $json.customer.email }}"
        }
      },
      "credentials": {
        "xeroOAuth2Api": {
          "id": "HZnbTfrr5leqrLUQ",
          "name": "Xero account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "15e1d23a-3c96-4037-83cd-97004e6aebe8",
      "name": "Créer la facture",
      "type": "n8n-nodes-base.xero",
      "position": [
        480,
        0
      ],
      "parameters": {
        "type": "ACCREC",
        "contactId": "={{ $json.ContactID }}",
        "lineItemsUi": {
          "lineItemsValues": [
            {
              "taxType": "INPUT",
              "itemCode": "={{ $('Format data').item.json.item.name }}",
              "unitAmount": "10",
              "accountCode": "200"
            }
          ]
        },
        "organizationId": "bc9a44a6-eb14-4f81-b24c-ca676c506446",
        "additionalFields": {}
      },
      "credentials": {
        "xeroOAuth2Api": {
          "id": "HZnbTfrr5leqrLUQ",
          "name": "Xero account"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2831fd4c-313c-4b63-b6d0-6b36428ae778",
      "name": "Agent IA",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        816,
        -432
      ],
      "parameters": {
        "text": "={{ $json }}",
        "options": {
          "systemMessage": "=You are an AI assistant that generates a professional invoice email that you get from an Xero response (newly created invoice), so you will recive an Xero invoice response and thus your job is to create a professional html email content because this html email content will be sent to the customer."
        },
        "promptType": "define"
      },
      "executeOnce": false,
      "typeVersion": 2.2
    },
    {
      "id": "3436d1ca-18bf-4929-982a-89fa802ff015",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        816,
        -224
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "ns8LVe1zpSS3Kw9p",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "5dbc3862-69b4-4174-8952-635f386cb81c",
      "name": "Note adhésive19",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        704,
        -560
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 480,
        "content": "## Send The Invoice\nSends the newly created invoice for that customer(via email)"
      },
      "typeVersion": 1
    },
    {
      "id": "8add409c-adb4-4d9b-9e6a-0db66e17093e",
      "name": "Envoyer l'email",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        1088,
        -432
      ],
      "webhookId": "e6595484-bef2-43b0-894f-23f53746c0af",
      "parameters": {
        "html": "={{ $json.output }}",
        "options": {},
        "subject": "=New Invoice",
        "toEmail": "={{ $('Create the invoice').item.json.Contact.EmailAddress }}",
        "fromEmail": "system@example.com"
      },
      "credentials": {
        "smtp": {
          "id": "awV8UBK3MYzosMxe",
          "name": "Mailtrap SMTP account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "d5ebc764-96f4-41e5-a5dd-ecc8b69470c5",
      "name": "Ajouter la configuration des rappels",
      "type": "n8n-nodes-base.set",
      "position": [
        800,
        320
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "={\n  \"dataTableId\": \"\",\n  \"reminderIntervalsInDays\": [2, 3, 5],\n  isInvoiceTrigger: {{ $json[\"Day of week\"] ? false : true }}\n}\n "
      },
      "typeVersion": 3.4
    },
    {
      "id": "f40da212-3f17-426d-bc58-5348b4488d9d",
      "name": "Envoyer l'email de rappel",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        2768,
        688
      ],
      "webhookId": "8f9ba8d7-7a97-4926-b640-8dc93c30eed8",
      "parameters": {
        "html": "=<!DOCTYPE html>\n<html>\n<head>\n  <style>\n    body {\n      font-family: Arial, sans-serif;\n      color: #333;\n      line-height: 1.6;\n    }\n    .container {\n      width: 100%;\n      max-width: 600px;\n      margin: 0 auto;\n      padding: 20px;\n      border: 1px solid #f1f1f1;\n      border-radius: 5px;\n      background-color: #f9f9f9;\n    }\n    .header {\n      text-align: center;\n      background-color: #007bff;\n      color: white;\n      padding: 10px;\n      border-radius: 5px;\n    }\n    .footer {\n      text-align: center;\n      color: #777;\n      font-size: 0.8em;\n      margin-top: 20px;\n    }\n    .button {\n      background-color: #28a745;\n      color: white;\n      text-decoration: none;\n      padding: 10px 20px;\n      border-radius: 5px;\n      display: inline-block;\n      margin-top: 20px;\n    }\n  </style>\n</head>\n<body>\n  <div class=\"container\">\n    <div class=\"header\">\n      <h2>Invoice Reminder: {{ $json.InvoiceNumber }}</h2>\n    </div>\n    \n    <p>Dear,</p>\n    \n    <p>This is a friendly reminder that your invoice with us is due soon. We kindly ask you to review and complete the payment as soon as possible to avoid any delays.</p>\n    \n    <p><strong>Invoice Number:</strong> {{ $json.InvoiceNumber }}</p>\n    \n    <p>Thank you for your prompt attention to this matter. If you have any questions or need assistance, feel free to contact us.</p>\n    \n    <p>Best regards, <br>\n    [Your Company Name] <br>\n    [Your Contact Information]</p>\n    \n    <div class=\"footer\">\n      <p>&copy; {{ $now.year }} [Your Company Name]. All rights reserved.</p>\n    </div>\n  </div>\n</body>\n</html>\n",
        "options": {},
        "subject": "=Friendly Reminder: Your Invoice is Due Soon – {{ $json.InvoiceNumber }}",
        "toEmail": "={{ $json.Contact.EmailAddress }}",
        "fromEmail": "reminders@example.com"
      },
      "credentials": {
        "smtp": {
          "id": "awV8UBK3MYzosMxe",
          "name": "Mailtrap SMTP account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "e220b58d-04f9-483a-90b0-e196b8088bd1",
      "name": "Insérer l'ID de facture dans la base de données",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1504,
        128
      ],
      "parameters": {
        "columns": {
          "value": {
            "currency": "={{ $('Create the invoice').item.json.CurrencyCode }}",
            "invoiceId": "={{ $('Create the invoice').item.json.InvoiceID }}",
            "remindersSent": "=0",
            "remainingAmount": "={{ $('Create the invoice').item.json.AmountDue }}"
          },
          "schema": [
            {
              "id": "invoiceId",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "invoiceId",
              "defaultMatch": false
            },
            {
              "id": "remainingAmount",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "remainingAmount",
              "defaultMatch": false
            },
            {
              "id": "currency",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "currency",
              "defaultMatch": false
            },
            {
              "id": "remindersSent",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "remindersSent",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "optimizeBulk": false
        },
        "dataTableId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Add reminders config').item.json.dataTableId }}"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ae2c88cb-764a-48be-bec0-c172dcf1732e",
      "name": "Obtenir les factures",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        1504,
        496
      ],
      "parameters": {
        "operation": "get",
        "returnAll": true,
        "dataTableId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Add reminders config').item.json.dataTableId }}"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "56a479b9-6fc2-4ad8-8a09-7bfd76c5da81",
      "name": "If2",
      "type": "n8n-nodes-base.if",
      "position": [
        1152,
        320
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "82853a4e-d488-49cd-8e36-ba1a737c519b",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.isInvoiceTrigger }}",
              "rightValue": "0"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "fc86c9e1-0f12-47a8-893c-4a2479207702",
      "name": "Envoyer le récapitulatif des rappels envoyés",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        2848,
        160
      ],
      "webhookId": "8f9ba8d7-7a97-4926-b640-8dc93c30eed8",
      "parameters": {
        "html": "={{ $json.output }}",
        "options": {},
        "subject": "=Summary of today's reminders sent",
        "toEmail": "=sales@example.com",
        "fromEmail": "reminders@example.com"
      },
      "credentials": {
        "smtp": {
          "id": "awV8UBK3MYzosMxe",
          "name": "Mailtrap SMTP account"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "a1b465b8-6884-4878-ab45-81731cc11306",
      "name": "Switch",
      "type": "n8n-nodes-base.switch",
      "position": [
        2512,
        736
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "outputKey": "send now",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "df179cc3-60b8-4b49-9fb7-0adabcc3e394",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.AmountDue > 0 && DateTime.fromISO($('Loop over invoices').item.json.updatedAt).plus($('Add reminders config').item.json.reminderIntervalsInDays[$('Loop over invoices').item.json.remindersSent], 'days').format('yyyy-MM-dd') == $now.format('yyyy-MM-dd') }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "already paid ",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "cf03d75d-6560-42ed-8293-3d5e9399b9e3",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": "={{ $json.AmountDue == 0 }}",
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            },
            {
              "outputKey": "send later",
              "conditions": {
                "options": {
                  "version": 2,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "81cb838e-79c8-4c92-964f-f7f5cd44a498",
                    "operator": {
                      "type": "boolean",
                      "operation": "true",
                      "singleValue": true
                    },
                    "leftValue": true,
                    "rightValue": ""
                  }
                ]
              },
              "renameOutput": true
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.3
    },
    {
      "id": "90f88e6b-c967-4ac7-b11a-4e86be5b9e40",
      "name": "Déclencheur de rappels programmés",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        384,
        544
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "5a708503-da01-49d5-af64-5b190f61bcb3",
      "name": "Note adhésive11",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        288,
        416
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 320,
        "content": "## Schedule Trigger\nSchedules reminders trigger daily at 8 AM"
      },
      "typeVersion": 1
    },
    {
      "id": "8f75c160-2d8e-4391-8d73-166a96fc7566",
      "name": "Note adhésive12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        704,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 368,
        "content": "## Add Reminders Config\nAdds reminders config details like `intervals in days` so first reminder will be sent after 2 days, second one after 3 days and final one after 5 days"
      },
      "typeVersion": 1
    },
    {
      "id": "9fbe84fe-3ed0-479c-ab9d-fc7d2a7bfff0",
      "name": "Note adhésive13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1056,
        144
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 368,
        "content": "## Check Trigger\nChecks if the previous node has been executed by the above workflow or by the schedule trigger"
      },
      "typeVersion": 1
    },
    {
      "id": "362c4c03-bd7f-4130-8e0c-060ad5e6957e",
      "name": "Note adhésive14",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1408,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 336,
        "content": "## Insert Invoice To DB\nInserts newly created invoice needed details to DB so customer will be notified later on about the invoice"
      },
      "typeVersion": 1
    },
    {
      "id": "6703f7ec-7901-4d28-9330-ef2ec277df60",
      "name": "Note adhésive15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1408,
        352
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 336,
        "content": "## Get All Invoices\nGets all the invoices from DB"
      },
      "typeVersion": 1
    },
    {
      "id": "aa2278cb-85aa-4038-b837-bbf085b9b245",
      "name": "Note adhésive16",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1760,
        368
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 320,
        "content": "## Loop Over Invoices\nLoops over invoices one by one"
      },
      "typeVersion": 1
    },
    {
      "id": "2620e88d-9c4a-418a-b378-f81aad2f991f",
      "name": "Boucle sur les factures",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1856,
        496
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "67f18351-969d-4489-89c7-b77a2d4ff283",
      "name": "Note adhésive17",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2112,
        160
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 352,
        "content": "## Get Sent Reminders\nGets today's sent reminders from DB"
      },
      "typeVersion": 1
    },
    {
      "id": "1c001fdd-4d76-4243-94f0-a93ed84b2cfa",
      "name": "Note adhésive18",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2112,
        560
      ],
      "parameters": {
        "color": 7,
        "width": 304,
        "height": 368,
        "content": "## Get Invoice Details\nGets the invoice details from Xero so we know whether or not any changes have been made or not"
      },
      "typeVersion": 1
    },
    {
      "id": "5949d37a-037b-4292-bbd4-722efc81d0a6",
      "name": "Obtenir les rappels envoyés aujourd'hui",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        2208,
        304
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "lastSentAt",
              "keyValue": "={{ $now.startOf('day').toUTC().toString() }}",
              "condition": "gte"
            }
          ]
        },
        "matchType": "allConditions",
        "operation": "get",
        "returnAll": true,
        "dataTableId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Add reminders config').item.json.dataTableId }}"
        }
      },
      "executeOnce": true,
      "typeVersion": 1
    },
    {
      "id": "f55fd793-3299-4ca7-ab12-6b73a2df3706",
      "name": "Incrémenter les rappels envoyés",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        2976,
        688
      ],
      "parameters": {
        "columns": {
          "value": {
            "lastSentAt": "={{ $now.toISO() }}",
            "remindersSent": "={{ $('Loop over invoices').item.json.remindersSent + 1 }} "
          },
          "schema": [
            {
              "id": "invoiceId",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "invoiceId",
              "defaultMatch": false
            },
            {
              "id": "remainingAmount",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "remainingAmount",
              "defaultMatch": false
            },
            {
              "id": "currency",
              "type": "string",
              "display": true,
              "removed": true,
              "readOnly": false,
              "required": false,
              "displayName": "currency",
              "defaultMatch": false
            },
            {
              "id": "remindersSent",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "remindersSent",
              "defaultMatch": false
            },
            {
              "id": "lastSentAt",
              "type": "dateTime",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "lastSentAt",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "filters": {
          "conditions": [
            {
              "keyName": "invoiceId",
              "keyValue": "={{ $('Loop over invoices').item.json.invoiceId }}"
            }
          ]
        },
        "options": {},
        "matchType": "allConditions",
        "operation": "update",
        "dataTableId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Add reminders config').item.json.dataTableId }}"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6bb0af0e-dc3d-438e-b811-ee897ccddd74",
      "name": "Supprimer la facture",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        3456,
        848
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyValue": "={{ $('Loop over invoices').item.json.id }}"
            }
          ]
        },
        "options": {},
        "matchType": "allConditions",
        "operation": "deleteRows",
        "dataTableId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Add reminders config').item.json.dataTableId }}"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "ad8ba6c6-d1f4-4329-90ea-b5f39ee7e37f",
      "name": "If3",
      "type": "n8n-nodes-base.if",
      "position": [
        3184,
        688
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "f7c9422b-bfd2-4006-9d81-d2332e95532a",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.remindersSent >= $('Add reminders config').item.json.reminderIntervalsInDays.length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "1e7c11be-4898-4d65-bec2-836d6d769849",
      "name": "Note adhésive20",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2464,
        560
      ],
      "parameters": {
        "color": 7,
        "width": 1184,
        "height": 480,
        "content": "## Send Reminders Logic\nThe logic that decides whether or not to send a reminder email now, skip it and send it later or delete the invoice/s from DB (because all the reminders have been sent or the invoice has been paid)"
      },
      "typeVersion": 1
    },
    {
      "id": "54b8f2b7-c849-48cb-9483-0d0a614575df",
      "name": "Agent IA1",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2576,
        160
      ],
      "parameters": {
        "text": "={{ $('Get today's sent reminders').all() }}",
        "options": {
          "systemMessage": "=You are an AI assistant that generates a daily reminder summary for invoices. You will receive a list of invoice data and your task is to summarize how many reminders have been sent for each invoice today.\n\nInput Data:\nThe input data is a list of invoices with the following fields:\n- remainingAmount: The remaining amount the customer still needs to pay.\n- currency: The currency of the remaining amount (e.g., USD, EUR).\n- remindersSent: The total number of reminders that have been sent for this invoice.\n\nGoal:\n1- Summarize the reminders sent today:\n- Count how many reminders have been sent for all invoices provided in the input.\n\n2- Generate a professional HTML email summary:\n- Use the information from the invoices to create a summary in HTML format.\n- Include a greeting for the team (e.g., \"Sales Team\", \"Finance Team\").\n- Display a total count of reminders sent today.\n- Include invoice-level details such as invoiceId, remainingAmount, currency, and remindersSent.\n\nFormatting Guidelines:\n1- The summary should always be structured as an HTML email.\n2- The summary should be clear, readable, and professional.\n3- You may choose the layout that feels most appropriate, but always include:\n  - A greeting (e.g., \"Dear Team,\").\n  - A total number of reminders sent today.\n  - A list of invoices with invoiceId, remainingAmount, currency, and remindersSent.\n4- Closing with generic sign-off.\n\nExample input:\n[\n  {\n    \"id\": 70,\n    \"createdAt\": \"2025-10-10T16:50:54.851Z\",\n    \"updatedAt\": \"2025-10-15T16:50:54.851Z\",\n    \"invoiceId\": \"158\",\n    \"remainingAmount\": 10,\n    \"currency\": \"USD\",\n    \"remindersSent\": 5\n  },\n  {\n    \"id\": 80,\n    \"createdAt\": \"2025-10-12T17:50:54.851Z\",\n    \"updatedAt\": \"2025-10-15T16:50:54.851Z\",\n    \"invoiceId\": \"160\",\n    \"remainingAmount\": 30,\n    \"currency\": \"EUR\",\n    \"remindersSent\": 3\n  }\n]\n\nExample of Expected Output:\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>Reminder Summary for Today</title>\n  <style>\n    body { font-family: Arial, sans-serif; color: #333; line-height: 1.6; }\n    .table { width: 100%; margin-top: 20px; border-collapse: collapse; }\n    .table th, .table td { border: 1px solid #ddd; padding: 8px; text-align: left; }\n    .table th { background-color: #f2f2f2; }\n    .summary { font-size: 16px; margin-top: 20px; }\n  </style>\n</head>\n<body>\n  <div class=\"content\">\n    <p>Dear Sales Team,</p>\n    \n    <p>Here is a summary of the reminders sent today:</p>\n    \n    <div class=\"summary\">\n      <strong>Total reminders sent today: 2</strong>\n    </div>\n\n    <table class=\"table\">\n      <thead>\n        <tr>\n          <th>Invoice ID</th>\n          <th>Remaining Amount</th>\n          <th>Currency</th>\n          <th>Total Reminders Sent</th>\n        </tr>\n      </thead>\n      <tbody>\n        <tr>\n          <td>158</td>\n          <td>$10.00</td>\n          <td>USD</td>\n          <td>5</td>\n        </tr>\n        <tr>\n          <td>160</td>\n          <td>€30.00</td>\n          <td>EUR</td>\n          <td>3</td>\n        </tr>\n      </tbody>\n    </table>\n\n    <p>If you need further details, feel free to reach out!</p>\n\n    <p>Best regards,<br>AI Assistant</p>\n  </div>\n</body>\n</html>"
        },
        "promptType": "define"
      },
      "executeOnce": true,
      "typeVersion": 2.2
    },
    {
      "id": "a8aeb3a0-f1fd-4038-9899-a7debeb396a3",
      "name": "OpenAI Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        2576,
        368
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "id": "ns8LVe1zpSS3Kw9p",
          "name": "OpenAi account"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "73ba208d-4c77-47f7-8a6c-b8d8d7e89ed8",
      "name": "Note adhésive21",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2464,
        32
      ],
      "parameters": {
        "color": 7,
        "width": 592,
        "height": 480,
        "content": "## Summarize Sent Reminders & Send An Email\nSummarizes today's sent reminders using AI and send a summery email to the team like sales team or finance team"
      },
      "typeVersion": 1
    },
    {
      "id": "a603f1f4-ca24-4c3d-b2bb-0209d999c05f",
      "name": "Obtenir la facture",
      "type": "n8n-nodes-base.xero",
      "position": [
        2208,
        720
      ],
      "parameters": {
        "invoiceId": "={{ $json.invoiceId }}",
        "operation": "get",
        "organizationId": "bc9a44a6-eb14-4f81-b24c-ca676c506446"
      },
      "credentials": {
        "xeroOAuth2Api": {
          "id": "HZnbTfrr5leqrLUQ",
          "name": "Xero account"
        }
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "pinData": {
    "Receive form submission": [
      {
        "json": {
          "body": {
            "name": "Adrian Mathews",
            "email": "yoled82772@elygifts.com",
            "phone": "(116) 777-9916",
            "itemName": "Design",
            "billingAddress": "Street Address: Nulla quia debitis est quam facilis amet enim cupidatat officia autem consequatur qui quis dolorem<br>Street Address Line 2: Possimus perferendis ad veritatis quia animi<br>City: Voluptatibus eveniet harum unde dolor doloremque cumque dol<br>State / Province: Reprehenderit rerum voluptas magni ut minim ad deleniti eni<br>Postal / Zip Code: 17167<br>Country: Seychelles<br>"
          }
        }
      }
    ]
  },
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "15956a08-b0e1-4140-952c-370bd5bae437",
  "connections": {
    "56a479b9-6fc2-4ad8-8a09-7bfd76c5da81": {
      "main": [
        [
          {
            "node": "e220b58d-04f9-483a-90b0-e196b8088bd1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "ae2c88cb-764a-48be-bec0-c172dcf1732e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ad8ba6c6-d1f4-4329-90ea-b5f39ee7e37f": {
      "main": [
        [
          {
            "node": "6bb0af0e-dc3d-438e-b811-ee897ccddd74",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "2620e88d-9c4a-418a-b378-f81aad2f991f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a1b465b8-6884-4878-ab45-81731cc11306": {
      "main": [
        [
          {
            "node": "f40da212-3f17-426d-bc58-5348b4488d9d",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "6bb0af0e-dc3d-438e-b811-ee897ccddd74",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "2620e88d-9c4a-418a-b378-f81aad2f991f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2831fd4c-313c-4b63-b6d0-6b36428ae778": {
      "main": [
        [
          {
            "node": "8add409c-adb4-4d9b-9e6a-0db66e17093e",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "54b8f2b7-c849-48cb-9483-0d0a614575df": {
      "main": [
        [
          {
            "node": "fc86c9e1-0f12-47a8-893c-4a2479207702",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "e495d2d4-3f6d-482a-bb95-7a4dfdbd5dba": {
      "main": [
        [
          {
            "node": "9153a6f7-10d8-44f6-976b-b0abdaf5fd20",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ae2c88cb-764a-48be-bec0-c172dcf1732e": {
      "main": [
        [
          {
            "node": "2620e88d-9c4a-418a-b378-f81aad2f991f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "6bb0af0e-dc3d-438e-b811-ee897ccddd74": {
      "main": [
        [
          {
            "node": "2620e88d-9c4a-418a-b378-f81aad2f991f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a603f1f4-ca24-4c3d-b2bb-0209d999c05f": {
      "main": [
        [
          {
            "node": "a1b465b8-6884-4878-ab45-81731cc11306",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "3436d1ca-18bf-4929-982a-89fa802ff015": {
      "ai_languageModel": [
        [
          {
            "node": "2831fd4c-313c-4b63-b6d0-6b36428ae778",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "15e1d23a-3c96-4037-83cd-97004e6aebe8": {
      "main": [
        [
          {
            "node": "2831fd4c-313c-4b63-b6d0-6b36428ae778",
            "type": "main",
            "index": 0
          },
          {
            "node": "d5ebc764-96f4-41e5-a5dd-ecc8b69470c5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "2620e88d-9c4a-418a-b378-f81aad2f991f": {
      "main": [
        [
          {
            "node": "5949d37a-037b-4292-bbd4-722efc81d0a6",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "a603f1f4-ca24-4c3d-b2bb-0209d999c05f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "a8aeb3a0-f1fd-4038-9899-a7debeb396a3": {
      "ai_languageModel": [
        [
          {
            "node": "54b8f2b7-c849-48cb-9483-0d0a614575df",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "f40da212-3f17-426d-bc58-5348b4488d9d": {
      "main": [
        [
          {
            "node": "f55fd793-3299-4ca7-ab12-6b73a2df3706",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d5ebc764-96f4-41e5-a5dd-ecc8b69470c5": {
      "main": [
        [
          {
            "node": "56a479b9-6fc2-4ad8-8a09-7bfd76c5da81",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "f55fd793-3299-4ca7-ab12-6b73a2df3706": {
      "main": [
        [
          {
            "node": "ad8ba6c6-d1f4-4329-90ea-b5f39ee7e37f",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "d7858d88-bccd-4bbb-8de0-c7ba96d74263": {
      "main": [
        [
          {
            "node": "e495d2d4-3f6d-482a-bb95-7a4dfdbd5dba",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "9153a6f7-10d8-44f6-976b-b0abdaf5fd20": {
      "main": [
        [
          {
            "node": "15e1d23a-3c96-4037-83cd-97004e6aebe8",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "5949d37a-037b-4292-bbd4-722efc81d0a6": {
      "main": [
        [
          {
            "node": "54b8f2b7-c849-48cb-9483-0d0a614575df",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "90f88e6b-c967-4ac7-b11a-4e86be5b9e40": {
      "main": [
        [
          {
            "node": "d5ebc764-96f4-41e5-a5dd-ecc8b69470c5",
            "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œuds39
Catégorie-
Types de nœuds13
Description de la difficulté

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

Liens externes
Voir sur n8n.io

Partager ce workflow

Catégories

Catégories: 34