Preface: this post is part of the Write Your First Advanced Trigger series.
Imagine for a moment that you’re enjoying the perfect meal in paradise:
Suddenly, it hits you like a tidal wave. The perfect trigger. This will surely solve that one problem that one person brought up in that meeting a few weeks ago! WAITER!! NAPKIN AND A PEN, PRONTO!!
Let’s begin writing pseudo-code for this chapter’s trigger! (Scroll down for the full trigger diagram)
Node #1: Begin Trigger on Accounts!
trigger ShareTerr on Account (after insert, before update) { .. }
Background learning: When to use before vs after triggers!
Node #2: Is the Account being inserted?
if (Trigger.isInsert) {// Move on to Node #9} else if (Trigger.isUpdate) {// Move on to Node #3 }
Background learning: Trigger Context variables.
Node #4: Has the Zip Code changed?
String oldZip = Trigger.oldMap.get(acc.Id).BillingPostalCode;String newZip = acc.BillingPostalCode; if (newZip != oldZip) { ... }
Background learning: Comparing old and new values in a trigger!
Node #7: Do a SOQL query for AccountShare records on the Account
List<AccountShare> shares = [SELECT Id FROM AccountShare WHERE AccountId = :acc.IdAND RowCause = 'Manual'];
Background learning #1: AccountShare object
Background learning #2: Using Apex variables in a SOQL query
Node #8: Delete AccountShare records
delete shares;
Background learning: Creating, updating, and deleting records
Node #10: Do a SOQL query to find a Territory based on Zip Code
Territory__c terr = [SELECT Id FROM Territory__c WHERE Zip_Code__c = :acc.BillingPostalCode];
Background learning: Using Apex variables in a SOQL query
Node #11: Is there a matching Territory?
if (terr != null) {// Move on to Node #13} else {// Move on to Node #12 }
Background learning: IF statements
Node #13: Do a SOQL query for all Territory Members on the Territory
Territory__c terr = [SELECT Id,(SELECT Id, User__c FROM Territory_Members__r)FROM Territory__c WHERE Zip_Code__c = :acc.BillingPostalCode];
Since we already do a query on the Territory__c object for Node #10, we might as well query for the related Territory Members in the same query too to reduce our overall number of SOQL queries!
Background learning #1: How to write a cross-object SOQL query (“downwards”)
Background learning #2: Why and how to Bulkify your Code
Node #14: Create an AccountShare record for each Territory Member
List<AccountShare> newShares = new List<AccountShare>();for (Territory_Member__c tm : terr.Territory_Members__r) {AccountShare aShare = new AccountShare();aShare.AccountId = acc.Id; aShare.UserOrGroupId = tm.User__c; aShare.AccountAccessLevel = 'Edit'; aShare.OpportunityAccessLevel = 'Edit';newShares.add(aShare); } insert newShares;
Notice the syntax used to iterate through each Territory Member associated with the Territory! It’s the same identifier used when writing a downwards SOQL query.
Background learning #1: Loops – FOR and FOREACH loops
Background learning #2: AccountShare object
Diagram of this chapter’s trigger:
Whew! Great pseudo-code brainstorming session!
But our code isn’t done, we haven’t even bulkified it yet!
Let’s hurry up and finish this meal so we can rush back to the hotel and write our full trigger!
Next post: Example: How to write an Advanced Trigger!
what is territory__c, Zip_Code__c and Territory_Members__r here. Are they supposed to be made by us or are they are satndard fields and object?
1.How does the Node #8 goes to Node# 9 in coding after “delete shares” in else if block and
2. for Node # 10 & 13, i think we have to use the List type for Territory__c terr.
Hey David,
I have query with respect to SOQl.
Suppose i have a value in a String and that value in the string is to be accessed in the Soql query then what is to be done
Code :-
String a=’dell’;
select qty from Store__c where name=?????
Check this post out!
https://www.sfdc99.com/2013/11/04/using-apex-variables-in-a-soql-query/
David,
Why do you interchangeably use lists and objects to store results of SOQL queries? Is there a certain advantage associated with the use of either one in different situations?
For example, you stored the result of AccountShare related SOQL query in a List variable (‘shares’) but the result of Territory related SOQL query in an object instance type variable (‘terr’) . Why is that?
You see this often because it saves you a few lines of code – use only when you know for sure a list will return only one record!
Hi, David
I want to give you small suggestion why can’t you make this site available in offline version mode like w3schools site.where people without the internet connection can also use your site to refer and study anytime.This is just my suggestion that can help people like me.
Great suggestion – let me see what I can do!
Hello David,
Many thanks to you, this site really motivating me to be better salesforce developer.
your teaching method so easy to understand for newbie like me..
Really loved your works, Keep up bro !!
Thank you!!
Hi David,
Loved ur work!! jus one doubt.. what is meant by RowCause = ‘Manual’ in SOQL query. why have you used it? I tried searching in google.. but did not understand properly. Thanks in Advance.
There has to be a reason for every “share”. Since you’re forcing a share instead of the share being created from a sharing rule, you must use the “manual” option!
gr8.. Thanks David!
Thanks David for all the efforts, it is working Great for me.
Not that I did not try learning from other sources, but you are the best .
Aw shucks, thanks Amitabh!
Hi David,
Excellent ! You have explained it in the best way. :-)
You are putting really great efforts for us.
Thank David.
Thanks, really enjoying this chapter Amit!
where are the rest content
Only on Chapter 7 right now, still working on the rest =P