You need to sign in to do that
Don't have an account?
Looking to twist the mind of a true guru, Please help if you can.
trigger CaseCloseNoOpen on Case (Before update) { List<Id> caseIds = new List<Id>(); Id caseRecordTypeId = [SELECT Id FROM RecordType WHERE Name = 'PM Case' AND SObjectType = 'Case'].Id; Id TaskRecordTypeId = [SELECT Id FROM RecordType WHERE Name = 'PM Task' AND SObjectType = 'Task'].Id; for(Case c : Trigger.New) { if(c.RecordTypeId == caseRecordTypeId && (c.Status == 'Completed' || c.Status == 'Closed')) { caseIds.add(c.Id); } } for(Training_Information__c customobj : [Select Id, Status__c,Case__c From Training_Information__c Where Case__c in: caseIds]) { if(customobj.Status__c == 'Pending' || customobj.Status__c == 'Scheduled') { Trigger.newMap.get(customobj.Case__c).addError('Training has not been completed.'); } } for(Development_Request__c customobj : [Select Id, Stage__c,Case__c From Development_Request__c Where Case__c in: caseIds]) { if(customobj.Stage__c != 'Completed' && customobj.Stage__c != 'Cancelled DR/ VOID' && customobj.Stage__c != 'Draft') { Trigger.newMap.get(customobj.Case__c).addError('There are open Development Request associated with this Case.'); } } for(Task T : [Select Id, Status, WhatId, RecordTypeId From Task Where WhatId in: caseIds]) { if(T.RecordTypeId == TaskRecordTypeId && (T.Status != 'Completed' && T.Status != 'Discarded')) { Trigger.newMap.get(T.WhatId).addError('There are still open PM Task on this Case.'); } } }
How can we make this trigger better? It is a trigger made to do the validation of no open task, training information records or development request records, so that a case which is being used for project management can't be closed until all of these three LOOKUP related objects are all resolved/Completed.
The above code works but I have questions like would it make sense to use a trigger to pass the newmap + oldmap into a class to do all of the heavy lifting?
Also, when evaluating please consider which approach would be easier to get code coverage on and why?
Please help if you can.
Thank you,
Steve Laycock
Steve,
I saw that you had posted earlier as well. I decided that I could give you some insight into your question. I work for a consulting firm and as a best practice we keep our triggers skinny and pass the lists or maps from the trigger into static methods on a class. The only logic allowed in a trigger are simple such as isInsert or isBefore. Handled this way the trigger is easily maintainable and one trigger can be defined for each object. This allows the triggers to be scalable and maintainable. When more logic needs to be performed on an object it is easy to pass another method into the trigger to handle the logic. The individual methods segregate the code and allow for easy debugging and if needed turning off a specific portion of a trigger. As for testing, the tests will be the same. Inserts, updates or deletes will be performed in your unit test and these DML operations will run through your trigger. Really the benefit comes from maintainability, scalability, and reusability. You will be able to reuse the methods found on the class. Just some thoughts. I am sure there are many arguments for or against this. But in my experience I have found that having a sort of service class to hold the methods for a trigger is beneficial.
All Answers
Steve,
I saw that you had posted earlier as well. I decided that I could give you some insight into your question. I work for a consulting firm and as a best practice we keep our triggers skinny and pass the lists or maps from the trigger into static methods on a class. The only logic allowed in a trigger are simple such as isInsert or isBefore. Handled this way the trigger is easily maintainable and one trigger can be defined for each object. This allows the triggers to be scalable and maintainable. When more logic needs to be performed on an object it is easy to pass another method into the trigger to handle the logic. The individual methods segregate the code and allow for easy debugging and if needed turning off a specific portion of a trigger. As for testing, the tests will be the same. Inserts, updates or deletes will be performed in your unit test and these DML operations will run through your trigger. Really the benefit comes from maintainability, scalability, and reusability. You will be able to reuse the methods found on the class. Just some thoughts. I am sure there are many arguments for or against this. But in my experience I have found that having a sort of service class to hold the methods for a trigger is beneficial.
Andrew, thank you I wasn't asking to prove that I was right, I wanted to know the pros and cons just like you have provided for me.
I really appriciate your input. You def won this one.
Thank you, have a great weekend.
Steve Laycock
great response andrew
Andrew what do you think of this solution to the issue? I built out the trigger for all scenarios, and am now using a class with a function to do what I need done now with room to grow any Case based apex need all out of the one trigger with the follow up additions to the class if and when need be. So what do you think?
I added a couple comments.
So when working with record types sometimes it is easier to have a static method on the service class that gets the record types...for example,
Then in your code you do the following...
if(c.RecordTypeId == recordTypesNameMap.get('PM Case').Id)
In this way your record type comparisons are always set up for any method in any class. You would create a service class for task and do the same thing with recordtypes. But it looks good. It will handle your bulk operations and does what you need it to do with the cross object validation.
Awesome! Thank you very much.
Have a great Thanksgiving!
Steve Laycock
So how would you do that but turn the sObject into a variable that you pass in from the class calling the service class? Also, how would you pass it?
Thanks,
Steve Laycock