3

I'm absolutly new to apex, started learning a few days ago and currently trying to set up a trigger, that updates a Lead, that is related via a look-up with my custom object. However, I'm failing at almost everything right now (even the tests ...)

I really hope you can hint me to what I'm doing wrong. I don't ask for you to code for me.

So here's my situation: MyCustomObject__c has a Lookup-Relationship AttachedLeadId__c with the Standard-Lead-Object. The Lead has a custom Checkbox "HasCustomObject__c".

My Trigger is on "after update" of MyCustomObject__c and should tick the checkbox to true, if a Lead is in the lookup (and vice versa, tick it to false, if the relationship is deleted). As far as I am concerned (and please, correct me if I am wrong), this isn't possible via workflowrules or the process designer, because a Lead can have multiple CustomObjects in his related list, and the Trigger should only untick the Checkbox, if the lead has exactly zero related CustomObjects.

I already figured out, that AttachedLeadId__r isn't available in my Trigger, so here's my code:

trigger UpdateRelatedCORecords on MyCustomObject__c (after update) {

    Map<Id, Lead> newLeads = new Map<Id, Lead>();
    Map<Id, Lead> oldLeads = new Map<Id, Lead>();

    for ( MyCustomObject__c po : Trigger.new ) {        

        if ( po.AttachedLeadId__c != Trigger.oldMap.get(po.Id).AttachedLeadId__c ) {

            // add ids of new leads to update-list
            if ( po.AttachedLeadId__c != NULL ) {
                newLeads.put(po.AttachedLeadId__c, NULL);           
            }

            // add ids of old leads to update-list
            if ( Trigger.oldMap.get(po.Id).AttachedLeadId__c != NULL) {                 
                oldLeads.put(po.AttachedLeadId__c, NULL);          
            }

        }
    }

    // update new Leads in bulk    
    newLeads.remove(null);
    newLeads.putAll([SELECT ID, hasCustomObject__c FROM Lead WHERE Id IN :newLeads.keySet()]);
    for ( Lead l : newLeads.values() ) {
        l.hasCustomObject__c = true;
    }
    update newLeads.values();

    // update new Leads in bulk
    oldLeads.remove(null);
    oldLeads.putAll([SELECT ID, hasCustomObject__c FROM Lead WHERE Id IN :oldLeads.keySet()]);
    for ( Lead l : oldLeads.values() ) {
        l.hasCustomObject__c = false;
    }
    update oldLeads.values();  
}

So, what's most devastating: When I manually relate a Lead with my CustomObject, the flag is set correctly. However, if I run the code anonymously (or in my tests), the checkbox-update doesn't work.

Can anyone spot the issue here? Please?

EDIT---

Anonymous code, that fails:

MyCustomObject__c testOrga = new MyCustomObject__c (Name='test@test.de', id__c='95', organization__c='Testaccount'); 
Lead testLeadOne = new Lead(LastName='sLastName1', Company = 'Testcompany'); 
insert testOrga; 
insert testLeadOne; 

testOrga.AttachedLeadId__c = testLeadOne.Id; 
update testOrga; 

System.debug(testOrga.AttachedLeadId__c);
System.debug(testLeadOne.hasCustomObject__c);
  • 1
    Your code looks fantastic for somebody who's been coding for so little time. How are you running your code anonymously? Or, rather, what code do you execute? – Sebastian Kessel Apr 8 '16 at 16:58
  • Thanks! I've been studying pretty hard for the last two weeks ^^. This is my anonymous code (and similar to my tests) MyCustomObject__c testOrga = new MyCustomObject__c(Name='test@test.de', id__c='95', organization__c='Testaccount'); Lead testLeadOne = new Lead(LastName='sLastName1', Company = 'Testcompany'); insert testOrga; insert testLeadOne; testOrga.AttachedLeadId__c = testLeadOne.Id; update testOrga; System.debug(testOrga.AttachedLeadId__c); System.debug(testLeadOne.IsOrganizer__c); I'm sorry, I don't know how to format these lines. – Jannis Lietzau Apr 8 '16 at 17:01
  • 3
    @JannisLietzau If you're expecting the last debug statement to show "true", that's where your mistake was. The record you have in memory is not a mirror of what's in the database, but a simple collection of fields (just like the values in a class might be). You have to explicitly query the lead back in memory after update testOrga, but before the debug statement. – sfdcfox Apr 8 '16 at 17:12
  • 2
    Yes, I expected that. Thank you for poiting that out! So System.assertEquals(true, testLeadOne.IsOrganizer__c); won't work either? Instead, I have to go with: Lead updatedLead = [SELECT hasCustomObject__c FROM Lead WHERE Id = :testLeadOne.Id] and assert on updatedLead like this? System.assertEquals(true, updatedLead.hasCustomObject__c);` – Jannis Lietzau Apr 8 '16 at 17:17
0

Even if the suggested solution provided by @sfdcfox of querying the lead again may solve your problem, I see another logic flaw in your trigger.

if ( Trigger.oldMap.get(po.Id).AttachedLeadId__c != NULL) { oldLeads.put(po.AttachedLeadId__c, NULL); }

This code populates the oldLeads map with the new lead id po.AttachedLeadId__c. So when you change the lead from lead A to lead B, your trigger will first update lead B's hasCustomObject__c field to true as its available in newLeads map. Then oldLeads map also have lead B only and updates its hasCustomObject__c to false.

So lead A will be having true and lead B will still have false.

So change that part to

if ( Trigger.oldMap.get(po.Id).AttachedLeadId__c != NULL) { oldLeads.put( Trigger.oldMap.get(po.Id).AttachedLeadId__c , NULL); }

Hope I make some sense.

  • Thank you, you are absolutly right. I figured this out by myself when I was debugging my code - but I didn't post the update. I think my specific question was solved by @sfdcfox, thanks alot. Everything else is more like general refactoring. So how can I mark the answer as "accepted"? The tutorial told me something about that :). – Jannis Lietzau Apr 9 '16 at 12:19

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.