function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Cloud EliteCloud Elite 

how to discover duplicate leads and be able to field update automatically ?

we have duplicate leads with different amounts, we want to be able to keep the one with the highest amount and the rest keep them inactive till users decide to keep them or delete them. is there a way i cna identify this automaticall and field update the ones with less  amount with in-active ? 

can this done by flows ? or apex? 
Waqar Hussain SFWaqar Hussain SF
I assume you identify a lead as duplicate by email.

You can develop a schedulable apex job and schedule it daily/hourly which will update the duplicate leads as inactive. 

Assuming that you have below fields on Lead
Amount__c
IsActive__c (checkbox field)
Email (standard field)

Schedulable apex Job
global class DeduplicateLeads implements Schedulable {
    global void execute(SchedulableContext ctx) {
          set<string> Emails = new set<string>();
		  list<Lead> Leads = [Select Id, Email, Amount__c, isActive__c from Lead where isconverted = false AND Email != null order by Amount__c desc];
		  
		  list<Lead> leadsToUpdate = new list<Lead>();
		  for(Lead l : leads){
			if(!Emails.add(l.Email)){
				l.isActive__c = false;
				leadsToUpdate.add(l);
			}
		  }
		  
		  if(leadsToUpdate.size() > 0)
		  update leadsToUpdate;
    }
}

See how to schedule apex jobs.
https://help.salesforce.com/articleView?id=code_schedule_batch_apex.htm&type=5

You can also run it from developer console.

Let me know If you have any question.
Cloud EliteCloud Elite
@waqar, thans for your reply. how can i run it from the developer console ? 
Cloud EliteCloud Elite
when i run this  Id batchJobId = Database.executeBatch(new DeduplicateLeads(), 200); 

i get the foolowing error 

Line: 1, Column: 26
Method does not exist or incorrect signature: void executeBatch(DeduplicateLeads, Integer) from the type Database
Cloud EliteCloud Elite
global class DeduplicateLeads implements Schedulable {
    global void execute(SchedulableContext ctx) {
          set<string> Lastname = new set<string>();
		  list<Lead> Leads = [Select Id, Lastname, Allowed_Total__c, isActive__c from Lead where isconverted = false AND Lastname != null order by Allowed_Total__c desc];
		  
		  list<Lead> leadsToUpdate = new list<Lead>();
		  for(Lead l : leads){
			if(!Lastname.add(l.Lastname)){
				l.isActive__c = false;
				leadsToUpdate.add(l);
			}
		  }
		  
		  if(leadsToUpdate.size() > 0)
		  update leadsToUpdate;
    }
}

 
Waqar Hussain SFWaqar Hussain SF
You can run this class from developer console by below code
DeduplicateLeads s=new DeduplicateLeads ();
s.excute(null) ;

You can also schedule this class vis UI. See 
https://help.salesforce.com/articleView?id=code_schedule_batch_apex.htm&type=5
Cloud EliteCloud Elite
i tried to schedule using the UI as per the arctile and i got an error when it ran: 

Scheduler: failed to execute scheduled job: jobId: 7073D00000D4DI8, class: common.apex.async.AsyncApexJobObject, reason: Too many query rows: 50001 

this is another error when i used the above: 
Line: 2, Column: 3
Method does not exist or incorrect signature: void excute(NULL) from the type DeduplicateLeads
Waqar Hussain SFWaqar Hussain SF
Hi, 

I think you have more than 50,000 records in the lead object, pleas limit the query to 50,000 as below.
global class DeduplicateLeads implements Schedulable {
    global void execute(SchedulableContext ctx) {
          set<string> Lastname = new set<string>();
		  list<Lead> Leads = [Select Id, Lastname, Allowed_Total__c, isActive__c from Lead where isconverted = false AND Lastname != null order by Allowed_Total__c desc limit 50000];
		  
		  list<Lead> leadsToUpdate = new list<Lead>();
		  for(Lead l : leads){
			if(!Lastname.add(l.Lastname)){
				l.isActive__c = false;
				leadsToUpdate.add(l);
			}
		  }
		  
		  if(leadsToUpdate.size() > 0)
		  update leadsToUpdate;
    }
}

And then use below code to run the class using developer console, the below example will schedule apex job after 5 minutes for only one time.
String hour = String.valueOf(Datetime.now().hour());
String min = String.valueOf(Datetime.now().minute() + 5); 
String ss = String.valueOf(Datetime.now().second());

//parse to cron expression
String nextFireTime = ss + ' ' + min + ' ' + hour + ' * * ?';

DeduplicateLeads s = new DeduplicateLeads(); 
System.schedule('Job Started At ' + String.valueOf(Datetime.now()), nextFireTime, s);

 
Cloud EliteCloud Elite
Hi Waqar, it didn't work. it says queued when i go to the apex jobs but when i check the scheduled jobs, it says started. what would be the issue ? 

i am trying to do a batch a job but i am getting an error that the field creditor_name__c is not a vailable. can you please review and tell me what is the issue ? can i use this instead? 
 
global class MarkLeads implements Database.Batchable<sObject>{

    global final String Query;
    global MarkLeads(String q){
        Query=q;    
    }

    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC,List<lead> scope){
        for(lead c : scope ) {
            if (!creditor_name__C.add(c.creditor_name__C)){ 
                c.Status = 'Unqualified';
                scope.add(c);
            }}
        if(scope.size()>0)
        update scope;
    }

    global void finish(Database.BatchableContext BC){}

    //MarkLeads.mask();
    global static void mask() {
        String query = 'Select Id, Lastname, Allowed_Total__c, status from Lead where isconverted = false AND Lastname != null order by Allowed_Total__c desc';
        MarkLeads updateBatch = new MarkLeads(query);
        Id BatchProcessId = Database.ExecuteBatch(updateBatch);
    }

}

 
Cloud EliteCloud Elite
creditor_name is a text field
Waqar Hussain SFWaqar Hussain SF
Use below code
 
global class MarkLeads implements Database.Batchable<sObject>{

    global final String Query;
    global set<string> CredSet;
    global MarkLeads(String q){
        Query=q;    
    }

    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC,List<lead> scope){
        if(CredSet == null)
            CredSet = new set<string>();
        for(lead c : scope ) {
            if (!CredSet.add(c.creditor_name__C)){ 
                c.Status = 'Unqualified';
                scope.add(c);
            }}
        if(scope.size()>0)
        update scope;
    }

    global void finish(Database.BatchableContext BC){}

    //MarkLeads.mask();
    global static void mask() {
        String query = 'Select Id, Lastname, Allowed_Total__c,creditor_name__c, status from Lead where isconverted = false AND creditor_name__c != null order by Allowed_Total__c desc';
        MarkLeads updateBatch = new MarkLeads(query);
        Id BatchProcessId = Database.ExecuteBatch(updateBatch);
    }

}