{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "6a71b550-8237-4761-aa17-bf3633012aa8",
      "name": "Generate Personalized Email",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        320,
        -640
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash-lite",
          "cachedResultName": "models/gemini-2.5-flash-lite"
        },
        "options": {
          "temperature": 0.4
        },
        "messages": {
          "values": [
            {
              "content": "=You are Daniel, a finance mortgage broker at Lendium in Australia. Write a professional, warm 3-4 sentence email to {{ $('Normalize lead name').item.json.first_name }} who just inquired about a {{ $('Normalize lead name').item.json.loan_type }} with an income of ${{ $('Normalize lead name').item.json.income }}.\n\nInclude:\n1. Thank them for their inquiry\n2. Acknowledge their specific loan type and mention one relevant insight about their situation\n3. Provide a clear next step (ask them to upload required documents on link provided below)\n4. Sign off professionally as Daniel from Lendium\n\n\nKeep the tone professional yet approachable. Return ONLY the email body text, no subject line."
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "bea5b817-6759-44dd-af3d-09721b7b1b5a",
      "name": "Create Gmail Draft",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1120,
        -640
      ],
      "parameters": {
        "message": "={{ $('Generate Personalized Email').item.json.content.parts[0].text }}\n\\n\\n\n<a href=\"https://13.211.164.241.nip.io/form/df9aebf7-3e4f-4114-bc43-424c3df3511e?folder_id={{ $node['Create Drive Folder'].json.id }}&client_name={{ $('Normalize lead name').item.json.first_name }}\"style=\"background-color: #4CAF50; color: white; padding: 10px 20px; text-decoration: none; border-radius: 5px;\">Upload Folder</a>",
        "options": {
          "sendTo": "={{ $('Normalize lead name').item.json.email }}"
        },
        "subject": "=Re: Your {{ $('Normalize lead name').item.json.loan_type }} Inquiry - Lendium Mortgage Services",
        "resource": "draft",
        "emailType": "html"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "37d4f043-78a6-4615-abfe-02c4946660f2",
      "name": "Aggregate Log Data",
      "type": "n8n-nodes-base.code",
      "position": [
        1568,
        -640
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// Aggregate all workflow data including errors and email approval status\nconst item = $input.item;\n\n// Initialize the aggregated data object\nconst aggregatedData = {\n  // Get email approval status from the Request Email Approval node\n  email_approved: null,\n  \n  // Initialize error tracking\n  lead_activity_error_details: null,\n  \n  // Preserve other important data\n  lead_first_name: null,\n  email: null\n};\n\ntry {\n  // 1. CAPTURE EMAIL APPROVAL STATUS\n  // Check if the approval node executed successfully\n  const approvalNode = $('Request Email Approval').item?.json;\n  \n  if (approvalNode) {\n    // The approval response is typically in the 'update' or 'message' field\n    // Telegram approval returns 'approve' or 'decline'\n    aggregatedData.email_approved = approvalNode.update?.callback_query?.data === 'approve' || \n                                    approvalNode.message?.text?.toLowerCase().includes('yes') ||\n                                    approvalNode.approved === true;\n  }\n  \n  // 2. CAPTURE ANY ERRORS FROM THE WORKFLOW\n  const errors = [];\n  \n  // Check each node for errors\n  const nodesToCheck = [\n    'Generate Strategy Insights',\n    'Generate Personalized Email',\n    'Create Drive Folder',\n    'Share Drive Folder',\n    'Store in Database',\n    'Create Gmail Draft'\n  ];\n  \n  nodesToCheck.forEach(nodeName => {\n    try {\n      const nodeData = $(nodeName).item?.json;\n      if (nodeData?.error || nodeData?.message?.includes('error')) {\n        errors.push({\n          node: nodeName,\n          error: nodeData.error || nodeData.message,\n          timestamp: new Date().toISOString()\n        });\n      }\n    } catch (e) {\n      // Node might not have executed, skip it\n    }\n  });\n  \n  // 3. FORMAT ERROR DETAILS\n  if (errors.length > 0) {\n    aggregatedData.lead_activity_error_details = JSON.stringify({\n      error_count: errors.length,\n      errors: errors,\n      workflow_completed: false\n    });\n  } else {\n    aggregatedData.lead_activity_error_details = JSON.stringify({\n      error_count: 0,\n      errors: [],\n      workflow_completed: true,\n      completed_at: new Date().toISOString()\n    });\n  }\n  \n  // 4. CAPTURE LEAD INFORMATION FOR REFERENCE\n  const webhookData = $('Typebot Webhook').item?.json?.body;\n  if (webhookData) {\n    aggregatedData.lead_first_name = webhookData.first_name;\n    aggregatedData.email = webhookData.email;\n  }\n  \n} catch (error) {\n  // If aggregation itself fails, log that error\n  aggregatedData.lead_activity_error_details = JSON.stringify({\n    error_count: 1,\n    errors: [{\n      node: 'Aggregate Log Data',\n      error: error.message,\n      timestamp: new Date().toISOString()\n    }],\n    workflow_completed: false\n  });\n}\n\n// Return the aggregated data\nreturn {\n  json: aggregatedData\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "8573b74a-e099-4d26-a557-ae769a797710",
      "name": "Create Drive Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        672,
        -640
      ],
      "parameters": {
        "name": "={{ $('Normalize lead name').item.json.first_name }} ({{ $('Normalize lead name').item.json.loan_type }})",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "1vleObg6ZBzUflpAVT2Joc5D7oBNYWNUw",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1vleObg6ZBzUflpAVT2Joc5D7oBNYWNUw",
          "cachedResultName": "Lendium Files"
        },
        "resource": "folder"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "00bca220-c70d-4ef0-8c64-84b5bedeca80",
      "name": "Share Drive Folder",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        896,
        -640
      ],
      "parameters": {
        "options": {},
        "resource": "folder",
        "operation": "share",
        "permissionsUi": {
          "permissionsValues": {
            "role": "writer",
            "type": "anyone"
          }
        },
        "folderNoRootId": {
          "__rl": true,
          "mode": "id",
          "value": "=1YJ026YLa4IT-rk-AqCUlHcdWaxvhDPLE"
        }
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "68481bfe-c542-4417-9fcf-368b0b0d5bcb",
      "name": "Store in Database",
      "type": "n8n-nodes-base.supabase",
      "position": [
        1792,
        -640
      ],
      "parameters": {
        "tableId": "leads_consolidated",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "lead_first_name",
              "fieldValue": "={{ $('Normalize lead name').item.json.first_name }}"
            },
            {
              "fieldId": "email",
              "fieldValue": "={{ $('Normalize lead name').item.json.email }}"
            },
            {
              "fieldId": "loan_type",
              "fieldValue": "={{ $('Normalize lead name').item.json.loan_type }}"
            },
            {
              "fieldId": "income",
              "fieldValue": "={{ $('Normalize lead name').item.json.income }}"
            },
            {
              "fieldId": "folder_link",
              "fieldValue": "=https://drive.google.com/drive/u/0/folders/{{ $('Create Drive Folder').item.json.id }}"
            },
            {
              "fieldId": "lead_last_name",
              "fieldValue": "={{ $('Normalize lead name').item.json.last_name }}"
            },
            {
              "fieldId": "created_at",
              "fieldValue": "={{ $now }}"
            },
            {
              "fieldId": "upload_form_link",
              "fieldValue": "=https://n8n.io/form/df9aebf7-3e4f-4114-bc43-424c3df3511e?folder_id={{ $('Create Drive Folder').item.json.id }}&client_name={{ $('Normalize lead name').item.json.first_name }}"
            },
            {
              "fieldId": "residency_status",
              "fieldValue": "={{ $('Normalize lead name').item.json.residency_status }}"
            },
            {
              "fieldId": "email_approved",
              "fieldValue": "Approved"
            },
            {
              "fieldId": "lead_activity_error_details",
              "fieldValue": "={{ $json.lead_activity_error_details }}"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "773a1dd9-0cd8-439f-af0c-e47bb0f4bc95",
      "name": "Validate Input",
      "type": "n8n-nodes-base.if",
      "position": [
        -608,
        192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "validation-1",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.folder_id }}",
              "rightValue": ""
            },
            {
              "id": "validation-2",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.client_name }}",
              "rightValue": ""
            },
            {
              "id": "validation-3",
              "operator": {
                "type": "number",
                "operation": "equals"
              },
              "leftValue": "={{ Object.keys($binary).length }}",
              "rightValue": 3
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "287b67ee-910c-434c-ac65-fae098b55318",
      "name": "Send Success Notification",
      "type": "n8n-nodes-base.telegram",
      "position": [
        736,
        96
      ],
      "parameters": {
        "text": "=\u2705 *All Documents Uploaded Successfully*\n\n\ud83d\udc64 *Client:* {{ $('Upload portal trigger').item.json.formQueryParameters.client_name }}\n\ud83d\udcc1 *Folder:* [View Folder](https://drive.google.com/drive/u/0/folders/{{ $('Upload portal trigger').item.json.folder_id }})",
        "chatId": "123456789",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f0e07519-5def-4db1-a9df-123c01435aee",
      "name": "Send Partial Failure Notification",
      "type": "n8n-nodes-base.telegram",
      "position": [
        736,
        288
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f *Partial Upload Failure*\n\n\ud83d\udc64 *Client:* {{ $json.client_name }}\n\ud83d\udcc5 *Time:* {{ $json.timestamp }}\n\n\u2705 *Successful:* {{ $json.successful_count }}/3\n{{ $json.successful_uploads.length > 0 ? $json.successful_uploads.map(u => `\u2022 ${u.name}: ${u.filename}`).join('\\n') : 'None' }}\n\n\u274c *Failed:* {{ $json.failed_count }}/3\n{{ $json.failed_uploads.map(f => `\u2022 ${f.name}: ${f.filename}\\n  Error: ${f.error}`).join('\\n') }}\n\n\ud83d\udcc1 [View Folder]({{ $json.folder_link }})\n\n*Action Required:* Please contact the client to re-upload failed documents.",
        "chatId": "123456789",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "545688ea-8362-4ac0-95b4-1b2829012792",
      "name": "Send Validation Error",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -384,
        288
      ],
      "parameters": {
        "text": "=\u274c *Validation Failed*\n\n\ud83d\udcc5 *Time:* {{ $now.toISO() }}\n\n*Issue:* Form submission failed validation checks.\n\nPossible reasons:\n\u2022 Missing folder_id or client_name\n\u2022 Not all 3 files were uploaded\n\u2022 Invalid form data\n\nPlease check the form configuration and try again.",
        "chatId": "123456789",
        "additionalFields": {
          "parse_mode": "Markdown",
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1efd1ad3-21d6-455e-9a23-7af5943c12b2",
      "name": "Upload ID1",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -384,
        96
      ],
      "parameters": {
        "name": "={{ $('Upload portal trigger').item.binary.ID.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Upload portal trigger').item.json.folder_id }}"
        },
        "inputDataFieldName": "={{ $('Upload portal trigger').item.binary.ID }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "continueOnFail": true
    },
    {
      "id": "80ef637a-2997-4084-8acc-58531f4836c0",
      "name": "Upload Payslip1",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -160,
        96
      ],
      "parameters": {
        "name": "={{ $('Upload portal trigger').item.binary.Payslip.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Upload portal trigger').item.json.folder_id }}"
        },
        "inputDataFieldName": "={{ $('Upload portal trigger').item.binary.Payslip }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "continueOnFail": true
    },
    {
      "id": "dddb0d6e-0641-462b-89a5-22b672b3b5af",
      "name": "Upload Bank Statement1",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        64,
        96
      ],
      "parameters": {
        "name": "={{ $('Upload portal trigger').item.binary['Bank_Statement'].fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive",
          "cachedResultName": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $('Upload portal trigger').item.json.folder_id }}"
        },
        "inputDataFieldName": "={{ $('Upload portal trigger').item.binary['Bank_Statement'] }}"
      },
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 3,
      "continueOnFail": true
    },
    {
      "id": "15775092-8702-4a1c-8ee4-3f4022f3ebed",
      "name": "Send Email Created Confirmation",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1344,
        -640
      ],
      "parameters": {
        "text": "=\ud83d\udce7 Draft Email Ready for {{ $('Normalize lead name').item.json.first_name }}.\n\n\n{{ $('Generate Personalized Email').item.json.content.parts[0].text }}\n\n\n\ud83d\udcc1 *Folder:* [View Folder](https://drive.google.com/drive/u/0/folders/{{ $('Create Drive Folder').item.json.id }})\n\n\n\u2705 Check your Gmail drafts to review and send.",
        "chatId": "123456789",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "fbcff950-a080-4366-b781-954deedc9915",
      "name": "Request Email Approval1",
      "type": "n8n-nodes-base.telegram",
      "position": [
        -128,
        -544
      ],
      "parameters": {
        "chatId": "123456789",
        "message": "=\ud83d\ude80 URGENT: High-Quality Lead!\n\n\ud83d\udc64 Full Name: {{ $('Normalize lead name').item.json.full_name_clean }}\n\ud83d\udce7 Email: {{ $('Normalize lead name').item.json.email }}\n\ud83d\udcb0 Income: ${{ $('Normalize lead name').item.json.income }}\n\ud83c\udfe0 Loan Type: {{ $('Normalize lead name').item.json.loan_type }}\n\ud83d\udccd Residency: {{ $('Normalize lead name').item.json.residency_status }}\n\n---\n\nApprove to draft the email?",
        "options": {
          "appendAttribution": false
        },
        "operation": "sendAndWait",
        "approvalOptions": {
          "values": {
            "approvalType": "double"
          }
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "5d9a6fd3-5fa9-4c05-aa98-acbea93ad832",
      "name": "On form submission",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -800,
        -544
      ],
      "parameters": {
        "options": {},
        "formTitle": "Provide Your details",
        "formFields": {
          "values": [
            {
              "fieldName": "name",
              "fieldLabel": "Name",
              "requiredField": true
            },
            {
              "fieldName": "email",
              "fieldType": "email",
              "fieldLabel": "Email",
              "requiredField": true
            },
            {
              "fieldName": "loan_type",
              "fieldType": "radio",
              "fieldLabel": "Looking to see if we can help with your loan?",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Home Loan"
                  },
                  {
                    "option": "Commercial"
                  },
                  {
                    "option": "Refinance"
                  }
                ]
              },
              "requiredField": true
            },
            {
              "fieldName": "income",
              "fieldType": "number",
              "fieldLabel": "Income in AUD",
              "requiredField": true
            },
            {
              "fieldName": "residency_status",
              "fieldType": "radio",
              "fieldLabel": "Are you an AU citizen?",
              "fieldOptions": {
                "values": [
                  {
                    "option": "Yes"
                  },
                  {
                    "option": "No"
                  }
                ]
              },
              "requiredField": true
            }
          ]
        }
      },
      "typeVersion": 2.5
    },
    {
      "id": "473bacef-d6d5-41f6-ab86-6d2a755de5ad",
      "name": "Check income threshold",
      "type": "n8n-nodes-base.if",
      "position": [
        -352,
        -544
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7d175798-af1e-4718-88d0-85bcc361b8f1",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.income }}",
              "rightValue": 80000
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "52793993-e72c-4926-8b69-a4437f35355b",
      "name": "Check approval response",
      "type": "n8n-nodes-base.if",
      "position": [
        96,
        -544
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7d175798-af1e-4718-88d0-85bcc361b8f1",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.data.approved }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "746733a1-676c-4b04-9b5a-5b9e2d496a88",
      "name": "Check all uploads successful",
      "type": "n8n-nodes-base.if",
      "position": [
        512,
        192
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "9c0bfdd5-4456-44a4-b8dd-611d7f25f0d5",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.all_success }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "ba73f9f0-970c-41c4-8806-c9438b489089",
      "name": "Normalize lead name",
      "type": "n8n-nodes-base.code",
      "position": [
        -576,
        -544
      ],
      "parameters": {
        "jsCode": "// Get and clean input\nconst fullNameRaw = $input.first().json.name.trim().toLowerCase();\n\n// Function to capitalize first letter of each word\nfunction toTitleCase(str) {\n  return str.replace(/\\b\\w/g, char => char.toUpperCase());\n}\n\n// Normalize full name\nconst normalizedFullName = toTitleCase(fullNameRaw);\n\n// Split into parts\nconst parts = normalizedFullName.split(/\\s+/);\n\nconst firstName = parts[0] || '';\nconst lastName = parts.length > 1 ? parts.slice(1).join(' ') : '';\n\n\n// Return the data with parsed names\nreturn {\n  json: {\n    ...($input.first().json),\n    first_name: firstName,\n    last_name: lastName,\n    full_name_clean: normalizedFullName\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "3799e719-fae7-47e7-9998-012dd70d0114",
      "name": "Evaluate upload results",
      "type": "n8n-nodes-base.code",
      "position": [
        288,
        96
      ],
      "parameters": {
        "jsCode": "// Get all upload results\nconst uploads = $input.all();\n\n// Track results\nconst successful = [];\nconst failed = [];\n\n// Check each upload\nuploads.forEach((upload, index) => {\n  const docType = index === 0 ? 'ID' : index === 1 ? 'Payslip' : 'Bank_Statement';\n  \n  if (upload.json.error) {\n    // Upload failed\n    failed.push({\n      document: docType,\n      error: upload.json.error\n    });\n  } else {\n    // Upload succeeded\n    successful.push({\n      document: docType,\n      file_id: upload.json.id,\n      link: upload.json.webViewLink\n    });\n  }\n});\n\n// Check if all successful\nconst allSuccess = failed.length === 0;\n\n// Prepare error details for Supabase (store as JSON string or null)\nconst errorDetails = failed.length > 0 ? JSON.stringify(failed) : null;\n\nreturn {\n  json: {\n    all_success: allSuccess,\n    document_upload_error_details: errorDetails,\n    successful_uploads: successful,\n    failed_uploads: failed,\n    successful_count: successful.length,\n    failed_count: failed.length\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "6f89d4a0-33d7-468a-8520-d4c5858ec503",
      "name": "Log declined lead",
      "type": "n8n-nodes-base.supabase",
      "position": [
        384,
        -448
      ],
      "parameters": {
        "tableId": "leads_consolidated",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "lead_first_name",
              "fieldValue": "={{ $('Normalize lead name').item.json.first_name }}"
            },
            {
              "fieldId": "email",
              "fieldValue": "={{ $('Normalize lead name').item.json.email }}"
            },
            {
              "fieldId": "loan_type",
              "fieldValue": "={{ $('Normalize lead name').item.json.loan_type }}"
            },
            {
              "fieldId": "income",
              "fieldValue": "={{ $('Normalize lead name').item.json.income }}"
            },
            {
              "fieldId": "lead_last_name",
              "fieldValue": "={{ $('Normalize lead name').item.json.last_name }}"
            },
            {
              "fieldId": "created_at",
              "fieldValue": "={{ $now }}"
            },
            {
              "fieldId": "residency_status",
              "fieldValue": "={{ $('On form submission').item.json.residency_status }}"
            },
            {
              "fieldId": "email_approved",
              "fieldValue": "Declined"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7b7e5098-2931-4403-8ce4-6f43336cb220",
      "name": "Update upload error log",
      "type": "n8n-nodes-base.supabase",
      "position": [
        512,
        0
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "lead_first_name",
              "keyValue": "={{ $('Upload portal trigger').item.json.client_name }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "leads_consolidated",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "document_upload_error_details",
              "fieldValue": "={{ $json.document_upload_error_details }}"
            }
          ]
        },
        "matchType": "allFilters",
        "operation": "update"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "368ba308-d5ae-4cb1-a315-beb9115cd6b2",
      "name": "Upload portal trigger",
      "type": "n8n-nodes-base.formTrigger",
      "position": [
        -832,
        192
      ],
      "parameters": {
        "options": {},
        "formTitle": "Document Upload Portal",
        "formFields": {
          "values": [
            {
              "fieldType": "file",
              "fieldLabel": "ID",
              "requiredField": true
            },
            {
              "fieldType": "file",
              "fieldLabel": "Payslip",
              "requiredField": true
            },
            {
              "fieldType": "file",
              "fieldLabel": "Bank_Statement",
              "requiredField": true
            },
            {
              "fieldName": "folder_id",
              "fieldType": "hiddenField"
            },
            {
              "fieldName": "client_name",
              "fieldType": "hiddenField"
            }
          ]
        },
        "formDescription": "Please upload your documents here. All fields are required."
      },
      "typeVersion": 2.5
    },
    {
      "id": "2dace547-f410-4302-b297-e4a97da90ca8",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1664,
        -688
      ],
      "parameters": {
        "width": 672,
        "height": 672,
        "content": "## Mortgage Lead Automation with AI and Human Approval\n\nThis workflow automates mortgage lead handling while keeping you in control.\n\nNew leads are captured and normalized. High income leads are sent to Telegram for approval before any outreach happens. Once approved, an AI generated email draft is created in Gmail and a dedicated Google Drive folder is provisioned.\n\nThe client receives a secure upload link to submit ID, payslip, and bank statement. Documents are validated, stored automatically, and logged in Supabase. You receive real time notifications for success or partial failures.\n\nThis template reduces admin time, prevents accidental outreach, and creates a structured document collection pipeline.\n\n## How it works\n1. Capture and normalize lead\n2. Apply income filter\n3. Request Telegram approval\n4. Draft AI email and create Drive folder\n5. Collect and validate documents\n6. Log results and notify broker\n\n## Setup steps\n1. Connect Gmail, Drive, Telegram, Supabase, Gemini\n2. Update Telegram chat ID\n3. Update Drive parent folder ID\n4. Adjust income threshold\n5. Test approval and upload flows"
      },
      "typeVersion": 1
    },
    {
      "id": "65fe3dc5-87d2-4692-9868-bf03951b5343",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -848,
        -736
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 400,
        "content": "Captures new mortgage inquiries and cleans name data.\nApplies income threshold before continuing.\nPrevents low quality leads from triggering AI and admin steps."
      },
      "typeVersion": 1
    },
    {
      "id": "9d13f6ac-973f-444a-b7b7-584151496c93",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -208,
        -736
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 400,
        "content": "Sends high value leads to Telegram for review.\nBroker must approve before AI email drafting.\nDeclined leads are logged in Supabase."
      },
      "typeVersion": 1
    },
    {
      "id": "5945c161-51ef-43d4-b353-9874ed9c2ee4",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        288,
        -736
      ],
      "parameters": {
        "color": 7,
        "width": 976,
        "height": 448,
        "content": "Generates personalized mortgage email using Gemini.\nCreates client specific Drive folder.\nPrepares Gmail draft with secure upload link."
      },
      "typeVersion": 1
    },
    {
      "id": "c618560b-ffeb-45eb-8696-c37c985c0786",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -880,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 656,
        "height": 576,
        "content": "Client uploads required documents through secure form.\nHidden fields link uploads to correct Drive folder.\nInput validation ensures required data is present."
      },
      "typeVersion": 1
    },
    {
      "id": "5dbbeca7-b331-4a06-b155-2c3f16e6757f",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        -16
      ],
      "parameters": {
        "color": 7,
        "width": 608,
        "height": 320,
        "content": "Uploads ID, payslip, and bank statement to Drive.\nHandles partial failures without breaking workflow.\nEvaluates overall upload status."
      },
      "typeVersion": 1
    },
    {
      "id": "f49871a9-702e-4707-9c71-ec3c0a66b133",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        -96
      ],
      "parameters": {
        "color": 7,
        "width": 512,
        "height": 608,
        "content": "Sends Telegram notifications for success or failure.\nAggregates errors and activity data.\nStores structured results in Supabase."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Upload ID1": {
      "main": [
        [
          {
            "node": "Upload Payslip1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Input": {
      "main": [
        [
          {
            "node": "Upload ID1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Validation Error",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload Payslip1": {
      "main": [
        [
          {
            "node": "Upload Bank Statement1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log declined lead": {
      "main": [
        []
      ]
    },
    "Store in Database": {
      "main": [
        []
      ]
    },
    "Aggregate Log Data": {
      "main": [
        [
          {
            "node": "Store in Database",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Gmail Draft": {
      "main": [
        [
          {
            "node": "Send Email Created Confirmation",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "On form submission": {
      "main": [
        [
          {
            "node": "Normalize lead name",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Share Drive Folder": {
      "main": [
        [
          {
            "node": "Create Gmail Draft",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create Drive Folder": {
      "main": [
        [
          {
            "node": "Share Drive Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize lead name": {
      "main": [
        [
          {
            "node": "Check income threshold",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upload portal trigger": {
      "main": [
        [
          {
            "node": "Validate Input",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check income threshold": {
      "main": [
        [
          {
            "node": "Request Email Approval1",
            "type": "main",
            "index": 0
          }
        ],
        []
      ]
    },
    "Upload Bank Statement1": {
      "main": [
        [
          {
            "node": "Evaluate upload results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check approval response": {
      "main": [
        [
          {
            "node": "Generate Personalized Email",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Log declined lead",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Evaluate upload results": {
      "main": [
        [
          {
            "node": "Check all uploads successful",
            "type": "main",
            "index": 0
          },
          {
            "node": "Update upload error log",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Request Email Approval1": {
      "main": [
        [
          {
            "node": "Check approval response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update upload error log": {
      "main": [
        []
      ]
    },
    "Generate Personalized Email": {
      "main": [
        [
          {
            "node": "Create Drive Folder",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check all uploads successful": {
      "main": [
        [
          {
            "node": "Send Success Notification",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send Partial Failure Notification",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email Created Confirmation": {
      "main": [
        [
          {
            "node": "Aggregate Log Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}