How would you improve this lead life cycle scheduled function?

How would you improve this lead life cycle scheduled function?

void schedule.IntegratedLeadProcessing()
{
    // STEP 1: Retrieve Leads from CRM
    leads = zoho.crm.getRecords("Leads",1,200);
    if(leads == null || leads.size() == 0)
    {
        return;
    }

    // STEP 2: Process Timeline Engagement & Update Lead Status
    currentDate = zoho.currentdate.toDate();
    thirtyDaysAgo = currentDate.addDay(-30);

    leadIds = list();
    for each  lead in leads
    {
        if(lead.get("id") != null)
        {
            leadIds.add(lead.get("id"));
        }
    }

    timelineMap = Map();
    for each  leadId in leadIds
    {
        timelineURL = "https://www.zohoapis.com/crm/v7/Leads/" + leadId + "/__timeline?sort_by=audited_time" + "&include_inner_details=field_history.data_type,field_history.field_label,field_history.enable_colour_code,field_history.pick_list_values,done_by.type__s,done_by.profile";
        timelineResponse = invokeurl
        [
            url :timelineURL
            type :GET
            connection:"zoho_crm"
        ];
        timelineList = list();
        if(timelineResponse.containsKey("__timeline"))
        {
            timelineList = timelineResponse.get("__timeline");
        }
        timelineMap.put(leadId,timelineList);
    }

    leadEngagementMap = Map();
    desiredModules = list();
    desiredModules.add("calls");
    desiredModules.add("meetings");
    desiredModules.add("emails");
    desiredModules.add("tasks");

    for each  lead in leads
    {
        leadId = lead.get("id");
        leadName = ifnull(lead.get("Lead_Name"),ifnull(lead.get("Full_Name"),"Unknown Lead"));
        createdTimeStr = lead.get("Created_Time");
        if(createdTimeStr != null)
        {
            createdDate = createdTimeStr.toDate("yyyy-MM-dd'T'HH:mm:ssXXX");
        }
        else
        {
            createdDate = currentDate;
        }
        lastEngagementDate = null;
        engagementDates = list();

        leadTimeline = timelineMap.get(leadId);
        for each  event in leadTimeline
        {
            if(event.containsKey("audited_time") && event.containsKey("record"))
            {
                rec = event.get("record");
                moduleName = "";
                if(rec.containsKey("link_data"))
                {
                    linkData = rec.get("link_data");
                    if(linkData != null && linkData.size() > 0)
                    {
                        moduleName = linkData.get(0);
                    }
                }
                if(moduleName == "" && rec.containsKey("module") && rec.get("module").containsKey("api_name"))
                {
                    moduleName = rec.get("module").get("api_name");
                }
                if(moduleName == "" && event.containsKey("description"))
                {
                    description = event.get("description").toLowerCase();
                    if(description.contains("task"))
                    {
                        moduleName = "tasks";
                    }
                    else if(description.contains("call"))
                    {
                        moduleName = "calls";
                    }
                    else if(description.contains("meeting"))
                    {
                        moduleName = "meetings";
                    }
                    else if(description.contains("email"))
                    {
                        moduleName = "emails";
                    }
                }
                moduleNameLower = moduleName.toLowerCase();

                if(desiredModules.contains(moduleNameLower))
                {
                    try 
                    {
                        eventTimeStr = event.get("audited_time");
                        eventDate = eventTimeStr.toDate("yyyy-MM-dd'T'HH:mm:ssXXX");
                        engagementDates.add(eventDate);
                    }
                    catch (e)
                    {
                    }
                }
            }
        }

        if(engagementDates.size() > 0)
        {
            mostRecentEvent = engagementDates.get(0);
            for each  dt in engagementDates
            {
                if(dt.toLong() > mostRecentEvent.toLong())
                {
                    mostRecentEvent = dt;
                }
            }
            lastEngagementDate = mostRecentEvent;
        }
        else
        {
            lastEngagementDate = createdDate;
        }

        daysSinceEngagement = (currentDate.toLong() - lastEngagementDate.toLong()) / 86400000;
        if(engagementDates.size() > 0)
        {
            if(daysSinceEngagement <= 7)
            {
                leadStatus = "Hot";
            }
            else if(daysSinceEngagement <= 14)
            {
                leadStatus = "Warm";
            }
            else
            {
                leadStatus = "Cold";
            }
        }
        else
        {
            leadStatus = "Cold";
        }
        updateData = Map();
        updateData.put("Last_Engagement_Date",lastEngagementDate.toString("yyyy-MM-dd"));
        updateData.put("Lead_Status",leadStatus);
        leadEngagementMap.put(leadId,updateData);
    }

    for each  leadId in leadEngagementMap.keys()
    {
        updateData = leadEngagementMap.get(leadId);
        updateResp = zoho.crm.updateRecord("Leads",leadId,updateData);
    }

    // STEP 3: Apply Score Decay Adjustments
    scoringRules = list();
    scoringRules.add("Industry_Fit");
    scoringRules.add("Company_Size");
    scoringRules.add("Location_Priority");
    scoringRules.add("Intent");
    scoringRules.add("Buying_Group_Role");
    baseScores = Map();
    baseScores.put("Industry_Fit",0);
    baseScores.put("Company_Size",15);
    baseScores.put("Location_Priority",10);
    baseScores.put("Intent",0);
    baseScores.put("Buying_Group_Role",0);

    processedCount = 0;
    updatedCount = 0;
    for each  lead in leads
    {
        processedCount = processedCount + 1;
        leadId = lead.get("id");
        positiveTP = ifnull(lead.get("Positive_Touch_Points"),0).toLong();
        negativeTP = ifnull(lead.get("Negative_Touch_Points"),0).toLong();
        engaged = positiveTP > 0 && positiveTP > negativeTP;
        refDate = lead.get("Last_Engagement_Date");
        if(refDate != null)
        {
            refDate = refDate.toDate();
        }
        else
        {
            refDate = lead.get("Created_Time");
            if(refDate != null)
            {
                refDate = refDate.toDate();
            }
        }
        updateData = Map();
        if(engaged)
        {
            updateData.put("Score_Decay_Counter",0);
            updateData.put("Score_Decay_Reason","");
            for each  rule in scoringRules
            {
                currentScore = 0;
                try 
                {
                    currentScore = ifnull(lead.get(rule),"0").toDecimal();
                }
                catch (e)
                {
                    currentScore = 0;
                }
                baseScore = baseScores.get(rule).toDecimal();
                if(currentScore < baseScore)
                {
                    updateData.put(rule,baseScore);
                }
            }
        }
        else if(refDate != null)
        {
            daysInactive = (currentDate.toLong() - refDate.toLong()) / 86400000;
            if(daysInactive >= 14)
            {
                decayCounter = (daysInactive / 14).toLong();
                for each  rule in scoringRules
                {
                    currentScore = 0;
                    try 
                    {
                        currentScore = ifnull(lead.get(rule),"0").toDecimal();
                    }
                    catch (e)
                    {
                        currentScore = 0;
                    }
                    if(currentScore > 0)
                    {
                        updateData.put(rule,currentScore * 0.95);
                    }
                }
                updateData.put("Score_Decay_Counter",decayCounter);
                updateData.put("Score_Decay_Reason","Score reduced due to lack of engagement (" + daysInactive.toLong() + " days since last engagement)");
            }
        }
        if(updateData.size() > 0)
        {
            updateResponse = zoho.crm.updateRecord("Leads",leadId,updateData);
            updatedCount = updatedCount + 1;
        }
    }

    // STEP 4: Process Tagging for Leads
    getTagsResp = invokeurl
    [
        url :settingsUrl
        type :GET
        connection:"zoho_crm"
    ];
    existingTagsList = list();
    if(getTagsResp.containsKey("tags"))
    {
        existingTagsList = getTagsResp.get("tags");
    }

    plannedTags = list();
    plannedTags.add({"name":"Introduction","color_code":"#F17574"});
    plannedTags.add({"name":"Rapport Building","color_code":"#F48435"});
    plannedTags.add({"name":"Existing Business","color_code":"#E7A826"});
    plannedTags.add({"name":"Closing","color_code":"#A8C026"});
    plannedTags.add({"name":"0-5m/yr","color_code":"#63C57E"});
    plannedTags.add({"name":"5-50m/yr","color_code":"#1DB9B4"});
    plannedTags.add({"name":"50m-100m/yr","color_code":"#57B1FD"});
    plannedTags.add({"name":"100m+/yr","color_code":"#879BFC"});
    plannedTags.add({"name":"0-20 Users","color_code":"#D297EE"});
    plannedTags.add({"name":"20-60 Users","color_code":"#FD87BD"});
    plannedTags.add({"name":"60+ Users","color_code":"#969696"});
    plannedTags.add({"name":"Wichita (Local)","color_code":"#658BA8"});
    plannedTags.add({"name":"Mid West (Regional)","color_code":"#B88562"});
    plannedTags.add({"name":"National","color_code":"#F17574"});
    plannedTags.add({"name":"Data Incomplete","color_code":"#ECE81A"});

    for each  tagMap in plannedTags
    {
        plannedTagName = tagMap.get("name");
        tagExists = false;
        for each  existTag in existingTagsList
        {
            if(existTag.get("name") == plannedTagName)
            {
                tagExists = true;
                break;
            }
        }
        if(!tagExists)
        {
            inputJSON = {"tags":{{"name":plannedTagName,"color_code":tagMap.get("color_code")}}};
            createResp = invokeurl
            [
                url :createUrl
                type :POST
                parameters:inputJSON.toString()
                connection:"zoho_crm"
            ];
        }
    }

    updated_leads = 0;
    for each  lead in leads
    {
        leadId = lead.get("id");
        newTagsList = list();
        leadDetails = zoho.crm.getRecordById("Leads",leadId);
        existingTags = ifnull(leadDetails.get("Tag"),list());
        if(existingTags.size() > 0)
        {
            removeParam = Map();
            removeParam.put("ids",list(leadId));
            removeParam.put("tags",existingTags);
            removeResp = invokeurl
            [
                url :removeTagsUrl
                type :POST
                parameters:removeParam.toString()
                connection:"zoho_crm"
            ];
        }

        newTagsList.add("Data Incomplete");
        if(newTagsList.size() > 0)
        {
            param = Map();
            formattedTags = list();
            for each  tagName in newTagsList
            {
                formattedTags.add({"name":tagName});
            }
            param.put("tags",formattedTags);
            param.put("ids",list(leadId));
            tagResp = invokeurl
            [
                url :addTagsUrl
                type :POST
                parameters:param.toString()
                connection:"zoho_crm"
            ];
            updated_leads = updated_leads + 1;
        }
    }

    // STEP 5: Lead Routing & Conversion
    salesAgents = list();
    salesAgents.add({"id":"owner_id","name":"owner_name"});
    totalAgents = salesAgents.size();
    currentAgentIndex = 0;
    agentLeadCount = Map();
    for each  agent in salesAgents
    {
        agentLeadCount.put(agent.get("id"),{"name":agent.get("name"),"count":0});
    }

    allLeads = zoho.crm.getRecords("Leads",1,200);
    if(allLeads == null || allLeads.isEmpty())
    {
        return;
    }

    for each  lead in allLeads
    {
        leadOwner = lead.get("Owner");
        if(leadOwner != null)
        {
            ownerId = leadOwner.get("id");
            ownerName = leadOwner.get("name");
            if(agentLeadCount.containsKey(ownerId))
            {
                agentLeadCount.put(ownerId,{"name":ownerName,"count":agentLeadCount.get(ownerId).get("count") + 1});
            }
            else
            {
                agentLeadCount.put(ownerId,{"name":ownerName,"count":1});
            }
        }
    }

    assignedLeads = 0;
    for each  lead in allLeads
    {
        if(lead.get("Owner") == null)
        {
            assignedAgent = salesAgents.get(currentAgentIndex % totalAgents);
            updateData = Map();
            updateData.put("Owner",assignedAgent.get("id"));
            updateResp = zoho.crm.updateRecord("Leads",lead.get("id"),updateData);
            assignedLeads = assignedLeads + 1;
            if(agentLeadCount.containsKey(assignedAgent.get("id")))
            {
                agentLeadCount.put(assignedAgent.get("id"),{"name":assignedAgent.get("name"),"count":agentLeadCount.get(assignedAgent.get("id")).get("count") + 1});
            }
            else
            {
                agentLeadCount.put(assignedAgent.get("id"),{"name":assignedAgent.get("name"),"count":1});
            }
            currentAgentIndex = (currentAgentIndex + 1) % totalAgents;
        }
    }

    convertedLeads = 0;
    currentDate = zoho.currentdate.toDate();
    sevenDaysAgo = currentDate.addDay(-7);
    for each  lead in allLeads
    {
        leadId = lead.get("id");
        timeline = zoho.crm.getRelatedRecords("Activities","Leads",leadId);
        if(timeline.isEmpty())
        {
            continue;
        }
        activityFound = false;
        lastValidActivity = null;
        for each  activity in timeline
        {
            activityType = activity.get("Activity_Type");
            activityStatus = activity.get("Status");
            activityTime = activity.get("Created_Time").toDate();
            if((activityType == "Call" || activityType == "Meeting") && activityTime >= sevenDaysAgo)
            {
                lastValidActivity = activity;
                if(activityStatus == "Completed")
                {
                    activityFound = true;
                    break;
                }
            }
        }
        if(activityFound)
        {
            conversionMap = Map();
            dealList = list();
            dealList.add("Deals");
            dealList.add("Accounts");
            conversionMap.put("create",dealList);
            convertResp = zoho.crm.convertLead(leadId,conversionMap);
            convertedLeads = convertedLeads + 1;
            assignedAgent = salesAgents.get(currentAgentIndex % totalAgents);
            dealData = Map();
            dealData.put("Owner",assignedAgent.get("id"));
            dealUpdateResp = zoho.crm.updateRecord("Deals",convertResp.get("Deals"),dealData);
            currentAgentIndex = (currentAgentIndex + 1) % totalAgents;
        }
    }
}

    • Sticky Posts

    • Kaizen #217 - Actions APIs : Tasks

      Welcome to another week of Kaizen! In last week's post we discussed Email Notifications APIs which act as the link between your Workflow automations and you. We have discussed how Zylker Cloud Services uses Email Notifications API in their custom dashboard.
    • Kaizen #216 - Actions APIs : Email Notifications

      Welcome to another week of Kaizen! For the last three weeks, we have been discussing Zylker's workflows. We successfully updated a dormant workflow, built a new one from the ground up and more. But our work is not finished—these automated processes are
    • Kaizen #152 - Client Script Support for the new Canvas Record Forms

      Hello everyone! Have you ever wanted to trigger actions on click of a canvas button, icon, or text mandatory forms in Create/Edit and Clone Pages? Have you ever wanted to control how elements behave on the new Canvas Record Forms? This can be achieved
    • Kaizen #142: How to Navigate to Another Page in Zoho CRM using Client Script

      Hello everyone! Welcome back to another exciting Kaizen post. In this post, let us see how you can you navigate to different Pages using Client Script. In this Kaizen post, Need to Navigate to different Pages Client Script ZDKs related to navigation A.
    • Kaizen #210 - Answering your Questions | Event Management System using ZDK CLI

      Hello Everyone, Welcome back to yet another post in the Kaizen Series! As you already may know, for the Kaizen #200 milestone, we asked for your feedback and many of you suggested topics for us to discuss. We have been writing on these topics over the