You need to sign in to do that
Don't have an account?
Salesforce2015
Trigger Help
Hi Experts,
I need a trigger help.
Two objects having lookup relationship.
Parent Object - Case
Child Object - Candidate_Task__c
Child object having one custom number field Resource_incurred_hours_Update__c.
Parent object having one custom number field Total_Hours_Update__c.
I need to calculate the sum of all “Resource incurred hours” field values and populate in “Total Hours” field.
Please find the below image and trigger.
Case Object and Custom Object (Project - Task - Resource):
Trigger:
trigger RollUpIncurredHours on Candidate_Task__c (after delete, after insert, after update) {
//Limit the size of list by using Sets which do not contain duplicate elements
set<iD> ProjectTaskResourceIds = new set<iD>();
//When adding new Incurred Hours or updating existing Incurred Hours
if(trigger.isInsert || trigger.isUpdate){
for(Candidate_Task__c p : trigger.new){
ProjectTaskResourceIds.add(p.Resource_incurred_hours_Update__c);
}
}
//When deleting Incurred Hours
if(trigger.isDelete){
for( Candidate_Task__c p : trigger.old){
ProjectTaskResourceIds.add(p.Resource_incurred_hours_Update__c);
}
}
//Map will contain one ProjectTaskResource Id to one sum value
map<Id,Double> ProjectTaskResourceMap = new map<Id,Double> ();
//Produce a sum of Resource_incurred_hours_Update__c and add them to the map
//use group by to have a single ProjectTaskResource Id with a single Incurred Hours
for(AggregateResult q : [select sum(Resource_incurred_hours_Update__c)
from Candidate_Task__c where Candidate_Task__c IN :ProjectTaskResourceIds group by Candidate_Task__c]){
ProjectTaskResourceMap.put((Id)q.get('Candidate_Task__c'),(Double)q.get('expr0'));
}
List ProjectTaskResourceToUpdate = new List();
//Run the for loop on ProjectTaskResource using the non-duplicate set of ProjectTaskResource Ids
//Get the sum value from the map and create a list of ProjectTaskResource to update
for(Candidate_Task__c o : [Select Id, Resource_incurred_hours_Update__c from Candidate_Task__c where Id IN :ProjectTaskResourceIds]){
Double IncurredHoursSum = ProjectTaskResourceMap.get(o.Id);
o.Resource_incurred_hours_Update__c = IncurredHoursSum;
ProjectTaskResourceToUpdate.add(o);
}
update ProjectTaskResourceToUpdate;
}
Anyone sort out my issue. Thanks in advance.
Thanks,
Manu
I need a trigger help.
Two objects having lookup relationship.
Parent Object - Case
Child Object - Candidate_Task__c
Child object having one custom number field Resource_incurred_hours_Update__c.
Parent object having one custom number field Total_Hours_Update__c.
I need to calculate the sum of all “Resource incurred hours” field values and populate in “Total Hours” field.
Please find the below image and trigger.
Case Object and Custom Object (Project - Task - Resource):
Trigger:
trigger RollUpIncurredHours on Candidate_Task__c (after delete, after insert, after update) {
//Limit the size of list by using Sets which do not contain duplicate elements
set<iD> ProjectTaskResourceIds = new set<iD>();
//When adding new Incurred Hours or updating existing Incurred Hours
if(trigger.isInsert || trigger.isUpdate){
for(Candidate_Task__c p : trigger.new){
ProjectTaskResourceIds.add(p.Resource_incurred_hours_Update__c);
}
}
//When deleting Incurred Hours
if(trigger.isDelete){
for( Candidate_Task__c p : trigger.old){
ProjectTaskResourceIds.add(p.Resource_incurred_hours_Update__c);
}
}
//Map will contain one ProjectTaskResource Id to one sum value
map<Id,Double> ProjectTaskResourceMap = new map<Id,Double> ();
//Produce a sum of Resource_incurred_hours_Update__c and add them to the map
//use group by to have a single ProjectTaskResource Id with a single Incurred Hours
for(AggregateResult q : [select sum(Resource_incurred_hours_Update__c)
from Candidate_Task__c where Candidate_Task__c IN :ProjectTaskResourceIds group by Candidate_Task__c]){
ProjectTaskResourceMap.put((Id)q.get('Candidate_Task__c'),(Double)q.get('expr0'));
}
List ProjectTaskResourceToUpdate = new List();
//Run the for loop on ProjectTaskResource using the non-duplicate set of ProjectTaskResource Ids
//Get the sum value from the map and create a list of ProjectTaskResource to update
for(Candidate_Task__c o : [Select Id, Resource_incurred_hours_Update__c from Candidate_Task__c where Id IN :ProjectTaskResourceIds]){
Double IncurredHoursSum = ProjectTaskResourceMap.get(o.Id);
o.Resource_incurred_hours_Update__c = IncurredHoursSum;
ProjectTaskResourceToUpdate.add(o);
}
update ProjectTaskResourceToUpdate;
}
Anyone sort out my issue. Thanks in advance.
Thanks,
Manu
Here is the modified simplier code that Rolls Up the 'Resource_incurred_hours_Update__c' field from all the child records to the parent Case field 'Total_Hours_Update__c'.
Just one thing to check before you use this code -
If you see I have used 'Double' for retrieving the value for Resource_incurred_hours_Update__c. If you get an error in your application because of it then try changing the Type to appropriate value like Integer as per the configuration done for fields Resource_incurred_hours_Update__c and Total_Hours_Update__c.
Thanks
AR
If the reply resolves your problem then please mark it as best answer.
All Answers
Try adding Adding id of the Candidate_Task__c record into the ProjectTaskResourceIds set instead of adding Resource_incurred_hours_Update__c field. So that your query will fetch appropriate records and the feild will be updated with correct value eventually.
Regards
Sai
P.S : If find the answer helpful and it resolves your issue. Please choose my answer as best answer.
Thanks for quick reply.
I'm newbie, please correct my trigger and paste in comment.
Please advise me where (Object) I need to write this trigger.
Thanks in advance.
You have done a small mistake here
for(Candidate_Task__c p : trigger.new){
ProjectTaskResourceIds.add(p.Resource_incurred_hours_Update__c); // Here you need to add the case lookup field
}
Go to Candidate_Task__c fileds check the look up field api name which create relationship with Case .\
Also you need to add undelete event in your trigger .
Please let me know if you need any help .Please post your lookup filed api name for further assistant .
Please find below infomation.
Parent Object - Case
Child Object - Candidate_Task__c
Child object custom number field - Resource_incurred_hours_Update__c
Parent object custom number field - Total_Hours_Update__c
Below is Lookup Field information on child object.
Field API Name - Case__c
Thanks,
Manu
Here is the modified simplier code that Rolls Up the 'Resource_incurred_hours_Update__c' field from all the child records to the parent Case field 'Total_Hours_Update__c'.
Just one thing to check before you use this code -
If you see I have used 'Double' for retrieving the value for Resource_incurred_hours_Update__c. If you get an error in your application because of it then try changing the Type to appropriate value like Integer as per the configuration done for fields Resource_incurred_hours_Update__c and Total_Hours_Update__c.
Thanks
AR
If the reply resolves your problem then please mark it as best answer.
Trigger saved sucessfully on object Candidate_Task__c.
But trigger not updating the total hours field on case object.
I had Account as Parent and Merchandise as child. Account's field was getting updated properly with the roll up value of a custom field present on Mercandise object.
I would suggest you to add couple of System.debug statements here and there, and check the outputs.
Thanks
AR
a.Total_Hours_Update__c = (Double)groupResult[0].get('expr0')
What is the type of field 'Total_Hours_Update__c' in your app?
And for adding System.debug statements, add them in every loop or If statement with some relevant value from that loop and see logs which all were executed and with what values.
Trigger trigger on Candidate_Task__c(After Insert) {
Map<Id, Integer> mapCaseIdToHoursValue = new Map<Id, Integer>();
list<Case> lstCase = new list<Case>();
for(Candidate_Task__c objCT : trigger.new)
{
if(objCT.Case__c != null && objCT.Resource_incurred_hours_Update__c != null)
{
if(mapCaseIdToHoursValue.containskey(objCT.Case__c))
mapCaseIdToHoursValue.put(objCT.Case__c, mapCaseIdToHoursValue.get(objCT.Case__c) + objCT.Resource_incurred_hours_Update__c);
else
mapCaseIdToHoursValue.put(objCT.Case__c, objCT.Resource_incurred_hours_Update__c);
}
}
for(Id objCaseId : mapCaseIdToHoursValue.keyset())
{
Case objUpdatedCase = new Case(Id = objCaseId);
objUpdatedCase.Total_Hours_Update__c = objUpdatedCase.Total_Hours_Update__c + mapCaseIdToHoursValue.get(objCaseId);
lstCase.add(objUpdatedCase);
}
if(!lstCase.isEmpty())
update lstCase;
}
Share the following information -
Data Type for fields Total_Hours_Update__c and Resource_incurred_hours_Update__c
I have made a few changes to the code and added some debug statements. Copy paste this code and do some tests like -
1. Create a new Case
2. Create few Candidate Task records with the Resource_incurred_hours_Update__c field filled with some hours for each child record
3. Check logs and share it here. I want to see which all debug statements got executed on creation of new child records.
Thanks
AR
Below are new case record and Debug logs.
Thanks,
Manu
Is the problem resolved? The best answer does not identify that though ;)
The logs you have shared does not help much as I am not able to see the main content. I would suggest you to add the log content as a reply post. I am basically interested to see the System.debug statements that executed, in the logs.
Thanks
AR
Below is my requirement.
Case record with child records (Project-Task-Resources):
Objects and Fields:
Requirement:
Update Case standard object "Total Hours" field from sum of child object (Project-Task-Resources) records having field "Resource Incurred hours".
Thanks,
Manu.
Correct me if I am wrong, I see big difference in the configuration of these two fields and what you are expecting.
Not sure if you realize this, but I can see the two highlighted fields above as Formula fields. How are you then trying to update them using a Trigger?? Secondly, the fields API names you have used in the Trigger are different than the ones shown above.
Have you highlighed wrong fields above, and even placed wrong fields on the page layout or what, please clarify.
You had shared that the fields in picture are -
Total_Hours_Update__c
Resource_incurred_hours_Update__c
But the above screenshot shows the fields as, both of which are formula fields -
Total_Hours__c
Resource_incurred_hours__c
AR
you are correct.
my recent post was my actual requirement.
Those two are formula fields, so i created two number fields with same name. But difference in api name as _Update for new fields.
So i given new fields info for reference.
Please use below new number fields for trigger.
Total_Hours_Update__c
Resource_incurred_hours_Update__c
Remaining all objects and fields are same.
Please let me know if you need further information.
Now i got it, i created number field as Resource_incurred_hours_Update__c.
First we need to update Resource_incurred_hours_Update__c number field with value, after then sum all fields Resource_incurred_hours_Update__c and populate in Total_Hours_Update__c number field.
I guess if the formula fields you created were to be used for the same pupose of holding the individual child record hours and the total rolled up hours then you should replace them with the number fields that you created with different API names.
And expose these fields on the page layout, as these fields are updated using the Trigger.
Then the roll up should properly work.
Thanks
AR
If you found my solution useful that solved your problem then mark it as best answer.
Please try with above code an dlet me knoe any issue ,I was bit busy in my work so i did not respond in time .
If class and trigger both fires rollup summary update.
What will hapen?
My scnario class only update, our trigger not fired. I copied your trigger on Candidate_Task__c and it not update the number field in case using trigger.
Please give me a suggestion.
Did you try exposing the number fields on the UI? Because the number fields are getting used in the code therefore the final roll up value will also be shown in them. First check them.
Thanks
AR
Thanks for quick response.
I tried to copy my code here, but character issue. So, please give me a test mail on manoharsfdc401@gmail.com
Thanks,
Manu
I checked, field showing on pagelayout. But trigger will not update the child value.
From google search i find solution, I tried in class its working fine, but it not updating wrong value for second case record.
Please look below images.
1st Case record for Rest Project - working fine (40+20+50 = 110).
2nd Case record for Rest Project - Updaing wrong value (1st case field value 110 + (20+30) = 160).
.
Thanks for the trigger.
I tested with your provided trigger with my object and fields modification like below in my Dev Org it working fine.
But, i have one more question.
As of now in our production org we have two triggers on same object Candidate_Task__c.
1. updateEmployeeField
2. HoursNoDeleteonCandidateTask
Current trigger was third trigger. Will three triggers working at a time (or) i need to club these three triggers as one trigger.
trigger RollUpIncurredHours on Candidate_Task__c (after delete, after insert, after update) {
//--- To hold the list of cases that needs to be updated with the latest roll up values
List <Case> CaseList = new List<Case>();
Candidate_Task__c[] objs = Trigger.isDelete ? Trigger.old : Trigger.new;
Id CaseId = Null;
for(Candidate_Task__c m : objs){
if(Trigger.isInsert || Trigger.isDelete)
CaseId = m.Case__c;
else if(Trigger.isUpdate) {
Candidate_Task__c mOld = Trigger.oldMap.get(m.Id);
if((mOld.Case__c != Null) && (m.Case__c == Null))
CaseId = mOld.Test__c;
else if(m.Case__c != Null)
CaseId = m.Case__c;
}
if(CaseId != Null) {
List<AggregateResult> groupResult = [select SUM(Resource_incurred_hours__c) from Candidate_Task__c where Case__c <> Null and Case__c = :CaseId group by Case__c];
Case c = [select Id, Total_Hours_new__c from Case where Id = :CaseId];
if(groupResult.size() > 0)
c.Total_Hours_new__c = (Double)groupResult[0].get('expr0');
else
c.Total_Hours_new__c = 0;
CaseList.add(c);
}
}
if(CaseId != Null)
update CaseList;
}
Thanks,
Manu
Good to hear that your problem is resolved.
Regarding multiple triggers on the same object -
1. Make sure that the functionalities implemented in these triggers do not contradict each other
2. As a best practise considering better code manageability, you should have one Trigger having all required events mentioned in it like before insert, after update etc. You can use the Trigger Context Variables to identify the different events for further processing. Here is the link to the same: https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables.htm
But again it is personal choice to combine multiple triggers on same object into one, though I would do that.
Thanks
AR
I'm already given my third trigger code on object Candidate_Task__c.
Please find the below two triggers. Please help me to comebine these three triggers.
1. updateEmployeeField
trigger updateEmployeeField on Candidate_Task__c (before insert, before update) {
System.debug('test');
if(Trigger.isUpdate) {
List<Id> resourceIds = new List<Id>();
//Populate a list of all related cases
for(Candidate_Task__c cs : trigger.new)
{
resourceIds.add(cs.Project_Resource__c);
}
if(resourceIds.size()>0)
{
//Query those resurces
List<Project_Resource__c> resources = [Select Id, Candiadate_user__c from Project_Resource__c where Id in: resourceIds];
//Create a map
Map<Id,Project_Resource__c> resourceMap = new Map<Id,Project_Resource__c>(resources);
//Update the Project_Resource__c objects
for(Candidate_Task__c cs : trigger.new) {
//Only process if there's a case mapped
if(resourceMap.containsKey(cs.Project_Resource__c)) {
//Set the values
cs.Employee__c = resourceMap.get(cs.Project_Resource__c).Candiadate_user__c;
}
}
}
}
if (trigger.isBefore && trigger.isInsert) {
List<Id> resourceIds = new List<Id>();
//Populate a list of all related cases
for(Candidate_Task__c cs : trigger.new)
{
resourceIds.add(cs.Project_Resource__c);
}
if(resourceIds.size()>0)
{
//Query those resurces
List<Project_Resource__c> resources = [Select Id, Candiadate_user__c from Project_Resource__c where Id in: resourceIds];
//Create a map
Map<Id,Project_Resource__c> resourceMap = new Map<Id,Project_Resource__c>(resources);
//Update the Project_Resource__c objects
for(Candidate_Task__c cs : trigger.new) {
//Only process if there's a case mapped
if(resourceMap.containsKey(cs.Project_Resource__c)) {
//Set the values
cs.Employee__c = resourceMap.get(cs.Project_Resource__c).Candiadate_user__c;
}
}
}
}
}
2. HoursNoDeleteonCandidateTask
/*
Raj Vooturi - display error for delete on Task
*/
trigger HoursNoDeleteonCandidateTask on Candidate_Task__c (before delete) {
for (Candidate_Task__c a : Trigger.old) {
if(trigger.isdelete) {
if ( (a.Resource_incurred_hours__c>0) || (a.Resource_Incurred_Expense__c>0) ) {
a.addError('You can\'t delete this Task Resource Record. This Task Resource has time and expense records that are submitted by resources');
}
}
}
}
Thanks,
Manu
Thank you for resolving my trigger issue.
Please see my below same question, but overlapping Apex Class and Apex trigger code.
Please look into below link.
https://developer.salesforce.com/forums/#!/feedtype=SINGLE_QUESTION_DETAIL&dc=Apex_Code_Development&criteria=OPENQUESTIONS&id=906F0000000BGvbIAG
Thanks,
Manu