{
  "id": "oPfF3svbkGBXTp2J",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Transform Your Employee Leave Sheet into a Smart Alert System",
  "tags": [],
  "nodes": [
    {
      "id": "generated-6ace5735-9c46-454a-aef7-196487beb8d3",
      "name": "Holiday Workflow Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -592,
        -496
      ],
      "parameters": {
        "width": 518,
        "height": 664,
        "content": "## Workflow Overview\n\n### How it works \n\nThis workflow automatically manages employee leave notifications based on a central Google Sheet. Every day at a scheduled time, it checks whether any employee\u2019s leave period has started or ended. If a leave period begins, the workflow sends a notification to a designated Slack channel and sends a reminder email to the employee to update their Slack status and availability. Once processed, the employee\u2019s status in the sheet is marked as \u201cActive\u201d to prevent duplicate notifications.\n\nWhen a leave period ends, the workflow detects it automatically. It posts an update to the same Slack channel and sends a \u201cWelcome Back\u201d reminder email to the employee. The sheet is then updated to mark the leave as \u201cInactive.\u201d All processing happens sequentially to avoid API limits and ensure reliability.\n\nThis automation is designed to be safe for shared environments. It does not modify user Slack profiles or Gmail settings directly. Instead, it sends reminders and keeps HR or operations teams informed through Slack notifications.\n\n### Setup Instructions\n\nConnect your Google Sheets OAuth2 credential.\n\nConnect your Slack OAuth2 credential.\n\nConnect your Gmail OAuth2 credential.\n"
      }
    },
    {
      "id": "generated-80e8e821-a933-4601-8b0a-6d3af492e1a0",
      "name": "Daily Leave Check Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        144,
        64
      ],
      "parameters": {
        "rule": {
          "values": [],
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      }
    },
    {
      "id": "c5d33038-aba0-497b-9aaf-2fdb19b47f1c",
      "name": "Fetch Leave Records",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        352,
        64
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 273133283,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit#gid=273133283",
          "cachedResultName": "dummy leave data"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit?usp=drivesdk",
          "cachedResultName": "Employee Leave Records1"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    },
    {
      "id": "44ed6649-3b28-43d4-9ea1-604c51e46b0b",
      "name": "Validate & Normalize Leave Data",
      "type": "n8n-nodes-base.code",
      "position": [
        576,
        64
      ],
      "parameters": {
        "jsCode": "const today = new Date();\ntoday.setHours(0,0,0,0);\n\nreturn items\n  .map(item => {\n    const email = item.json[\"Employee Email\"];\n    const name = item.json[\"Name\"];\n    const startRaw = item.json[\"Start Date\"];\n    const endRaw = item.json[\"End Date\"];\n    const status = item.json[\"Status\"] || \"Inactive\";\n\n    // Validate required fields\n    if (!email || !startRaw || !endRaw) {\n      return null;\n    }\n\n    const startDate = new Date(startRaw);\n    const endDate = new Date(endRaw);\n\n    // Normalize time\n    startDate.setHours(0,0,0,0);\n    endDate.setHours(0,0,0,0);\n\n    if (isNaN(startDate) || isNaN(endDate)) {\n      return null;\n    }\n\n    const isWithinLeave = today >= startDate && today <= endDate;\n    const isLeaveEnded = today > endDate;\n\n    return {\n      json: {\n        email,\n        name,\n        startDate: startDate.toISOString().split(\"T\")[0],\n        endDate: endDate.toISOString().split(\"T\")[0],\n        returnDate: endDate.toISOString().split(\"T\")[0],\n        currentStatus: status,\n        today: today.toISOString().split(\"T\")[0],\n        isWithinLeave,\n        isLeaveEnded,\n        needsActivation: isWithinLeave && status !== \"Active\",\n        needsReset: isLeaveEnded && status === \"Active\"\n      }\n    };\n  })\n  .filter(item => item !== null);\n"
      },
      "typeVersion": 2
    },
    {
      "id": "generated-baa5999e-cb81-460b-975f-8e53e0c7627b",
      "name": "Check Needs Activation",
      "type": "n8n-nodes-base.if",
      "position": [
        928,
        64
      ],
      "parameters": {
        "options": {
          "ignoreCase": true,
          "looseTypeValidation": true
        },
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4e3b451e-dc0e-4b65-9e7e-7153d3238634",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{$json.needsActivation}}",
              "rightValue": ""
            }
          ]
        }
      }
    },
    {
      "id": "18952c94-d843-44f8-9ca5-dc89917dafb7",
      "name": "Check Needs Reset",
      "type": "n8n-nodes-base.if",
      "position": [
        1104,
        288
      ],
      "parameters": {
        "options": {
          "ignoreCase": true
        },
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": false,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "4e3b451e-dc0e-4b65-9e7e-7153d3238634",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{$json.needsReset}}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "b53131b4-d779-4483-b0ce-ce5f1d7ec28f",
      "name": "Process Activations Sequentially",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1296,
        16
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "1f73b0d8-bee5-49e8-bfad-3e3f2f237409",
      "name": "Notify HR Channel",
      "type": "n8n-nodes-base.slack",
      "position": [
        1584,
        32
      ],
      "parameters": {
        "text": "=\ud83d\udcc5 Leave Activated\n\nEmployee: {{$json.name}}\nEmail: {{$json.email}}\nLeave Period: {{$json.startDate}} \u2192 {{$json.endDate}}\n\nReminder email sent to employee.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09L70CVDL3",
          "cachedResultName": "alerting-channel"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2.4
    },
    {
      "id": "84e16891-9f27-4447-9dfe-15f62f61d0b0",
      "name": "Send OOO Reminder Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1792,
        32
      ],
      "parameters": {
        "sendTo": "={{ \"forreferal04@gmail.com\" || !$('Process Activations Sequentially').item.json.email }}",
        "message": "=Hi {{$('Process Activations Sequentially').item.json.name}},\n\nOur records show your leave from {{$('Process Activations Sequentially').item.json.startDate}} to {{$('Process Activations Sequentially').item.json.endDate}}.\n\nPlease make sure to:\n\u2022 Update your Slack status to \"Out of Office\"\n\u2022 Inform your team if needed\n\nRegards,\nHR Automation System",
        "options": {},
        "subject": "=Leave Reminder \u2013 Please Enable Out of Office"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2.2
    },
    {
      "id": "2b00a36a-857e-42e7-a798-5460fd639373",
      "name": "Process Resets Sequentially",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        1392,
        272
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "5e70ba30-ba79-4701-9b5b-f7acc759cd3d",
      "name": "Notify HR Leave Reset",
      "type": "n8n-nodes-base.slack",
      "position": [
        1680,
        288
      ],
      "parameters": {
        "text": "=\ud83d\udd04 Leave Completed\n\nEmployee: {{$json.name}}\nEmail: {{$json.email}}\nLeave Period: {{$json.startDate}} \u2192 {{$json.endDate}}\n\nEmployee has returned from leave.\nStatus reset automatically.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09L70CVDL3",
          "cachedResultName": "alerting-channel"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2.4
    },
    {
      "id": "c9207def-24de-49cd-b012-42b83302c648",
      "name": "Send Welcome Back Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1888,
        288
      ],
      "parameters": {
        "sendTo": "={{ \"forreferal04@gmail.com\" || !$('Process Resets Sequentially').item.json.email }}",
        "message": "=Hi {{$('Process Resets Sequentially').item.json.name}},\n\nOur records show your leave ended on {{$('Process Resets Sequentially').item.json.endDate}}.\n\nWelcome Back !!\n\nHave a productive day!\n\nHR Leave Automation System",
        "options": {},
        "subject": "=Welcome Back \u2013 Leave Completed"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 2.2
    },
    {
      "id": "2d6c5d35-a7a2-4208-8233-efaf14be065a",
      "name": "Mark Leave As Inactive",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2112,
        288
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "={{ \"Inactive\" }}",
            "Last Updated": "={{ $('Process Resets Sequentially').item.json.today }}",
            "Employee Email": "={{ $('Process Resets Sequentially').item.json.email }}"
          },
          "schema": [
            {
              "id": "Employee Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Employee Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Start Date",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Start Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "End Date",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "End Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Updated",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Last Updated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Employee Email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 273133283,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit#gid=273133283",
          "cachedResultName": "dummy leave data"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit?usp=drivesdk",
          "cachedResultName": "Employee Leave Records1"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    },
    {
      "id": "07b1bdf9-8ed4-444a-b2c8-ff9ba89c71f7",
      "name": "Mark Leave as Active",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        2016,
        32
      ],
      "parameters": {
        "columns": {
          "value": {
            "Status": "={{ \"Active\" }}",
            "Last Updated": "={{ $('Process Activations Sequentially').item.json.today }}",
            "Employee Email": "={{ $('Process Activations Sequentially').item.json.email }}"
          },
          "schema": [
            {
              "id": "Employee Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Employee Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Name",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Name",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Start Date",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "Start Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "End Date",
              "type": "string",
              "display": true,
              "removed": true,
              "required": false,
              "displayName": "End Date",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Last Updated",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Last Updated",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": true,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Employee Email"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 273133283,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit#gid=273133283",
          "cachedResultName": "dummy leave data"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1bqwC7pOQE_szyOD9yNZXa3edVmeqH6UoT00vPM12xR8/edit?usp=drivesdk",
          "cachedResultName": "Employee Leave Records1"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 4.7
    },
    {
      "id": "ecf90988-0392-4baf-96fe-1f7231651c7c",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 1360,
        "height": 384,
        "content": "Handles employees whose leave starts today. Sends Slack notification, emails reminder, updates sheet status, and prevents duplicate activations."
      },
      "typeVersion": 1
    },
    {
      "id": "6c36d41d-6c25-4249-9f25-44ca1a123fcd",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1040,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 1264,
        "height": 352,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\nHandles employees whose leave has ended. Sends return notification, emails reminder, and resets status to inactive in the sheet."
      },
      "typeVersion": 1
    },
    {
      "id": "54ffe19f-2914-4561-b209-2bf5493623c6",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        96,
        -80
      ],
      "parameters": {
        "color": 7,
        "width": 752,
        "height": 368,
        "content": "Triggers daily execution, loads configuration values, reads leave records from Google Sheets, validates inputs, and calculates activation and reset conditions."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "270ca519-f458-4f77-96cc-c4a8f7f358d0",
  "connections": {
    "Check Needs Reset": {
      "main": [
        [
          {
            "node": "Process Resets Sequentially",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify HR Channel": {
      "main": [
        [
          {
            "node": "Send OOO Reminder Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Leave Records": {
      "main": [
        [
          {
            "node": "Validate & Normalize Leave Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Leave as Active": {
      "main": [
        [
          {
            "node": "Process Activations Sequentially",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify HR Leave Reset": {
      "main": [
        [
          {
            "node": "Send Welcome Back Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Needs Activation": {
      "main": [
        [
          {
            "node": "Process Activations Sequentially",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Check Needs Reset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mark Leave As Inactive": {
      "main": [
        [
          {
            "node": "Process Resets Sequentially",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send OOO Reminder Email": {
      "main": [
        [
          {
            "node": "Mark Leave as Active",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Welcome Back Email": {
      "main": [
        [
          {
            "node": "Mark Leave As Inactive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Daily Leave Check Trigger": {
      "main": [
        [
          {
            "node": "Fetch Leave Records",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Resets Sequentially": {
      "main": [
        [],
        [
          {
            "node": "Notify HR Leave Reset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate & Normalize Leave Data": {
      "main": [
        [
          {
            "node": "Check Needs Activation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Activations Sequentially": {
      "main": [
        [],
        [
          {
            "node": "Notify HR Channel",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}