1

I've created a scheduled flow that triggers on the following conditions:

  1. Lead has a related account via a Lookup
  2. Lead Has_Activity__c = True
  3. Lead IsConverted = False

When this is scheduled to trigger it will call upon my Apex Class to convert the leads however I am running into Flow Errors saying that "n Apex error occurred: System.DmlException: ConvertLead failed. First exception on row 0; first error: CANNOT_UPDATE_CONVERTED_LEAD However the lead was not converted

How can I update my Apex Code so that it wont return this error? I tried to attempt this by creating batch based on what ChatGPT told me to do :) But I think I need one of you experts to help me out :)

public with sharing class ConvertLeads {

    public class LeadConvertRequest {

        @InvocableVariable(
            label = 'Lead ID'
            description = 'ID of the Lead to convert'
            required = true
        )
        public ID leadId;

        @InvocableVariable(
            label = 'Account ID'
            description = 'The specific Account to convert Lead into. If blank then creates new Account.'
        )
        public ID accountId;

        @InvocableVariable(
            label = 'Contact ID'
            description = 'The specific Contact to convert Lead into. If blank then creates new Contact.'
        )
        public ID contactId;

        @InvocableVariable(
            label = 'Create Opportunity?'
            description = 'Create an Opportunity? Default is true.'
        )
        public Boolean createOpportunity = false;

        @InvocableVariable(
            label = 'Owner ID'
            description = 'Specific user to own the new Account, Contact, and Opportunity records created. Default is the Lead owner.'
        )
        public ID ownerId;

    }

    public class LeadConvertResult {

        @InvocableVariable( label = 'Lead ID' )
        public ID leadId;

        @InvocableVariable( label = 'Account ID' )
        public ID accountId;

        @InvocableVariable( label = 'Contact ID' )
        public ID contactId;

        @InvocableVariable( label = 'Opportunity ID' )
        public ID opportunityId;

    }

    // --------------------------------------------------------------------------------

    @InvocableMethod(
        label = 'Convert Leads'
    )
    public static void convertLeads( List<LeadConvertRequest> requests ) {
        
    LeadStatus ConvertedStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true Limit 1];    
    List<Database.LeadConvert> convertRequests = new List<Database.LeadConvert>();
    for(LeadConvertRequest request : requests) {
        Database.LeadConvert leadConvert = new Database.LeadConvert();
        leadConvert.setLeadId(request.leadId);
        if(request.accountId?.getSObjectType() == Account.sObjectType) {
            leadConvert.setAccountId(request.accountId);
        }
        if(request.contactId?.getSObjectType() == Contact.sObjectType) {
            leadConvert.setContactId(request.contactId);
        }
        leadConvert.setDoNotCreateOpportunity(request.createOpportunity == false);
        if(request.ownerId?.getSObjectType() == User.sObjectType) {
            leadConvert.setOwnerId(request.ownerId);
        }
        convertRequests.add(leadConvert);
        }
        List<Database.LeadConvertResult> convertResults = Database.convertLead(convertRequests, true);

        Database.convertLead(convertRequests, true);
    }
    


        private static Database.LeadConvert transform( LeadConvertRequest request, String convertedStatus ) {

        Database.LeadConvert convertRequest = new Database.LeadConvert();

        convertRequest.setLeadId( request.leadId );
        convertRequest.setConvertedStatus( convertedStatus  ); // Use the variable retrieved from the query

        if ( request.accountId != null ) {
            convertRequest.setAccountId( request.accountId );
        }

        if ( request.contactId != null ) {
            convertRequest.setContactId( request.contactId );
        }

        if ( request.createOpportunity != null && !request.createOpportunity ) {
            convertRequest.setDoNotCreateOpportunity( !request.createOpportunity );
        }

        if ( request.ownerId != null ) {
            convertRequest.setOwnerId( request.ownerId );
        }

        return convertRequest;
    }


    public class ConvertLeadException extends Exception {}
}

1 Answer 1

2

You don't need to query the lead records to convert them, as you already have the Lead Id, and you have all the other details already (they're in LeadConvertRequest). Also, you can't query in a loop if you want to avoid limits, so move the query to get the converted status to the convertLeads method. Finally, don't use 500 for the batch size. Triggers are in batches of 200, so using 500 would split, for example, a list of 1000 items into 6 transactions instead of 5.

Your code can be as simple as:

public static void convertLeads(List<LeadConvertRequest> requests) {
        LeadStatus ConvertedStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true Limit 1];
    List<Database.LeadConvert> convertRequests = new List<Database.LeadConvert>();
    for(LeadConvertRequest request : requests) {
        Database.LeadConvert leadConvert = new Database.LeadConvert();
        leadConvert.setLeadId(request.leadId);
        leadConvert.setConvertedStatus(ConvertedStatus.MasterLabel);
        if(request.accountId?.getSObjectType() == Account.sObjectType) {
            leadConvert.setAccountId(request.accountId);
        }
        if(request.contactId?.getSObjectType() == Contact.sObjectType) {
            leadConvert.setContactId(request.contactId);
        }
        leadConvert.setDoNotCreateOpportunity(request.createOpportunity == false);
        if(request.ownerId?.getSObjectType() == User.sObjectType) {
            leadConvert.setOwnerId(request.ownerId);
        }
        convertRequests.add(leadConvert);
    }
    Database.convertLead(batch, true);
}

Note: you shouldn't use global unless you plan on making this an ISV managed package to install in subscriber orgs. public is just fine for most use cases.

9
  • Man I am really screwing this up where you have Database.convertLead(batch, true) Do I replace batch with Database.convertLead(convertRequests, true);
    – andrew
    Commented Apr 21, 2023 at 22:29
  • I just edited the original submission to what I currently have @sfdcfox I removed batch with ConvertRequests since it was saying "Variable does not exist: batch" and at least for now im not getting any errors
    – andrew
    Commented Apr 21, 2023 at 22:34
  • Ah but when I run the flow I get this error An Apex error occurred: System.NullPointerException: Attempt to de-reference a null object
    – andrew
    Commented Apr 21, 2023 at 22:37
  • @andrew Yes, there was a typo in the code. contactId.getSobjectType() should have been contactId?.getSobjectType(). I've edited that in.
    – sfdcfox
    Commented Apr 21, 2023 at 22:58
  • Do you know why I would be getting there Apex Error when running my flow :( An Apex error occurred: System.DmlException: ConvertLead failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, convertedStatus is required.: [Status]
    – andrew
    Commented Apr 21, 2023 at 23:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .