1

I am working with 2 objects - Leads and Company__c.

My requirement is this:

When a lead is created (sometimes done in 5k+ batches but not frequently), sometimes a field (rWeb_Domain__c) is filled out but it is not required.

If this field is populated, I want to either

  1. Populate a lookup field on the Lead with the Company__c record that has the matching rWeb_Domain__c field

  2. If no Company__c record with a matching rWeb_Domain__c field, create such a record and then populate the lookup on Lead

The eventual goal is to flag a lead that belongs to a company that has already been contacted. Once the lookup relationship to the Company__c object is complete I can take it from there declaratively, but I am pretty new to Apex and found this task a bit much for the Process Builder.

My thought so far has been to create two triggers - one for the Lead which searches for a company that matches rWeb_Domain__c or else create one. The other trigger is on the Company object and would search for all leads with the matching rWeb_Domain__c field and update the lookup field.

I am receiving this error when attempting to create a lead:

Error: Invalid Data. Review all error messages below to correct your data. Apex trigger CompanyCreate caused an unexpected exception, contact your administrator: CompanyCreate: execution of BeforeInsert caused by: System.SObjectException: DML statement cannot operate on trigger.new or trigger.old: Trigger.CompanyCreate: line 47, column 1

Lead Trigger:

trigger CompanyCreate on Lead (after insert, after update) {


    //Get list of all rWeb Domains in trigger
    Set<String> doms = new Set<String>();

    for (Lead L : trigger.new) {
        if (doms.contains(L.rWeb_Domain__c) == false) {
            doms.add(L.rWeb_Domain__c);
        }
    }

    //Find existing company records
    Map<String, Company__c> existingCompanies = new Map<String, Company__c>();

    for (Company__c c : [SELECT rWeb_Domain__c, id FROM Company__c WHERE rWeb_Domain__c = :doms]) {
        existingCompanies.put(c.rWeb_Domain__c, c);
    }

    //Create list of companies for non-existing rWebs
    List<Company__c> companyInsert = new List<Company__c>();

for (Lead L : trigger.new) {
    if (existingCompanies.keyset().contains(L.rWeb_Domain__c) == false) {
        Company__c comp = new Company__c();
        comp.Name = L.name;
        comp.rWeb_Domain__c = L.rWeb_Domain__c;
        companyInsert.add(comp);
    }
}

//Insert new companies
insert companyInsert;
}

Company__c trigger:

trigger CompanyLeadAssociation on Company__c (after insert) {

    //Collect domains and companies in a Map to search leads
    Map<String, Company__c> rWebs = new Map<String, Company__c>();

    for (Company__c comps : trigger.new) {
        rWebs.put(comps.rWeb_Domain__c, comps );
    }

    //Search leads related to new Company
    Map<String, Lead> leads = new Map<String, Lead>();
    List<Lead> leadsUpdate = new List<Lead>();

    for (Lead L : [SELECT rWeb_Domain__c, id FROM Lead WHERE rWeb_Domain__c = :rWebs.keyset()]){
        leads.put(L.rWeb_Domain__c, L);
        L.Company__r.id = rWebs.get(L.rWeb_Domain__c).id;
        leadsUpdate.add(L); //<-- only line that fails test case
    }
    update leadsUpdate;
}

Test Class:

@isTest

private Class CompanyCreateTestClass {

    static TestMethod void valdiateCompanyCreate() {

        Company__c c = new Company__c(Name='ABC Corp', rWeb_Domain__c='abc.com');
        insert c;

        Lead L = new Lead(Company='ABC Corp', rWeb_Domain__c='abc.com', LastName='abc');
        insert L;

        Lead L2 = new Lead(Company='DEF Corp', rWeb_Domain__c='def.com', LastName='def');
        insert L2;

        Lead L3 = new Lead(Company='GHI Corp', rWeb_Domain__c='ghi.com', LastName='ghi');
        insert L3;

        System.assertEquals(c.Id, L.Company__r.id);
        System.assert(L2.Company__c != null);

    }

}

1 Answer 1

1

You need to create a new instance of Lead during after insert. Because record is readonly in after insert and DML is not allowed on trigger.new or trigger.old.

trigger CompanyLeadAssociation on Company__c (after insert) {

    //Collect domains and companies in a Map to search leads
    Map<String, Company__c> rWebs = new Map<String, Company__c>();

    for (Company__c comps : trigger.new) {
        rWebs.put(comps.rWeb_Domain__c, comps );
    }

    //Search leads related to new Company
    Map<String, Lead> leads = new Map<String, Lead>();
    List<Lead> leadsUpdate = new List<Lead>();

    for (Lead L : [SELECT rWeb_Domain__c, id FROM Lead WHERE rWeb_Domain__c = :rWebs.keyset()])
    {
        leads.put(L.rWeb_Domain__c, L);
        Lead leadObj = new Lead(); //create new instance
        leadObj.Id = L.Id; //assign Lead Id
        leadObj.Company__c = rWebs.get(L.rWeb_Domain__c).id;  //assign Company      
        leadsUpdate.add(leadObj); //add new object instance in the list
    }
    update leadsUpdate; //finally update.
}
1
  • 1
    This worked perfectly and I've learned something new today. Thank you!
    – JaredT
    Aug 5, 2017 at 14:35

You must log in to answer this question.

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