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
Dwain BowmanDwain Bowman 

Apex trigger to create junction object records on insert or update of related object record.

I am attempting to create a simple register "app" for a small sports charity.

Key Objects 
1Contact
2Participation_Events__c
3Participation_Data__c (junction between 1 and 2)

However, I would like to use another Junction (Participant_Group for example), so users can create groups and add multiple contacts to one event at a time - plus store that data in the pre mentioned junction  (3Participation_Data__c)

Additional Objects
4)Group_at_Session__c (lookup between 2 and 6)
5)Participant_Group_Member__c (junction between 1 and 6)
6)Participant_Group__c (information about the group)

Process
Create Contacts
Create Groups
Create Event, add group via lookup
system
- take lookup group and add group to the group_at_session junction (working fine)
- find contact ids in group (seems to be working)
- create new junction records with loop (not working)
- remove lookup value from the new Event record (not working)

There is a bunch of logic on the Participation_Events__c object, it may not make complete sense to do it this way, but the event seems to be the main focal point for the org. 

Here is the code, please take a look. 
 
trigger AddGroupToSession on Participation_Events__c (after insert, after update) {
    for(Participation_Events__c session : Trigger.new) {
        //if(trigger == before update)    
        //  session.Participant_Group__c = null;
        
        if (session.Participant_Group__c != null)
        {
            
            Group_at_Session__c sgroup = new Group_at_Session__c();
            
            sgroup.Sessions__c= session.id;
            sgroup.Participant_Group__c= session.Participant_Group__c;
            
            insert sgroup;
            
            ID groupId = session.Participant_Group__c; 
            
            system.debug('groupId - '+groupId);  
            
            
            list<Participant_Group_Member__c> contactIds = 
                [SELECT Contact__c
                 FROM Participant_Group_Member__c 
                 WHERE Crew_Name__c = :groupId 
                 //Limit 1
                ];            
            
            system.debug('contactIds 1st - '+contactIds.get(0));
            system.debug('contactIds last - '+contactIds[contactIds.size()-1]);
            system.debug('contactIds count - '+contactIds.size());                
            
            if(session.Register_Group__c == true){   
                for(integer i = 0; i < contactIds.size(); i++)  {
                    
                    Participation_Data__c obj = new Participation_Data__c(); 
                    
                    obj.Event__c = session.Id; 
                    obj.Participant_Registered__c= contactIds.get(i);
                    obj.Registered__c=TRUE;
                    
                    insert obj;
                    system.debug('Register = True - '+obj); 
                }
            }
            else{                
                for(integer i = 0; i < contactIds.size(); i++)  {
                    
                    Participation_Data__c obj = new Participation_Data__c(); 
                    
                    obj.Event__c = session.Id; 
                    obj.Participant_Registered__c= contactIds[i];
                    obj.Registered__c=FALSE;
                    
                    insert obj;
                    system.debug('Register = False - '+obj); 
                }
            }   
        }
    }
}



I keep getting the same error; I was hoping someone could help. Error message: "Illegal assignment from Participant_Group_Member__c to Id", which occurs on lines (38,51). However, the system.debug shows that the correct Contact Ids are being pulled by the SOQL query, so I am a bit confused. This is my first attempt at coding, so please explain where I've gone wrong.

Thank you in advance!


 
karthikeyan perumalkarthikeyan perumal
Hello, 

Use below upadated code. 

While referencing a object you have to assign id for them instaed of assing list of object  contactIds  is list of object records from  Participant_Group_Member__c.
trigger AddGroupToSession on Participation_Events__c (after insert, after update) {
    for(Participation_Events__c session : Trigger.new) {
        //if(trigger == before update)    
        //  session.Participant_Group__c = null;
        
        if (session.Participant_Group__c != null)
        {
            
            Group_at_Session__c sgroup = new Group_at_Session__c();
            
            sgroup.Sessions__c= session.id;
            sgroup.Participant_Group__c= session.Participant_Group__c;
            
            insert sgroup;
            
            ID groupId = session.Participant_Group__c; 
            
            system.debug('groupId - '+groupId);  
            
            
            list<Participant_Group_Member__c> contactIds = 
                [SELECT Contact__c
                 FROM Participant_Group_Member__c 
                 WHERE Crew_Name__c = :groupId 
                 //Limit 1
                ];            
            
            system.debug('contactIds 1st - '+contactIds.get(0));
            system.debug('contactIds last - '+contactIds[contactIds.size()-1]);
            system.debug('contactIds count - '+contactIds.size());                
            
            if(session.Register_Group__c == true){   
                for(integer i = 0; i < contactIds.size(); i++)  {
                    
                    Participation_Data__c obj = new Participation_Data__c(); 
                    
                    obj.Event__c = session.Id; 
                    obj.Participant_Registered__c= contactIds.get(i).Id;
                    obj.Registered__c=TRUE;
                    
                    insert obj;
                    system.debug('Register = True - '+obj); 
                }
            }
            else{                
                for(integer i = 0; i < contactIds.size(); i++)  {
                    
                    Participation_Data__c obj = new Participation_Data__c(); 
                    
                    obj.Event__c = session.Id; 
                    obj.Participant_Registered__c= contactIds[i].Id;
                    obj.Registered__c=FALSE;
                    
                    insert obj;
                    system.debug('Register = False - '+obj); 
                }
            }   
        }
    }
}

Hope this will help you. 

Thanks
karthik
 
jigarshahjigarshah
Dwain,

The contactIds list contains an instance of a Contact record at each of its list index. Hence the statements
contactIds[i]
or 
contactIds.get(i)
would return an instance of the respective Contact SObject record and not a single Id value which I believe is what you are trying to extract. Also the field Participant_Registered__c on Participation_Data__c object is expecting an Id value. Hence, there is datatype mismatch in what is expected i.e. dat of type Id versus what is provided i.e. an Sobject record instance which results in the error. Modify your code at line # 38 and 51 as follows.

Updated code for line # 38
obj.Participant_Registered__c= contactIds.get(i).Id;

Updated code for line # 38
obj.Participant_Registered__c= contactIds[i].Id;

By modifying the above lines of code, you are providing a value from the Id column of the respective Sobject Contact record at the specified index.
Hope this helps.

Please DO NOT forget to mark this thread as SOLVED if this answer helps resolve your issue.
Dwain BowmanDwain Bowman
Hello and thank you for your prompt reply. @jigarshah @karthikeyan

I did try adding .id before, I read it on a forum somewhere... but this is the issue. 

The SOQL statement grabs both Contact__c and Group_Member Id in { , }
07:15:50:032 USER_DEBUG [28]|DEBUG|contactIds 1st - Participant_Group_Member__c:{Contact__c=003g000001VsgfpAAB, Id=a0Og0000006zxU7EAI}

Then the main junction Participant_Registered(Contact) is populated with the Group_Member id.
07:15:50:032 USER_DEBUG [53]|DEBUG|Register = False - Participation_Data__c:{Event__c=a09g00000093FLoAAM, Participant_Registered__c=a0Og0000006zxU7EAI, Registered__c=false}

I believe if I can get the first column of the SOQL array for each [ i ], it will work. 

Thanks again,
karthikeyan perumalkarthikeyan perumal
Hello, 

you want to assign Participant_Registered__c=Contact__c(003g000001VsgfpAAB) is this correct? 

For Example:  

"Register = False - Participation_Data__c:{Event__c=a09g00000093FLoAAM, Participant_Registered__c=003g000001VsgfpAAB, Registered__c=false}"  

If your Answer if yes.. make your debug log  like below and let me now the result. 

system.debug('contactIds 1st - '+contactIds.get(0).Contact__c);


if you are getting correct value for this modify your  code 38, 52 like below, 

 obj.Participant_Registered__c= contactIds.get(i).Conect__c;
obj.Participant_Registered__c= contactIds[i].Contact__c;

Hope this will help you.

Thanks
karthik.
 
jigarshahjigarshah
Update lines #38 and #51 with the following code.

Updated code for line # 38
obj.Participant_Registered__c = contactIds.get(i).Contact__c;

Updated code for line # 51
obj.Participant_Registered__c= contactIds[i].Contact__c;

This should help resolve your issue.
Dwain BowmanDwain Bowman
This is the error that I am getting after the .Contact__c change. 


AddGroupToSession: execution of AfterUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AddGroupToSession: maximum trigger depth exceeded Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo]: [] Trigger.AddGroupToSession: line 57, column 1


I believe the insert method for obj is not working. 
However, obj contains the right information to create junction object.  see debug below.
18:18:56:783 USER_DEBUG [53]|DEBUG|

obj- Participation_Data__c:{Event__c=a09g00000093FLoAAM, Participant_Registered__c=003g000001VshWYAAZ, Registered__c=false}



 
jigarshahjigarshah
Dwain, can you post your updated code here? This will help us troubleshoot your issue.
Dwain BowmanDwain Bowman
trigger AddGroupToSession on Participation_Events__c (after insert, after update) {
    for(Participation_Events__c session : Trigger.new) {
        //if(trigger == before update)    
        //  session.Participant_Group__c = null;
        
        if (session.Participant_Group__c != null)
        {
            
            Group_at_Session__c sgroup = new Group_at_Session__c();
            
            sgroup.Sessions__c= session.id;
            sgroup.Participant_Group__c= session.Participant_Group__c;
            
            insert sgroup;
            
            ID groupId = session.Participant_Group__c; 
            
            system.debug('groupId - '+groupId);  
            
            
            list<Participant_Group_Member__c> contactIds = 
                [SELECT Contact__c
                 FROM Participant_Group_Member__c 
                 WHERE Crew_Name__c = :groupId 
                 //Limit 1
                ];            
            
            system.debug('contactIds 1st - '+contactIds.get(0));
            system.debug('contactIds last - '+contactIds[contactIds.size()-1]);
            system.debug('contactIds count - '+contactIds.size());                
            
            if(session.Register_Group__c == true){   
                for(integer i = 0; i < contactIds.size(); i++)  {
                    
                    Participation_Data__c obj = new Participation_Data__c(); 
                    
                    obj.Event__c = session.Id; 
                    obj.Participant_Registered__c= contactIds.get(i).Contact__c;
                    obj.Registered__c=TRUE;
                    obj.RecordTYpeId='012700000009Y3I';

                    system.debug('Register = True - '+obj);   
                        insert obj;
                     
                        }
            }
            else{                
                for(integer i = 0; i < contactIds.size(); i++)  {
                    
                    Participation_Data__c obj = new Participation_Data__c(); 
                    
                    obj.Event__c = session.Id; 
                    obj.Participant_Registered__c= contactIds[i].Contact__c;
                    obj.Registered__c=FALSE;
                    obj.RecordTYpeId='012700000009Y3I';
                    system.debug('Register = b4False - '+obj);                    
                   
                    insert obj;
                    
                }
            }   
        }
    }
}

Review the following errors
AddGroupToSession: execution of AfterUpdate caused by: System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, AddGroupToSession: maximum trigger depth exceeded Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo] Participation_Events trigger event AfterUpdate for [a09g00000093FLo]: [] Trigger.AddGroupToSession: line 58, column 1
karthikeyan perumalkarthikeyan perumal
Hello, 

its look like  one or more trigger may be linked with circular way. make sure your all trigger run only once.

Info to avoid circular dependency

Use static variable, 
Use trigger context variable properly. 
Use  oldMap and newmap.

hope it wil be solve your issue. 

Thanks
karthik

 
jigarshahjigarshah
Dwain,

The error in code is because the Trigger that you have written is executing recursively due to certain operations which are causing the same trigger to be invoked again. As stated, you can use static variables as a mechanism to check if the code has not been already executed and accordingly permit the execution.
 
trigger AddGroupToSession on Participation_Events__c (after insert, after update) {

	private static Boolean isRecursiveExecution = false;
	
	//Execute the trigger only if it has not already executed
	if(!isRecursiveExecution){
	
		//Set the variable to true to avoid recursive execution
		isRecursiveExecution = true;
		
		//Further processing logic goes in here.
		.
		.
		.
	}
}

Also, the code provided, is performing SOQL Queries and DML statements within a for loop at line # 23, 41 and 58 and it is not a recommended practice. Salesforce has limits in terms of the total number of DML statements and SOQL queries that can be executed in a single execution context.

As stated in the documentation, the Execution Governor Limits for SOQL and DML statements for a single execution ontext  is as stated below.
1. Total number of SOQL queries issued1 (This limit doesn’t apply to custom metadata types. In a single Apex transaction, custom metadata records can have unlimited SOQL queries. - 100 (synchronous execution)

2. Total number of DML statements issued - 150


Refer the following link to understand the Salesforce Execution Governor Limits further - https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm

Executing SOQL and DMl statement in a loop would result in hitting the Execution governor limits which will raise a Limit exception which cannot be caught using the standard try / catch code blocks. Hence, the only way to avoid them is to bulkify your code using a combination of Salesforce provided collections such as Lists, Maps and Sets (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_collections.htm).

for e.g. instead of making a call to the insert statement at line # 23, you could use the following code as a guideline to bulkify your code
trigger AddGroupToSession on Participation_Events__c (after insert, after update) {

    private Set<Id> sessionparticpantGroupIdSet = new Set<Id>();
    private List<Group_at_Session__c> groupAtSessionList = new List<Group_at_Session__c>();

    for(Participation_Events__c session : Trigger.new) {
    
        if (session.Participant_Group__c != null){
            
            groupAtSessionList.add(
                new Group_at_Session__c(
                    sgroup.Sessions__c = session.id;
                    sgroup.Participant_Group__c = session.Participant_Group__c;
                );
            );
            
            //Prepare a unique set of session particpant group ids
            sessionparticpantGroupIdSet.add(Participant_Group__c);
        }        
    }//for
    
    //Insert group session records to avoid DML statements within for loop
    if(!groupAtSessionList.isEmpty()){
        try{
            insert(groupAtSessionList);
        }
        catch(System.DmlException dmlExceptionInstance){
            System.debug('GroupSession Insert Error: ' + dmlExceptionInstance.getMessage());
        }
    }
    
    //Remaining processing logic could be added here
    .
    .
    .
    
}//AddGroupToSession

Moreover, the RecordType Ids are hardcoded and is not something that should be done within your code. This is because any Id would change as the envrionment on which the code executes, changes i.e from a Sandbox to a Production instance unless you are using a Full Copy Sandbox.

Use the following code snippet to fetch the Record Type Ids dynamically based on the developer name.
RecordTypeId = 	   Schema.SObjectType.Account.getRecordTypeInfosByName().get('<your_recordtype_developer_name>').getRecordTypeId();
Please DO NOT forget to mark this thread as SOLVED if this answer helps resolve your issue.
jigarshahjigarshah
Please remove the html <i> tags that are automaitcally appended within the code to fetch recordtype id dynamically.