{"workflow":{"id":13705,"name":"Manage WhatsApp property maintenance tickets with WATI and Google Sheets","views":49,"recentViews":0,"totalViews":49,"createdAt":"2026-02-25T12:41:51.827Z","description":"Empower your property management with a high-efficiency automated support desk. This workflow manages the complete maintenance lifecycle—from initial issue classification and ticket creation to team assignment, status updates, and tenant feedback—all centralized through WhatsApp using WATI and Google Sheets.\n\n---\n\n## 🎯 What This Workflow Does\n\nTurns WhatsApp into an intelligent bridge between tenants, maintenance teams, and landlords:\n\n- 📝 **Instant Ticket Creation**  \n  Tenants can report any property issue via WhatsApp. The system automatically classifies the problem (Plumbing, Electrical, etc.) and assigns a priority level based on keywords.\n\n- 🚦 **Smart Command Routing**  \n  A master switch node handles incoming messages based on intent:\n  - **New Issue:** Classifies and logs a new ticket.\n  - **update &lt;id&gt; &lt;status&gt;:** Allows maintenance teams to update progress.\n  - **rate &lt;id&gt; &lt;1-5&gt;:** Captures tenant satisfaction scores.\n  - **mystatus:** Provides tenants a view of their active tickets.\n  - **dashboard:** Gives landlords an overview of property health.\n\n- 🛠️ **Maintenance Coordination**  \n  Simultaneously notifies the tenant of their Ticket ID and pings the relevant maintenance team with full issue details and an SLA deadline.\n\n- 🚨 **Proactive SLA Monitoring**  \n  A daily morning trigger scans all open tickets for SLA breaches (e.g., High Priority overdue after 4 hours) and alerts the landlord and teams for immediate action.\n\n---\n\n## ✨ Key Features\n\n- **Keyword Intelligence:** Uses built-in logic to detect urgent issues like \"leak\" or \"no power\" and auto-flags them as High Priority.\n- **Team Mapping:** Automatically routes requests to specific teams (Plumbing, Electrical, Structural) based on the detected category.\n- **Service Rating Loop:** Automatically prompts tenants for a 1-5 star rating once a ticket is marked \"resolved,\" logging feedback directly for the landlord.\n- **Property Dashboard:** Landlords receive a visual summary including total open tickets, average ratings, and category breakdowns.\n- **Audit Trail:** Every status change and team note is timestamped and saved in the `lastUpdated` column in Google Sheets.\n\n---\n\n## 💼 Perfect For\n\n- **Property Managers:** Handling requests for multiple buildings without a manual call center.\n- **Landlords:** Keeping a transparent, timestamped record of all repairs and contractor performance.\n- **Facility Management Firms:** Coordinating various specialized technical teams across different sites.\n- **Co-living Spaces:** Providing a modern, mobile-first support experience for young professional tenants.\n\n---\n\n## 🔧 What You'll Need\n\n### Required Integrations\n\n- **WATI** – To receive tenant issues and send status updates to all parties.\n- **Google Sheets** – To act as your centralized ticket database and landlord dashboard.\n\n### Optional Customizations\n\n- **Photo Evidence:** Add a node to allow tenants to upload photos of the damage to be saved in a Google Drive folder.\n- **AI Summarization:** Integrate OpenAI to summarize long tenant descriptions for quicker team review.\n\n---\n\n## 🚀 Quick Start\n\n1. **Import Template** – Copy the JSON and import it into your n8n instance.\n2. **Set Credentials** – Connect your WATI and Google Sheets accounts.\n3. **Configure Teams** – Edit the `teamMap` in the Classify Issue node to include your contractors' actual WhatsApp numbers.\n4. **Configure Sheets** – Ensure your Google Sheet has a **Tickets** tab with headers:\n\n   `ticketId`, `phone`, `tenantName`, `issueText`, `category`, `priority`, `status`, `assignedTeam`, `teamPhone`, `createdAt`, `slaDueAt`, `rating`, `lastUpdated`, `notes`\n\n5. **Test the Loop** – Send `\"My sink is leaking\"` to your WATI number, then use a team number to reply `update &lt;ID&gt; in-progress`.\n\n---\n\n## 📈 Expected Results\n\n- Zero manual routing: Issues reach the right technician without administrative intervention.\n- Improved transparency: Tenants are never \"left in the dark\" about the status of their repairs.\n- Data-driven management: Identify recurring structural issues and underperforming teams via the dashboard.\n- Accountability: SLA breach alerts ensure no emergency ticket is forgotten.\n\n---\n\nReady to simplify your property management? Import this template and connect your Google Sheets to start tracking maintenance requests today!","workflow":{"meta":{"instanceId":"277842713620d9f5554de3b1518b865a152c8c4db680008bd8aec536fc18b4a8","templateCredsSetupCompleted":true},"nodes":[{"id":"9708565d-ec6a-4933-96a1-75998a3f62b7","name":"📋 Main Overview","type":"n8n-nodes-base.stickyNote","position":[0,-48],"parameters":{"width":580,"height":488,"content":"## 🏠 Tenant Support System – Maintenance Request Tracker\n\n**Tenant journey in 4 steps:**\n\n① Tenant WhatsApps an issue → ticket auto-created in Google Sheets\n② Ticket assigned to right maintenance team based on category\n③ Maintenance team updates status → tenant gets notified automatically\n④ Tenant rates the service → feedback logged for landlord dashboard\n\n**Two entry points:**\n- **WATI Trigger** → handles all tenant & maintenance replies\n- **Schedule Trigger** → daily SLA breach check & overdue alerts\n\n**Credentials:** WATI + Google Sheets OAuth2 only"},"typeVersion":1},{"id":"85564ffc-a450-4d3c-9466-1bbaaab885e4","name":"Sticky – Ticket Creation","type":"n8n-nodes-base.stickyNote","position":[1200,32],"parameters":{"color":7,"width":868,"height":616,"content":"### 🎫 Ticket Creation Path\nTenant texts any issue → **Classify Issue Code** uses keyword matching to auto-detect category (Plumbing / Electrical / Appliance / Security / Other) and priority (High / Medium / Low) → **Sheets Append** creates ticket with unique ID → Tenant gets ticket confirmation AND maintenance team is notified simultaneously."},"typeVersion":1},{"id":"9930a9c6-cf6e-42fa-85df-edce3612876e","name":"Sticky – Status Updates","type":"n8n-nodes-base.stickyNote","position":[1200,720],"parameters":{"color":7,"width":988,"height":488,"content":"### 🔁 Status Update Path\nMaintenance team replies with *update <ticket-id> <status> <note>* → **Parse Update Code** extracts fields → **Sheets Update** changes ticket status → Two WATI messages sent: ack to team + status card to tenant.\n\nValid statuses: `assigned` `in-progress` `resolved` `closed`"},"typeVersion":1},{"id":"e26e0843-9fb8-43cc-9802-6a893660c073","name":"Sticky – Feedback & Reports","type":"n8n-nodes-base.stickyNote","position":[1232,1248],"parameters":{"color":7,"width":908,"height":648,"content":"### ⭐ Feedback & Landlord Dashboard\nWhen ticket marked *resolved* → tenant receives a rating prompt → tenant replies *rate <ticket-id> <1-5>* → rating logged in Sheets.\n\nLandlord texts *dashboard* → gets full property overview: open tickets, SLA breaches, avg rating, category breakdown."},"typeVersion":1},{"id":"12a863c5-8bac-4a24-8a3f-4e79b8b6146b","name":"Sticky – SLA Monitor","type":"n8n-nodes-base.stickyNote","position":[2400,864],"parameters":{"color":2,"width":1160,"height":440,"content":"### 🚨 SLA Breach Monitor\n**Schedule Trigger** runs every morning at 8AM.\nReads all open tickets → flags any ticket older than the SLA threshold per priority:\n- 🔴 High → 4 hours\n- 🟡 Medium → 24 hours\n- 🟢 Low → 72 hours\n\nSends breach report to landlord AND pings each maintenance team for their overdue tickets."},"typeVersion":1},{"id":"e910d4bb-a1d5-4303-8cb4-ab6b9fc88ed3","name":"Master Router","type":"n8n-nodes-base.switch","position":[624,880],"parameters":{"rules":{"values":[{"outputKey":"Status Update","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"773beeb3-125d-4177-b48e-0c3676871761","operator":{"type":"string","operation":"startsWith"},"leftValue":"={{ $json.text }}","rightValue":"update "}]},"renameOutput":true},{"outputKey":"Rate Ticket","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"69f1d90f-a51f-4c90-9b8c-04932b1135c2","operator":{"type":"string","operation":"startsWith"},"leftValue":"={{ $json.text }}","rightValue":"rate "}]},"renameOutput":true},{"outputKey":"My Tickets","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"55521424-4afb-4241-b890-5d49cd250a0a","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.text.toLowerCase().trim() }}","rightValue":"mystatus"}]},"renameOutput":true},{"outputKey":"Dashboard","conditions":{"options":{"version":1,"leftValue":"","caseSensitive":true,"typeValidation":"strict"},"combinator":"and","conditions":[{"id":"a3569247-bdc7-49e6-b192-e79f6d8b73f1","operator":{"type":"string","operation":"equals"},"leftValue":"={{ $json.text.toLowerCase().trim() }}","rightValue":"dashboard"}]},"renameOutput":true}]},"options":{"fallbackOutput":"extra"}},"typeVersion":3},{"id":"fd7fcf42-47e0-4662-9771-f4c30ee4bb83","name":"Classify Issue & Create Ticket","type":"n8n-nodes-base.code","position":[1264,352],"parameters":{"jsCode":"// Classify Issue & Create Ticket\n// Auto-detects category and priority from the tenant's message\n\nconst text = ($json.text || '').toLowerCase().trim();\nconst phone = $json.waId || $json.from || 'unknown';\nconst tenantName = $json.senderName || 'Tenant';\nconst now = new Date();\n\nconst categories = {\n  Plumbing:   ['leak', 'pipe', 'water', 'tap', 'drain', 'toilet', 'flush', 'sink', 'shower', 'sewage'],\n  Electrical: ['light', 'power', 'electricity', 'switch', 'socket', 'outlet', 'fuse', 'wiring', 'fan', 'ac', 'air condition'],\n  Appliance:  ['fridge', 'washing machine', 'oven', 'microwave', 'dishwasher', 'heater', 'geyser', 'appliance'],\n  Security:   ['lock', 'door', 'window', 'cctv', 'camera', 'key', 'gate', 'security', 'break', 'stolen'],\n  Structural: ['wall', 'ceiling', 'floor', 'crack', 'roof', 'paint', 'damp', 'mold', 'mould', 'termite'],\n  Other:      []\n};\n\nlet detectedCategory = 'Other';\nfor (const [cat, keywords] of Object.entries(categories)) {\n  if (keywords.some(k => text.includes(k))) { detectedCategory = cat; break; }\n}\n\nconst highPriorityWords = ['emergency', 'urgent', 'flood', 'fire', 'gas leak', 'no power', 'burst', 'danger', 'break-in'];\nconst lowPriorityWords  = ['minor', 'small', 'whenever', 'no rush', 'paint', 'cosmetic'];\n\nlet priority = 'Medium';\nif (highPriorityWords.some(w => text.includes(w))) priority = 'High';\nelse if (lowPriorityWords.some(w => text.includes(w))) priority = 'Low';\n\nconst slaHours = { High: 4, Medium: 24, Low: 72 };\nconst slaDue = new Date(now.getTime() + slaHours[priority] * 60 * 60 * 1000);\n\nconst datePart = now.toISOString().split('T')[0].replace(/-/g, '');\nconst randPart = Math.random().toString(36).substring(2, 6).toUpperCase();\nconst ticketId = `TKT-${datePart}-${randPart}`;\n\nconst teamMap = {\n  Plumbing:   { name: 'Plumbing Team',   phone: 917727827113 },\n  Electrical: { name: 'Electrical Team', phone: '917024935915' },\n  Appliance:  { name: 'Appliance Team',  phone: 'APPLIANCE_TEAM_PHONE' },\n  Security:   { name: 'Security Team',   phone: 'SECURITY_TEAM_PHONE' },\n  Structural: { name: 'Structural Team', phone: 'STRUCTURAL_TEAM_PHONE' },\n  Other:      { name: 'General Team',    phone: 'GENERAL_TEAM_PHONE' }\n};\n\nconst assignedTeam = teamMap[detectedCategory];\nconst priorityEmoji = { High: '\\u{1F534}', Medium: '\\u{1F7E1}', Low: '\\u{1F7E2}' }[priority];\n\nconst tenantMsg = [\n  `\\uD83C\\uDFAB *Ticket Created Successfully!*`,\n  '',\n  `\\uD83D\\uDCCB *Ticket ID:* \\`${ticketId}\\``,\n  `\\uD83C\\uDFF7\\uFE0F *Category:* ${detectedCategory}`,\n  `${priorityEmoji} *Priority:* ${priority}`,\n  `\\uD83D\\uDCDD *Issue:* ${$json.text}`,\n  `\\uD83D\\uDD50 *Logged At:* ${now.toLocaleString('en-IN')}`,\n  `\\u23F0 *Expected Resolution:* Within ${slaHours[priority]} hours`,\n  '',\n  'Our team has been notified and will be in touch shortly.',\n  `Save your Ticket ID *${ticketId}* for future reference.`,\n  '',\n  'Reply *mystatus* anytime to check your open tickets.'\n].join('\\n');\n\nconst teamMsg = [\n  `\\uD83D\\uDD14 *New Maintenance Ticket*`,\n  '',\n  `\\uD83C\\uDFAB *Ticket ID:* ${ticketId}`,\n  `${priorityEmoji} *Priority:* ${priority}`,\n  `\\uD83C\\uDFF7\\uFE0F *Category:* ${detectedCategory}`,\n  `\\uD83D\\uDC64 *Tenant:* ${tenantName}`,\n  `\\uD83D\\uDCDE *Phone:* ${phone}`,\n  `\\uD83D\\uDCDD *Issue:* ${$json.text}`,\n  `\\u23F0 *SLA Deadline:* ${slaDue.toLocaleString('en-IN')}`,\n  '',\n  'To update status, reply:',\n  `*update ${ticketId} in-progress Your note here*`\n].join('\\n');\n\nreturn { json: {\n  ticketId, phone, tenantName,\n  issueText: $json.text,\n  category: detectedCategory,\n  priority,\n  status: 'Open',\n  assignedTeam: assignedTeam.name,\n  teamPhone: assignedTeam.phone,\n  createdAt: now.toISOString(),\n  slaDueAt: slaDue.toISOString(),\n  rating: '',\n  tenantMsg,\n  teamMsg\n}};"},"typeVersion":2},{"id":"837321fe-bcd5-43bf-9c2b-56caf5169e94","name":"Google Sheets – Create Ticket","type":"n8n-nodes-base.googleSheets","position":[1504,352],"parameters":{"columns":{"value":{"phone":"={{ $json.phone }}","status":"Open","category":"={{ $json.category }}","priority":"={{ $json.priority }}","slaDueAt":"={{ $json.slaDueAt }}","ticketId":"={{ $json.ticketId }}","createdAt":"={{ $json.createdAt }}","issueText":"={{ $json.issueText }}","teamPhone":"={{ $json.teamPhone }}","tenantName":"={{ $json.tenantName }}","lastUpdated":"={{ $json.createdAt }}","assignedTeam":"={{ $json.assignedTeam }}"},"schema":[{"id":"ticketId","type":"string","display":true,"required":false,"displayName":"ticketId","defaultMatch":false,"canBeUsedToMatch":true},{"id":"phone","type":"string","display":true,"required":false,"displayName":"phone","defaultMatch":false,"canBeUsedToMatch":true},{"id":"tenantName","type":"string","display":true,"required":false,"displayName":"tenantName","defaultMatch":false,"canBeUsedToMatch":true},{"id":"issueText","type":"string","display":true,"required":false,"displayName":"issueText","defaultMatch":false,"canBeUsedToMatch":true},{"id":"category","type":"string","display":true,"required":false,"displayName":"category","defaultMatch":false,"canBeUsedToMatch":true},{"id":"priority","type":"string","display":true,"required":false,"displayName":"priority","defaultMatch":false,"canBeUsedToMatch":true},{"id":"status","type":"string","display":true,"required":false,"displayName":"status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"assignedTeam","type":"string","display":true,"required":false,"displayName":"assignedTeam","defaultMatch":false,"canBeUsedToMatch":true},{"id":"teamPhone","type":"string","display":true,"required":false,"displayName":"teamPhone","defaultMatch":false,"canBeUsedToMatch":true},{"id":"createdAt","type":"string","display":true,"required":false,"displayName":"createdAt","defaultMatch":false,"canBeUsedToMatch":true},{"id":"slaDueAt","type":"string","display":true,"required":false,"displayName":"slaDueAt","defaultMatch":false,"canBeUsedToMatch":true},{"id":"rating","type":"string","display":true,"required":false,"displayName":"rating","defaultMatch":false,"canBeUsedToMatch":true},{"id":"lastUpdated","type":"string","display":true,"required":false,"displayName":"lastUpdated","defaultMatch":false,"canBeUsedToMatch":true},{"id":"notes","type":"string","display":true,"removed":false,"required":false,"displayName":"notes","defaultMatch":false,"canBeUsedToMatch":true}],"mappingMode":"defineBelow","matchingColumns":[],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"append","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit#gid=0","cachedResultName":"Tickets"},"documentId":{"__rl":true,"mode":"list","value":"1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit?usp=drivesdk","cachedResultName":"Untitled spreadsheet"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"33807f78-b11b-4ef0-9878-4b98ce3d8c0d","name":"WATI – Confirm to Tenant","type":"n8n-nodes-wati.wati","position":[1712,224],"parameters":{"target":"={{ $('Classify Issue & Create Ticket').item.json.phone }}","messageText":"={{ $('Classify Issue & Create Ticket').item.json.tenantMsg }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"0da128fb-8b49-464b-a600-a57f9f0bbfa5","name":"WATI – Notify Maintenance Team","type":"n8n-nodes-wati.wati","position":[1712,416],"parameters":{"target":"=917024935915","messageText":"={{ $('Classify Issue & Create Ticket').item.json.teamMsg }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"ddd1b7ad-9af2-4299-b79e-d1d1341299dd","name":"Google Sheets – Read Tickets (Update)","type":"n8n-nodes-base.googleSheets","position":[1232,928],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit#gid=0","cachedResultName":"Tickets"},"documentId":{"__rl":true,"mode":"list","value":"1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit?usp=drivesdk","cachedResultName":"Untitled spreadsheet"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"a4975e18-e634-4293-81a3-e7facc774ba6","name":"Parse Status Update","type":"n8n-nodes-base.code","position":[1456,928],"parameters":{"jsCode":"// Parse Status Update from Maintenance Team\n// Format: 'update TKT-20240225-ABCD in-progress Technician arriving at 3PM'\n\nconst text = ($('Wati Trigger').item.json.text || '').trim();\nconst updaterPhone = $('Wati Trigger').item.json.waId || $('Wati Trigger').item.json.from;\n\nconst parts = text.replace(/^update\\s+/i, '').split(' ');\nconst ticketId = (parts[0] || '').toUpperCase();\nconst newStatus = (parts[1] || '').toLowerCase();\nconst note = parts.slice(2).join(' ') || '';\n\nconst validStatuses = ['assigned', 'in-progress', 'resolved', 'closed'];\nif (!ticketId || !validStatuses.includes(newStatus)) {\n  return [{ json: {\n    updaterPhone,\n    errorMessage: `\\u26A0\\uFE0F Invalid format. Use:\\n*update <TICKET-ID> <status> <note>*\\n\\nValid statuses: ${validStatuses.join(', ')}\\n\\nExample:\\n*update TKT-20240225-ABCD in-progress Technician on the way*`,\n    hasError: true\n  }}];\n}\n\nconst allRows = $input.all();\nconst ticketRow = allRows.find(r => (r.json.ticketId || '').toUpperCase() === ticketId);\n\nif (!ticketRow) {\n  return [{ json: {\n    updaterPhone,\n    errorMessage: `\\u274C Ticket *${ticketId}* not found. Please check the ticket ID.`,\n    hasError: true\n  }}];\n}\n\nconst ticket = ticketRow.json;\nconst now = new Date();\nconst priorityEmoji = { High: '\\uD83D\\uDD34', Medium: '\\uD83D\\uDFE1', Low: '\\uD83D\\uDFE2' }[ticket.priority] || '\\u26AA';\nconst statusEmoji   = { assigned: '\\uD83D\\uDC77', 'in-progress': '\\uD83D\\uDD27', resolved: '\\u2705', closed: '\\uD83D\\uDD12' }[newStatus] || '\\uD83D\\uDCCB';\n\nconst ackMessage = [\n  `${statusEmoji} *Ticket Updated*`,\n  `\\uD83C\\uDFAB ${ticketId} \\u2192 *${newStatus.toUpperCase()}*`,\n  note ? `\\uD83D\\uDCDD Note: ${note}` : '',\n  `\\uD83D\\uDD50 Updated at ${now.toLocaleTimeString('en-IN', {hour:'2-digit', minute:'2-digit'})}`\n].filter(Boolean).join('\\n');\n\nconst tenantLines = [\n  `${statusEmoji} *Ticket Update \\u2013 ${ticketId}*`,\n  '',\n  'Your maintenance request has been updated:',\n  '',\n  `\\uD83D\\uDCCB *Status:* ${newStatus.toUpperCase()}`,\n  `\\uD83C\\uDFF7\\uFE0F *Category:* ${ticket.category}`,\n  `${priorityEmoji} *Priority:* ${ticket.priority}`,\n  note ? `\\uD83D\\uDCDD *Note from team:* ${note}` : '',\n  `\\uD83D\\uDD50 *Updated:* ${now.toLocaleString('en-IN')}`\n].filter(Boolean);\n\nif (newStatus === 'resolved') {\n  tenantLines.push('');\n  tenantLines.push('\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501');\n  tenantLines.push('\\u2B50 *How did we do?*');\n  tenantLines.push(`Reply: *rate ${ticketId} <1-5>*`);\n  tenantLines.push(`Example: *rate ${ticketId} 5*`);\n} else {\n  tenantLines.push('');\n  tenantLines.push('Reply *mystatus* to see all your tickets.');\n}\n\nreturn [{ json: {\n  ticketId,\n  tenantPhone: ticket.phone,\n  updaterPhone,\n  newStatus, note,\n  updatedAt: now.toISOString(),\n  ackMessage,\n  tenantMessage: tenantLines.join('\\n'),\n  isResolved: newStatus === 'resolved',\n  hasError: false\n}}];"},"typeVersion":2},{"id":"7dd2214e-71a4-4e8b-a94f-ea018d229bc6","name":"Google Sheets – Update Ticket Status","type":"n8n-nodes-base.googleSheets","position":[1696,928],"parameters":{"columns":{"value":{"notes":"={{ $node[\"Parse Status Update\"].json.note || \"\" }}","status":"={{ $node[\"Google Sheets – Read Tickets (Update)\"].json.status }}","ticketId":"={{ $items(\"Google Sheets – Read Tickets (Update)\")[0].json.ticketId }}","row_number":0,"lastUpdated":"={{ $node[\"Google Sheets – Read Tickets (Update)\"].json.lastUpdated }}"},"schema":[{"id":"ticketId","type":"string","display":true,"required":false,"displayName":"ticketId","defaultMatch":false,"canBeUsedToMatch":true},{"id":"phone","type":"string","display":true,"removed":true,"required":false,"displayName":"phone","defaultMatch":false,"canBeUsedToMatch":true},{"id":"tenantName","type":"string","display":true,"removed":true,"required":false,"displayName":"tenantName","defaultMatch":false,"canBeUsedToMatch":true},{"id":"issueText","type":"string","display":true,"removed":true,"required":false,"displayName":"issueText","defaultMatch":false,"canBeUsedToMatch":true},{"id":"category","type":"string","display":true,"removed":true,"required":false,"displayName":"category","defaultMatch":false,"canBeUsedToMatch":true},{"id":"priority","type":"string","display":true,"removed":true,"required":false,"displayName":"priority","defaultMatch":false,"canBeUsedToMatch":true},{"id":"status","type":"string","display":true,"required":false,"displayName":"status","defaultMatch":false,"canBeUsedToMatch":true},{"id":"assignedTeam","type":"string","display":true,"removed":true,"required":false,"displayName":"assignedTeam","defaultMatch":false,"canBeUsedToMatch":true},{"id":"teamPhone","type":"string","display":true,"removed":true,"required":false,"displayName":"teamPhone","defaultMatch":false,"canBeUsedToMatch":true},{"id":"createdAt","type":"string","display":true,"removed":true,"required":false,"displayName":"createdAt","defaultMatch":false,"canBeUsedToMatch":true},{"id":"slaDueAt","type":"string","display":true,"removed":true,"required":false,"displayName":"slaDueAt","defaultMatch":false,"canBeUsedToMatch":true},{"id":"rating","type":"string","display":true,"removed":true,"required":false,"displayName":"rating","defaultMatch":false,"canBeUsedToMatch":true},{"id":"lastUpdated","type":"string","display":true,"required":false,"displayName":"lastUpdated","defaultMatch":false,"canBeUsedToMatch":true},{"id":"notes","type":"string","display":true,"required":false,"displayName":"notes","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":["ticketId"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"update","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit#gid=0","cachedResultName":"Tickets"},"documentId":{"__rl":true,"mode":"list","value":"1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit?usp=drivesdk","cachedResultName":"Untitled spreadsheet"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"85ff89e9-cdda-4ae4-be5c-f328124b919a","name":"WATI – Acknowledge Team","type":"n8n-nodes-wati.wati","position":[1920,832],"parameters":{"target":"={{ $('Parse Status Update').item.json.updaterPhone }}","messageText":"=ji"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"45bcbe7a-80b6-46d8-9b76-5663d4f0c52f","name":"WATI – Notify Tenant of Update","type":"n8n-nodes-wati.wati","position":[1920,1008],"parameters":{"target":"={{ $items(\"Wati Trigger\")[0].json.waId }}","messageText":"={{ $('Parse Status Update').item.json.errorMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"13bd3e03-fd28-41c2-bfe3-f1fe5251b0d1","name":"Parse Rating","type":"n8n-nodes-base.code","position":[1312,1376],"parameters":{"jsCode":"// Parse & Log Rating\n// Format: 'rate TKT-20240225-ABCD 5'\n\nconst text = ($('Wati Trigger').item.json.text || '').trim();\nconst phone = $('Wati Trigger').item.json.waId || $('Wati Trigger').item.json.from;\nconst tenantName = $('Wati Trigger').item.json.senderName || 'Tenant';\n\nconst parts = text.replace(/^rate\\s+/i, '').split(' ');\nconst ticketId = (parts[0] || '').toUpperCase();\nconst rating   = parseInt(parts[1] || '0');\n\nif (!ticketId || isNaN(rating) || rating < 1 || rating > 5) {\n  return [{ json: {\n    phone,\n    ratingMessage: `\\u26A0\\uFE0F Invalid format. Use:\\n*rate <TICKET-ID> <1-5>*\\n\\nExample: *rate TKT-20240225-ABCD 5*`,\n    hasError: true\n  }}];\n}\n\nconst stars = '\\u2B50'.repeat(rating) + '\\u2606'.repeat(5 - rating);\nconst feedbackMap = { 5: 'Excellent!', 4: 'Good!', 3: 'Average', 2: 'Below expectations', 1: 'Poor \\u2013 we will improve' };\n\nconst ratingLines = [\n  `${stars} *Thank you for your feedback!*`,\n  '',\n  `You rated ticket *${ticketId}*: *${rating}/5 \\u2013 ${feedbackMap[rating]}*`,\n  '',\n  'Your feedback helps us improve our service.',\n  'For any new issues, just send us a message! \\uD83C\\uDFE0'\n];\n\nreturn [{ json: {\n  phone, ticketId, rating,\n  ratingMessage: ratingLines.join('\\n'),\n  ratedAt: new Date().toISOString(),\n  hasError: false\n}}];"},"typeVersion":2},{"id":"9cb7e77f-8db2-4948-87e3-43020648b909","name":"Google Sheets – Save Rating","type":"n8n-nodes-base.googleSheets","position":[1552,1376],"parameters":{"columns":{"value":{"rating":"={{ $json.rating }}","ticketId":0,"lastUpdated":"={{ $json.ratedAt }}"},"schema":[{"id":"ticketId","type":"number","display":true,"required":true,"displayName":"ticketId","defaultMatch":true,"canBeUsedToMatch":true},{"id":"rating","type":"number","display":true,"required":false,"displayName":"rating","defaultMatch":false,"canBeUsedToMatch":false},{"id":"lastUpdated","type":"string","display":true,"required":false,"displayName":"lastUpdated","defaultMatch":false,"canBeUsedToMatch":false}],"mappingMode":"defineBelow","matchingColumns":["ticketId"],"attemptToConvertTypes":false,"convertFieldsToString":false},"options":{},"operation":"update","sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit#gid=0","cachedResultName":"Tickets"},"documentId":{"__rl":true,"mode":"list","value":"1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit?usp=drivesdk","cachedResultName":"Untitled spreadsheet"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"75f17e80-623e-477d-8e36-ecc6db4f2cdc","name":"WATI – Send Rating Thanks","type":"n8n-nodes-wati.wati","position":[1840,1376],"parameters":{"target":"={{ $('Parse Rating').item.json.phone }}","messageText":"={{ $('Parse Rating').item.json.ratingMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"81203671-ef43-4218-89ca-bd91ad5c7f14","name":"Google Sheets – Read My Tickets","type":"n8n-nodes-base.googleSheets","position":[1312,1536],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit#gid=0","cachedResultName":"Tickets"},"documentId":{"__rl":true,"mode":"list","value":"1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit?usp=drivesdk","cachedResultName":"Untitled spreadsheet"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"dee9ba78-1d4b-4bfd-87c0-bd0059d292b0","name":"Build My Tickets View","type":"n8n-nodes-base.code","position":[1552,1536],"parameters":{"jsCode":"// Build My Tickets Status Card\n\nconst phone = $('Wati Trigger').item.json.waId || $('Wati Trigger').item.json.from;\nconst tenantName = $('Wati Trigger').item.json.senderName || 'Tenant';\nconst allRows = $input.all();\n\nconst myTickets = allRows\n  .filter(r => r.json.phone === phone)\n  .sort((a, b) => new Date(b.json.createdAt) - new Date(a.json.createdAt));\n\nif (myTickets.length === 0) {\n  return [{ json: {\n    phone,\n    myTicketsMessage: `\\uD83D\\uDCCB *No tickets found, ${tenantName}!*\\n\\nTo report a maintenance issue, just describe your problem in a message.\\nExample: *The kitchen tap is leaking*`\n  }}];\n}\n\nconst open   = myTickets.filter(r => !['resolved','closed'].includes((r.json.status||'').toLowerCase()));\nconst closed = myTickets.filter(r =>  ['resolved','closed'].includes((r.json.status||'').toLowerCase())).slice(0, 3);\n\nconst statusEmoji = { open: '\\uD83D\\uDFE0', assigned: '\\uD83D\\uDC77', 'in-progress': '\\uD83D\\uDD27', resolved: '\\u2705', closed: '\\uD83D\\uDD12' };\nconst priorityEmoji = { High: '\\uD83D\\uDD34', Medium: '\\uD83D\\uDFE1', Low: '\\uD83D\\uDFE2' };\n\nconst lines = [`\\uD83D\\uDCCB *My Maintenance Tickets*`, `\\uD83D\\uDC64 *${tenantName}*`, ''];\n\nif (open.length > 0) {\n  lines.push(`*Open Tickets (${open.length}):*`);\n  for (const r of open) {\n    const se = statusEmoji[(r.json.status||'open').toLowerCase()] || '\\uD83D\\uDCCB';\n    const pe = priorityEmoji[r.json.priority] || '\\u26AA';\n    let created = r.json.createdAt;\n    try { created = new Date(r.json.createdAt).toLocaleDateString('en-IN', { day:'numeric', month:'short' }); } catch(e) {}\n    lines.push(`${se} *${r.json.ticketId}* ${pe} ${r.json.priority}`);\n    lines.push(`   ${r.json.category} | ${r.json.status || 'Open'}`);\n    lines.push(`   \\uD83D\\uDCC5 Raised: ${created}`);\n    if (r.json.notes) lines.push(`   \\uD83D\\uDCDD ${r.json.notes}`);\n    lines.push('');\n  }\n}\n\nif (closed.length > 0) {\n  lines.push(`*Recently Closed (${closed.length}):*`);\n  for (const r of closed) {\n    const rating = r.json.rating ? `\\u2B50 ${r.json.rating}/5` : 'Not rated';\n    lines.push(`\\u2705 ${r.json.ticketId} \\u2013 ${r.json.category} | ${rating}`);\n  }\n  lines.push('');\n}\n\nlines.push('\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501\\u2501');\nlines.push('To report a new issue, just describe it in a message.');\n\nreturn [{ json: { phone, myTicketsMessage: lines.join('\\n') } }];"},"typeVersion":2},{"id":"aea2f273-5455-4895-801d-14156d4cea68","name":"WATI – Send My Tickets","type":"n8n-nodes-wati.wati","position":[1824,1536],"parameters":{"target":"={{ $('Build My Tickets View').item.json.phone }}","messageText":"={{ $('Build My Tickets View').item.json.myTicketsMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"646cd7f6-7320-49fe-b260-48d760ed0986","name":"Google Sheets – Read All Tickets (Dashboard)","type":"n8n-nodes-base.googleSheets","position":[1312,1696],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit#gid=0","cachedResultName":"Tickets"},"documentId":{"__rl":true,"mode":"list","value":"1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit?usp=drivesdk","cachedResultName":"Untitled spreadsheet"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"11af040b-24f2-45ff-83f1-79340bfd0fec","name":"Build Landlord Dashboard","type":"n8n-nodes-base.code","position":[1552,1696],"parameters":{"jsCode":"// Build Landlord Dashboard\n\nconst allRows = $input.all();\nconst now = new Date();\nconst requesterPhone = $('Wati Trigger').item.json.waId || $('Wati Trigger').item.json.from;\n\nconst allTickets = allRows.map(r => r.json);\nconst openTickets = allTickets.filter(t => !['resolved','closed'].includes((t.status||'').toLowerCase()));\nconst resolvedTickets = allTickets.filter(t => ['resolved','closed'].includes((t.status||'').toLowerCase()));\n\nconst breached = openTickets.filter(t => { const due = new Date(t.slaDueAt || 0); return due < now; });\n\nconst catCount = {};\nfor (const t of openTickets) { const c = t.category || 'Other'; catCount[c] = (catCount[c] || 0) + 1; }\n\nconst rated = allTickets.filter(t => t.rating && parseFloat(t.rating) > 0);\nconst avgRating = rated.length > 0 ? (rated.reduce((s, t) => s + parseFloat(t.rating), 0) / rated.length).toFixed(1) : 'N/A';\n\nconst highOpen = openTickets.filter(t => t.priority === 'High').length;\nconst medOpen  = openTickets.filter(t => t.priority === 'Medium').length;\nconst lowOpen  = openTickets.filter(t => t.priority === 'Low').length;\n\nconst recent5 = openTickets.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)).slice(0, 5);\n\nconst lines = [\n  `\\uD83C\\uDFE0 *Property Management Dashboard*`,\n  `\\uD83D\\uDCC5 ${now.toLocaleDateString('en-IN', { weekday: 'long', day: 'numeric', month: 'long' })}`,\n  '',\n  `\\u2501\\u2501 *Ticket Overview* \\u2501\\u2501`,\n  `\\uD83D\\uDCC2 Total Open:     *${openTickets.length}*`,\n  `\\u2705 Resolved:       *${resolvedTickets.length}*`,\n  `\\uD83D\\uDEA8 SLA Breaches:   *${breached.length}*`,\n  `\\u2B50 Avg Rating:     *${avgRating}/5*`,\n  '',\n  `\\u2501\\u2501 *By Priority* \\u2501\\u2501`,\n  `\\uD83D\\uDD34 High: ${highOpen}  |  \\uD83D\\uDFE1 Medium: ${medOpen}  |  \\uD83D\\uDFE2 Low: ${lowOpen}`,\n  '',\n  `\\u2501\\u2501 *By Category* \\u2501\\u2501`,\n  ...Object.entries(catCount).map(([c, n]) => `  ${c}: ${n}`)\n];\n\nif (breached.length > 0) {\n  lines.push('');\n  lines.push(`\\u2501\\u2501 \\uD83D\\uDEA8 *SLA Breaches* \\u2501\\u2501`);\n  for (const t of breached.slice(0, 5)) {\n    const pe = { High: '\\uD83D\\uDD34', Medium: '\\uD83D\\uDFE1', Low: '\\uD83D\\uDFE2' }[t.priority] || '\\u26AA';\n    lines.push(`${pe} *${t.ticketId}* \\u2013 ${t.category}`);\n    lines.push(`   Tenant: ${t.tenantName} | Status: ${t.status}`);\n  }\n}\n\nif (recent5.length > 0) {\n  lines.push('');\n  lines.push('\\u2501\\u2501 *Recent Open Tickets* \\u2501\\u2501');\n  for (const t of recent5) {\n    const pe = { High: '\\uD83D\\uDD34', Medium: '\\uD83D\\uDFE1', Low: '\\uD83D\\uDFE2' }[t.priority] || '\\u26AA';\n    let created = t.createdAt;\n    try { created = new Date(t.createdAt).toLocaleDateString('en-IN', { day:'numeric', month:'short' }); } catch(e) {}\n    lines.push(`${pe} *${t.ticketId}* \\u2013 ${t.category} (${t.status})`);\n    lines.push(`   ${t.tenantName} | ${created}`);\n  }\n}\n\nreturn [{ json: { phone: requesterPhone, dashboardMessage: lines.join('\\n') } }];"},"typeVersion":2},{"id":"5a791ebb-f34c-4391-b8fd-faedd270d24b","name":"WATI – Send Dashboard","type":"n8n-nodes-wati.wati","position":[1792,1696],"parameters":{"target":"={{ $('Build Landlord Dashboard').item.json.phone }}","messageText":"={{ $('Build Landlord Dashboard').item.json.dashboardMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"9f7fc13e-880b-499a-8aee-340878112a99","name":"Schedule Trigger – Daily SLA Check 8AM","type":"n8n-nodes-base.scheduleTrigger","position":[2464,1088],"parameters":{"rule":{"interval":[{"field":"cronExpression","expression":"0 8 * * *"}]}},"typeVersion":1.2},{"id":"dfb02e9b-712e-4911-b7ec-611f09aae8f3","name":"Google Sheets – Read Tickets (SLA)","type":"n8n-nodes-base.googleSheets","position":[2672,1088],"parameters":{"options":{},"sheetName":{"__rl":true,"mode":"list","value":"gid=0","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit#gid=0","cachedResultName":"Tickets"},"documentId":{"__rl":true,"mode":"list","value":"1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc","cachedResultUrl":"https://docs.google.com/spreadsheets/d/1F7rsFG0c-ORJPf9t0hb2nwSMkXqxtyAp_5IyIV4rkdc/edit?usp=drivesdk","cachedResultName":"Untitled spreadsheet"}},"credentials":{"googleSheetsOAuth2Api":{"id":"Kz2DdSp11rxqwlFt","name":"Google Sheets account - Deepanshi"}},"typeVersion":4.5},{"id":"9af61a1c-e535-4209-ab00-f5369dbf7523","name":"Check SLA Breaches","type":"n8n-nodes-base.code","position":[2912,1088],"parameters":{"jsCode":"// Daily SLA Breach Check\nconst allRows = $input.all();\nconst now = new Date();\n\nconst openTickets = allRows.map(r => r.json).filter(t => !['resolved','closed'].includes((t.status||'').toLowerCase()));\n\nif (openTickets.length === 0) {\n  return [{ json: { message: 'No open tickets \\u2013 all clear!', hasBreaches: false } }];\n}\n\nconst breached = [];\nconst dueSoon  = [];\nconst onTrack  = [];\n\nfor (const t of openTickets) {\n  const due = new Date(t.slaDueAt || 0);\n  const hoursLeft = (due - now) / (1000 * 60 * 60);\n  if (hoursLeft < 0)       breached.push({ ...t, hoursOverdue: Math.abs(hoursLeft).toFixed(1) });\n  else if (hoursLeft <= 4) dueSoon.push({ ...t, hoursLeft: hoursLeft.toFixed(1) });\n  else                     onTrack.push(t);\n}\n\nconst pe = { High: '\\uD83D\\uDD34', Medium: '\\uD83D\\uDFE1', Low: '\\uD83D\\uDFE2' };\n\nconst landlordLines = [\n  `\\uD83D\\uDCCA *Daily SLA Report \\u2013 ${now.toLocaleDateString('en-IN')}*`,\n  '',\n  `\\uD83D\\uDCC2 Open: ${openTickets.length} | \\uD83D\\uDEA8 Breached: ${breached.length} | \\u26A0\\uFE0F Due Soon: ${dueSoon.length} | \\u2705 On Track: ${onTrack.length}`,\n  ''\n];\n\nif (breached.length > 0) {\n  landlordLines.push('\\uD83D\\uDEA8 *SLA BREACHED \\u2013 Immediate Action Required:*');\n  for (const t of breached) {\n    landlordLines.push(`${pe[t.priority]||'\\u26AA'} *${t.ticketId}* \\u2013 ${t.category} (${t.hoursOverdue}h overdue)`);\n    landlordLines.push(`   \\uD83D\\uDC64 ${t.tenantName} | Team: ${t.assignedTeam} | Status: ${t.status}`);\n  }\n  landlordLines.push('');\n}\n\nif (dueSoon.length > 0) {\n  landlordLines.push('\\u26A0\\uFE0F *Due Within 4 Hours:*');\n  for (const t of dueSoon) {\n    landlordLines.push(`${pe[t.priority]||'\\u26AA'} *${t.ticketId}* \\u2013 ${t.category} (${t.hoursLeft}h left)`);\n    landlordLines.push(`   \\uD83D\\uDC64 ${t.tenantName} | Team: ${t.assignedTeam}`);\n  }\n}\n\nconst teamAlerts = breached.map(t => ({\n  teamPhone: t.teamPhone,\n  teamMessage: [\n    `\\uD83D\\uDEA8 *SLA BREACH ALERT*`,\n    `\\uD83C\\uDFAB Ticket *${t.ticketId}* is *${t.hoursOverdue} hours overdue!*`,\n    `\\uD83C\\uDFF7\\uFE0F ${t.category} | ${pe[t.priority]||'\\u26AA'} ${t.priority}`,\n    `\\uD83D\\uDC64 Tenant: ${t.tenantName} (${t.phone})`,\n    `\\uD83D\\uDCDD Issue: ${t.issueText}`,\n    '',\n    'Please resolve or update immediately!',\n    `*update ${t.ticketId} in-progress <your note>*`\n  ].join('\\n')\n}));\n\nreturn [{ json: {\n  landlordPhone: 'LANDLORD_WHATSAPP_NUMBER',\n  landlordReport: landlordLines.join('\\n'),\n  teamAlerts,\n  hasBreaches: breached.length > 0\n}}];"},"typeVersion":2},{"id":"63d80507-51ba-456e-bc72-e8458181785a","name":"WATI – Send SLA Report to Landlord","type":"n8n-nodes-wati.wati","position":[3248,944],"parameters":{"target":"=LANDLORD_WHATSAPP_NUMBER","messageText":"={{ $('Check SLA Breaches').item.json.landlordReport }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"027ffd3b-2912-4f76-aaf1-187df092dcf3","name":"Split Team Alerts","type":"n8n-nodes-base.code","position":[3152,1152],"parameters":{"jsCode":"// Send breach alerts to each maintenance team\nconst alerts = $('Check SLA Breaches').item.json.teamAlerts || [];\nif (alerts.length === 0) return [{ json: { message: 'No team alerts to send' } }];\nreturn alerts.map(a => ({ json: a }));"},"typeVersion":2},{"id":"3cd2bc71-e6e8-4923-9f2e-f8d6f985c477","name":"WATI – Alert Teams of SLA Breach","type":"n8n-nodes-wati.wati","position":[3392,1152],"parameters":{"target":"={{ $json.teamPhone }}","messageText":"={{ $json.teamMessage }}"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1},{"id":"7b78a766-e12b-46dc-a871-02d7bbe65c33","name":"Wati Trigger","type":"n8n-nodes-wati.watiTrigger","position":[432,928],"webhookId":"ceb8d7d4-0ea8-4491-9bec-89f94a3feb35","parameters":{"event":"messageReceived"},"credentials":{"watiApi":{"id":"LeAm3lDk4hC1D2Qy","name":"wati - templates"}},"typeVersion":1,"alwaysOutputData":true}],"pinData":{"Wati Trigger":[{"id":"699eec310169e4e6f8a4077d","data":null,"text":"rate","type":"text","waId":"917024935915","owner":false,"created":"2026-02-25T12:33:53.5760245Z","sourceId":null,"ticketId":"699d5bece335b461449f4b91","avatarUrl":null,"eventType":"message","forwarded":false,"listReply":null,"sourceUrl":null,"timestamp":"1772022832","assignedId":null,"senderName":"Deepanshi Singhal","sourceType":7,"buttonReply":null,"operatorName":null,"statusString":"SENT","operatorEmail":null,"conversationId":"699d5becb12153808a3300f0","messageContact":null,"replyContextId":"","whatsappMessageId":"wamid.HBgMOTE3MDI0OTM1OTE1FQIAEhggQUNGRUFBNjg1NzY5MEQ5MTE3REMxOUM2OUQwMUY4RjIA","frequentlyForwarded":false,"interactiveButtonReply":null}]},"connections":{"Parse Rating":{"main":[[{"node":"Google Sheets – Save Rating","type":"main","index":0}]]},"Wati Trigger":{"main":[[{"node":"Master Router","type":"main","index":0}]]},"Master Router":{"main":[[{"node":"Google Sheets – Read Tickets (Update)","type":"main","index":0}],[{"node":"Parse Rating","type":"main","index":0}],[{"node":"Google Sheets – Read My Tickets","type":"main","index":0}],[{"node":"Google Sheets – Read All Tickets (Dashboard)","type":"main","index":0}],[{"node":"Classify Issue & Create Ticket","type":"main","index":0}]]},"Split Team Alerts":{"main":[[{"node":"WATI – Alert Teams of SLA Breach","type":"main","index":0}]]},"Check SLA Breaches":{"main":[[{"node":"WATI – Send SLA Report to Landlord","type":"main","index":0},{"node":"Split Team Alerts","type":"main","index":0}]]},"Parse Status Update":{"main":[[{"node":"Google Sheets – Update Ticket Status","type":"main","index":0}]]},"Build My Tickets View":{"main":[[{"node":"WATI – Send My Tickets","type":"main","index":0}]]},"Build Landlord Dashboard":{"main":[[{"node":"WATI – Send Dashboard","type":"main","index":0}]]},"Google Sheets – Save Rating":{"main":[[{"node":"WATI – Send Rating Thanks","type":"main","index":0}]]},"Classify Issue & Create Ticket":{"main":[[{"node":"Google Sheets – Create Ticket","type":"main","index":0}]]},"Google Sheets – Create Ticket":{"main":[[{"node":"WATI – Confirm to Tenant","type":"main","index":0},{"node":"WATI – Notify Maintenance Team","type":"main","index":0}]]},"Google Sheets – Read My Tickets":{"main":[[{"node":"Build My Tickets View","type":"main","index":0}]]},"Google Sheets – Read Tickets (SLA)":{"main":[[{"node":"Check SLA Breaches","type":"main","index":0}]]},"Google Sheets – Update Ticket Status":{"main":[[{"node":"WATI – Acknowledge Team","type":"main","index":0},{"node":"WATI – Notify Tenant of Update","type":"main","index":0}]]},"Google Sheets – Read Tickets (Update)":{"main":[[{"node":"Parse Status Update","type":"main","index":0}]]},"Schedule Trigger – Daily SLA Check 8AM":{"main":[[{"node":"Google Sheets – Read Tickets (SLA)","type":"main","index":0}]]},"Google Sheets – Read All Tickets (Dashboard)":{"main":[[{"node":"Build Landlord Dashboard","type":"main","index":0}]]}}},"lastUpdatedBy":1,"workflowInfo":{"nodeCount":31,"nodeTypes":{"n8n-nodes-base.code":{"count":7},"n8n-nodes-wati.wati":{"count":9},"n8n-nodes-base.switch":{"count":1},"n8n-nodes-base.stickyNote":{"count":5},"n8n-nodes-wati.watiTrigger":{"count":1},"n8n-nodes-base.googleSheets":{"count":7},"n8n-nodes-base.scheduleTrigger":{"count":1}}},"status":"published","readyToDemo":null,"user":{"name":"Jitesh Dugar","username":"jiteshdugar","bio":"AI Automation Specialist - OpenAI, CRM & Automation Expert with a solid understanding of various tools that include Zapier, Make, Zoho CRM, Hubspot, Google Sheets, Airtable, Pipedrive, Google Analytics, and more.","verified":true,"links":["https://www.linkedin.com/in/jiteshdugar"],"avatar":"https://gravatar.com/avatar/edaa3abb99806b0586dced559d0a5417f24a507e7c4464a63960f0638a4b1b90?r=pg&d=retro&size=200"},"nodes":[{"id":18,"icon":"file:googleSheets.svg","name":"n8n-nodes-base.googleSheets","codex":{"data":{"alias":["CSV","Sheet","Spreadsheet","GS"],"resources":{"generic":[{"url":"https://n8n.io/blog/love-at-first-sight-ricardos-n8n-journey/","icon":"❤️","label":"Love at first sight: Ricardo’s n8n journey"},{"url":"https://n8n.io/blog/why-business-process-automation-with-n8n-can-change-your-daily-life/","icon":"🧬","label":"Why business process automation with n8n can change your daily life"},{"url":"https://n8n.io/blog/automatically-adding-expense-receipts-to-google-sheets-with-telegram-mindee-twilio-and-n8n/","icon":"🧾","label":"Automatically Adding Expense Receipts to Google Sheets with Telegram, Mindee, Twilio, and n8n"},{"url":"https://n8n.io/blog/supercharging-your-conference-registration-process-with-n8n/","icon":"🎫","label":"Supercharging your conference registration process with n8n"},{"url":"https://n8n.io/blog/creating-triggers-for-n8n-workflows-using-polling/","icon":"⏲","label":"Creating triggers for n8n workflows using polling"},{"url":"https://n8n.io/blog/no-code-ecommerce-workflow-automations/","icon":"store","label":"6 e-commerce workflows to power up your Shopify s"},{"url":"https://n8n.io/blog/migrating-community-metrics-to-orbit-using-n8n/","icon":"📈","label":"Migrating Community Metrics to Orbit using n8n"},{"url":"https://n8n.io/blog/automate-google-apps-for-productivity/","icon":"💡","label":"15 Google apps you can combine and automate to increase productivity"},{"url":"https://n8n.io/blog/your-business-doesnt-need-you-to-operate/","icon":" 🖥️","label":"Hey founders! Your business doesn't need you to operate"},{"url":"https://n8n.io/blog/how-honest-burgers-use-automation-to-save-100k-per-year/","icon":"🍔","label":"How Honest Burgers Use Automation to Save $100k per year"},{"url":"https://n8n.io/blog/how-a-digital-strategist-uses-n8n-for-online-marketing/","icon":"💻","label":"How a digital strategist uses n8n for online marketing"},{"url":"https://n8n.io/blog/why-this-product-manager-loves-workflow-automation-with-n8n/","icon":"🧠","label":"Why this Product Manager loves workflow automation with n8n"},{"url":"https://n8n.io/blog/sending-automated-congratulations-with-google-sheets-twilio-and-n8n/","icon":"🙌","label":"Sending Automated Congratulations with Google Sheets, Twilio, and n8n "},{"url":"https://n8n.io/blog/how-a-membership-development-manager-automates-his-work-and-investments/","icon":"📈","label":"How a Membership Development Manager automates his work and investments"},{"url":"https://n8n.io/blog/aws-workflow-automation/","label":"7 no-code workflow automations for Amazon Web Services"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.googlesheets/"}],"credentialDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/credentials/google/oauth-single-service/"}]},"categories":["Data & Storage","Productivity"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"input\",\"output\"]","defaults":{"name":"Google Sheets"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCI+PGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiPjxwYXRoIGZpbGw9IiMyOEI0NDYiIGQ9Ik0zNS42OSAxIDUyIDE3LjIyNXYzOS4wODdhMy42NyAzLjY3IDAgMCAxLTEuMDg0IDIuNjFBMy43IDMuNyAwIDAgMSA0OC4yOTMgNjBIMTIuNzA3YTMuNyAzLjcgMCAwIDEtMi42MjMtMS4wNzhBMy42NyAzLjY3IDAgMCAxIDkgNTYuMzEyVjQuNjg4YTMuNjcgMy42NyAwIDAgMSAxLjA4NC0yLjYxQTMuNyAzLjcgMCAwIDEgMTIuNzA3IDF6Ii8+PHBhdGggZmlsbD0iIzZBQ0U3QyIgZD0iTTM1LjY5IDEgNTIgMTcuMjI1SDM5LjM5N2MtMi4wNTQgMC0zLjcwNy0xLjgyOS0zLjcwNy0zLjg3MnoiLz48cGF0aCBmaWxsPSIjMjE5QjM4IiBkPSJNMzkuMjExIDE3LjIyNSA1MiAyMi40OHYtNS4yNTV6Ii8+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTIwLjEyIDMxLjk3NWMwLS44MTcuNjYyLTEuNDc1IDEuNDgzLTEuNDc1aDE3Ljc5NGMuODIxIDAgMS40ODIuNjU4IDEuNDgyIDEuNDc1djE1LjQ4N2MwIC44MTgtLjY2MSAxLjQ3NS0xLjQ4MiAxLjQ3NUgyMS42MDNhMS40NzYgMS40NzYgMCAwIDEtMS40ODItMS40NzRWMzEuOTc0em0yLjIyNSAxLjQ3NWg2LjY3MnYyLjIxMmgtNi42NzJ6bTAgNS4xNjJoNi42NzJ2Mi4yMTNoLTYuNjcyem0wIDUuMTYzaDYuNjcydjIuMjEyaC02LjY3MnptOS42MzgtMTAuMzI1aDYuNjcydjIuMjEyaC02LjY3MnptMCA1LjE2Mmg2LjY3MnYyLjIxM2gtNi42NzJ6bTAgNS4xNjNoNi42NzJ2Mi4yMTJoLTYuNjcyeiIvPjxwYXRoIGZpbGw9IiMyOEI0NDYiIGQ9Ik0zNC42OSAwIDUxIDE2LjIyNXYzOS4wODdhMy42NyAzLjY3IDAgMCAxLTEuMDg0IDIuNjFBMy43IDMuNyAwIDAgMSA0Ny4yOTMgNTlIMTEuNzA3YTMuNyAzLjcgMCAwIDEtMi42MjMtMS4wNzhBMy42NyAzLjY3IDAgMCAxIDggNTUuMzEyVjMuNjg4YTMuNjcgMy42NyAwIDAgMSAxLjA4NC0yLjYxQTMuNyAzLjcgMCAwIDEgMTEuNzA3IDB6Ii8+PHBhdGggZmlsbD0iIzZBQ0U3QyIgZD0iTTM0LjY5IDAgNTEgMTYuMjI1SDM4LjM5N2MtMi4wNTQgMC0zLjcwNy0xLjgyOS0zLjcwNy0zLjg3MnoiLz48cGF0aCBmaWxsPSIjMjE5QjM4IiBkPSJNMzguMjExIDE2LjIyNSA1MSAyMS40OHYtNS4yNTV6Ii8+PHBhdGggZmlsbD0iI0ZGRiIgZD0iTTE5LjEyIDMwLjk3NWMwLS44MTcuNjYyLTEuNDc1IDEuNDgzLTEuNDc1aDE3Ljc5NGMuODIxIDAgMS40ODIuNjU4IDEuNDgyIDEuNDc1djE1LjQ4N2MwIC44MTgtLjY2MSAxLjQ3NS0xLjQ4MiAxLjQ3NUgyMC42MDNhMS40NzYgMS40NzYgMCAwIDEtMS40ODItMS40NzRWMzAuOTc0em0yLjIyNSAxLjQ3NWg2LjY3MnYyLjIxMmgtNi42NzJ6bTAgNS4xNjJoNi42NzJ2Mi4yMTNoLTYuNjcyem0wIDUuMTYzaDYuNjcydjIuMjEyaC02LjY3MnptOS42MzgtMTAuMzI1aDYuNjcydjIuMjEyaC02LjY3MnptMCA1LjE2Mmg2LjY3MnYyLjIxM2gtNi42NzJ6bTAgNS4xNjNoNi42NzJ2Mi4yMTJoLTYuNjcyeiIvPjwvZz48L3N2Zz4="},"displayName":"Google Sheets","typeVersion":5,"nodeCategories":[{"id":3,"name":"Data & Storage"},{"id":4,"name":"Productivity"}]},{"id":112,"icon":"fa:map-signs","name":"n8n-nodes-base.switch","codex":{"data":{"alias":["Router","If","Path","Filter","Condition","Logic","Branch","Case"],"resources":{"generic":[{"url":"https://n8n.io/blog/2021-the-year-to-automate-the-new-you-with-n8n/","icon":"☀️","label":"2021: The Year to Automate the New You with n8n"},{"url":"https://n8n.io/blog/how-to-get-started-with-crm-automation-and-no-code-workflow-ideas/","icon":"👥","label":"How to get started with CRM automation (with 3 no-code workflow ideas"},{"url":"https://n8n.io/blog/build-your-own-virtual-assistant-with-n8n-a-step-by-step-guide/","icon":"👦","label":"Build your own virtual assistant with n8n: A step by step guide"},{"url":"https://n8n.io/blog/automation-for-maintainers-of-open-source-projects/","icon":"🏷️","label":"How to automatically manage contributions to open-source projects"}],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.switch/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Flow"]}}},"group":"[\"transform\"]","defaults":{"name":"Switch","color":"#506000"},"iconData":{"icon":"map-signs","type":"icon"},"displayName":"Switch","typeVersion":3,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":565,"icon":"fa:sticky-note","name":"n8n-nodes-base.stickyNote","codex":{"data":{"alias":["Comments","Notes","Sticky"],"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers"]}}},"group":"[\"input\"]","defaults":{"name":"Sticky Note","color":"#FFD233"},"iconData":{"icon":"sticky-note","type":"icon"},"displayName":"Sticky Note","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]},{"id":834,"icon":"file:code.svg","name":"n8n-nodes-base.code","codex":{"data":{"alias":["cpde","Javascript","JS","Python","Script","Custom Code","Function"],"details":"The Code node allows you to execute JavaScript in your workflow.","resources":{"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.code/"}]},"categories":["Development","Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0","subcategories":{"Core Nodes":["Helpers","Data Transformation"]}}},"group":"[\"transform\"]","defaults":{"name":"Code"},"iconData":{"type":"file","fileBuffer":"data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMF8xMTcxXzQ0MSkiPgo8cGF0aCBkPSJNMTcwLjI4MyA0OEgxOTYuNUMyMDMuMTI3IDQ4IDIwOC41IDQyLjYyNzQgMjA4LjUgMzZWMTJDMjA4LjUgNS4zNzI1OCAyMDMuMTI3IDAgMTk2LjUgMEgxNzAuMjgzQzEyNi4xIDAgOTAuMjgzIDM1LjgxNzIgOTAuMjgzIDgwVjE3NkM5MC4yODMgMjA2LjkyOCA2NS4yMTA5IDIzMiAzNC4yODMgMjMySDIzQzE2LjM3MjYgMjMyIDExIDIzNy4zNzIgMTEgMjQ0VjI2OEMxMSAyNzQuNjI3IDE2LjM3MjQgMjgwIDIyLjk5OTYgMjgwTDM0LjI4MyAyODBDNjUuMjEwOSAyODAgOTAuMjgzIDMwNS4wNzIgOTAuMjgzIDMzNlY0NDBDOTAuMjgzIDQ3OS43NjQgMTIyLjUxOCA1MTIgMTYyLjI4MyA1MTJIMTk2LjVDMjAzLjEyNyA1MTIgMjA4LjUgNTA2LjYyNyAyMDguNSA1MDBWNDc2QzIwOC41IDQ2OS4zNzMgMjAzLjEyNyA0NjQgMTk2LjUgNDY0SDE2Mi4yODNDMTQ5LjAyOCA0NjQgMTM4LjI4MyA0NTMuMjU1IDEzOC4yODMgNDQwVjMzNkMxMzguMjgzIDMwOS4wMjIgMTI4LjAxMSAyODQuNDQzIDExMS4xNjQgMjY1Ljk2MUMxMDYuMTA5IDI2MC40MTYgMTA2LjEwOSAyNTEuNTg0IDExMS4xNjQgMjQ2LjAzOUMxMjguMDExIDIyNy41NTcgMTM4LjI4MyAyMDIuOTc4IDEzOC4yODMgMTc2VjgwQzEzOC4yODMgNjIuMzI2OSAxNTIuNjEgNDggMTcwLjI4MyA0OFoiIGZpbGw9IiNGRjk5MjIiLz4KPHBhdGggZD0iTTMwNSAzNkMzMDUgNDIuNjI3NCAzMTAuMzczIDQ4IDMxNyA0OEgzNDIuOTc5QzM2MC42NTIgNDggMzc0Ljk3OCA2Mi4zMjY5IDM3NC45NzggODBWMTc2QzM3NC45NzggMjAyLjk3OCAzODUuMjUxIDIyNy41NTcgNDAyLjA5OCAyNDYuMDM5QzQwNy4xNTMgMjUxLjU4NCA0MDcuMTUzIDI2MC40MTYgNDAyLjA5OCAyNjUuOTYxQzM4NS4yNTEgMjg0LjQ0MyAzNzQuOTc4IDMwOS4wMjIgMzc0Ljk3OCAzMzZWNDMyQzM3NC45NzggNDQ5LjY3MyAzNjAuNjUyIDQ2NCAzNDIuOTc5IDQ2NEgzMTdDMzEwLjM3MyA0NjQgMzA1IDQ2OS4zNzMgMzA1IDQ3NlY1MDBDMzA1IDUwNi42MjcgMzEwLjM3MyA1MTIgMzE3IDUxMkgzNDIuOTc5QzM4Ny4xNjEgNTEyIDQyMi45NzggNDc2LjE4MyA0MjIuOTc4IDQzMlYzMzZDNDIyLjk3OCAzMDUuMDcyIDQ0OC4wNTEgMjgwIDQ3OC45NzkgMjgwSDQ5MEM0OTYuNjI3IDI4MCA1MDIgMjc0LjYyOCA1MDIgMjY4VjI0NEM1MDIgMjM3LjM3MyA0OTYuNjI4IDIzMiA0OTAgMjMyTDQ3OC45NzkgMjMyQzQ0OC4wNTEgMjMyIDQyMi45NzggMjA2LjkyOCA0MjIuOTc4IDE3NlY4MEM0MjIuOTc4IDM1LjgxNzIgMzg3LjE2MSAwIDM0Mi45NzkgMEgzMTdDMzEwLjM3MyAwIDMwNSA1LjM3MjU4IDMwNSAxMlYzNloiIGZpbGw9IiNGRjk5MjIiLz4KPC9nPgo8ZGVmcz4KPGNsaXBQYXRoIGlkPSJjbGlwMF8xMTcxXzQ0MSI+CjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo="},"displayName":"Code","typeVersion":2,"nodeCategories":[{"id":5,"name":"Development"},{"id":9,"name":"Core Nodes"}]},{"id":839,"icon":"fa:clock","name":"n8n-nodes-base.scheduleTrigger","codex":{"data":{"alias":["Time","Scheduler","Polling","Cron","Interval"],"resources":{"generic":[],"primaryDocumentation":[{"url":"https://docs.n8n.io/integrations/builtin/core-nodes/n8n-nodes-base.scheduletrigger/"}]},"categories":["Core Nodes"],"nodeVersion":"1.0","codexVersion":"1.0"}},"group":"[\"trigger\",\"schedule\"]","defaults":{"name":"Schedule Trigger","color":"#31C49F"},"iconData":{"icon":"clock","type":"icon"},"displayName":"Schedule Trigger","typeVersion":1,"nodeCategories":[{"id":9,"name":"Core Nodes"}]}],"categories":[{"id":40,"name":"Support Chatbot"},{"id":47,"name":"AI Chatbot"}],"image":[]}}