{
  "nodes": [
    {
      "id": "f18976c8-bd79-424f-8bf3-10f6f2d003c7",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        272,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 480,
        "height": 176,
        "content": "## AI Generation & Google Docs Save\n\nAI fills all template placeholders with actual\ncandidate data while preserving formatting, then\nsaves the final document to Google Docs."
      },
      "typeVersion": 1
    },
    {
      "id": "ff59c2fb-009b-4615-8f1f-232d3af40913",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -480,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 240,
        "content": "## Template Selection & Loading\n\nChecks if the user selected \"Offer Letter\" or\n\"Contract\", then loads the appropriate template\nwith all placeholders ready for AI filling."
      },
      "typeVersion": 1
    },
    {
      "id": "d88f0685-9b44-454e-a6ac-316f51d11ab8",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1072,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 192,
        "content": "## Form Submission & Document Processing\n\nReceives candidate details via form, splits\nuploaded Indentity card and Resume files, then extracts\ntext from both PDFs and merges the data."
      },
      "typeVersion": 1
    },
    {
      "id": "681a25ee-79db-4803-817e-037961a3c2c5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1744,
        -160
      ],
      "parameters": {
        "width": 432,
        "height": 832,
        "content": "## AI-Powered HR Document Generator\n\nThis workflow automatically generates professional Offer Letters\nor Employment Contracts for new hires. HR submits a form with\nthe candidate's documents (Identity card & Resume), job details, and\ndocument type. The system extracts the candidate's name from\nuploaded files, auto-calculates the joining date, selects the\nappropriate template, and uses AI to intelligently fill all\nplaceholders while preserving formatting. The final document\nis saved directly to Google Docs \u2014 ready to send.\n\n## How it works\n1. HR fills a form with Identity card, Resume, Job Role, Salary, and Type.\n2. System splits uploaded files and auto-generates joining date.\n3. Extracts candidate name and details from PDF documents.\n4. Routes to Offer Letter or Contract template based on selection.\n5. AI fills all placeholders with actual data while keeping formatting.\n6. Final document is saved to Google Docs automatically.\n\n## Setup steps\n1. Connect Google Docs OAuth credentials.\n2. Add OpenAI API key for GPT-4.1-mini model.\n3. Update Google Docs document URL in the save node.\n4. Customize Offer Letter and Contract templates as needed.\n5. Share the form link with your HR team to start generating documents."
      },
      "typeVersion": 1
    },
    {
      "id": "3a9e1ad1-867e-41a4-aa5a-0895b12b45d1",
      "name": "Save Document to Google Docs",
      "type": "n8n-nodes-base.googleDocs",
      "position": [
        656,
        144
      ],
      "parameters": {
        "actionsUi": {
          "actionFields": [
            {
              "text": "={{ $json.output }}",
              "action": "insert"
            }
          ]
        },
        "operation": "update",
        "documentURL": "doc_url"
      },
      "credentials": {
        "googleDocsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "78e62aa7-6027-442c-a9b5-f2ef49ec12c8",
      "name": "OpenAI GPT-4.1 Mini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        272,
        384
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "5b3b0775-cfac-48bd-a60c-1a27dcc40ba5",
      "name": "Fill Template with AI",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        272,
        144
      ],
      "parameters": {
        "text": "=Adhar Card: {{ $('Receive Candidate Details via Form').item.json.Aadhar }}\nResume: {{ $('Receive Candidate Details via Form').item.json.Resume[0] }}\nForm Data:\nJob Role: {{ $('Receive Candidate Details via Form').item.json['Job Role'] }}\nSalary Details: {{ $item(0).$node[\"Split Documents and Calculate Dates\"].json[\"Salary Details\"] }}\nForm Date: {{ $item(0).$node[\"Split Documents and Calculate Dates\"].json.FormDate }}\nJoining Data: {{ \n  (() => {\n    const formDate = new Date($item(0).$node[\"Split Documents and Calculate Dates\"].json.FormDate);\n    const nextMonth = new Date(formDate.getFullYear(), formDate.getMonth() + 1, 1);\n    return nextMonth.toLocaleDateString(\"en-GB\", { day: \"numeric\", month: \"long\", year: \"numeric\" });\n  })()\n}}\n\n",
        "options": {
          "systemMessage": "=You are an HR assistant.\n\nYour task is to generate a professional HR document (Offer Letter or Contract) based on the Document Type.\n\nUse the template provided in JSON below.  \nDo NOT paraphrase, merge, or rewrite sentences.  \nDo NOT remove or add any text.  \nReplace ALL placeholders in the template with the actual data provided.  \n**Preserve all line breaks and blank lines exactly as in the template.**\n\n---\n\n### Template_Offer Letter\n`{{ $json.template_offer || \" \" }}`\n\n### Template_Contract\n`{{ $json.template_contract || \" \" }}`\n\n---\n\n### Data\nDocument Type: {{ $('Receive Candidate Details via Form').item.json.Type }}\nCandidate Name: {{ $('Merge Extracted Document Texts').item.json.text[1].text }}\nJob Role: {{ $('Receive Candidate Details via Form').item.json['Job Role'] }}\nDepartment/Team Name: {{ $('Receive Candidate Details via Form').item.json['Department Name'] || \"Automation Team\" }}\nJoining Date: {{ $item(0).$node[\"Split Documents and Calculate Dates\"].json.JoiningDate }}\nSalary Details: {{ $('Receive Candidate Details via Form').item.json['Salary Details'] }}\nProbation Period: {{ $('Receive Candidate Details via Form').item.json['Probation Period'] || 6 }}\nWork Location: {{ $('Receive Candidate Details via Form').item.json['Work Location'] || \"Delhi\" }}\nReporting Manager/Team Lead: {{ $('Receive Candidate Details via Form').item.json['Reporting Manager'] || \"Team Lead\" }}\nCompany Name: Incrementors Web Solution\n\n---\n\n### Instructions\n1. If Document Type includes \u201coffer\u201d, generate the document using **Template_Offer Letter**.  \n2. If Document Type includes \u201ccontract\u201d, generate the document using **Template_Contract**.  \n3. Replace **all placeholders** exactly with the corresponding values from Data.  \n4. **Keep all line breaks, blank lines, emojis, and formatting** exactly as in the template.  \n5. Do NOT merge paragraphs, paraphrase, or add extra text.  \n6. Output **only the final filled document**, nothing else.\n"
        },
        "promptType": "define"
      },
      "typeVersion": 2.2
    },
    {
      "id": "fcb486d1-484b-465b-a3aa-8b72e1d52c5a",
      "name": "Load Contract Template",
      "type": "n8n-nodes-base.set",
      "position": [
        0,
        256
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "91c81f7d-3d0a-48d2-a5a3-f20fe29ef105",
              "name": "template_contract",
              "type": "string",
              "value": "Dear [Candidate Name],  We are pleased to confirm your appointment as [Job Role] in the [Department/Team Name] at [Company Name], effective [Joining Date].  This Employment Contract outlines the terms and conditions of your employment:\\n\n1. **Position & Reporting**   You will serve as [Job Role] reporting to [Reporting Manager/Team Lead]. Your responsibilities will include all tasks reasonably assigned to you within the scope of your position.\\n\n2. **Compensation & Benefits**   Your compensation package will be [Salary Details] per annum, along with applicable benefits as per the company policy.\\n\n3. **Probation**   You will be on probation for a period of [Probation Period] months, during which your performance will be reviewed. Continuation of employment will be confirmed upon satisfactory completion of the probation period.\\n\n4. **Working Hours & Location**   Your working hours will be as per company policy. Your primary work location will be [Work Location]. The company may request relocation or travel as necessary.\\n\n5. **Confidentiality & Non-Disclosure**   You agree to maintain the confidentiality of all company information and adhere to the company\u2019s Non-Disclosure Agreements.\\n\n6. **Termination**   Either party may terminate this contract with notice as per company policy. The company reserves the right to terminate employment if performance, conduct, or cultural fit is unsatisfactory.\\n\n7. **Miscellaneous**   All other employment terms will be governed by company policies, which may be amended from time to time.  Please sign and return a copy of this contract after reviewing all terms. By doing so, you acknowledge your agreement to the above terms.\\n\n\nBest Regards,\\n\n\nHR Team | Incrementors Web Solutions \\n\n\n\ud83d\udce7 Email: Hrincrementors.com  \\n\n\n\ud83d\udcde Phone: +1234567890   \\n\n\n\ud83c\udf10 Web: https://www.incrementors.com/"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "5695158d-2afe-4006-a864-6cf8ec723671",
      "name": "Load Offer Letter Template",
      "type": "n8n-nodes-base.set",
      "position": [
        0,
        48
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "e7020468-e616-4ae3-a338-feb893b1aa3f",
              "name": "template_offer",
              "type": "string",
              "value": "Dear [Candidate Name],  We are pleased to offer you the position of [Job Role] in the [Department/Team Name] at [Company Name], effective [Joining Date].  To proceed:  Kindly confirm your acceptance.  Kindly upload your joining documents for further approval using the button below.  This offer is contingent upon satisfactory credential verification and reference checks. Your compensation package will be as per our agreed terms.  A formal Joining Letter will be provided upon completion of joining formalities. Please note that your performance will be monitored. If you are found unsuitable for the role or culturally unfit, we reserve the right to discontinue your employment with fair feedback. \nBest Regards,\nHR Team | [Company Name]  \n\ud83d\udce7 Email: Hrincrementors.com  \n\ud83d\udcde Phone: +1234567890 \n\ud83c\udf10 Web: https://www.incrementors.com/"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "0b868d5a-8ca7-4ba0-baa7-44d940fc8b1a",
      "name": "Check Document Type Selection",
      "type": "n8n-nodes-base.if",
      "position": [
        -480,
        160
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "497d284a-0da7-4bc8-b39c-11b358bf7760",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Receive Candidate Details via Form').item.json.Type }}",
              "rightValue": "Offer Letter"
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a0061fac-29cb-4bb1-b007-1d9361b4351e",
      "name": "Merge Extracted Document Texts",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -656,
        160
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "text"
      },
      "typeVersion": 1
    },
    {
      "id": "c9657af8-bc03-4456-8e30-8f1d9e1b05cc",
      "name": "Extract Text from Aadhar and Resume",
      "type": "n8n-nodes-base.extractFromFile",
      "position": [
        -864,
        160
      ],
      "parameters": {
        "options": {},
        "operation": "pdf",
        "binaryPropertyName": "Document"
      },
      "typeVersion": 1
    },
    {
      "id": "8019d0ae-1771-4407-914f-d5b0595a7733",
      "name": "Split Documents and Calculate Dates",
      "type": "n8n-nodes-base.code",
      "position": [
        -1072,
        160
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst outputItems = [];\n\nitems.forEach(item => {\n  const jobRole = item.json.JobRole || '';\n\n  // Auto-generate FormDate (submission date)\n  const formDate = new Date();\n  const formDateStr = formDate.toISOString().split('T')[0];\n\n  // Auto-generate Joining Date \u2192 1st of next month\n  const nextMonth = new Date(formDate.getFullYear(), formDate.getMonth() + 1, 1);\n  const joiningDateStr = nextMonth.toISOString().split('T')[0];\n\n  if (item.binary) {\n    if (item.binary.Aadhar) {\n      outputItems.push({\n        json: {\n          ...item.json,\n          documentType: 'Aadhar',\n          JobRole: jobRole,\n          FormDate: formDateStr,\n          JoiningDate: joiningDateStr,\n          \n        },\n        binary: { Document: item.binary.Aadhar }\n      });\n    }\n\n    if (item.binary.Resume) {\n      outputItems.push({\n        json: {\n          ...item.json,\n          documentType: 'Resume',\n          JobRole: jobRole,\n          FormDate: formDateStr,\n          JoiningDate: joiningDateStr,\n          \n        },\n        binary: { Document: item.binary.Resume }\n      });\n    }\n  }\n});\n\nreturn outputItems;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "6ae56a05-adc8-4efa-ae15-eb501f691482",
      "name": "Receive Candidate Details via Form",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -1280,
        160
      ],
      "parameters": {
        "options": {},
        "formTitle": "Basic Details",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "Aadhar",
              "requiredField": true
            },
            {
              "fieldType": "file",
              "fieldLabel": "Resume",
              "requiredField": true
            },
            {
              "fieldLabel": "Job Role",
              "requiredField": true
            },
            {
              "fieldType": "number",
              "fieldLabel": "Salary Details",
              "requiredField": true
            },
            {
              "fieldType": "dropdown",
              "fieldLabel": "Type",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Offer Letter"
                  },
                  {
                    "option": "Contract"
                  }
                ]
              },
              "requiredField": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    }
  ],
  "connections": {
    "Fill Template with AI": {
      "main": [
        [
          {
            "node": "Save Document to Google Docs",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Load Contract Template": {
      "main": [
        [
          {
            "node": "Fill Template with AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI GPT-4.1 Mini Model": {
      "ai_languageModel": [
        [
          {
            "node": "Fill Template with AI",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Load Offer Letter Template": {
      "main": [
        [
          {
            "node": "Fill Template with AI",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Document Type Selection": {
      "main": [
        [
          {
            "node": "Load Offer Letter Template",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Load Contract Template",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Extracted Document Texts": {
      "main": [
        [
          {
            "node": "Check Document Type Selection",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Receive Candidate Details via Form": {
      "main": [
        [
          {
            "node": "Split Documents and Calculate Dates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Text from Aadhar and Resume": {
      "main": [
        [
          {
            "node": "Merge Extracted Document Texts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Documents and Calculate Dates": {
      "main": [
        [
          {
            "node": "Extract Text from Aadhar and Resume",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}