diff --git a/backgroundWorker.js b/backgroundWorker.js
index dca3f9362916c1ea93c1367b13bf564247512010..53c776bff0e038b9077182a18793cab0e12f480b 100644
--- a/backgroundWorker.js
+++ b/backgroundWorker.js
@@ -1,8 +1,8 @@
 import axios from "axios";
-
+import async from "async";
 const targetURL = process.env.TARGET_URL || "https://hasura.upsmfac.org";
 const notificationURL = process.env.REACT_APP_API_URL || "https://uphrh.in/api/api";
-const emailAuthToken = process.env.REACT_APP_AUTH_TOKEN || "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJSR3RkMkZzeG1EMnJER3I4dkJHZ0N6MVhyalhZUzBSSyJ9.kMLn6177rvY53i0RAN3SPD5m3ctwaLb32pMYQ65nBdA";
+const emailAuthToken = process.env.REACT_APP_AUTH_TOKEN;
 
 const getBulkUploadAssessorSchedule = '/api/rest/getBulkUploadAssessorSchedule';
 const filterAssessments = '/api/rest/filterAssessments';
@@ -16,6 +16,7 @@ const notify = '/email/notify';
 const getFormSubmissionsByFormIds = '/api/rest/getFormSubmissionsByFormIds';
 const updateStatusToBulkUpload = '/api/rest/updateStatusToBulkUpload';
 const getAllAssessorsAPI = '/api/rest/getAllAssessors';
+const getAdminDetailsById = '/api/rest/getRegulator';
 
 // Creating an Axios instance with custom headers
 const axiosInstance = axios.create({
@@ -28,41 +29,21 @@ const axiosInstance = axios.create({
 });
 
 const getBulkUpload = (processStr) => {
-  return new Promise(resolve => {
-      setTimeout(async() => {
+  return new Promise(async(resolve) => {
           try {
-              console.log(processStr);
+              //console.log(processStr);
               const response = await axiosInstance.post(targetURL + getBulkUploadAssessorSchedule, processStr);
               //console.log(response.data);
               resolve(response.data.assessor_schedule_bulk_upload); 
-       //     return response.data;
           } catch (error) {
               console.error('Error getBulkUpload:', error.message);
               throw error;
           }
-     }, 1000);
   });
 };
-const getSchedule = (processStr) => {
-  return new Promise(resolve => {
-       setTimeout(async() => {
-           try {
-               
-               //console.log(processStr);
-               const response = await axiosInstance.post(targetURL + filterAssessments, processStr);
-               //console.log(response.data);
-               resolve(response.data.assessment_schedule); 
-      //return response.data;
-           } catch (error) {
-               console.error('Error getSchedule:', error.message);
-               throw error;
-           }
-       }, 1000);
-   });
- };
+
  const getAllAssessors = () => {
-  return new Promise(resolve => {
-      setTimeout(async() => {
+  return new Promise(async(resolve) => {
           try {
             const processStr = {"offsetNo":0,"limit": 100000}
              //console.log(processStr);
@@ -71,35 +52,15 @@ const getSchedule = (processStr) => {
              const assessors = response.data.assessors;
              const users = assessors.filter(obj => obj["workingstatus"] == "Valid");
              resolve(users); 
-             //return response.data;
           } catch (error) {
               console.error('Error getUsersForScheduling:', error.message);
               throw error;
           }
-      }, 1000);
  });
 };
- const getUsersForScheduling = (processStr) => {
-   return new Promise(resolve => {
-       setTimeout(async() => {
-           try {
-               
-              //console.log(processStr);
-              const response = await axiosInstance.post(targetURL + getUsersForSchedulingAssessment, processStr);
-              //console.log(response.data.assessors);
-              resolve(response.data.assessors); 
-              //return response.data;
-           } catch (error) {
-               console.error('Error getUsersForScheduling:', error.message);
-               throw error;
-           }
-       }, 1000);
-  });
- };
  
 const addAssessmentScheduleToDB = (scheduleStr) => {
-  return new Promise(resolve => {
-      setTimeout(async() => {
+  return new Promise(async(resolve) => {
           try {
               //console.log(scheduleStr);
               const response = await axiosInstance.post(targetURL + addAssessmentSchedule, scheduleStr);
@@ -110,12 +71,10 @@ const addAssessmentScheduleToDB = (scheduleStr) => {
               console.error('Error addAssessmentScheduleToDB:', error.message);
               throw error;
           }
-      }, 1000);
  });
 };
 const addInstituteCourseToDB = (instituteStr) => {
-  return new Promise(resolve => {
-      setTimeout(async() => {
+  return new Promise(async(resolve) => {
           try {
               //console.log(instituteStr);
               const response = await axiosInstance.post(targetURL + addInstituteCourse, instituteStr);
@@ -126,12 +85,10 @@ const addInstituteCourseToDB = (instituteStr) => {
               console.error('Error addInstituteCourse:', error.message);
               throw error;
           }
-      }, 1000);
  });
 };
 const addEventsToDB = (eventsStr) => {
-  return new Promise(resolve => {
-      setTimeout(async() => {
+  return new Promise(async(resolve) => {
           try {
              // console.log(eventsStr);
               const response = await axiosInstance.post(targetURL + addEvents, eventsStr);
@@ -142,12 +99,10 @@ const addEventsToDB = (eventsStr) => {
               console.error('Error addEvents:', error.message);
               throw error;
           }
-      }, 1000);
  });
 };
 const updateFormToDB = (formStr) => {
-  return new Promise(resolve => {
-      setTimeout(async() => {
+  return new Promise(async(resolve) => {
           try {
               //console.log(formStr);
               const response = await axiosInstance.put(targetURL + updateForm, formStr);
@@ -158,16 +113,24 @@ const updateFormToDB = (formStr) => {
               console.error('Error updateForm:', error.message);
               throw error;
           }
-      }, 1000);
  });
 };
 
-const getApplicantDeviceIdFromDB = async (postData) => {
-  const res = await axiosInstance.post(targetURL + getApplicantDeviceId,postData);
-  return res;
+const getAdminDetails = async (adminId) => {
+  try {
+    const postData = {"user_id":adminId};
+    console.log(postData);
+    const res = await axiosInstance.post(targetURL + getAdminDetailsById , postData);
+    //console.log(res);
+    return res.data.regulator;
+  } catch (error) {
+    console.error('Error getAdminDetails:', error.message);
+    throw error;
+  }
 };
 
 const sendEmailNotification = async (postData) => {
+  return new Promise(async(resolve) => {
   const res = await axiosInstance.post(
     notificationURL + notify,
     postData,
@@ -178,11 +141,11 @@ const sendEmailNotification = async (postData) => {
       },
     }
   );
-  return res;
+  resolve( res);
+});
 };
 const getFormSubmissionsByFormId = (arr) => {
-  return new Promise(resolve => {
-      setTimeout(async() => {
+  return new Promise(async(resolve) => {
           try {
               const reqData = {"params": arr};
               const response = await axiosInstance.post(targetURL+getFormSubmissionsByFormIds, reqData);
@@ -191,13 +154,11 @@ const getFormSubmissionsByFormId = (arr) => {
               console.error('Error getFormSubmissionsByFormId:', error.message);
               throw error;
           }
-      }, 1000);
   });
 };
 
 const updateStatusToBulkUploadData = (obj) => {
-  return new Promise(resolve => {
-      setTimeout(async() => {
+  return new Promise(async(resolve) => {
           try {             
               const response = await axiosInstance.post(targetURL + updateStatusToBulkUpload, obj);
               resolve(response.data); 
@@ -205,7 +166,6 @@ const updateStatusToBulkUploadData = (obj) => {
               console.error('Error updateStatusToBulkUploadData :', error.message);
               throw error;
           }
-      }, 1000);
   });
 };
 
@@ -237,99 +197,125 @@ function getDatesFromTodayTo90Days() {
 
   return datesArray;
 }
+function createEmailTable(emailTableRows, id, process_id, application_id, form_title,           
+  application_type, course_type, assessor_id, uploaded_date, updateStatus, updateRemarks){
+  if(emailTableRows.length()===1){
+    emailTableRows.append("<tr><td>Id</td><td>Process_Id</td><td>Form_Id</td><td>Form_Title</td><td>Application_Type</td><td>Course_Type</td><td>Assessor_Id</td><td>Uploaded_Date</td><td>Status</td><td>Remarks</td></tr>");
+  }
+  emailTableRows.append("<tr><td>"+id);
+  emailTableRows.append("</td> <td>" + process_id );
+  emailTableRows.append("</td> <td>" + application_id);
+  emailTableRows.append("</td> <td>" + form_title );
+  emailTableRows.append("</td> <td>" + application_type);
+  emailTableRows.append("</td> <td>" + course_type );
+  emailTableRows.append("</td> <td>" + assessor_id );
+  emailTableRows.append("</td> <td>" + uploaded_date );
+  emailTableRows.append("</td> <td>" + updateStatus );
+  emailTableRows.append("</td> <td>" + updateRemarks +"</td></tr>");
+  return emailTableRows;
+}
+class StringBuffer {
+  constructor() {
+    this.buffer = [];
+  }
 
-const  performBackgroundTask = async () => {
-  const emailTemplate = "<!DOCTYPE html><html><head><meta charset=\'utf-8\'><title>Your Email Title</title><link href=\'https://fonts.googleapis.com/css2?family=Mulish:wght@400;600&display=swap\' rel=\'stylesheet\'></head>"+
-  "<body style=\'font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 0;\'>"+
-  "<table width=\'100%\' bgcolor=\'#ffffff\' cellpadding=\'0\' cellspacing=\'0\' border=\'0\'>"+
-  "<tr><td style=\'padding: 20px; text-align: center; background-color: #F5F5F5;\'><img src=\'https://regulator.upsmfac.org/images/upsmf.png\' alt=\'Logo\' style=\'max-width: 360px;\'></td></tr></table>"+
-  "<table width=\'100%\' bgcolor=\'#ffffff\' cellpadding=\'0\' cellspacing=\'0\' border=\'0\'><tr><td style=\'padding: 36px;\'><p style=\'color: #555555; font-size: 18px; font-family: \'Mulish\', Arial, sans-serif;\'>Dear ${applicantName},</p>"+
-  "<p style=\'color: #555555; font-size: 18px; line-height: 1.6; font-family: \'Mulish\', Arial, sans-serif;\'>We hope this email finds you well. We are glad to inform you that your application has been processed and was found fit for our next step which is on-ground assessment. "+
-  "On-ground assessment for your application have been scheduled. Please expect us to visit your institute very soon.</p><p style=\'color: #555555; font-size: 18px; line-height: 1.6; font-family: \'Mulish\', Arial, sans-serif;\'>Following information will help you prepare for the scheduled on-ground assessment:\\n      "+
-  "<br/>1. A team of assessors will visit your institute for on-ground assessment. To make this process fair and transparent, institutes are not supposed to know the date of on-ground assessment and assessors are not supposed to know the institute they will be assessing till the day of assessment.\\n      "+
-  "<br/>2. We expect your institute open and accessible to our on-ground assessment team on any working day.\\n      "+
-  "<br/>3. Once on-ground assessment team prove their identity, they should be allowed to enter the institute and given full cooperation to carry out the on-ground assessment.</p>"+
-  "<p style=\'color: #555555; font-size: 18px; line-height: 1.6; font-family: \'Mulish\', Arial, sans-serif;\'>If you have any questions or need further clarification regarding the resubmission process, "+
-  "please do not hesitate to reach out to our support executives at <Contact Details>. We are here to assist you and provide any necessary guidance.</p>"+
-  "<p style=\'color: #555555; font-size: 18px; line-height: 1.6; font-family: \'Mulish\', Arial, sans-serif;\'>Thank you for your time and continued interest in getting affiliated from our organization.</p></td></tr></table></body></html>";
+  append(str) {
+    this.buffer.push(str);
+    return this; // Returning the instance for method chaining
+  }
 
+  toString() {
+    return this.buffer.join('');
+  }
+  length() {
+    return this.buffer.length;
+  }
+}
+const getSchedule = async(processStr, callback) => {
+  //return new Promise(async(resolve) => {
+           try {               
+              const response = await axiosInstance.post(targetURL + filterAssessments, processStr);
+             // console.log(response.data.assessment_schedule);
+              var formSchedules = response.data.assessment_schedule;
+              //resolve (formSchedules); 
+              callback(null,formSchedules);
+           } catch (error) {
+               console.error('Error getSchedule:', error.message);
+               throw error;
+           }
+  // });
+ };
+ const getScheduless = async(processStr, callback) => {
+  //return new Promise(async(resolve) => {
+           try {               
+              const response = await axiosInstance.post(targetURL + filterAssessments, processStr);
+             // console.log(response.data.assessment_schedule);
+              var formSchedules = response.data.assessment_schedule;
+              //resolve (formSchedules); 
+              callback(null,formSchedules);
+           } catch (error) {
+               console.error('Error getSchedules:', error.message);
+               throw error;
+           }
+  // });
+ };
+const addAssessorSchedule = (formSubmissionObj, element, assessorObj, callback)=>{
   try {
-    const dateRange = getDatesFromTodayTo90Days();
-    const activeAssessors = await getAllAssessors();
-
-    var bulkUploadData = await getBulkUpload({"where" : {"status": {"_eq": "Pending"}}});
- 
-    // Find duplicates based on the "application_id" attribute
-    const duplicates = findDuplicateRecords(bulkUploadData, 'application_id','process_id');
-    duplicates.forEach(async element => {
-        var updateStatus = "Failed";
-        var updateRemarks = "Duplicate Record";
-        
-        const updateData = await updateStatusToBulkUploadData({id:element.id,status:updateStatus,remarks:updateRemarks});
-        bulkUploadData = bulkUploadData.filter(obj => (obj["application_id"] !== element.application_id && obj["id"]==element.id));      
-    });
-    
-    const formIdArr = bulkUploadData.filter(obj => obj.hasOwnProperty("application_id")).map(obj => obj["application_id"]);
-    const formSubData = await getFormSubmissionsByFormId(formIdArr);
-  
-    var updateStatus = "Success";
-    var updateRemarks = "";
-    
-    bulkUploadData.forEach(async element => {
-        if(formSubData.length == 0){
-          updateRemarks = "Form Application id is not existing in system or payment is not complete.";
-          updateStatus = "Failed";
-        } else {
-          const formSubmissionObj = formSubData.filter(obj => obj["form_id"] === element.application_id);
-          const assessorObj = activeAssessors.filter(assessor => assessor["code"] === (element.assessor_id)+"");
-          if(assessorObj.length == 0){
-            updateRemarks = "Assessor code is not existing in system.";
-            updateStatus = "Failed";
-          } else {
-            //get existing form application schedules
-            const scheduleCriteria1 = {"offsetNo":0,"limit": 100000,"condition": {"applicant_form_id": {"_eq": element.application_id}}};
-            const formSchedules = await getSchedule(scheduleCriteria1);
-            if(formSchedules.length == 0){
-              //get existing assessor schedules
-              var datesNotInArray = [];
-              const scheduleCriteria = {"offsetNo":0,"limit": 100000,"condition": {"assessor_code": {"_eq": element.assessor_id+""}}};
-              const schedules = await getSchedule(scheduleCriteria);
-                            
-              //if no existing schedules, pick the nearest one
-              if(schedules.length == 0){
-                datesNotInArray = dateRange;
-              }else{
-                const scheduledDates = schedules.filter(obj => obj.hasOwnProperty("date")).map(obj => obj["date"]);
-                datesNotInArray = dateRange.filter(date => !scheduledDates.includes(date));
-              }
-              const nearestUpcomingFreeDate = datesNotInArray[0];
-
+  //get existing assessor schedules
+  var datesNotInArray = [];   
+  const scheduleCriteria = {"offsetNo":0,"limit": 100000,"condition": {"assessor_code": {"_eq": element.assessor_id+""}}};
+  getScheduless(scheduleCriteria,(error,schedules)=> {
+      if(error){
+        console.error(`Error getScheduless ${element.id}:`, error);
+        throw error;
+      }else{                                
+        const dateRange = getDatesFromTodayTo90Days();       
+        //if no existing schedules, pick the nearest one
+        if(schedules.length == 0){
+          datesNotInArray = dateRange;
+        }else{
+          const scheduledDates = schedules.filter(obj => obj.hasOwnProperty("date")).map(obj => obj["date"]);
+          datesNotInArray = dateRange.filter(date => !scheduledDates.includes(date));
+          const nearestUpcomingFreeDate = datesNotInArray[0];
+          async.waterfall([
+            function addSchedul(callback1){
               //assign new schedule
               const scheduleStr ={"assessment_schedule":[{
                 "assessor_code":assessorObj[0].code,
-                "date":nearestUpcomingFreeDate,//nextDate.toLocaleString(),
+                "date":nearestUpcomingFreeDate,
                 "institute_id":formSubmissionObj[0].institute.id,
                 "applicant_form_id":formSubmissionObj[0].form_id}]};
-              const addedRec = await addAssessmentScheduleToDB(scheduleStr);
-              //scheduledDates.push(nearestUpcomingFreeDate);
-
+              const addedRec = addAssessmentScheduleToDB(scheduleStr);
+              console.log("added schedule");
+              callback1(null,addedRec);
+            },
+            function addinst(addedRec, callback2){
               const instituteStr ={"institute_course":[{
                 "institute_id":formSubmissionObj[0].institute.id,
                 "institute_type":"[{\"courseType\":\""+formSubmissionObj[0].course_type+"\",\"courseLevel\":\""+formSubmissionObj[0].course_level+"\"}]"}],
                 "institute_form":[{"course_id":formSubmissionObj[0].course_id,"applicant_form_id":formSubmissionObj[0].form_id,"institute_id":formSubmissionObj[0].institute.id,"assessment_date":nearestUpcomingFreeDate}]};
               const addInstRec = addInstituteCourseToDB(instituteStr);
-
+              console.log("added Institute");
+              callback2(null,addInstRec);
+            },
+            function addEve(addInstRec, callback3){
               const eventsStr = {"events":[{
                 "created_date":new Date().toLocaleString(),
                 "entity_id":formSubmissionObj[0].form_id+"",
                 "entity_type":"form",
                 "event_name":"Inspection Scheduled",
                 "remarks":"Round 1 inspection scheduled"}]};
-              const addeventsRec = await addEventsToDB(eventsStr);
-
+              const addeventsRec = addEventsToDB(eventsStr);
+              console.log("Added event");
+              callback3(null,addeventsRec);
+            },
+            function updateFormSub(addeventsRec,callback4){
               const formStr = {"form_id":formSubmissionObj[0].form_id,"form_status":"Inspection Scheduled"};
-              const addFormRec = await updateFormToDB(formStr);
-              
+              const addFormRec = updateFormToDB(formStr);
+              console.log("Updated From Sub");
+              callback4(null,addFormRec);
+            },
+            function sendMail(addFormRec, callback5){
               var email = emailTemplate.replace("${applicantName}",formSubmissionObj[0].institute.name);
               const emailData = {
                 "recipientEmail":[formSubmissionObj[0].institute.email],
@@ -337,22 +323,246 @@ const  performBackgroundTask = async () => {
                 "emailBody":email
               };
               sendEmailNotification(emailData);
-              console.log('Notification sent..');   
-              updateRemarks = "Updated Successfully.";
-              updateStatus = "Success";
+              console.log('Applicant notification sent');   
+              callback5(null,"Success");
+            },
+            function returningCallback(status){
+              callback(null, true, status, "Updated Successfully.");
+            }
+          ], (error, finalResult) => {
+            if (error) {
+              console.error(`Error for element ${element.id}:`, error);
+            } else {
+              console.log(`Final Result for element ${element.id}:`, finalResult);
+            }
+          });
+        }
+      }
+    }
+  );
+} catch (error) {
+  console.error('Error addAssessorSchedule:', error.message);
+  throw error;
+}
+  
+}
+const executeBulkUpload = (bulkUploadData,  emailTableRows, adminId, formSubData, activeAssessors, callback1) => {
+    var updateStatus = "";
+    var updateRemarks = "";
+    console.log("step 5.1 - "+bulkUploadData.length +" adminId "+adminId);
+    var itemsProcessed = 0;
+    var assessorObj;
+    if(bulkUploadData.length === 0){
+      callback1(null,"success",emailTableRows, adminId);
+    }else{
+      bulkUploadData.forEach((element) => { 
+        async.waterfall([   
+          function checkAssessor(callback2){
+          var isUpdate = false;          
+          assessorObj = activeAssessors.filter(assessor => assessor["code"] === (element.assessor_id)+"");
+          if(assessorObj.length === 0){
+            updateRemarks = "Assessor code is not existing in system.";
+            updateStatus = "Failed";
+            callback2(null, true, updateStatus, updateRemarks);
+          }else{
+            callback2(null, false, "", "");
+          }
+        },
+        function getSchedul(isUpdate, updateStatus, updateRemarks, callback3) {
+          if(!isUpdate){         
+            //get existing form application schedule
+            const scheduleCriteria1 = {"offsetNo":0,"limit": 100000,"condition": {"applicant_form_id": {"_eq": element.application_id}}};
+            getSchedule(scheduleCriteria1, (error,formSchedules)=> {
+              if(error){
+                console.error(`Error getSchedule ${element.id}:`, error);
+                throw error;
+              }else{                    
+                 if(formSchedules.length === 0){              
+                    callback3(null, false, "", "");    
+                  }else{
+                    updateRemarks = "Form Schedule Already Exists.";
+                    updateStatus = "Failed";
+                    callback3(null, true, updateStatus, updateRemarks);
+                  }
+                
+              }});           
             }else{
-              updateRemarks = "Form Schedule Already Exists.";
-              updateStatus = "Failed";
+              callback3(null, isUpdate, updateStatus, updateRemarks);
+            }
+        },
+        function addRecords(isUpdate, updateStatus, updateRemarks, callback41){
+            if(!isUpdate){
+              var formSubmissionObj = formSubData.filter(obj => obj["form_id"] === element.application_id);
+              addAssessorSchedule(formSubmissionObj, element, assessorObj,(error,isUpdate, updateStatus,updateRemarks)=>{
+                if(error){
+                  console.error(`Error addAssessorSchedule ${element.id}:`, error);
+                  throw error;
+                }else{  
+                    callback41(null, isUpdate, updateStatus, updateRemarks);
+                }
+              });
+              
+            }else{ 
+              callback41(null, isUpdate, updateStatus, updateRemarks);
             }
+        },
+        function updateDB1(isUpdate, updateStatus, updateRemarks){
+          const updateData = updateStatusToBulkUploadData({id:element.id,status:updateStatus,remarks:updateRemarks});
+          emailTableRows.append(createEmailTable(emailTableRows, element.id, element.process_id, element.application_id, element.form_title,           
+            element.application_type, element.course_type, element.assessor_id, element.uploaded_date, updateStatus, updateRemarks));
+            console.log("Updated id :" + element.id);
+          adminId = element.uploaded_by;
+          itemsProcessed++;
+          if(itemsProcessed === bulkUploadData.length){
+            callback1(null,"success",emailTableRows, adminId);
+          }                 
+        }
+      ], (error, finalResult) => {
+        if (error) {
+          console.error(`Error for element ${element.id}:`, error);
+        } else {
+          console.log(`Final Result for element ${element.id}:`, finalResult);
+        }
+      });
+    }); 
+  }
+};
+
+const findMissingRecords = (object1, object2, key1,key2) => {
+  const set1 = new Set(object1.map(item1 => item1[key1]));
+  const missingRecords = object2.filter(item2 => !set1.has(item2[key2]));
+  return missingRecords;
+};
+const removeDuplicatesFromBulkUpload = (bulkUploadData, emailTableRows, callback) =>{
+  // Find duplicates based on the "application_id" attribute
+  const duplicates = findDuplicateRecords(bulkUploadData, 'application_id','process_id');
+  var itemsProcessed = 0;
+  var adminId = "";
+  console.log("duplicates "+ duplicates.length+" : "+bulkUploadData.length);
+  if(duplicates.length === 0){
+    callback(null,"success",bulkUploadData,emailTableRows,adminId);
+  }else{
+    duplicates.forEach(element => {
+      async.waterfall([
+        function updatedbrec(callback1){
+          var updateStatus = "Failed";
+          var updateRemarks = "Duplicate Record";
+          const updateData = updateStatusToBulkUploadData({id:element.id,status:updateStatus,remarks:updateRemarks});
+          callback1(null, updateStatus, updateRemarks);
+        },
+        function removDup( updateStatus, updateRemarks){
+          emailTableRows.append(createEmailTable(emailTableRows, element.id, element.process_id, element.application_id, element.form_title,           
+            element.application_type, element.course_type, element.assessor_id, element.uploaded_date, updateStatus, updateRemarks));          
+
+          bulkUploadData = bulkUploadData.filter(obj => (obj["id"] !== element.id));         
+          adminId = element.uploaded_by;  
+          itemsProcessed++;               
+          if(itemsProcessed === duplicates.length) {
+            callback(null,"success",bulkUploadData,emailTableRows,adminId);
+          }
+      }]); 
+    });
+  }  
+};
+
+const removeInvalidFormSubmissionIds = async (bulkUploadData, emailTableRows, adminId, formSubData, callback) =>{
+  var itemsProcessed = 0;
+  const missingRecords = findMissingRecords( formSubData, bulkUploadData,"form_id", "application_id");
+  console.log("missingRecords "+ missingRecords.length+" : "+bulkUploadData.length+":"+formSubData.length);
+  if(missingRecords.length === 0){
+    callback(null,"success",bulkUploadData,emailTableRows,adminId);
+  } else {
+    missingRecords.forEach(async (element) => {
+      async.waterfall([
+        function updatedbrec(callback1){
+          var updateRemarks = "Form Application id is not existing in system or payment is not complete.";
+          var updateStatus = "Failed";
+          const updateData = updateStatusToBulkUploadData({id:element.id,status:updateStatus,remarks:updateRemarks});
+          callback1(null, updateStatus, updateRemarks);
+        },
+        function removDup( updateStatus, updateRemarks){
+          emailTableRows.append(createEmailTable(emailTableRows, element.id, element.process_id, element.application_id, element.form_title,           
+            element.application_type, element.course_type, element.assessor_id, element.uploaded_date, updateStatus, updateRemarks));
+          bulkUploadData = bulkUploadData.filter(obj => ( obj["id"]!==element.id));   
+          adminId = element.uploaded_by;
+          itemsProcessed++;   
+          if(itemsProcessed === missingRecords.length) {
+            callback(null,"success",bulkUploadData,emailTableRows,adminId);
           } 
-        } 
-        const updateData = await updateStatusToBulkUploadData({id:element.id,status:updateStatus,remarks:updateRemarks});
-      
+        }]);
+    });
+  }
+};
+var emailTemplate = "<!DOCTYPE html><html><head><meta charset=\'utf-8\'><title>Your Email Title</title><link href=\'https://fonts.googleapis.com/css2?family=Mulish:wght@400;600&display=swap\' rel=\'stylesheet\'></head>"+
+"<body style=\'font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 0;\'>"+
+"<table width=\'100%\' bgcolor=\'#ffffff\' cellpadding=\'0\' cellspacing=\'0\' border=\'0\'>"+
+"<tr><td style=\'padding: 20px; text-align: center; background-color: #F5F5F5;\'><img src=\'https://regulator.upsmfac.org/images/upsmf.png\' alt=\'Logo\' style=\'max-width: 360px;\'></td></tr></table>"+
+"<table width=\'100%\' bgcolor=\'#ffffff\' cellpadding=\'0\' cellspacing=\'0\' border=\'0\'><tr><td style=\'padding: 36px;\'><p style=\'color: #555555; font-size: 18px; font-family: \'Mulish\', Arial, sans-serif;\'>Dear ${applicantName},</p>"+
+"<p style=\'color: #555555; font-size: 18px; line-height: 1.6; font-family: \'Mulish\', Arial, sans-serif;\'>We hope this email finds you well. We are glad to inform you that your application has been processed and was found fit for our next step which is on-ground assessment. "+
+"On-ground assessment for your application have been scheduled. Please expect us to visit your institute very soon.</p><p style=\'color: #555555; font-size: 18px; line-height: 1.6; font-family: \'Mulish\', Arial, sans-serif;\'>Following information will help you prepare for the scheduled on-ground assessment:\\n      "+
+"<br/>1. A team of assessors will visit your institute for on-ground assessment. To make this process fair and transparent, institutes are not supposed to know the date of on-ground assessment and assessors are not supposed to know the institute they will be assessing till the day of assessment.\\n      "+
+"<br/>2. We expect your institute open and accessible to our on-ground assessment team on any working day.\\n      "+
+"<br/>3. Once on-ground assessment team prove their identity, they should be allowed to enter the institute and given full cooperation to carry out the on-ground assessment.</p>"+
+"<p style=\'color: #555555; font-size: 18px; line-height: 1.6; font-family: \'Mulish\', Arial, sans-serif;\'>If you have any questions or need further clarification regarding the resubmission process, "+
+"please do not hesitate to reach out to our support executives at <Contact Details>. We are here to assist you and provide any necessary guidance.</p>"+
+"<p style=\'color: #555555; font-size: 18px; line-height: 1.6; font-family: \'Mulish\', Arial, sans-serif;\'>Thank you for your time and continued interest in getting affiliated from our organization.</p></td></tr></table></body></html>";
+
+var adminEmailTemplate = "<!DOCTYPE html><html><head><meta charset=\'utf-8\'><title>Your Email Title</title><link href=\'https://fonts.googleapis.com/css2?family=Mulish:wght@400;600&display=swap\' rel=\'stylesheet\'></head>"+
+"<body style=\'font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 0; padding: 0;\'>"+
+"<table width=\'100%\' bgcolor=\'#ffffff\' cellpadding=\'0\' cellspacing=\'0\' border=\'0\'>"+
+"<tr><td style=\'padding: 20px; text-align: center; background-color: #F5F5F5;\'><img src=\'https://regulator.upsmfac.org/images/upsmf.png\' alt=\'Logo\' style=\'max-width: 360px;\'></td></tr></table>"+
+"<table width=\'100%\' bgcolor=\'#ffffff\' cellpadding=\'0\' cellspacing=\'0\' border=\'0\'><tr><td style=\'padding: 36px;\'><p style=\'color: #555555; font-size: 18px; font-family: \'Mulish\', Arial, sans-serif;\'>Dear ${adminName},</p>"+
+"<p style=\'color: #555555; font-size: 18px; line-height: 1.6; font-family: \'Mulish\', Arial, sans-serif;\'>Please find the assessor upload status below: "+
+"<table width=\'100%\' bgcolor=\'#ffffff\' cellpadding=\'5\' border=\'1\'>${emailTableRows}</table>"+
+"</p></td></tr></table></body></html>";
+
+const  performBackgroundTask = async () => {
+
+  try {
+    const emailTableRows = new StringBuffer();
+    emailTableRows.append("")
+    const activeAssessors = await getAllAssessors();
+    var bulkUploadData = await getBulkUpload({"where" : {"status": {"_eq": "Pending"}}});
+    removeDuplicatesFromBulkUpload(bulkUploadData, emailTableRows, async (error,result,bulkUploadData,emailTableRows,adminId)=>{
+      if(error){
+        console.error('Error removeDuplicatesFromBulkUpload:', error.message);
+        throw error;
+      }else{
+        const formIdArr = bulkUploadData.filter(obj => obj.hasOwnProperty("application_id")).map(obj => obj["application_id"]);
+        const formSubData = await getFormSubmissionsByFormId(formIdArr);  
+
+        await removeInvalidFormSubmissionIds(bulkUploadData,  emailTableRows, adminId, formSubData,(error,result,bulkUploadData,emailTableRows,adminId)=>{
+        if(error){
+          console.error('Error removeInvalidFormSubmissionIds:', error.message);
+          throw error;
+        }else{
+          executeBulkUpload(bulkUploadData, emailTableRows,adminId, formSubData, activeAssessors, async (error,result,emailTableRows,adminId) => {
+          if(error){
+            console.error('Error executeBulkUpload:', error.message);
+            throw error;
+          }else{
+            if(adminId !==""){
+            const adminDetails = await getAdminDetails(adminId);
+            var adminEmail = adminEmailTemplate.replace("${adminName}", adminDetails[0].full_name);   
+            adminEmail = adminEmail.replace("${emailTableRows}", emailTableRows.toString());
+            const adminEmailData = {
+              "recipientEmail":[adminDetails[0].email,"reshmi.nair@tarento.com"],
+              "emailSubject":"Assessor Upload Status",
+              "emailBody":adminEmail
+            };
+            sendEmailNotification(adminEmailData);
+            console.log('Admin notification sent..');
+          }
+          }
+        });
+      }
+      });
+    }
     });
     // Process the API response
-    //console.log('API Response:', bulkUploadData);
   } catch (error) {
     console.error('Error making API call:', error.message);
+    throw error;
   }
 }
 
diff --git a/index.js b/index.js
index bbddd96dd0ad8136af004ad6cfb138a28527cfed..6d66070c08faa9596b82a8b12e6e97e9292dd79a 100644
--- a/index.js
+++ b/index.js
@@ -2,6 +2,7 @@ import express from "express";
 import { createProxyMiddleware } from "http-proxy-middleware";
 import endpoints from "./endpoints/endpoints.js";
 import easyPay from "./utils/easypay.js";
+import scheduledJob from "./scheduler.js";
 import axios  from "axios";
 
 const app = express();
@@ -13,7 +14,7 @@ import multer from "multer";
 //const multer = require('multer');
 import csv from "csv-parser";
 //const csv = require('csv-parser');
-import fs from "fs";
+import exceljs from "exceljs";
 //const fs = require('fs');
 import stream from "stream";
 
@@ -136,94 +137,98 @@ app.post("/payment/v2/generatelink", async (req, res) => {
   }
 });
 
-// Parse CSV header
-const parseHeader = (csvData) => {
-  const lines = csvData.split('\n');
-  if (lines.length > 0) {
-    return lines[0].split(',').map(header => header.trim().toLowerCase());
-  }
-  return [];
-};
 const bulkUploadAssessorSchedule = '/api/rest/bulkUploadAssessorSchedule';
 const bulkUpload = (updateStr) => {
-  return new Promise(resolve => {
-      setTimeout(async() => {
+  return new Promise(async(resolve) => {
           try {
               console.log(updateStr);
               const response = await axiosInstance.post(targetURL+bulkUploadAssessorSchedule, updateStr);
               resolve(response.data.insert_assessor_schedule_bulk_upload.returning); 
           } catch (error) {
-              console.error('Error updating status:', error.message);
+              console.error('Error in updating data to bulk upload table:', error.message);
               throw error;
           }
-      }, 1000);
   });
 };
 
-// Endpoint for uploading CSV file
-app.post('/upload/assessor/schedule', upload.single('csvFile'), (req, res) => {
+// Endpoint for uploading file
+app.post('/upload/assessor/schedule', upload.single('file'), async(req, res) => {
+  if (!req.file) {
+    return res.status(400).json({ error: 'No file uploaded' });
+  }
+  if (!req.body.userId) {
+    return res.status(400).json({ error: 'UserId is not provided' });
+  }
   try {
-    //const validCSVHeaders = [form_id,form_title,aplication_type,course_type,assessor_id];
-    
-    // Get CSV data from the uploaded file
-    const csvDataString = req.file.buffer.toString('utf8');
+    const processId = uuidv4();
 
-    // Get CSV header
-    const csvHeader = parseHeader(csvDataString);
-    //console.log(csvHeader)
+    const validfileHeaders = ["form_id","form_title","application_type","course_type","assessor_id"];
+    const { userId } = req.body;
+
+    // Get data from the uploaded file
+    const fileDataString = req.file.buffer;    
+    const readableStream = stream.Readable.from(fileDataString);
     
-    const readableStream = stream.Readable.from(csvDataString);
-    const processId = uuidv4();
-    // Parse CSV data
+    const workbook = new exceljs.Workbook();
+    await workbook.xlsx.read(readableStream);
+    const worksheet = workbook.getWorksheet(1); // Assuming the first sheet
+
     const results = [];
-    const parseOptions = {
-      mapHeaders: ({ header, index }) => header.toLowerCase().trim(), // Normalize header names
-      mapValues: ({ value }) => value.trim(), // Trim whitespace from values
-    };
-    //console.log(parseOptions)
-    //const response = {};
-    //DISTRICT,PARENT CENTER CODE,CHILD CENTER CODE,INSTITUTE NAME,ASSESSMENT DATE,ASSESSOR IDS,STATUS
-    //find application id using institute name
-    readableStream.pipe(csv(parseOptions))
-      .on('data', (data) => {
-        const formid = /\d/.test(data.form_id)==true?parseInt(data.form_id, 10):0;
-        const assessor_code = /\d/.test(data.assessor_id)==true?parseInt(data.assessor_id, 10):0;
-          if(formid != 0 && assessor_code!= 0 ){
-            const newObj = {
-              "application_id" : formid,
-              "form_title" : data.form_title,
-              "application_type": data.application_type,
-              "course_type" : data.course_type,
-              "assessor_id" : assessor_code
-            };
-            results.push(newObj);
+    const header = [];
+    // Iterate over rows and columns
+    worksheet.eachRow((row, rowNumber) => {
+      const rowData = {};
+      row.eachCell((cell, colNumber) => {
+        // Assuming the first row contains headers
+        if (rowNumber === 1) {
+          header [colNumber]= cell.value.trim().toLowerCase().replace(/ /g, '_');
+        } else {
+          if(validfileHeaders.includes(header [colNumber])) {
+            var cellValue;
+            if(header [colNumber] == "form_id"){
+              cellValue = /\d/.test(cell.value)==true?parseInt(cell.value, 10):0;
+              rowData["application_id"] = cellValue;
+            }else if(header [colNumber] == "assessor_id") {
+              cellValue = /\d/.test(cell.value)==true?parseInt(cell.value, 10):0;
+              rowData[header [colNumber]] = cellValue;
+            }else{
+              cellValue = cell.value;
+              rowData[header [colNumber]] = cellValue;
+            }
           }
-      })
-      .on('end', async () => {        
-        results.forEach((item) => {
-          item["process_id"]=processId;
-          item["uploaded_by"]="system";
-          item["status"]="Pending";
-          item["uploaded_date"]=new Date().toLocaleString();
-        });
-        //{"assessor_schedule_bulk_upload": [{"id": 1,"process_id":1,"uploaded_by":"system","uploaded_date": "2023-11-17","application_id":234,"assessor_id":232}]} 
-        const bulkUploadDetails = bulkUpload({"assessor_schedule_bulk_upload":results});
-
-        const worker = new Worker('./backgroundWorker.js');
-        worker.on('message', (message) => {
-          console.log(`Background Worker Message: ${message}`);
-        });
-        worker.on('error', (error) => {
-          console.error(`Background Worker Error: ${error}`);
-        });
-        worker.on('exit', (code) => {
-          console.log(`Background Worker exited with code ${code}`);
-        });
-
-        // Process the parsed CSV data
-        res.json({ data: results });
-        
+        }
       });
+      if(Object.keys(rowData).length !== 0){
+        if(rowData.assessor_id == undefined){
+          rowData["assessor_id"]=0;
+        }
+        results.push(rowData);
+      }
+    });        
+    results.forEach((item) => {
+      item["process_id"]=processId;
+      item["uploaded_by"]=userId;
+      item["status"]="Pending";
+      item["uploaded_date"]=new Date().toLocaleString();
+    });
+    //{"assessor_schedule_bulk_upload": [{"id": 1,"process_id":1,"uploaded_by":"system","uploaded_date": "2023-11-17","application_id":234,"assessor_id":232}]} 
+    const bulkUploadDetails = bulkUpload({"assessor_schedule_bulk_upload":results});
+
+    const worker = new Worker('./backgroundWorker.js');
+    worker.on('message', (message) => {
+      console.log(`Background Worker Message: ${message}`);
+    });
+    worker.on('error', (error) => {
+      console.error(`Background Worker Error: ${error}`);
+    });
+    worker.on('exit', (code) => {
+      console.log(`Background Worker exited with code ${code}`);
+    });
+
+    // Process the parsed CSV data
+    res.json({ data: results });
+      
+
   } catch (error) {
     console.error("Error:", error);
     console.error("Error message:", error.message);
@@ -231,7 +236,28 @@ app.post('/upload/assessor/schedule', upload.single('csvFile'), (req, res) => {
   }
 });
 
+// Custom Stream class to create a readable stream from a buffer
+class BufferStream {
+  constructor(buffer) {
+    this.buffer = buffer;
+    this.position = 0;
+  }
+
+  read(size) {
+    if (this.position >= this.buffer.length) {
+      return null;
+    }
+
+    const chunk = this.buffer.slice(this.position, this.position + size);
+    this.position += chunk.length;
+
+    return chunk;
+  }
+}
 
 app.listen(port, () => {
   console.log(`Server is listening on port ${port}`);
 });
+
+
+
diff --git a/package-lock.json b/package-lock.json
index ae1c4cf0a0254844b397780d41ec1da8145355c1..99816d9672a5adf29ba103992b3fad5c299d7753 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -827,4 +827,4 @@
       }
     }
   }
-}
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index 5426fffe637d6c5eb6b5016ca2946f80c2de9929..fa7b37379da3dfe3fe941132d53d2c0b51c36945 100644
--- a/package.json
+++ b/package.json
@@ -13,6 +13,7 @@
   "dependencies": {
     "axios": "^1.4.0",
     "csv-parser": "^3.0.0",
+    "exceljs": "^4.4.0",
     "express": "^4.18.2",
     "http-proxy-middleware": "^2.0.6",
     "multer": "^1.4.5-lts.1",
diff --git a/scheduler.js b/scheduler.js
index 6d62e691f2d37774004a7a640704c43b1adb2453..3c7919548cbcd5816523bdb531517402f18ec56d 100644
--- a/scheduler.js
+++ b/scheduler.js
@@ -21,9 +21,7 @@ const axiosInstance = axios.create({
 
 //Get threshold days from DB
 const fetchThreshold = () => {
-
-    return new Promise(resolve => {
-        setTimeout(async() => {
+    return new Promise(async(resolve) => {
             try {
                 const reqData = {"searchString" : {"status": {"_eq": true}, "type": {"_eq": "scheduler"}},"offSet":0,"limit": 100};
                 const response = await axiosInstance.post(targetURL+GET_THRESHOLD_DAYS,reqData);
@@ -32,15 +30,13 @@ const fetchThreshold = () => {
                 console.error('Error fetching threshold days:', error.message);
                 throw error;
             }
-        }, 1000);
       });
     
 };
 
 //Get submitted date and reviewed date from DB
 const fetchData = (arr) => {
-    return new Promise(resolve => {
-        setTimeout(async() => {
+    return new Promise(async(resolve) => {
             try {
                 const reqData = {"params": arr};
                 const response = await axiosInstance.post(targetURL+GET_FORM_SUBMISSIONS_BY_STATUS, reqData);
@@ -49,14 +45,12 @@ const fetchData = (arr) => {
                 console.error('Error fetching application data:', error.message);
                 throw error;
             }
-        }, 1000);
     });
 };
 
 // Update status using the API
 const updateStatus = (updateStr) => {
-    return new Promise(resolve => {
-        setTimeout(async() => {
+    return new Promise(async(resolve) => {
             try {
                 console.log(updateStr);
                 const response = await axiosInstance.post(targetURL+UPDATE_ENDPOINT, updateStr);
@@ -65,7 +59,6 @@ const updateStatus = (updateStr) => {
                 console.error('Error updating status:', error.message);
                 throw error;
             }
-        }, 1000);
     });
   };
 
@@ -84,7 +77,8 @@ const updateStatus = (updateStr) => {
   };
 
 // Schedule the task to run every day at midnight
-cron.schedule('0 0 * * *', async () => {
+const scheduledJob = cron.schedule('0 0 * * *', async () => {
+  console.log('Cron job running at 12 AM');
   try {
     const currentDate = new Date();    
     const thresholdDaysMap = await fetchThreshold();
@@ -117,7 +111,7 @@ cron.schedule('0 0 * * *', async () => {
                       emailBody: email,
                     };
           
-                    sendEmailNotification(emailData);
+                    await sendEmailNotification(emailData);
                     console.log('Notification sent..');    
                 });
             }
@@ -126,6 +120,12 @@ cron.schedule('0 0 * * *', async () => {
   } catch (error) {
     console.error('Error updating status:', error.message);
   }
+}, {
+  //scheduled: true,
+  timezone: 'Asia/Kolkata', 
 });
 
-console.log('Scheduler started. Waiting for scheduled tasks...');
\ No newline at end of file
+console.log('Scheduler started. Waiting for scheduled tasks...');
+export default {
+  scheduledJob
+};
\ No newline at end of file