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
KitagawaSan85KitagawaSan85 

Trigger Update (std) Parent from (custom) Child

We have created a custom many-to-many connection record between the standard Opportunity object the User object called 'business_consultant__c'. There is a checkbox on the connection record that shows records if it is the 'lead' consultant or not. 

 

I am trying to write a trigger on create / save of 'business_consultant__c' that will check to see if the record is a lead consultant, and if so, update another lookup on the opportunity to the users called "Lead_Bus_Consultant__c". 

 

The requirement here is to have the lead business consultant listed on the actual opportunity record. 

 

I am trying to piece this together... 

//Get Ids of lead = true business_consultant__c records that were updated for bulk (just grab the first 1 if there are multiple)

Set<Id> opportunityIds - new Set<Id>();
for (Business_Consultant__c busCon : trigger.new){
   opportunityIds.add(busCon.Opportunity__c);
}

//Check to see if it is the lead
if(busCon.Lead_Consultant__c == TRUE){

//Get Ids of related Opportunities 
List<opportunity> relatedOpportunities = 
[SELECT Opportunity__c FROM Business_Consultant__c WHERE Id in: opportunityIds];

//Set the 'Lead_Bus_Consultant__c' on the Opportunity to the consultant__c field on the connection record. 
for(Opportunity opp : relatedOpportunities){
opp.Lead_Bus_Consultant__c = busCon.Consultant__c;
}else{ //NOTHING
}

 

Is there an easier way of accomplishing this? The field on the Opportunity does not have to be a lookup, it could be a text field with just a name, although user would provide additional functionality. 

 

Any help is greatly appreciated!!

sivaextsivaext

Hi 

 

I think the code is wrong. TRY this

 

 set<id> opportunitiesid = new set<id>();

for(Business_Consultant__c buscon: Trigger.New) {

   opportunitiesid.add(buscon.Opportunity__c)

}

List<Opportunity> updatelst = new List<Opportunity>();

List<Opportunity> lstopp =[select id, Lead_bus_consultant__c from Opportunity where id IN:opportunitiesid];

 

for(Business_Consultant__c buscon:Trigger.New) {

 

  if(buscon.Lead_Consultant__c!=null) {

 

        for(Opportunity opp:lstopp) {

                 if(opp.id == buscon.opportunity__c) {

 

                     opp.Lead_bus_consultant__c = buscon.consultant__r.name;

                      updatelst.add(opp);

}

}

}

}

update updatelst;

 

Note:I used similar field names. Please use proper field names.

 

vishal@forcevishal@force

Hello,

 

This should ideally be done by trigger - so that part is fine.

 

However, in the trigger, you'll have to cover up all scenarios like

 

1. On insert of a new Business Consultant record on an Opportunity, if the Lead_Consultant field is checked, you update the Opportunity - this is done.

 

2. On update of a Business Consultant record, if I uncheck the Lead Consultant field, I again need to update the Opportunity - Not done.

 

3. On delete of a BC record, if I delete the record where Lead Consultant was checked, I have to update the Opportunity - not done.

 

Also, one question that arises here is - can more than one Business Consultant records for a given Opportunity have Lead Consultant checked? If yes, write your logic that way for update and delete cases.

 

 

KitagawaSan85KitagawaSan85

Thanks! 

 

I've gotten most of that covered with the following Trigger (needs to be cleaned up still) 

 

trigger UpdateOpptyLeadBusCon on Business_Consultant__c (after update, after insert, before delete) {

set<id> opportunitiesid = new set<id>();
for(Business_Consultant__c buscon: Trigger.New) {
   opportunitiesid.add(buscon.Opportunity__c);
}
List<Opportunity> updatelst = new List<Opportunity>();
List<Opportunity> lstopp =[select id, Lead_bus_consultant__c from Opportunity where id IN:opportunitiesid];
 
if(trigger.isInsert){

for(Business_Consultant__c buscon:Trigger.New) {
  if(buscon.Lead_Consultant__c == TRUE) {
 
        for(Opportunity opp:lstopp) {
                 if(opp.id == buscon.opportunity__c) {
 
                     opp.Lead_bus_consultant__c = buscon.consultant__c;
                      updatelst.add(opp);
}
}
}}} else {
    for(Business_Consultant__c buscon:Trigger.New){
    Business_Consultant__c oldBusCon = Trigger.oldMap.get(buscon.Id);
    if( (Trigger.isUpdate && buscon.Lead_Consultant__c != oldBusCon.Lead_Consultant__c  && buscon.Lead_Consultant__c != TRUE) || (Trigger.isDelete && buscon.Lead_Consultant__c == TRUE)){
        for(Opportunity opp:lstopp){
            if(opp.id == buscon.opportunity__c){
                opp.Lead_bus_consultant__c = null;
                    updatelst.add(opp);
            }
        } 
    }else{if(buscon.Lead_Consultant__c == TRUE) {
 
        for(Opportunity opp:lstopp) {
                 if(opp.id == buscon.opportunity__c) {
 
                     opp.Lead_bus_consultant__c = buscon.consultant__c;
                      updatelst.add(opp);
}
}
}
}}}

update updatelst;
}

 

However, I am running into a null point exception on line 4 for the isDeletes. 

 

I thought that making it before delete would help... is the issue that if the record is deleted there is no reference to the opportunity__c field anymore? 

 

EDIT: 

I suppose the other option is to prevent users with a vRule from deleting connections where lead_bus_consultant__c == True... but I would rather do it in the trigger :)

KitagawaSan85KitagawaSan85

I modified to code a bit to fix it... didn't realize that you cant use trigger.new for deletes 

 

Code below seems to be working correctly. 

 

trigger UpdateOpptyLeadBusCon on Business_Consultant__c (after update, after insert, before delete) {

//Get the Business Consultant & Opportunity records
set<id> opportunitiesid = new set<id>();

//Set trigger.new or trigger.old depending on if isUpdate / isInsert / isDelete
if(trigger.isUpdate || trigger.isInsert){
    for(Business_Consultant__c buscon: Trigger.New) {
        opportunitiesid.add(buscon.Opportunity__c);
        }
    }else{
    for(Business_Consultant__c buscon: Trigger.Old) {
        opportunitiesid.add(buscon.Opportunity__c);
        }
}

//Create the lists of opportunities        
    List<Opportunity> updatelst = new List<Opportunity>();
    List<Opportunity> lstopp =[select id, Lead_bus_consultant__c from Opportunity where id IN:opportunitiesid];

 
//If isInsert && lead_consultant__c = True, then set the opportunity lead_bus_consultant__c
if(trigger.isInsert){
    for(Business_Consultant__c buscon:Trigger.New) {
        if(buscon.Lead_Consultant__c == TRUE) {
            for(Opportunity opp:lstopp) {
                 if(opp.id == buscon.opportunity__c) {
                     opp.Lead_bus_consultant__c = buscon.consultant__c;
                      updatelst.add(opp);
                 }
            }
        }
    }
}

//If isUpdate check to see if it is changed
if(trigger.isUpdate){
    
    for(Business_Consultant__c buscon:Trigger.New){
    Business_Consultant__c oldBusCon = Trigger.oldMap.get(buscon.Id);
    //If the checkbox has changed position and is no longer true, clear out the opportunity.lead_bus_consultant__c field
    if(Trigger.isUpdate && buscon.Lead_Consultant__c != oldBusCon.Lead_Consultant__c  && buscon.Lead_Consultant__c != TRUE){
        for(Opportunity opp:lstopp){
            if(opp.id == buscon.opportunity__c){
                opp.Lead_bus_consultant__c = null;
                    updatelst.add(opp);
            }
        } 
    }else{
    //Otherwise if the checkbox is checked, set the opportunity.lead_bus_consultant__c field as the consultant from the connector
    if(buscon.Lead_Consultant__c == TRUE) {
 
        for(Opportunity opp:lstopp) {
                 if(opp.id == buscon.opportunity__c) {
 
                     opp.Lead_bus_consultant__c = buscon.consultant__c;
                      updatelst.add(opp);
                }
        }
    }
    }
    }
} 
//If isDelete set the opportunity.lead_bus_consultant__c to null 
else {
if(trigger.isDelete){

    for(Business_Consultant__c buscon:Trigger.Old){
        Business_Consultant__c oldBusCon = Trigger.oldMap.get(buscon.Id);
        if(Trigger.isDelete && buscon.Lead_Consultant__c == TRUE){
            for(Opportunity opp:lstopp){
                if(opp.id == buscon.opportunity__c){
                    opp.Lead_bus_consultant__c = null;
                        updatelst.add(opp);
                }
            } 
        } 
    } 
} 
}
//Update the list of opportnities
update updatelst;
}

 

 

KitagawaSan85KitagawaSan85

Hi, 

I am working on the test class now but still running into some problems that I can't seem to figure out... 

I have this as a test class but it is failing the first system.assertEquals. 
When I try this manually everything is working correctly, but it is not working in the testClass. 

 

Any ideas would be greatly appreciated! 

-Justin 

 

@isTest 
private class testUpdateOpptyLeadBusCon {
    static testMethod void myUnitTest() {

//Create test profile 
Profile p = [select id from profile where name='QAD Sales Rep'];

//Create Users 
User User1 = new User(alias = 'u1', email='u1@testorg.com',
      emailencodingkey='UTF-8', lastname='Testing', languagelocalekey='en_US',
      localesidkey='en_US', profileid = p.Id, country='United States',
      timezonesidkey='America/Los_Angeles', username='u1@testorg.com');
insert User1;

User User2 = new User(alias = 'u2', email='u2@testorg.com',
      emailencodingkey='UTF-8', lastname='Testing', languagelocalekey='en_US',
      localesidkey='en_US', profileid = p.Id, country='United States',
      timezonesidkey='America/Los_Angeles', username='u2@testorg.com');
insert User2;

//Create Q-Scan Opportunity 
Opportunity op = new Opportunity (name='Q-Scan Opportunity', Type='Q-Scan', stageName='Targeted Accounts', closeDate=system.today());
insert op;

//Test isInsert portion of code
//Create Business_Consultant__c 'BC1' (lead = false)
Business_Consultant__c BC1 = new Business_Consultant__c(Consultant__c = User1.id, Opportunity__c = op.id, Lead_Consultant__c = False); 
insert BC1; 

//Create Business_Consultant__c 'BC2' (lead = true)
Business_Consultant__c BC2 = new Business_Consultant__c(Consultant__c = User2.id, Opportunity__c = op.id, Lead_Consultant__c = True); 
insert BC2; 

    //Test that opportunity.Lead_bus_Consultant__c = User2
    System.assertEquals(op.Lead_Bus_Consultant__c, User2.id);
    
//Test isUpdate portion of code
//Uncheck the lead designation on BC2
BC2.Lead_Consultant__c = False;
update BC2;

    //Test that lead business consultant = null 
    system.assertEquals(op.Lead_Bus_Consultant__c, null);

//Set Lead_Bus_Consultant=TRUE on BC1
BC1.Lead_Consultant__c = True; 
update BC1;

    //Test that lead business consultant = User1
    system.assertEquals(op.Lead_Bus_Consultant__c, User1.id);
   
//Delete BC1 
delete BC1;

    //Test that lead business consultant = null 
    system.assertEquals(op.Lead_Bus_Consultant__c, null);
    
//Done. 
}}

 

KitagawaSan85KitagawaSan85

Has anybody had this before, where the trigger works when tested manually, but in a test class it doesnt seem to work? 

vishal@forcevishal@force

Meaning - you getting some error or the code coverage doesn't give expected results?