You need to sign in to do that
Don't have an account?
Trigger - updating records with same prefix
I have an object MPIAccounts__c. On this object is text a field called Alert__c. The MPIAccounts__c follows a naming convention e.g 91234-0001, 91234-0002,91234-0003,76111-4556,76111-3120,76111-9458
I want to write a trigger such that if the text in Alert__c is changed on a record, I want to find all records in MPIAccounts__c that has the same prefix as this record and updated these with the same alert text.
e.g if the Alert__c on 91234-0001 is changed to 'This is an invoice', 91234-0002, 91234-0003 should also have it's Alert__c updated to 'This is an invoice'
similarly if the Alert__c on 76111-9458 is changed to 'This is the balance', 76111-4556,76111-3120 should also have it's Alert__c updated to 'This is the balance'.
Note: The MPIAccounts__c are not children of the same parent. So it's not like updating the children of the same same parent.
Any suggestions?
Thanks heaps!!
The more I started thinking about it, the more I realized bulkifying this trigger will be trickier than I initially thought, but still definitely doable. Here's how I'm thinking to do it at a high-level:
1. Loop through the Trigger.new list, comparing the Alert__c value with what's in the Trigger.old value. If they aren't the same, perform the prefix truncation, add it to a list of strings; add said string to a map as such: <truncatedString, Alert__c>
2. If the list of strings is not empty, iterate through it building your query string. Each iteration should append something like 'Name LIKE ' + prefix + '% OR '. After you're done iterating, chop off the last 4 characters of the built string so there's no extra OR conditional operator.
3. Use the built string to query all the related MPIAccount records and put them in a list.
4. Iterate through list of MPIAccounts. Each iteration should perform the same prefix truncation that was done in step 1. Use the truncated prefix string to get the Alert__c value from the previously created map. Apply said value to current MPIAccount record in list.
5. Update MPIAccount list.
You'll also need to create a simple external class with a static variable to ensure that the trigger doesn't re-invoke itself when you perform the DML update in step 5, something like what's shown in the "Using Static Methods and Variables" section at: http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_static.htm
Let me know if you don't really follow along, and I'd be happy to take a crack at writing the trigger for you. You'll just be responsible for debugging and validating the logic :)
All Answers
My initial thought is to use dynamic SOQL... truncate the name of the MPIAccount__c record that fired the trigger by using the dash as a delimiter, then use what's on the left as part of the query string.
The more I started thinking about it, the more I realized bulkifying this trigger will be trickier than I initially thought, but still definitely doable. Here's how I'm thinking to do it at a high-level:
1. Loop through the Trigger.new list, comparing the Alert__c value with what's in the Trigger.old value. If they aren't the same, perform the prefix truncation, add it to a list of strings; add said string to a map as such: <truncatedString, Alert__c>
2. If the list of strings is not empty, iterate through it building your query string. Each iteration should append something like 'Name LIKE ' + prefix + '% OR '. After you're done iterating, chop off the last 4 characters of the built string so there's no extra OR conditional operator.
3. Use the built string to query all the related MPIAccount records and put them in a list.
4. Iterate through list of MPIAccounts. Each iteration should perform the same prefix truncation that was done in step 1. Use the truncated prefix string to get the Alert__c value from the previously created map. Apply said value to current MPIAccount record in list.
5. Update MPIAccount list.
You'll also need to create a simple external class with a static variable to ensure that the trigger doesn't re-invoke itself when you perform the DML update in step 5, something like what's shown in the "Using Static Methods and Variables" section at: http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_classes_static.htm
Let me know if you don't really follow along, and I'd be happy to take a crack at writing the trigger for you. You'll just be responsible for debugging and validating the logic :)
I will give it a shot. If need help will reach out.
you are right. the challenge is bulkifying and trigger reinvoking itself .
I am on the right path but my problem now is assigning the Alert__c value of the updated MyAccount to all other MyAccounts whose names start with the same prefix as this one.
Based on suggestions by @ k_bentsen and trying to do as suggested in the blog http://blog.jeffdouglas.com/2009/10/02/preventing-recursive-future-method-calls-in-salesforce/
for (MyAccount__c a : [Select Id, Name,Alert__c From MyAccount__c where Name like :names])
{
Sorry for the late reply. Here are a few comments:
1. I'm not sure why you're splitting the account name by the "-" and then putting it back together before adding it to your list of string names. In your code below, I had thought to do something more along the lines of:
prefixnames.add(part1);
2. Also, I would suggest creating a map something along the lines of:
map<String, String> AlertsMap = new Map<String, String>();
Then within your loop, you do:
AlertsMap.add(part1, myacc.Alert__c)
This way, you'll have the Alert__c value at the ready for all MyAccount__c records with a matching prefix.
3. Your SOQL query is not going to work. You cannot use the LIKE operator on a list of strings. It must be a hardcoded string such as LIKE 'Dave%' or possibly a single string value, such a String str = 'Dave%', LIKE :str but I've never tried/tested this way so I'm not sure. This is why I suggested to use dynamic SOQL, because you will need to build your SOQL query string with your list of prefixes:
String queryStr = 'SELECT Name, (other fields) FROM MyAccount__c where Name ';
for(String s : prefixnames)
queryStr += 'LIKE \'' + s + '%\' OR Name ';
queryStr = queryStr.substring(0, queryString.length()-9); // chop off the last 'OR Name clause
List<MyAccount__c> myRelAccList = Database.query(queryStr);
Keep in mind I'm writing this code in the forum page box, so I can't guarantee accurate syntax, but hopefully you can interpret the behavior I'm trying to relay.
4. This is more of a personal preference for aesthetics/cleanliness, but I'm not sure why half-way through your trigger, you move into a processor class. I would just keep everything in the trigger, or move everything into the processor class and just have your trigger be one line:
MyAccountProcessor.processAccounts(Trigger.new);
Again, just sharing my preference :) Hope this info helps you along.
Thanks k_bentsen. Much appreciated.
I am still struggling.. In the process of rewriting the code.
I am splitting the account name becuase it is in the format 'x-xxxxx-xxxxxxx' e.g 1-90111-7766554 , 2-88777-6545654
and I want to apply the Alert__c update to all accounts that has the same prefix before the second dash.
i.e if i change the alert on 2-88777-6545654, all accounts with the prefix 2-88777 will get the same Alert__c value
Then then code you have should work just fine for getting the account prefix. In your original post, the naming convention did not include the leading single digit, so I was not accounting for that.
What are you still struggling with?
Thank you for all your help. Truly appreciated!!!!
Finally I got it. I know there are asthetic blemishes as you pointed out earlier.
If possible can you please go through my code and give some feedback and how i could improve it from functionality point of view and if the code needs improvement in regards to governor limits.
Thanks once again.
I'm definitely glad to have helped. I take it that this trigger is functioning as intended? If so, then I'll take away something from this in that I had no idea you could use a list of strings on the right side of a LIKE operator.
Otherwise, everything looks good. You have no SOQL or DML inside loops, which is generally the biggest concern for triggers.
Yes so far so good. it is working as intended.
Thanks for all your help.