Lead assignment

server script:

request_data = frappe.form_dict
frappe.log(request_data)
filters = request_data.get(‘filters’)
order_by = request_data.get(‘order_by’)
limit_lead = int(request_data.get(‘limit_lead’))
person_to_start = int(request_data.get(‘person_to_start’))
table_main = json.loads(request_data.get(‘table_main’))

leadAssignment =

counter = 0
total_daily_limit = 0

for value in table_main:
temp_var = {
‘name’: value.get(‘name’),
“sales_person”: value.get(‘sales_person’),
“user_email”: value.get(‘user_email’),
‘daily_total_count’: value.get(‘daily_total_count’),
‘daily_limit’: value.get(‘daily_limit’),
‘assign_leads’: ,
‘last_active’: value.get(‘last_active’)
}
# Get All Data present in table of Lead Rule
leadAssignment.append(temp_var)
counter = counter + value.get(‘daily_total_count’)
total_daily_limit = total_daily_limit + value.get(‘daily_limit’)

Condition Defined for to check daliy limit

if total_daily_limit > counter:
# Length Of table is defined
tableLength = len(table_main)
# Total number of available Lead
leadList = frappe.db.get_list(‘Lead’, filters=filters, fields=[“*”], order_by=order_by)

leadListLength = len(leadList)

temp_leadListLength = leadListLength if leadListLength < limit_lead else limit_lead

# Flag to check the number of Lead Assignments
total_lead_assigned = 0
# Create A Lead Queue and Table Queue to distibute in round robin:---

table_queue = [x for x in range(tableLength)]
lead_queue = [x for x in range(leadListLength)]

lead_received = {person : leadAssignment[person].get('daily_total_count') for person in table_queue}
max_lead_per_person = {person : leadAssignment[person].get('daily_limit') for person in table_queue}

# total_expected_lead = temp_leadListLength if temp_leadListLength < total_daily_limit else total_daily_limit
total_lead_assigned = counter
total_lead_to_be_assign = total_daily_limit
rem_no_lead_to_be_assign = total_lead_to_be_assign - total_lead_assigned

total_expected_lead = temp_leadListLength if temp_leadListLength < rem_no_lead_to_be_assign else rem_no_lead_to_be_assign

lead_assigned_counter = 0

temp_person_to_start = person_to_start
# frappe.log_error(table_queue)
# tt = True
no_lead_assigned = False
while (lead_queue and lead_assigned_counter < total_expected_lead):
# while(tt):
    
    total_no_of_lead_to_be_assined = 0
    lead_assigned = 0
    for person in table_queue:
        
        
        person = (person + temp_person_to_start) % tableLength
        person_to_start = person
        userDoc = ''
        last_active = ''
        
        
        if leadAssignment[person].get('user_email'):

            userDoc = frappe.get_cached_doc('User', leadAssignment[person].get('user_email'))
            last_active = userDoc.get('last_active')
            # frappe.log_error([last_active,lead_queue, leadAssignment[person].get('user_email'),  leadAssignment[person]['daily_total_count'] , max_lead_per_person[person], leadAssignment[person].get('user_email') , frappe.utils.date_diff(last_active, frappe.utils.now_datetime())])
        if lead_queue and leadAssignment[person]['daily_total_count'] < max_lead_per_person[person] and leadAssignment[person].get('user_email') and frappe.utils.date_diff(last_active, frappe.utils.now_datetime()) == 0: # max_lead_per_person is dynamic need to check..
            # frappe.log_error([lead_queue, leadAssignment[person].get('user_email'),  leadAssignment[person]['daily_total_count'] , max_lead_per_person[person], leadAssignment[person].get('user_email') , frappe.utils.date_diff(last_active, frappe.utils.now_datetime())])
            lead_popped = lead_queue.pop(0)

            

            # if (
            #     leadAssignment[person].get('daily_limit') > leadAssignment[person].get('daily_total_count') 
            #     and leadAssignment[person].get('user_email') 
            #     and frappe.utils.date_diff(last_active, frappe.utils.now_datetime()) == 0
            # ):

            if not leadAssignment[person].get('last_active'):
                leadAssignment[person]['last_active'] = last_active #if not leadAssignment[person].get('last_active') else leadAssignment[person].get('last_active')
            leadAssignment[person]['daily_total_count'] = leadAssignment[person]['daily_total_count'] + 1
            leadAssignment[person]['assign_leads'].append(leadList[lead_popped].name)
            # frappe.log_error([lead_popped],"lead_popped")
            leadDoc = frappe.get_cached_doc('Lead', leadList[lead_popped].name)
            leadDoc.lead_owner = leadAssignment[person].get('user_email')
            leadDoc.contact_date = ''
            leadDoc.sales_person = leadAssignment[person].get('sales_person')
            leadDoc.lead_owner_counter = leadDoc.lead_owner_counter + 1
            leadDoc.lead_assign_time = frappe.utils.now_datetime()
            leadDoc.save(ignore_permissions=1)
            lead_assigned_counter = lead_assigned_counter + 1
            total_no_of_lead_to_be_assined = total_no_of_lead_to_be_assined + max_lead_per_person[person]
            lead_assigned = lead_assigned + leadAssignment[person]['daily_total_count']
        if (lead_assigned_counter >= total_expected_lead):
            
            # no_lead_assigned = True
            break
    if total_no_of_lead_to_be_assined == 0 and  lead_assigned == 0:
        no_lead_assigned = True
        break
    # tt = False
base_condition = len(lead_queue) if (rem_no_lead_to_be_assign - lead_assigned_counter) > len(lead_queue) else (rem_no_lead_to_be_assign - lead_assigned_counter)
frappe.response['result'] = leadAssignment, leadListLength,len(lead_queue),base_condition, person_to_start + 1, no_lead_assigned

client script:

frappe.ui.form.on(“Lead Rule”, {
validate: function(frm){
// All the variables of fields to filter out the data
let name = frm.doc.name;
let stage = frm.doc.stage;
let leadStatus = frm.doc.contact_status;
let temperature = frm.doc.lead_status;
let converted = frm.doc.converted;
let dndCheck = frm.doc.dnd;
let assign_count_from = frm.doc.assign_count_from;
let assign_count_to = frm.doc.assign_count_to;
let contactStatus = frm.doc.contact_status;
let routing_method = frm.doc.routing_method;
let leadOwnerLR = frm.doc.sales_person;
let leadReply = frm.doc.lead_reply;
let leadRuleTable = frm.doc.table_main;
let leadRuleCondition = frm.doc.attempted_reply; // attempted_reply
let leadRuleSecondCond = frm.doc.lead_reply; // lead_reply
// let assignvaluesSeperated = frm.doc.assign_count;
let from_date = frm.doc.from_date;
let to_date = frm.doc.to_date;
let campaign_name = frm.doc.campaign_name;
let grade = frm.doc.grade;
let final_array_dist = ;
let creationTimeLead = “”;
let attemptedReply = “”;
let dateTimeNow = frappe.datetime.now_date();
let filters = ;
let order_by = “”;

    let modified_from_date = frm.doc.modified_from_date;
    let modified_to_date = frm.doc.modified_to_date;
    
    // Take all the filters and consolidate at one place
    
    if (contactStatus === "Not Contacted"){
        leadReply = "";
        attemptedReply = "";
    }else if(contactStatus === "Attempted to Contact"){
        leadReply = "";
        attemptedReply = leadRuleCondition;
    }else if(contactStatus === "Contacted"){
        leadReply = leadRuleSecondCond;
        attemptedReply = "";
    }
    if(routing_method === "Created LIFO"){
        order_by = "creation DESC";
    }else if(routing_method === "Created FIFO"){
        order_by = "creation ASC";
    }
    if(leadOwnerLR){
        filters.push(["Lead","sales_person","=",leadOwnerLR]);
    }
    if(from_date && to_date){
        filters.push(["Lead","creation","between",[from_date,to_date]]);
    }
    if(modified_from_date && modified_to_date){
        filters.push(["Lead","modified","between",[modified_from_date,modified_to_date]]);
    }
    
    if(assign_count_from){
        filters.push(["Lead","lead_owner_counter",">=",assign_count_from]);
    }
    if(assign_count_to){
        filters.push(["Lead","lead_owner_counter","<=",assign_count_to]);
    }
    if(attemptedReply){
        filters.push(["Lead","attempted_reply","=",attemptedReply]);
    }
    if(leadReply){
        filters.push(["Lead", "lead_reply", "=", leadReply]);
    }
    if(dndCheck){
        filters.push(["Lead", "dnd", "=", dndCheck]);
    }
    if(converted){
        filters.push(["Lead", "converted_lead", "=", converted]);
    }
    if(leadStatus){
        filters.push(["Lead", "lead_status", "=", leadStatus]);
    }
    if(stage){
        filters.push(["Lead", "status", "=", stage]);
    }
    if(temperature){
        filters.push(["Lead", "temperature", "=", temperature]);
    }
    if(campaign_name){
        filters.push(["Lead", "campaign_name", "=", campaign_name]);
    }
    if(grade){
        filters.push(["Lead", "grade", "=", grade]);
    }
    
    // Append Filtered records in single array
    // console.log(filters,"filters");
    
    // Frappe to custom created API to set the data based on filters
    frappe.call({
        method:"get_lead_count",
        type:"POST",
        args:{
            filters:filters,
            order_by: order_by,
        },
        callback: function(r){
            // console.log(r,'r');
            let result = r.result;
            // console.log(result,'result');
            // Set value of lead count
            if(frm.doc.lead_count || frm.doc.lead_count === 0){
                frm.set_value('lead_count',result);
                // frm.save();
            }
        }
    });
},
before_save: function (frm) {
    // Function to make attempted reply and lead reply as blank when Contact Status is Contacted
    action_on_contact_status(frm);
},
refresh: function (frm) {
    // Lead rule Execution on click of button
    frm.add_custom_button(__("Execute"), function(){
        
        // All the variables of fields to filter out the data
        
        let name = frm.doc.name;
        let stage = frm.doc.stage;
        let leadStatus = frm.doc.contact_status;
        let temperature = frm.doc.lead_status;
        let converted = frm.doc.converted;
        let dndCheck = frm.doc.dnd;
        let assign_count_from = frm.doc.assign_count_from;
        let assign_count_to = frm.doc.assign_count_to;
        let contactStatus = frm.doc.contact_status;
        let routing_method = frm.doc.routing_method;
        let leadOwnerLR = frm.doc.sales_person;
        let leadReply = frm.doc.lead_reply;
        let leadRuleTable = frm.doc.table_main;
        // let assignvaluesSeperated = frm.doc.assign_count;
        let leadRuleCondition = frm.doc.attempted_reply; // attempted_reply
        let leadRuleSecondCond = frm.doc.lead_reply; // lead_reply
        let from_date = frm.doc.from_date;
        let to_date = frm.doc.to_date;
        let campaign_name = frm.doc.campaign_name;
        let grade = frm.doc.grade;
        let final_array_dist = [];
        let creationTimeLead = "";
        let attemptedReply = "";
        let dateTimeNow = frappe.datetime.now_date();
        let filters = [];
        let order_by = "";
        let modified_from_date = frm.doc.modified_from_date;
        let modified_to_date = frm.doc.modified_to_date;
        
        // Take all the filters and consolidate at one place
        
        if (contactStatus === "Not Contacted"){
            leadReply = "";
            attemptedReply = "";
        }else if(contactStatus === "Attempted to Contact"){
            leadReply = "";
            attemptedReply = leadRuleCondition;
        }else if(contactStatus === "Contacted"){
            leadReply = leadRuleSecondCond;
            attemptedReply = "";
        }
        if(routing_method === "Created LIFO"){
            order_by = "creation DESC";
        }else if(routing_method === "Created FIFO"){
            order_by = "creation ASC";
        }
        if(leadOwnerLR){
            filters.push(["Lead","sales_person","=",leadOwnerLR]);
        }
        if(from_date && to_date){
            filters.push(["Lead","creation","between",[from_date,to_date]]);
        }
        if(modified_from_date && modified_to_date){
            filters.push(["Lead","modified","between",[modified_from_date,modified_to_date]]);
        }
    
        if(assign_count_from){
            filters.push(["Lead","lead_owner_counter",">=",assign_count_from]);
        }
        if(assign_count_to){
            filters.push(["Lead","lead_owner_counter","<=",assign_count_to]);
        }
        if(attemptedReply){
            filters.push(["Lead","attempted_reply","=",attemptedReply]);
        }
        if(leadReply){
            filters.push(["Lead", "lead_reply", "=", leadReply]);
        }
        if(dndCheck){
            filters.push(["Lead", "dnd", "=", dndCheck]);
        }
        if(converted){
            filters.push(["Lead", "converted_lead", "=", converted]);
        }
        if(leadStatus){
            filters.push(["Lead", "lead_status", "=", leadStatus]);
        }
        if(stage){
            filters.push(["Lead", "status", "=", stage]);
        }
        if(temperature){
            filters.push(["Lead", "temperature", "=", temperature]);
        }
        if(campaign_name){
            filters.push(["Lead", "campaign_name", "=", campaign_name]);
        }
        if(grade){
            filters.push(["Lead", "grade", "=", grade]);
        }
        
        // Append Filtered records in single array
        // console.log(filters,"filters");
        
        // Frappe to custom created API to set the data based on filters
        let updated_table_value = []
        let lead_count_after_assignment = undefined;
        let count = 0
        let flag = true
        let person_to_start = 0;
        let limit_lead = 200;
        let table_main = cur_frm.doc.table_main
        async function to_call_once(){
            while(flag){
                async function lead_assignment(){
                    
                    await frappe.call({
                        method:"assign_leads_based_on_filters",
                        type:"POST",
                        args:{
                            filters:filters,
                            order_by: order_by,
                            table_main:table_main,
                            limit_lead:limit_lead,
                            person_to_start: person_to_start
                        },
                        freeze: true,
                        timeout: 300000,
                        callback: function(r){
                            console.log(r,'r');
                            let result = r.result;
                            // console.log(result,'result')
                            let usersLead = result[0];
                            // Set value of lead count
                            frm.set_value('lead_count',r.result[2]);
                            lead_count_after_assignment = r.result[2]
                            if(limit_lead > lead_count_after_assignment){
                                limit_lead = lead_count_after_assignment;
                            }
                            
                            person_to_start = r.result[4]
                            if(r.result[1] === 0){
                                frappe.msgprint(__("No Filtered Leads Found To Assign"));
                            }
                            if(r.result[3] <= 0){
                                flag = false
                            }
                            if(r.result[5] == 1){
                                frappe.msgprint("Lead Can't be Assigned")
                                flag = false
                            }
                            
                            else{
                                count += 1;
                                let user_activity = []
                                table_main = usersLead
                                updated_table_value = usersLead
                                // console.log(usersLead,'usersLead')
                                // usersLead.forEach((values) =>{
                                    
                                //     frappe.model.set_value('Lead Rule Table', values.name, "daily_total_count", values.daily_total_count);
                                //     frappe.model.set_value('Lead Rule Table', values.name, "last_activity_time", values.last_active);
                                    
                                //     user_activity.push(values.last_active);
                                //     refresh_field(frm.doc.table_main);
                                // });
                                
                                // frm.save();
                            }
                        },
                        error: function(err) {
                            frappe.msgprint(__('Error during API call. Please try again.'));
                            console.error(err);
                        }
                    });
                }
                // flag = false;
                await lead_assignment()
            }
            console.log(updated_table_value, lead_count_after_assignment, count, person_to_start,table_main)
            frm.set_value('lead_count',lead_count_after_assignment);
            updated_table_value.forEach((values) =>{
                                        
                frappe.model.set_value('Lead Rule Table', values.name, "daily_total_count", values.daily_total_count);
                frappe.model.set_value('Lead Rule Table', values.name, "last_activity_time", values.last_active);
                
                // user_activity.push(values.last_active);
                refresh_field(frm.doc.table_main);
            });
            frm.save()
        }
        to_call_once()
        
    });
}

});

I am facing the error request timed out when hitting the execute button. Can anyone help me, please?