

What Happens | Business Impact |
Customer says "too expensive" in a note | Deal lost to competitor offering lower price |
Customer cancels 2 meetings in a row | Prevent deals from going cold by detecting repeated meeting cancellations early and triggering timely follow-ups. |
Customer mentions "evaluating other options" | Identify when customers start evaluating other options and respond quickly before they finalize their decision. |
Customer says "not a priority right now" | Deal sits in pipeline for months, inflating forecasts |

S.No | Field Label | API Name | Data Type | values |
1 | Risk | Risk | Picklist | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 Risk: 1 = low risk, Risk 10 = high risk |
2 | Sentiment | Sentiment | Picklist | Positive, Neutral, Negative |
3 | AI Analysis | AI_Analysis | Multi-line Text | — |
4 | Previous Risk | Previous_Risk | Number | — |
5 | Risk Trend | Risk_Trend | Picklist | Increasing, Stable, Decreasing |
6 | Alert Sent | Alert_Sent | Checkbox | — |
dealData = zoho.crm.getRecordById("Deals", dealIdLong); dealName = ifnull(dealData.get("Deal_Name"), ""); dealStage = ifnull(dealData.get("Stage"), ""); dealAmount = ifnull(dealData.get("Amount"), "0"); closeDate = ifnull(dealData.get("Closing_Date"), "Not defined"); // Existing Risk existingRisk = ifnull(dealData.get("Risk"), "0").toString().toNumber(); // Owner Info owner = dealData.get("Owner"); ownerName = ifnull(owner.get("name"), ""); ownerEmail = ifnull(owner.get("email"), ""); |
dealNotes = zoho.crm.getRelatedRecords("Notes", "Deals", dealIdLong); notesContext = ""; for each note in dealNotes { notesContext = notesContext + "- " + ifnull(note.get("Note_Content"), "") + "\n"; } |
chatEntry = Map(); chatEntry.put("role", "user"); chatEntry.put("content", "Deal Name: " + dealName + "\nStage: " + dealStage + "\nAmount: " + dealAmount + "\nClose Date: " + closeDate + "\n\n=== DEAL NOTES ===\n" + notesContext ); assistantMap.put("chat_history", {chatEntry}); assistantMap.put("prompt", "<custom sentiment + scoring prompt>"); response = invokeurl [ type :POST parameters: payload.toString() connection:"zohocrm" ]; |
aiText = ""; if(response.get("assistant") != null) { aiText = response.get("assistant").get("details").get("data"); } |
// Extract & clean risk riskLine = riskLine.replaceAll("[^0-9]", "", false); riskScore = riskLine.toNumber(); if(riskScore > 10) riskScore = 10; if(riskScore < 1) riskScore = 1; // Normalize sentiment sentimentLower = sentiment.toLowerCase(); if(sentimentLower.contains("negative")) sentiment = "Negative"; else if(sentimentLower.contains("positive")) sentiment = "Positive"; else sentiment = "Neutral"; |
riskTrend = "Stable"; if(riskScore > existingRisk) { riskTrend = "Increasing"; } else if(riskScore < existingRisk) { riskTrend = "Decreasing"; } |
updateMap = Map(); updateMap.put("Risk", riskScore.toString()); updateMap.put("Sentiment", sentiment); updateMap.put("AI_Analysis", analysis); updateMap.put("Previous_Risk", existingRisk.toString()); updateMap.put("Risk_Trend", riskTrend); zoho.crm.updateRecord("Deals", dealIdLong, updateMap); |
previousAlertSent = ifnull(dealData.get("Alert_Sent"), false); if(riskScore > 8 && (previousAlertSent == false || riskScore > existingRisk) && ownerEmail != "") { // Send alert email mailPayload = { "from": {"user_name": ownerName, "email": zoho.crm.getOrgVariable("defaultMail")}, "to": {{"user_name": ownerName, "email": ownerEmail}}, "subject": "🚨 Deal At Risk: " + dealName, "content": "Risk Score: " + riskScore + "/10<br>Sentiment: " + sentiment + "<br><br>" + analysis, "mail_format": "html" }; invokeurl [ url :"https://www.zohoapis.com/crm/v8/Deals/" + dealIdLong + "/actions/send_mail" type :POST parameters: {"data": {mailPayload}}.toString() headers: {"Content-Type":"application/json"} connection: "zohocrm" ]; zoho.crm.updateRecord("Deals", dealIdLong, {"Alert_Sent": true}); } else if(riskScore <= 8) { // Reset alert flag zoho.crm.updateRecord("Deals", dealIdLong, {"Alert_Sent": false}); } |
if(riskScore > 8) { invokeurl [ url :"https://www.zohoapis.com/crm/v8/Deals/" + dealIdLong + "/actions/add_tags" type :POST parameters: tagPayload.toString() connection:"zohocrm" ]; } else { invokeurl [ url :"https://www.zohoapis.com/crm/v8/Deals/" + dealIdLong + "/actions/remove_tags" type :POST parameters: tagPayload.toString() connection:"zohocrm" ]; |
