Hi all, I am a bit new to salesforce and i succesfully wrote this trigger. But i am lack of ideas on bulkifying it. The below trigger is a basic trigger to check if a contact is linked to a program or opportunity or account.
trigger CheckLinktoPrograms on Contact (after update,before delete) {
if(trigger.isupdate){ List<ProgramContactRole__c> lstConRole = new List<ProgramContactRole__c>(); List<AccountContactRole> lstConRole3 = new List<AccountContactRole>(); List<OpportunityContactRole> lstConRole4 = new List<OpportunityContactRole>(); Set<Id> setContactId = new Set<Id>();
for(Contact c:trigger.new){ setContactId.add(c.id); } lstConRole=[select id,name,ContactId__c,ProgramId__c,ProgramId__r.name from ProgramContactRole__c where ContactId__c IN:setContactId]; lstConRole3=[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactId]; lstConRole4=[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactId];
for(integer i=0;i<trigger.new.size();i++){
if(trigger.new[i].Active__c==false ){
for(ProgramContactRole__c pcr:lstConRole){ if(pcr.ContactId__c==trigger.new[i].id){ trigger.new[0].addError('Cannot inactivate Contact if its linked to a Program: '+pcr.ProgramId__r.name); } }
for(AccountContactRole acr:lstConRole3){ if(acr.ContactId==trigger.new[i].id){ trigger.new[0].addError('Cannot inactivate Contact if its linked to an Account: '+acr.Account.name); } }
for(OpportunityContactRole ocr:lstConRole4){ if(ocr.ContactId==trigger.new[i].id){ trigger.new[0].addError('Cannot inactivate Contact if its linked to an Opportunity: '+ocr.Opportunity.name); } }
} if(trigger.new[i].To_be_deleted__c == true){ for(ProgramContactRole__c pcr:lstConRole){ if(pcr.ContactId__c==trigger.new[i].id){ trigger.new[0].addError('Cannot mark as delete if its linked to a Program: '+pcr.ProgramId__r.name); } }
for(AccountContactRole acr:lstConRole3){ if(acr.ContactId==trigger.new[i].id){ trigger.new[0].addError('Cannot mark as delete if its linked to an Account: '+acr.Account.name); } }
for(OpportunityContactRole ocr:lstConRole4){ if(ocr.ContactId==trigger.new[i].id){ trigger.new[0].addError('Cannot mark as delete if its linked to an Opportunity: '+ocr.Opportunity.name); } } } } }
if(trigger.isdelete){ List<AccountContactRole> lstConRole1 = new List<AccountContactRole>(); List<OpportunityContactRole> lstConRole2 = new List<OpportunityContactRole>(); Set<Id> setContactId = new Set<Id>();
} lstConRole1=[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactId]; lstConRole2=[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactId];
for(integer i=0;i<trigger.old.size();i++){
for(AccountContactRole acr:lstConRole1){ if(acr.ContactId==trigger.old[i].id){ string accountname='<html><bold>'; accountname+=acr.Account.name; accountname+='</body></html>'; trigger.old[0].addError('Cannot delete Contact if its linked to an Account: '+accountname+' with a Role ( Contact Role ) '); } }
for(OpportunityContactRole ocr:lstConRole2){ if(ocr.ContactId==trigger.old[i].id){ trigger.old[0].addError('Cannot delete Contact if its linked to an Opportunity: '+ocr.Opportunity.name+' with a Role ( Contact Role ) '); } }
trigger CheckLinktoPrograms on Contact (after update,before delete) {
if(trigger.isupdate){
List<ProgramContactRole__c> lstConRole = new List<ProgramContactRole__c>();
List<AccountContactRole> lstConRole3 = new List<AccountContactRole>();
List<OpportunityContactRole> lstConRole4 = new List<OpportunityContactRole>();
// new varable for delete operation
List<ProgramContactRole__c> lstConRoleForDelete = new List<ProgramContactRole__c>();
List<AccountContactRole> lstConRole3ForDelete = new List<AccountContactRole>();
List<OpportunityContactRole> lstConRole4ForDelete = new List<OpportunityContactRole>();
Set<Id> setContactId = new Set<Id>();
Set<Id> setContactIdForDelete = new Set<Id>();
for(Contact c:trigger.new){
if(c.Active__c == false)
setContactId.add(c.id);
if(c.To_be_deleted__c == true)
setContactIdForDelete.add(c.id);
}
lstConRole=[select id,name,ContactId__c,ProgramId__c,ProgramId__r.name from ProgramContactRole__c where ContactId__c IN:setContactId];
lstConRole3=[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactId];
lstConRole4=[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactId];
for(ProgramContactRole__c pcr:lstConRole){
pcr.addError('Cannot inactivate Contact if its linked to a Program: '+pcr.ProgramId__r.name);
}
for(AccountContactRole acr:lstConRole3){
acr.addError('Cannot inactivate Contact if its linked to an Account: '+acr.Account.name);
}
for(OpportunityContactRole ocr:lstConRole4){
ocr.addError('Cannot inactivate Contact if its linked to an Opportunity: '+ocr.Opportunity.name);
}
// new query
lstConRoleForDelete = [select id,name,ContactId__c,ProgramId__c,ProgramId__r.name from ProgramContactRole__c where ContactId__c IN:setContactIdForDelete];
lstConRole3ForDelete =[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactIdForDelete];
lstConRole4ForDelete =[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactIdForDelete];
for(ProgramContactRole__c pcr:lstConRoleForDelete){
pcr.addError('Cannot mark as delete if its linked to a Program: '+pcr.ProgramId__r.name);
}
for(AccountContactRole acr:lstConRole3ForDelete){
acr.addError('Cannot mark as delete if its linked to an Account: '+acr.Account.name);
}
for(OpportunityContactRole ocr:lstConRole4ForDelete){
ocr.addError('Cannot mark as delete if its linked to an Opportunity: '+ocr.Opportunity.name);
}
}
trigger CheckLinktoPrograms on Contact (after update,before delete) {
if(trigger.isupdate){
List<ProgramContactRole__c> lstConRole = new List<ProgramContactRole__c>();
List<AccountContactRole> lstConRole3 = new List<AccountContactRole>();
List<OpportunityContactRole> lstConRole4 = new List<OpportunityContactRole>();
// new varable for delete operation
List<ProgramContactRole__c> lstConRoleForDelete = new List<ProgramContactRole__c>();
List<AccountContactRole> lstConRole3ForDelete = new List<AccountContactRole>();
List<OpportunityContactRole> lstConRole4ForDelete = new List<OpportunityContactRole>();
Set<Id> setContactId = new Set<Id>();
Set<Id> setContactIdForDelete = new Set<Id>();
for(Contact c:trigger.new){
if(c.Active__c == false)
setContactId.add(c.id);
if(c.To_be_deleted__c == true)
setContactIdForDelete.add(c.id);
}
lstConRole=[select id,name,ContactId__c,ProgramId__c,ProgramId__r.name from ProgramContactRole__c where ContactId__c IN:setContactId];
lstConRole3=[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactId];
lstConRole4=[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactId];
for(ProgramContactRole__c pcr:lstConRole){
pcr.addError('Cannot inactivate Contact if its linked to a Program: '+pcr.ProgramId__r.name);
}
for(AccountContactRole acr:lstConRole3){
acr.addError('Cannot inactivate Contact if its linked to an Account: '+acr.Account.name);
}
for(OpportunityContactRole ocr:lstConRole4){
ocr.addError('Cannot inactivate Contact if its linked to an Opportunity: '+ocr.Opportunity.name);
}
// new query
lstConRoleForDelete = [select id,name,ContactId__c,ProgramId__c,ProgramId__r.name from ProgramContactRole__c where ContactId__c IN:setContactIdForDelete];
lstConRole3ForDelete =[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactIdForDelete];
lstConRole4ForDelete =[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactIdForDelete];
for(ProgramContactRole__c pcr:lstConRoleForDelete){
pcr.addError('Cannot mark as delete if its linked to a Program: '+pcr.ProgramId__r.name);
}
for(AccountContactRole acr:lstConRole3ForDelete){
acr.addError('Cannot mark as delete if its linked to an Account: '+acr.Account.name);
}
for(OpportunityContactRole ocr:lstConRole4ForDelete){
ocr.addError('Cannot mark as delete if its linked to an Opportunity: '+ocr.Opportunity.name);
}
}
Thanks for posting the code. I keep getting the error message
Error:Apex trigger CheckLinktoPrograms caused an unexpected exception, contact your administrator: CheckLinktoPrograms: execution of AfterUpdate caused by: System.FinalException: SObject row does not allow errors: Trigger.CheckLinktoPrograms: line 41, column 1
when i try to update the To_be_deleted__c = true on my contact object
It worked like a charm with few modifications. below is the modified code
trigger CheckLinktoPrograms on Contact (after update,before delete) {
if(trigger.isupdate){ List<ProgramContactRole__c> lstConRole = new List<ProgramContactRole__c>(); List<AccountContactRole> lstConRole3 = new List<AccountContactRole>(); List<OpportunityContactRole> lstConRole4 = new List<OpportunityContactRole>();
// new varable for delete operation List<ProgramContactRole__c> lstConRoleForDelete = new List<ProgramContactRole__c>(); List<AccountContactRole> lstConRole3ForDelete = new List<AccountContactRole>(); List<OpportunityContactRole> lstConRole4ForDelete = new List<OpportunityContactRole>(); Set<Id> setContactId = new Set<Id>(); Set<Id> setContactIdForDelete = new Set<Id>();
for(Contact c:trigger.new){ if(c.Active__c == false) setContactId.add(c.id); if(c.To_be_deleted__c == true) setContactIdForDelete.add(c.id); } lstConRole=[select id,name,ContactId__c,ProgramId__c,ProgramId__r.name from ProgramContactRole__c where ContactId__c IN:setContactId]; lstConRole3=[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactId]; lstConRole4=[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactId]; for(integer i=0;i<trigger.new.size();i++){ for(ProgramContactRole__c pcr:lstConRole){ if(pcr.ContactId__c == trigger.new[i].id){ trigger.new[i].addError('Cannot inactivate Contact if its linked to a Program: '+pcr.ProgramId__r.name); } } for(AccountContactRole acr:lstConRole3){ if(acr.ContactId == trigger.new[i].id){ trigger.new[i].addError('Cannot inactivate Contact if its linked to an Account: '+acr.Account.name); } } for(OpportunityContactRole ocr:lstConRole4){ if(ocr.ContactId == trigger.new[i].id){ trigger.new[i].addError('Cannot inactivate Contact if its linked to an Opportunity: '+ocr.Opportunity.name); } } }
// new query lstConRoleForDelete = [select id,name,ContactId__c,ProgramId__c,ProgramId__r.name from ProgramContactRole__c where ContactId__c IN:setContactIdForDelete]; lstConRole3ForDelete =[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactIdForDelete]; lstConRole4ForDelete =[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactIdForDelete]; for(integer i=0;i<trigger.new.size();i++){ for(ProgramContactRole__c pcr:lstConRoleForDelete){ if(pcr.ContactId__c == trigger.new[i].id){ trigger.new[i].addError('Cannot mark as delete if its linked to a Program: '+pcr.ProgramId__r.name); } }
for(AccountContactRole acr:lstConRole3ForDelete){ if(acr.ContactId == trigger.new[i].id){ trigger.new[i].addError('Cannot mark as delete if its linked to an Account: '+acr.Account.name); } } for(OpportunityContactRole ocr:lstConRole4ForDelete){ if(ocr.ContactId == trigger.new[i].id){ ocr.addError('Cannot mark as delete if its linked to an Opportunity: '+ocr.Opportunity.name); } } } } }
Many Thanks for this code. I created this class and when i hit the Run Test Button for this class it display 0/1 test passed. But when i see in the debug log it correctly displays the expected custom error message as follows:
16:30:49.619 (619100000)|CODE_UNIT_FINISHED|CheckLinktoPrograms on Contact trigger event AfterUpdate for [0039000000RdDVv]
16:30:49.620 (620839000)|DML_END|[37]
16:30:49.620 (620936000)|EXCEPTION_THROWN|[37]|System.DmlException: Update failed. First exception on row 0 with id 0039000000RdDVvAAN; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Cannot inactivate Contact if its linked to an Opportunity: test: []
16:30:49.621 (621676000)|HEAP_ALLOCATE|[37]|Bytes:187
16:30:49.621 (621736000)|FATAL_ERROR|System.DmlException: Update failed. First exception on row 0 with id 0039000000RdDVvAAN; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Cannot inactivate Contact if its linked to an Opportunity: test: []
Class.MileageTrackerTestSuite.runPositiveTestCases: line 37, column 1
16:30:49.621 (621752000)|FATAL_ERROR|System.DmlException: Update failed. First exception on row 0 with id 0039000000RdDVvAAN; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Cannot inactivate Contact if its linked to an Opportunity: test: []
Is it the correct way to HIT the Run Test Button to test the class?
Here is the output after hitting the Run Test.Also i can see 53% code coverage on the trigger.
Time Started 8/22/2013 5:16 PM Class MileageTrackerTestSuite Method Name runPositiveTestCases Pass/Fail Fail Error Message System.DmlException: Update failed. First exception on row 0 with id 0039000000RdDgGAAV; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Cannot mark as delete if its linked to an Opportunity: test: [] Stack Trace
Class.MileageTrackerTestSuite.runPositiveTestCases: line 37, column 1
The Test is showing failed status because of the error message initiated from the trigger--custom error..
I am enhancing your code to do the negative test as well.
I have checked casually only isupdate block,
here is some code you can refer.
All Answers
I have checked casually only isupdate block,
here is some code you can refer.
Hi Asish,
Thanks for posting the code. I keep getting the error message
Error:Apex trigger CheckLinktoPrograms caused an unexpected exception, contact your administrator: CheckLinktoPrograms: execution of AfterUpdate caused by: System.FinalException: SObject row does not allow errors: Trigger.CheckLinktoPrograms: line 41, column 1
when i try to update the To_be_deleted__c = true on my contact object
Any suggestions?
Is it working fine when you are making Active = false?
Hi Ashish,
It worked like a charm with few modifications. below is the modified code
trigger CheckLinktoPrograms on Contact (after update,before delete) {
if(trigger.isupdate){
List<ProgramContactRole__c> lstConRole = new List<ProgramContactRole__c>();
List<AccountContactRole> lstConRole3 = new List<AccountContactRole>();
List<OpportunityContactRole> lstConRole4 = new List<OpportunityContactRole>();
// new varable for delete operation
List<ProgramContactRole__c> lstConRoleForDelete = new List<ProgramContactRole__c>();
List<AccountContactRole> lstConRole3ForDelete = new List<AccountContactRole>();
List<OpportunityContactRole> lstConRole4ForDelete = new List<OpportunityContactRole>();
Set<Id> setContactId = new Set<Id>();
Set<Id> setContactIdForDelete = new Set<Id>();
for(Contact c:trigger.new){
if(c.Active__c == false)
setContactId.add(c.id);
if(c.To_be_deleted__c == true)
setContactIdForDelete.add(c.id);
}
lstConRole=[select id,name,ContactId__c,ProgramId__c,ProgramId__r.name from ProgramContactRole__c where ContactId__c IN:setContactId];
lstConRole3=[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactId];
lstConRole4=[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactId];
for(integer i=0;i<trigger.new.size();i++){
for(ProgramContactRole__c pcr:lstConRole){
if(pcr.ContactId__c == trigger.new[i].id){
trigger.new[i].addError('Cannot inactivate Contact if its linked to a Program: '+pcr.ProgramId__r.name);
}
}
for(AccountContactRole acr:lstConRole3){
if(acr.ContactId == trigger.new[i].id){
trigger.new[i].addError('Cannot inactivate Contact if its linked to an Account: '+acr.Account.name);
}
}
for(OpportunityContactRole ocr:lstConRole4){
if(ocr.ContactId == trigger.new[i].id){
trigger.new[i].addError('Cannot inactivate Contact if its linked to an Opportunity: '+ocr.Opportunity.name);
}
}
}
// new query
lstConRoleForDelete = [select id,name,ContactId__c,ProgramId__c,ProgramId__r.name from ProgramContactRole__c where ContactId__c IN:setContactIdForDelete];
lstConRole3ForDelete =[select id,ContactId,AccountId,Account.name from AccountContactRole where ContactId IN: setContactIdForDelete];
lstConRole4ForDelete =[select id,ContactId,OpportunityId,Opportunity.name from OpportunityContactRole where ContactId IN: setContactIdForDelete];
for(integer i=0;i<trigger.new.size();i++){
for(ProgramContactRole__c pcr:lstConRoleForDelete){
if(pcr.ContactId__c == trigger.new[i].id){
trigger.new[i].addError('Cannot mark as delete if its linked to a Program: '+pcr.ProgramId__r.name);
}
}
for(AccountContactRole acr:lstConRole3ForDelete){
if(acr.ContactId == trigger.new[i].id){
trigger.new[i].addError('Cannot mark as delete if its linked to an Account: '+acr.Account.name);
}
}
for(OpportunityContactRole ocr:lstConRole4ForDelete){
if(ocr.ContactId == trigger.new[i].id){
ocr.addError('Cannot mark as delete if its linked to an Opportunity: '+ocr.Opportunity.name);
}
}
}
}
}
Hi,
Could you please post the test class for this trigger as well...
Many Thanks!
Hi
I am sharing some test code, you may need to modify some code.
Hi Ashish,
Many Thanks for this code. I created this class and when i hit the Run Test Button for this class it display 0/1 test passed. But when i see in the debug log it correctly displays the expected custom error message as follows:
yes ,It is the correct way. After that you can see your trigger how much code is covered,
When you click on run test button can you see the status is pass or fail,
If status is fail then there may be some exception so try to avoid that exceptions.
If everything is good then give kudos for my post which helps you
Hi,
Here is the output after hitting the Run Test.Also i can see 53% code coverage on the trigger.
Time Started 8/22/2013 5:16 PM Class MileageTrackerTestSuite Method Name runPositiveTestCases Pass/Fail Fail Error Message System.DmlException: Update failed. First exception on row 0 with id 0039000000RdDgGAAV; first error: FIELD_CUSTOM_VALIDATION_EXCEPTION, Cannot mark as delete if its linked to an Opportunity: test: [] Stack Trace
Class.MileageTrackerTestSuite.runPositiveTestCases: line 37, column 1
The Test is showing failed status because of the error message initiated from the trigger--custom error..
I am enhancing your code to do the negative test as well.
Modify your test class or you can make your validation rule which is on Contact I think as inacive.
Add these line to your test class
Contact con1 = new Contact();
con1.LastName = 'testfinal';
con1.Active__c = fasle;
con1.To_be_deleted__c = true;
con1.AccountId = act.id;
insert con1;
modify these line
con1.LastName = 'test2';
upsert con1;
Rest all are same.
Whatt we are doing here is we are just creating another conatct and updating that conat which is not linked to opportunity.
It is better you can make in active that rule for a while run the test class, after code coverage you can make it active