Overview :
Data Migration Wizard allows you to migrate data into Zoho CRM, and at times there are instances where the CRM already has data which is manually created in Zoho CRM which is similar or identical to the data that you are migrating. Data Migration will create new records in this case, which is not a desirable outcome for businesses.
Partner wants to perform a phased migration for a Client where they import Contacts and Deals in more than one phase. Each phase had same contacts associated with different set of Deals and each time the Contact had some updates as the data was fetched from their live environment where they are migrating from.
Requirement :
Contacts module contains duplicates with each phased migration bringing in the same Contacts with a different set of Deals. We need to de-duplicate the Contacts and maintain the association with the Deals from each migration. Their unique identifier for Contacts is the Email field which would be used to identify the duplicates.
Merging Records using Deduplication or Find & Merge can be a tedious task that requires a lot of manual work when the volume of duplicate records is high.
Solution :
To use Custom Function to merge the Contact Records using Merge Record API on the Contacts under a Custom View and search the Contact -> Fetch Duplicates -> Merge against the Contact in the Custom View.
Expected result is the Contacts merged as one using the unique identifier and the Associated Deals migrated during the data migration to be associated with the Merged Contact.
Action Plan :
Newly migrated Contacts will be considered as Master Records by adding a extra column for Custom Checkbox which will be True for all Newly Migrated Records
Create a Custom View in Contacts Module using the Custom Checkbox to pull the Master Contacts separately.
Create a Scheduler to run every 2 hours to execute the Custom Function
Key Points :
- To check and determine the API credits available and manage the execution within the limit to avoid failures due to API exhaustion
- To update the Custom Checkbox field so after the merge is completed, the Contact will be moved out of the Custom List View
- Send an Email as fail safe if the execution fails and copy the Contact ID which fails.
- Plan the schedule execution outside the business hours to avoid being updated in between.
Setup / Configuration :
Create a schedule to run after business hours on Friday for every 2 hours associate and write your own Custom Function script as below
Create the Custom Checkbox field in the Layout Editor :
Create the Custom List View :
Custom Function Script :
- void schedule.mergeContacts()
- {
- listrec = invokeurl
- [
- url :"https://www.zohoapis.com/crm/v7/Contacts?cvid=638969*******7354017&page=1&per_page=100"
- type :GET
- connection:"zohocrm"
- ];
- // get the master records from the custom list view
- master_reclist = listrec.get("data");
- for each master_rec in master_reclist
- {
- uniqueemail = master_rec.get("Email");
- uniqueemailid = master_rec.get("id");
- info "master record id : " + uniqueemailid + " unique email : " + uniqueemail;
- searchrec = invokeurl
- [
- url :"https://www.zohoapis.com/crm/v7/Contacts/search?email=" + uniqueemail
- type :GET
- connection:"zohocrm"
- ];
- // search the child record using the email address of the master record
- totalrec = searchrec.get("data");
- totalsize = totalrec.size();
- if(totalsize > 0)
- {
- for each elem in totalrec
- {
- recid = elem.get("id");
- info uniqueemailid;
- if(recid != uniqueemailid)
- {
- info "Execute for - RecId : " + recid + " & Email : " + uniqueemail;
- fieldList = Map();
- fieldList.put("api_name","Phone");
- // fieldList is the values from the new records that needs to be overwritter
- overwritefields = List();
- overwritefields.add(fieldList);
- master_idslist = Map();
- master_idslist.put("id",recid);
- master_idslist.put("_fields",overwritefields);
- master_rec_det = List();
- master_rec_det.add(master_idslist);
- m = Map();
- // m.put("master_record_fields",master_rec_det);
- m.put("data",master_rec_det);
- dat = List();
- dat.add(m);
- mergedata = Map();
- mergedata.put("merge",dat);
- mergedataJson = mergedata.ToString();
- // info "MergeData : " + mergedataJson;
- try
- {
- mergerec = invokeurl
- [
- url :"https://www.zohoapis.com/crm/v7/Contacts/" + uniqueemailid + "/actions/merge"
- type :POST
- parameters:mergedataJson
- connection:"zohocrm"
- ];
- info mergerec;
- // record merge and response
- fieldupdmp.put("customCheckBox","");
- fieldupdmp = Map();
- updrec = zoho.crm.updateRecord("Contacts",uniqueemailid,fieldupdmp);
- // to finally update the Custom Checkbox so the Contact will no longer be available under the Custom List View
- }
- catch (e)
- {
- status = mergerec.get("code");
- info "Status" + status + " Reason :" + mergerec;
- if(status != "success")
- {
- emailmessage = "<p>Execution Failed Master Id : " + uniqueemailid + " & Child Id : " + recid + "---- Status : " + status + "</p>" + e;
- sub = "Migration Failure Ids - Failsafe";
- sendmail
- [
- from :zoho.adminuserid
- to :"admin1@xyz.com,admin2@xyz.com,admin3@xyz.com"
- subject :sub
- message :emailmessage
- ]
- // send email as try and catch with the failed record ids
- }
- }
- }
- }
- }
- }
- }
Modifications to the Custom Function Script :
Create a custom connection "zohocrm" with the scope "ZohoCRM.modules.Contacts.ALL"
Use the correct API name of the CustomCheckbox from your Zoho CRM Org
Line no 5:, please use the correct Custom List View ID which you can fetch from the URL
Expected Results :
- Merge Successful :
{"merge":[{"code":"SUCCESS","details":{"id":"5434640000015154110"},"message":"The records have been merged successfully","status":"success"}]}
Above message is printed in the logs when the Merge Contact record was successful.
- No Duplicate Contact found with the Email from Master Contact Record :
{"code":"INVALID_DATA","details":{"resource_path_index":1},"message":"Master record is not found","status":"error"}
Above message is printed in the logs when there is no Contact with the same email as the Master Contact Record.
- Failure Emails :
- CustomCheckbox was updated from false to true

- You can also check the logs by going to Setup > Developer Hub > Functions > My Functions > Schedules > Choose the Custom Function > Logs > Choose the Timeframe > Click on the Execution instance > find the logs printed or any error that is encountered.

Note : This is a sample log executed as standalone, not schedule for showcasing the execution log.
Completion :
Once all the Child Contacts are merged after execution, you can delete the CustomCheckbox field and stop the scheduler. Relax the usage of the API Credits and check the Merged Contact Records.