+ Start a Discussion
StaceyWStaceyW 

Trigger to updated parent field if child type does not already exist.

Hi All,

 

I am a complete novice to the development side, especially Apex and am trying to create a trigger that will 'roll-up' or sum a field from a child record and I can't use standard roll ups due to limits. I have found a lot of code that can help with normal roll ups but the tricky part of what I am trying to do is that the child records of a specific 'type' can only be counted once and there is also another requirement that a field on the child record can't be empty. And that field is only populated, by other code, after the record is inserted. 

 

So basically it's a child object linked to Accounts. When a child is updated, the trigger will need to check if a child record with a specific type already exists for that account. The 'type' field on the child object  is a picklist field. If it does NOT already exist then the field on accoints called points will need to be increased by 10.  If it does already exist then nothing will happen and the record will just be updated as normal. Also, there will need to be an after delete so that when a child record is removed and it is the only one of that type, 10 points will need to be removed from the field on accounts. 

 

I am probably over complicating it but does anyone out there have a similar code I could take a look at that would give me a good starting point?

 

Best Answer chosen by Admin (Salesforce Developers) 
AdrianCCAdrianCC
trigger doStuff on Child__c (after insert, after update, after delete, after undelete) {
	
	Set<String> accIdsSet = new Set<String>();
	if (trigger.isInsert || trigger.isUpdate || trigger.isUndelete) {
		for (Child__c c: trigger.new) {
			if (c.Type__c != null) accIdsSet.add(c.Account__c);
		}
	}

	if (trigger.isDelete) {
		// we use old cause after delete new is not accesible
		for (Child__c c: trigger.old) {
			if (c.Type__c != null) accIdsSet.add(c.Account__c);
		}
	}

	Map<Id, Account> accMap = new Map<Id, Account>([SELECT Id FROM Account WHERE Id IN:accIdsSet]);
	List<Child__c> childrenList = [SELECT Id, Type__c, Account__c FROM Child__c WHERE Account__c IN:accIdsSet AND Type__c!=null];

	List<Account> updatedAccList = new List<Account>();
	Map<Id, List<Child>> accIdToChildrenList = new Map<Id, List<Child>>();
	for (Child__c c: childrenList) {
		if (accIdToChildrenList.get(c.Account__c) == null) {
			List<Child__c> cList = new List<Child__c>();
			cList.add(c);
			accIdToChildrenList.put(c.Account__c, cList);
		} else {
			accIdToChildrenList.get(c.Account__c).add(c);
		}
	}

	for (Id accId: accIdToChildrenList.keyset()) {
		Decimal sum = 0;
		String foundTypes = '';

		for (Child__c c: accIdToChildrenList.get(accId)) {
			if (!foundTypes.contains(c.Type__c)) {
				sum += 10;
				foundTypes += c.Type__c;
			}
		}

		Account acc = accMap.get(accId);
		acc.Rollup_of_10s_c = sum;

		updatedAccList.add(acc);
	}

	System.debug('updatedAccList has this value: ' + updatedAccList);
	update updatedAccList;
}

 

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers.htm

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables_considerations.htm

 

Also, your task now is to write a test class for this... I've left out a scenario where the code breaks :) for you to test and find out

 

Ty,

Adrian

All Answers

AdrianCCAdrianCC
trigger doStuff on Child__c (after insert, after update, after delete, after undelete) {
	
	Set<String> accIdsSet = new Set<String>();
	if (trigger.isInsert || trigger.isUpdate || trigger.isUndelete) {
		for (Child__c c: trigger.new) {
			if (c.Type__c != null) accIdsSet.add(c.Account__c);
		}
	}

	if (trigger.isDelete) {
		// we use old cause after delete new is not accesible
		for (Child__c c: trigger.old) {
			if (c.Type__c != null) accIdsSet.add(c.Account__c);
		}
	}

	Map<Id, Account> accMap = new Map<Id, Account>([SELECT Id FROM Account WHERE Id IN:accIdsSet]);
	List<Child__c> childrenList = [SELECT Id, Type__c, Account__c FROM Child__c WHERE Account__c IN:accIdsSet AND Type__c!=null];

	List<Account> updatedAccList = new List<Account>();
	Map<Id, List<Child>> accIdToChildrenList = new Map<Id, List<Child>>();
	for (Child__c c: childrenList) {
		if (accIdToChildrenList.get(c.Account__c) == null) {
			List<Child__c> cList = new List<Child__c>();
			cList.add(c);
			accIdToChildrenList.put(c.Account__c, cList);
		} else {
			accIdToChildrenList.get(c.Account__c).add(c);
		}
	}

	for (Id accId: accIdToChildrenList.keyset()) {
		Decimal sum = 0;
		String foundTypes = '';

		for (Child__c c: accIdToChildrenList.get(accId)) {
			if (!foundTypes.contains(c.Type__c)) {
				sum += 10;
				foundTypes += c.Type__c;
			}
		}

		Account acc = accMap.get(accId);
		acc.Rollup_of_10s_c = sum;

		updatedAccList.add(acc);
	}

	System.debug('updatedAccList has this value: ' + updatedAccList);
	update updatedAccList;
}

 

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers.htm

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables_considerations.htm

 

Also, your task now is to write a test class for this... I've left out a scenario where the code breaks :) for you to test and find out

 

Ty,

Adrian

This was selected as the best answer
StaceyWStaceyW

Thank you, Adrian!

 

You are officially my hero :P I can now see where I was going wrong as well. Definitely helps with my mission to learn this language! I will work on the test class and figuring out where it breaks! :D

 

Thanks again!