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

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.
}
| improve this answer | |
  • 1
    This worked perfectly and I've learned something new today. Thank you! – JaredT Aug 5 '17 at 14:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.