function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
ABC XYZ 39ABC XYZ 39 

Urgently Need help with triggers - Both after insert and After update trigger firing at the same time for new records created -REPOSTING 3rd time

Hi, 
Basic Logic:
 Create Contact Scenario - 
 Conditions - Last Name should not be same as Account Name, Contact type is Customer
  Everytime a new contact is created meeting the above conditions, it is written to Queue object
   In this case, Description would be 'New Contact' (to be written into Queue object)
   
 Update Contact Scenario -
 2 scenarios here -   
  1) In addition to abouve conditions being valid, if custom field PID is missing and any of the 
    fields in Contact record are updated, push the record to Queue object.
    In this case, Description would be 'PID Missing'
    
  2)  In addition to above conditions - Last Nane not same as Account Name, Contact type being 'Customer'
     type,  if custom fields A, B, C or D are changed on the existing record, push the record to 
       Queue object.
      In this case, Description would be 'Updated Contact' 
  
Behavior Observed Now :
Whenever a  new contact  is created, 2 copies of the same record are inserted into the Queue object. This I am assuming is happening because 'after insert' and 'after update' triggers aer firing for every new contact created. 

Insert Scenario(New Contact Creation) - Update scenario triggered - 'MDM Id Missing' message observed; Record inserted into Queue object twice
Update Scenario (PID null and record updated) - Working as expected - 'MDM Id Missing' message written into Queue object
Update scenario ( A,B,C or D field values change) - Update Scenario triggerd - 'Update contact' message written into Queue object



I don't understand why this is happening. There are no workflows impacting the behavior . It has to do with logic in the class below or the way I am invoking the trigger. 
Controller Class and Trigger Invocation are below.

I am trying to fix this code for sometime without any luck. I need to fix it as soon as possible. I am new to programming and can't figure out how to make this functionality work. I have posted the same queury for  past couple of days. I will greatly appreciate if you could help identify and fix this issue..Thanks.









// Controller Class with processContact method

public class ContactController {

public  void processContact(Map<Id, Contact> newContactMap, Map<Id, Contact> oldContactMap)
{
       List<Queue__c> lstQ = new List<Queue__c>();   
         Id idContactCustomerRecType;
         Map<Id, String> mapIdToAccountName = new Map<Id, String>();
       
           List<RecordType> lstRecType = new List<RecordType>([SELECT Id FROM RecordType WHERE Name = 'Customer' AND SobjectType = 'Contact']);
          
      if(!lstRecType.isEmpty())
     idContactCustomerRecType = lstRecType[0].Id;
       
        if(idContactCustomerRecType != null)
         {
         // we can't fetch parent fields directly, so collecting account Ids first
           for(Contact objContact : newContactMap.values())
              {
                  if(objContact.AccountId != null)
                mapIdToAccountName.put(objContact.AccountId, null);
              }
          }
 
         // iterate over account with matching collected Ids and fetch names
          for(Account objAccount : [SELECT Id, Name FROM Account WHERE Id IN : mapIdToAccountName.keySet()])
          {
           mapIdToAccountName.put(objAccount.Id, objAccount.Name);
           }
  
         // loop again to perform business logic
        for(Contact objContact : newContactMap.values())
        {
             /* 1. If Contact RecordType is Customer AND if LastName != Account.Name, insert Queue **/
            if( objContact.RecordTypeId == idContactCustomerRecType
               && objContact.AccountId != null   && objContact.LastName != mapIdToAccountName.get(objContact.AccountId)
             {
             if(Trigger.isUpdate)
             {
                 if(label.Unauthorized_User!=objContact.lastmodifiedbyid)
                 {
                    if(objContact.A__c!= oldContactMap.get(objContact.Id).A__c
                        || objContact.B__c!= oldContactMap.get(objContact.Id).B__c
                        || objContact.D__c!= oldContactMap.get(objContact.Id).D__c)
                  {
                  
                   objQ.Description__c= 'Updated Contact';
                   objQ.Record_Id__c = objContact.Id;
                   objQ.Notification_Timestamp__c= objContact.CreatedDate;
                   lstQ.add(objQ);
                   }
                   
                   else if(objContact.PID__c == null)
                   {
                   objQ.Description__c= 'PID Missing';
                   objQ.Record_Id__c = objContact.Id;
                   objQ.Notification_Timestamp__c= objContact.CreatedDate;
                   lstQ.add(objQ);
                   
                   }
                   
                 }
             }
             
               if(Trigger.isInsert)
               {
                 objQ.Description__c= 'New Contact';
                   objQ.Record_Id__c = objContact.Id;
                   objQ.Notification_Timestamp__c= objContact.CreatedDate;
                   lstQ.add(objQ);
                   
               }
             }

            
                   
                
       }

       if(!lstQ.isEmpty())
       insert lstQ;
             
    }
     
    
     
}


Trigger Invocation :

Contact - After Insert 

if(Trigger.isInsert && Trigger.isAfter){
   ContactController.processContact(Trigger.newMap, Trigger.oldMap);
   }

Contact - After Update 

 if(Trigger.isUpdate && Trigger.isAfter){
        ContactController.processContact(Trigger.newMap, Trigger.oldMap);
    } 
mritzimritzi
On the fly i found a fundamental problem in your code:
You are calling same method of COntactController class from your trigger and thats why youa re facing problem.

Call two separate methods and your problem should be resolved assuing that the logic in controller is correct.

Something like this:
trigger sampleTrigger on Contact(before Insert, after Insert,
								 before Update, after Update,
								 before Delete, after Delete,){
	if(Trigger.isInsert && Trigger.isAfter)
	   ContactController.processContact1(Trigger.newMap, Trigger.oldMap);
	if(Trigger.isUpdate && Trigger.isAfter)
			ContactController.processContact2(Trigger.newMap, Trigger.oldMap);
			
}

in processContact1 method write only that part of code that should execute for newly inserted records
and in processContact2 method write only that part of code that should execute for recently updated records.

Mark this as Best Answer, if this solves your problem.
ABC XYZ 39ABC XYZ 39
Thanks for your response ....I tried to invoke using 2 separate methods  as per your suggestion. But I am still facing the same issue.  Both after insert and after update are firing.
ABC XYZ 39ABC XYZ 39
Can you pls look at the code and check if my logic is wrong somewhere in the code?
ABC XYZ 39ABC XYZ 39
I found that After Update Trigger is getting fired before After Insert triggger.  Ideally, only After Insert trigger should fire when a record is created
mritzimritzi
trigger sampleTrigger on Contact(before Insert, after Insert,
								 before Update, after Update,
								 before Delete, after Delete){
	if(Trigger.isInsert && Trigger.isAfter)
	   ContactController.processContact1(Trigger.newMap, Trigger.oldMap);
	else if(Trigger.isUpdate && Trigger.isAfter)
			ContactController.processContact2(Trigger.newMap, Trigger.oldMap);
			
}

Hope it works now.
ABC XYZ 39ABC XYZ 39
Hi mritzi, Tried this as well. Still it does not work...
mritzimritzi
Apex:
public class ContactController{
	//method called when records are inserted
	public void processContact1(List<Contact> contactList){
		List<Queue__c> lstQ = new List<Queue__c>();
		for(Contact objContact:contactList){
			//check contact's last name with related account's name
			if(objContact.LastName!=objContact.AccountId.Name){
				Queue__c objQ = new Queue__c();
				// u hadn't included name field, it's madatory, change its value, if its text field
				//no issues if it's auto number
				//objQ.Name = 'someName';
				objQ.Description__c= 'New Contact';
                objQ.Record_Id__c = objContact.Id;
                objQ.Notification_Timestamp__c= objContact.CreatedDate;
                lstQ.add(objQ);
			}
		}
		if(lstQ.size()>0)
			insert lstQ;
	}
	// method called when records are updated
	public void processContact2(List<Contact> contactList, Map<id,Contact> oldContactMap){
		List<Queue__c> lstQ = new List<Queue__c>();
		for(Contact objContact:contactList){
			//check PID field of contact field
			// update trigger is fired only when atleast one field is changed from its previous value
			// if you want to check contact's last name == account's name,
			// you can add that condition in the line below
			if(objContact.PID__c==''){
				Queue__c objQ = new Queue__c();
				//objQ.Name = 'someName';
				objQ.Description__c= 'PID Missing';
                objQ.Record_Id__c = objContact.Id;
                objQ.Notification_Timestamp__c= objContact.CreatedDate;
                lstQ.add(objQ);
			}
			// check contact's last not equal to account's name
			// please note: Type field is associated with account and not with contact.
			// if you have created a custom "Type__c" field on contact object, then please change api name in the following line
			else if(objContact.LastName!=objContact.AccountId.Name && objContact.AccountId.Type=='Customer'){
				Contact tmpC = new Contact(oldContactMap.get(objContact.id));
				//compare values of custom field in old record and updated record
				if(objContact.A__c!=tmpC.A__c || objContact.B__c!=tmpC.B__c || objContact.C__c!=tmpC.C__c || objContact.D__c!=tmpC.D__c){
					Queue__c objQ = new Queue__c();
					//objQ.Name = 'someName';
					objQ.Description__c= 'Updated Contact';
					objQ.Record_Id__c = objContact.Id;
					objQ.Notification_Timestamp__c= objContact.CreatedDate;
					lstQ.add(objQ);
				}
			}
		}
		if(lstQ.size()>0)
			insert lstQ;
	}
}

Trigger:
trigger sampleTrigger on Contact(before Insert, after Insert,
								 before Update, after Update,
								 before Delete, after Delete){
	if(Trigger.isInsert && Trigger.isAfter)
	   ContactController.processContact1(Trigger.new);
	else if(Trigger.isUpdate && Trigger.isAfter)
	   ContactController.processContact2(Trigger.new, Trigger.oldMap);
			
}

Correct typing mistakes, syntax errors if any.
Add additional conditions in the code, depending on your requirement.

Mark this as Best Answer, if this helps.
ABC XYZ 39ABC XYZ 39
Hi, Thanks for your response. I tried this as well. It didn't work. I don't understand what is the issue here.