{
  "id": "bmkUvICtIGmaEAUA",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Weekly Client Report Generator",
  "tags": [],
  "nodes": [
    {
      "id": "74f8e71a-17c3-482a-8cfb-d86fef73673a",
      "name": "Start workflow",
      "type": "n8n-nodes-base.manualTrigger",
      "position": [
        -400,
        -48
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "1d75f247-1432-4d4f-aef3-7c322d19a87d",
      "name": "Format Report",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        -64
      ],
      "parameters": {
        "jsCode": "const output = $json.output || \"\";\n\n// Remove markdown (**)\nconst cleanOutput = output.replace(/\\*\\*/g, \"\");\n\n// Convert sections to HTML\nconst formatted = cleanOutput\n  .replace(/Summary:/gi, \"<b>Summary:</b><br>\")\n  .replace(/Key Highlights:/gi, \"<b>Key Highlights:</b><br>\")\n  .replace(/Risk Analysis:/gi, \"<b>Risk Analysis:</b><br>\")\n  .replace(/Future Outlook:/gi, \"<b>Future Outlook:</b><br>\")\n  .replace(/\\n/g, \"<br>\");\n\n// Final HTML\nconst formattedReport = `\n<div>\n  <p>${formatted}</p>\n</div>\n`;\n\nreturn [\n  {\n    json: {\n      ...$json,   \n      formattedReport\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "d87b22b5-d255-49fd-98f2-20e092f2a529",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -880,
        -272
      ],
      "parameters": {
        "width": 336,
        "height": 960,
        "content": "# Weekly Client Report Generator\n\n# How It Works\n\nThis workflow automatically generates and emails weekly portfolio reports to clients. It fetches client data from Google Sheets, calculates investment, profit and growth, then uses AI to create a short, clear report. The report is formatted in HTML, sent via Gmail and the Google Sheet is updated to mark the email \u201cSent,\u201d keeping track of all reports automatically.\n\n# Setup Steps\n## Prepare Google Sheet\nMake sure your sheet has columns: Client, Email, Invested, Current Value and Status.\n\n## Connect Accounts in n8n\nAdd credentials for Google Sheets, Gmail and Groq AI.\n\n## Start Workflow\nUse a trigger to begin.\n\n## Process Data\nFetch client data, calculate portfolio metrics, generate AI report.\n\n## Send Email & Update Sheet\nSend the report via Gmail and update the Status column in Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "0393ca71-aa77-45a8-8d93-e1c3efb07d12",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 896,
        "height": 432,
        "content": "## Client Data Fetch & Batch Processing\n\nThis section starts the workflow manually, fetches client data from Google Sheets and processes clients in batches. It ensures each client\u2019s investment details (Invested, Current Value, Email) are handled individually, preparing accurate data for portfolio calculations and personalized report generation."
      },
      "typeVersion": 1
    },
    {
      "id": "41c5e3d7-7586-4393-9799-c3a4b610bb0e",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        -240
      ],
      "parameters": {
        "color": 7,
        "width": 768,
        "height": 560,
        "content": "## Portfolio Calculation & Report Generation\n\nThese nodes calculate each client\u2019s total investment, profit and growth. Then, AI generates a short, simple weekly report including Summary, Key Highlights, Risk Analysis and Future Outlook, also format the report."
      },
      "typeVersion": 1
    },
    {
      "id": "d76ab043-6bb3-4ab7-bb9b-d061eb47aa95",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1280,
        -224
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 512,
        "content": "## Final Delivery & Tracking\n\nThe Wait node ensures smooth processing, the Gmail node sends the weekly report to the client and the Google Sheets update node marks the \u201cStatus\u201d as Sent, so you can track which clients have received their reports."
      },
      "typeVersion": 1
    },
    {
      "id": "b904b524-7647-495b-a46d-e8e0e1fecc32",
      "name": "Prepare Data for Sheet",
      "type": "n8n-nodes-base.set",
      "position": [
        1520,
        -64
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8266d657-66aa-424c-8251-7c4345c3efe3",
              "name": "=Client",
              "type": "string",
              "value": "={{$json.Client}}"
            },
            {
              "id": "7f76db0b-59e5-4145-9692-9612267cc255",
              "name": "=Invested",
              "type": "number",
              "value": "={{ $json.Invested }}"
            },
            {
              "id": "d19c16fc-9e2d-4c75-bcf5-7d8dc1c06af9",
              "name": "Current Value",
              "type": "string",
              "value": "={{ $json['Current Value'] }}"
            },
            {
              "id": "c01d2b24-39fa-4166-9010-13befcf5b48c",
              "name": "Email",
              "type": "string",
              "value": "={{ $json.Email }}"
            },
            {
              "id": "e2326aef-0d40-47de-82cf-f6262e07d671",
              "name": "formattedReport",
              "type": "string",
              "value": "={{ $json.formattedReport }}"
            },
            {
              "id": "5c3ad6a2-b313-401c-a925-fcb906305921",
              "name": "Status",
              "type": "string",
              "value": "Sent"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "c4f016c1-2a1b-4a6f-a9cb-8a6f9e71aad5",
      "name": "Pause Before Sending Email",
      "type": "n8n-nodes-base.wait",
      "position": [
        1312,
        -64
      ],
      "parameters": {},
      "typeVersion": 1.1
    },
    {
      "id": "0b5dd762-3fff-419a-b239-e18c7c0a3359",
      "name": "Get Client Data from Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -192,
        -48
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w/edit?usp=drivesdk",
          "cachedResultName": "weekely clientData"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d12d0923-eb79-4013-9c96-86668e8bb786",
      "name": "Process Clients in Batches",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        16,
        -48
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "f1b22db7-e35c-46fd-8b81-94c4ebff35d3",
      "name": "Compute Investment, Profit & Growth",
      "type": "n8n-nodes-base.code",
      "position": [
        288,
        -32
      ],
      "parameters": {
        "jsCode": "const invested = Number($json[\"Invested\"] || 0);\nconst current = Number($json[\"Current Value\"] || 0);\n\nconst profit = current - invested;\n\nconst growth = invested > 0\n  ? ((profit / invested) * 100).toFixed(2)\n  : 0;\n\nreturn [\n  {\n    json: {\n      ...$json,   // keep original data (Email, Client)\n      totalInvested: invested,\n      totalCurrent: current,\n      profit,\n      growth\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "ced41c5e-69ac-44fc-91f8-7b76d228122d",
      "name": "Generate Weekly Portfolio Report",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        544,
        -64
      ],
      "parameters": {
        "text": "=You are a financial analyst.\n\nGenerate a weekly client portfolio report using the data below:\n\nTotal Investment: {{$json.totalInvested}}\nCurrent Value: {{$json.totalCurrent}}\nProfit: {{$json.profit}}\nGrowth: {{$json.growth}}%\n\nYour report must include:\n\n1. Summary (overall performance in simple words)\n2. Key Highlights (profit/loss insights)\n3. Risk Analysis (low/medium/high risk)\n4. Future Outlook (next week expectation)\n\nKeep the report:\n- Simple\n- Professional\n- Short (5\u20136 lines)\n\nDo not use complex financial jargon.",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "8c18d666-7ebb-47e4-8180-557c4a47f16b",
      "name": "Generate Weekly Portfolio Report1",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "position": [
        560,
        160
      ],
      "parameters": {
        "model": "openai/gpt-oss-120b",
        "options": {}
      },
      "credentials": {
        "groqApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "08dbdd32-5200-48bd-94cd-f988515edaf5",
      "name": "Prepare AI Output for Formatting",
      "type": "n8n-nodes-base.code",
      "position": [
        880,
        -64
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  return {\n    json: {\n      ...$node[\"Compute Investment, Profit & Growth\"].json, // original client data\n      output: item.json.output\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "465ac0ba-4a12-4d79-a88a-e5403108ed5e",
      "name": "Send Report via Gmail",
      "type": "n8n-nodes-base.gmail",
      "position": [
        1712,
        -64
      ],
      "parameters": {
        "sendTo": "={{ $json.Email }}",
        "message": "=Hello {{ $json.Client }},\n\nHere is your weekly portfolio report:\n\n{{ $json.formattedReport }}\n\nRegards,\nYour Company",
        "options": {},
        "subject": "Weekly Portfolio Report"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "a394285b-286e-4dbe-b15f-ec2299213f69",
      "name": "Update Client Status in Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1920,
        -64
      ],
      "parameters": {
        "columns": {
          "value": {
            "Email": "={{ $('Pause Before Sending Email').item.json.Email }}",
            "Client": "={{ $('Pause Before Sending Email').item.json.Client }}",
            "Status": "Sent",
            "Invested": "={{ $('Pause Before Sending Email').item.json.Invested }}",
            "row_number": 0,
            "Current Value": "={{ $('Pause Before Sending Email').item.json['Current Value'] }}"
          },
          "schema": [
            {
              "id": "Client",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Client",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Invested",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Invested",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Current Value",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Current Value",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Email",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Email",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "Status",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "Status",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "row_number",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": true,
              "required": false,
              "displayName": "row_number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "Client"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1GwBgjfbdWzXLA5eOiob1O1YFzgqPPW69sOYWTZWQw-w/edit?usp=drivesdk",
          "cachedResultName": "weekely clientData"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    }
  ],
  "active": false,
  "settings": {
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "2817799c-11b5-4711-80c7-e14e7e7d0f60",
  "connections": {
    "Format Report": {
      "main": [
        [
          {
            "node": "Pause Before Sending Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start workflow": {
      "main": [
        [
          {
            "node": "Get Client Data from Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Report via Gmail": {
      "main": [
        [
          {
            "node": "Update Client Status in Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Data for Sheet": {
      "main": [
        [
          {
            "node": "Send Report via Gmail",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pause Before Sending Email": {
      "main": [
        [
          {
            "node": "Prepare Data for Sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Clients in Batches": {
      "main": [
        [],
        [
          {
            "node": "Compute Investment, Profit & Growth",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Client Status in Sheet": {
      "main": [
        [
          {
            "node": "Process Clients in Batches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Weekly Portfolio Report": {
      "main": [
        [
          {
            "node": "Prepare AI Output for Formatting",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare AI Output for Formatting": {
      "main": [
        [
          {
            "node": "Format Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Weekly Portfolio Report1": {
      "ai_languageModel": [
        [
          {
            "node": "Generate Weekly Portfolio Report",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Get Client Data from Google Sheets": {
      "main": [
        [
          {
            "node": "Process Clients in Batches",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compute Investment, Profit & Growth": {
      "main": [
        [
          {
            "node": "Generate Weekly Portfolio Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}