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
Justin.WilliamsJustin.Williams 

Trigger/Class not firing on some records in an insert/update import to custom object feature

I just created an architecture for central trigger processing based on Dan Appleman's book, 'advanced apex programming'.  It works fine unless I use the standard feature, imprort custom object where the import has a mix of inserts and updates based on an external ID.  If the list is all inserts or all updates the trigger fires for all records.  When it is a mix of the two it only fires for the inserts.  The updates will have their records updated as the spreadsheet says but the trigger won't fire.

Central Dispatch class
--------------------------
<pre>
public class Dispatch{
   
    Public Interface ITriggerEntry{
        void MainEntry(Boolean IsUpdate, Boolean IsInsert,
                       Boolean IsDelete, Boolean IsExecuting,
                       Boolean IsBefore, Boolean IsAfter,
                       LIST<sObject> NewList, Map<Id,sObject> NewMap,
                       LIST<sObject> OldList, MAP<Id,sObject> OldMap);
       
        void InProgressEntry(Boolean IsUpdate, Boolean IsInsert,
                             Boolean IsDelete, Boolean IsExecuting,
                             Boolean IsBefore, Boolean IsAfter,
                             LIST<sObject> NewList, Map<Id,sObject> NewMap,
                             LIST<sObject> OldList, MAP<Id,sObject> OldMap);
    }
   
    Public Static ITriggerEntry activeclass = null;
   
    Public Static Void FrontDoor(String TriggerObject, Boolean IsUpdate, Boolean IsInsert, Boolean IsDelete, Boolean IsExecuting, Boolean IsBefore, Boolean IsAfter, LIST<sObject> NewList, Map<Id,sObject> NewMap, LIST<sObject> OldList, MAP<Id,sObject> OldMap){       
        If(activeclass != null){
            activeclass.InProgressEntry(IsBefore,IsDelete,IsAfter,IsInsert,IsUpdate,IsExecuting,NewList,NewMap,OldList,OldMap);
            return;
        }
               
        If(TriggerObject == 'CPM_Contract__c'){
            IF(IsAfter && (IsInsert || IsUpdate)){
                activeclass = new CPMeContractProcess();
                activeclass.MainEntry(IsUpdate, IsInsert, IsDelete, IsExecuting, IsBefore, IsAfter, NewList, NewMap, OldList, OldMap);
            }
        }
    } 
}
</pre>

Justin.WilliamsJustin.Williams
Here is the main working class that won't fire for updates when imporing with a mix of inserts and updates.

<pre>
public class CPMeContractProcess Implements Dispatch.ITriggerEntry{

    Public Static Void MainEntry(Boolean IsUpdate, Boolean IsInsert, Boolean IsDelete, Boolean IsExecuting, Boolean IsBefore, Boolean IsAfter, LIST<sObject> NewList, Map<Id,sObject> NewMap, LIST<sObject> OldList, MAP<Id,sObject> OldMap){
      
        Map<Id,CPM_Contract__c>NewContract = (Map<Id,CPM_Contract__c>)NewMap;
        Map<Id,CPM_Contract__c>OldContract = (Map<Id,CPM_Contract__c>)OldMap;
      
        Map<String,CPM_Contract__c> GC = new Map<String,CPM_Contract__C>();
        Map<String,CPM_Contract__c> Sub = new Map<String,CPM_Contract__C>();
        Map<String,CPM_Contract__c> User = new Map<String,CPM_Contract__C>();
        Map<String,CPM_Contract__c> Proj = new Map<String,CPM_Contract__c>();
        Map<String,CPM_Contract__c> Contr = New Map<String,CPM_Contract__c>();
  
        list<Org_ID__c> UpdateGCAccount = new List<Org_ID__c>();
        list<Org_ID__c> UpdateSubAccount = new List<Org_ID__c>();
     list<User_ID__c> UpdateUser = new List<User_ID__c>();
     list<CPM_Project__c> UpdateProj = new List<CPM_Project__c>();
        List<String> AllCrtIds = New List<String>();
  
     list<Account> NewGCAccount = new List<Account>();
     list<Account> NewSubAccount = new List<Account>();
     list<Contact> NewUser = new List<Contact>();
     list<CPM_Project__c> NewProject = new List<CPM_Project__c>();
        list<Report_Date__c> UpdateReport = new list<Report_Date__c>();
        date ReportDate = null;
   
     String ARTID = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Textura').getRecordTypeId();
     String CRTID = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('Textura Contact').getRecordTypeId();
        id ReportID = null;

//------------------------ Parse the results into different maps to be processed later -----------------------
                                   
        For (CPM_Contract__c SetCtr: NewContract.values()){
            GC.put(SetCtr.Textura_Customer_Number_GC__c,SetCtr);
            Sub.put(SetCtr.Textura_Customer_Number_Sub__c,SetCtr);
            Proj.put(SetCtr.Project_ID__c,SetCtr);
            User.put(SetCtr.User_ID__c,SetCtr);
            Contr.put(SetCtr.Contract_Number__c,SetCtr);
            AllCrtIds.add(SetCtr.Contract_Number__c);
            if(SetCtr.Report_Date__c != null){
                ReportDate = SetCtr.Report_Date__c;
            }
     }
      
//------------------------ Re-set the Report Date Object -----------------------------
        if(ReportDate!=null){
         for(Report_Date__c RD : [select Last_Report_Date__c, Name, ID from Report_Date__c where Name = 'CPM Contract Export']){
             RD.Last_Report_Date__c = ReportDate;
             ReportID = RD.Id;
             UpdateReport.add(RD);
         }
            update UpdateReport;
        }
              
//------------------------ GC Account Handling --------------------------------------
  
     Map<String,Org_ID__c> OldGCMap = New Map<String,Org_ID__c>();
     For(Org_ID__c AddOldGC : [Select ID__c, Account__r.ID From Org_ID__c Where Solution__c = 'CPM' And ID__c in :GC.keySet()]){
         OldGCMap.put(AddOldGC.ID__c,AddOldGC);
     }
  
     //Add missing Accounts
     For(CPM_Contract__c NewA1 : GC.values()){
            IF(NewA1.Textura_Customer_Number_GC__c == Null){
                Continue;
            }Else If(!OldGCMap.containsKey(NewA1.Textura_Customer_Number_GC__c)){
             Account A1 = new Account();
             A1.Name = NewA1.Company_Name_GC__c;
             A1.RecordTypeID = ARTID;
             A1.BillingStreet = NewA1.Street_1_GC__c + '\r\n' + NewA1.Street_2_GC__c;
             A1.BillingCity = NewA1.City_GC__c;
             A1.BillingState = NewA1.State_GC__c;
             A1.BillingPostalCode = NewA1.Zip_GC__c;
             A1.CPM_Org_ID__c = NewA1.Textura_Customer_Number_GC__c;
             A1.Phone = NewA1.Phone_GC__c;
             A1.Fax = NewA1.Fax_GC__c;
             A1.Email_Domain__c = NewA1.Email_GC__c;
             A1.Type = 'General Contractor';
             NewGCAccount.add(A1);
         }
     }
     Insert NewGCAccount;
 
   
        //updated existing GC ORG IDs
     For(Org_ID__c GCNow : [Select ID__c from ORG_ID__c where Solution__c = 'CPM' AND ID__c in : GC.KeySet()]){
            If(OldGCMap.containsKey(GCNow.ID__c)){
          GCNow.Company_Name__c = GC.get(GCNow.ID__c).Company_Name_GC__c;
          GCNow.Street_1__c = GC.get(GCNow.ID__c).Street_1_GC__c;
          GCNow.Street_2__c=GC.get(GCNow.ID__c).Street_2_GC__c;
          GCNow.City__c=GC.get(GCNow.ID__c).City_GC__c;
          GCNow.State__c=GC.get(GCNow.ID__c).State_GC__c;
          GCNow.Postal_Code__c=GC.get(GCNow.ID__c).Zip_GC__c;
          GCNow.Email__c = GC.get(GCNow.ID__c).Email_GC__c;
          GCNow.Phone__c = GC.get(GCNow.ID__c).Phone_GC__c;
          GCNow.Fax__c = GC.get(GCNow.ID__c).Fax_GC__c;
          GCNow.Tax_ID__c = GC.get(GCNow.ID__c).Tax_ID_GC__c;
          UpdateGCAccount.add(GCNow);
            }
     }
     Update UpdateGCAccount;
  
     // Grab the final list of all Org IDs and their respective Account ID to link the GC with the Project
     Map<String,Org_ID__c> NewGCMap = new Map<String,Org_ID__c>();
     FOR(Org_ID__c AddNewGC : [Select ID__c, Account__r.ID From Org_ID__c Where Solution__c = 'CPM' And ID__c in : GC.keySet()]){
         NewGCMap.put(AddNewGC.ID__c,AddNewGC);
     }
  
//------------------------ Subcontractor Handling --------------------------

     Map<String,Org_ID__c> OldSubMap = new Map<String,Org_ID__c>();
     FOR(Org_ID__c AddOldSub : [Select ID__c From Org_ID__c Where Solution__c = 'CPM' And ID__c in : Sub.keySet()]){
         OldSubMap.put(AddOldSub.ID__c,AddOldSub);
     }
  
     //Add missing Accounts
     For(CPM_Contract__c NewA2 : Sub.values()){
            IF(NewA2.Textura_Customer_Number_Sub__c==Null){
                Continue;
            }ELSE IF(!OldSubMap.containsKey(NewA2.Textura_Customer_Number_Sub__c)){
             Account A2 = new Account();
             A2.Name = NewA2.Company_Name_Sub__c;
             A2.RecordTypeID = ARTID;
             A2.BillingStreet = NewA2.Street_1_Sub__c + '\r\n' + NewA2.Street_2_Sub__c;
             A2.BillingCity = NewA2.City_Sub__c;
             A2.BillingState = NewA2.State_Sub__c;
             A2.BillingPostalCode = NewA2.Zip_Sub__c;
             A2.CPM_Org_ID__c = NewA2.Textura_Customer_Number_Sub__c;
             A2.Phone = NewA2.Phone_Sub__c;
             A2.Fax = NewA2.Fax_Sub__c;
             A2.Email_Domain__c = NewA2.Email_Sub__c;
             A2.Type = 'Subcontractor';
             NewSubAccount.add(A2);
         }
     }
     Insert NewSubAccount;
  
     //updated existing Sub ORG IDs
     For(Org_ID__c SubNow : [Select ID__c from ORG_ID__c where Solution__c = 'CPM' AND ID__c in :Sub.keySet()]){
            IF(OldSubMap.containsKey(SubNow.ID__c)){
          SubNow.Company_Name__c = Sub.get(SubNow.ID__c).Company_Name_Sub__c;
          SubNow.Street_1__c = Sub.get(SubNow.ID__c).Street_1_Sub__c;
          SubNow.Street_2__c=Sub.get(SubNow.ID__c).Street_2_Sub__c;
          SubNow.City__c=Sub.get(SubNow.ID__c).City_Sub__c;
          SubNow.State__c=Sub.get(SubNow.ID__c).State_Sub__c;
          SubNow.Postal_Code__c=Sub.get(SubNow.ID__c).Zip_Sub__c;
          SubNow.Email__c = Sub.get(SubNow.ID__c).Email_Sub__c;
          SubNow.Phone__c = Sub.get(SubNow.ID__c).Phone_Sub__c;
          SubNow.Fax__c = Sub.get(SubNow.ID__c).Fax_Sub__c;
          SubNow.Tax_ID__c = Sub.get(SubNow.ID__c).Tax_ID_Sub__c;
          UpdateSubAccount.add(SubNow);
            }
     }
     Update UpdateSubAccount;

     // Grab the final list of all Org IDs and their respective Account ID to link the GC with the Project
     Map<String,Org_ID__c> NewSubMap = new Map<String,Org_ID__c>();
     FOR(Org_ID__c AddNewSub : [Select ID__c, Account__r.ID From Org_ID__c Where Solution__c = 'CPM' And ID__c in : Sub.keySet()]){
         NewSubMap.put(AddNewSub.ID__c,AddNewSub);
     }
  
//------------------------ User Handling -----------------------------------
  
     Map<String,User_ID__c> OldUserMap = new Map<String,User_ID__c>();
     FOR(User_ID__c AddOldUser : [Select External_System_ID__c from User_ID__c where Solution__c = 'CPM' AND External_System_ID__c in :User.keySet()]){
         OldUserMap.put(AddOldUser.External_System_ID__c,AddOldUser);
     }
  
     //Add missing User
     For(CPM_Contract__c NewU : User.values()){
            IF(NewU.User_ID__c==Null){
                Continue;
            }Else IF(!OldUserMap.containsKey(NewU.User_ID__c)){
             Contact U = new Contact();
             U.FirstName = NewU.First_Name__c;
             U.LastName = NewU.Last_Name__c;
             U.Email = NewU.Email_User__c;
             U.Phone = NewU.Phone_1__c;
             U.RecordTypeID = CRTID;
             U.CPM_User_ID__c = NewU.User_ID__c;
             U.AccountId = NewSubMap.get(NewU.Textura_Customer_Number_Sub__c).Account__r.ID;
             NewUser.add(U);
             }
         }
         Insert NewUser;

     //updated existing User IDs
     For(User_ID__c UserNow : [Select External_System_ID__c from User_ID__c where Solution__c = 'CPM' AND External_System_ID__c in :User.keySet()]){
            IF(OldUserMap.containsKey(UserNow.External_System_ID__c)){
          UserNow.First_Name__c = User.get(UserNow.External_System_ID__c).First_Name__c;
          UserNow.Last_Name__c = User.get(UserNow.External_System_ID__c).Last_Name__c;
          UserNow.Email__c = User.get(UserNow.External_System_ID__c).Email_User__c;
          UserNow.Phone_1__c = User.get(UserNow.External_System_ID__c).Phone_1__c;
          UserNow.Phone_2__c = User.get(UserNow.External_System_ID__c).Phone_2__c;
          UserNow.Related_Org_ID__c = User.get(UserNow.External_System_ID__c).Textura_Customer_Number_Sub__c;
          UpdateUser.add(UserNow);
            }
     }
     Update UpdateUser;
  
     // Grab the final list of all User IDs and their respective Contact ID to link the GC with the Project
     Map<String,User_ID__c> NewUserMap = new Map<String,User_ID__c>();
     FOR(User_ID__c AddNewUser : [Select External_System_ID__c from User_ID__c where Solution__c = 'CPM' AND External_System_ID__c in :User.keySet()]){
         NewUserMap.put(AddNewUser.External_System_ID__c,AddNewUser);
     }
                                   
//------------------------ Project Handling -------------------------------
  
     Map<String,CPM_Project__c> OldProjMap = new Map<String,CPM_Project__c>();
     FOR(CPM_Project__c AddOldProj : [Select Project_ID__c From CPM_Project__c Where Project_ID__c in :proj.keySet()]){
         OldProjMap.put(AddOldProj.Project_ID__c,AddOldProj);
     }
      
     //Add missing Projects
     For(CPM_Contract__c NewP : [Select Project_ID__c, Project_Name__c, Project_Street_1__c, Project_Street_2__c, Project_State__C, Project_City__c, Project_Postal_Code__c, Project_Description__c, Notary__c, Notary_State__c, Textura_Customer_Number_GC__c From CPM_Contract__c Where Project_ID__c In :Proj.keySet()]){
            IF(NewP.Project_ID__c==Null){
                Continue;
            }Else If(!OldProjMap.containsKey(NewP.Project_ID__c)){
              
                CPM_Project__c P = new CPM_Project__c();
             P.Project_ID__c = NewP.Project_ID__c;
             P.Project_Name__C = NewP.Project_Name__c;
             P.Street_1__c = NewP.Project_Street_1__c;
             P.Street_2__c = NewP.Project_Street_2__c;
             P.State__c = NewP.Project_State__C;
             P.City__c = NewP.Project_City__c;
             P.Postal_Code__c = NewP.Project_Postal_Code__c;
             P.Project_Description__c = NewP.Project_Description__c;
             P.Notary__c = NewP.Notary__c;
             P.Notary_State__c = NewP.Notary_State__c;
             P.GC_ID__c = NewP.Textura_Customer_Number_GC__c;
             NewProject.add(P);
            }
     }
        Insert NewProject;
   
  
     //Project Updates
     For(CPM_Project__c ProjNow : [Select Project_ID__c from CPM_Project__c where project_ID__c in :proj.keySet()]){
            If(OldProjMap.containsKey(ProjNow.Project_ID__c)){
                ProjNow.Project_Name__c = Proj.get(ProjNow.Project_ID__c).Project_Name__c;
           ProjNow.Street_1__c = Proj.get(ProjNow.Project_ID__c).Project_Street_1__c;
          ProjNow.Street_2__c = Proj.get(ProjNow.Project_ID__c).Project_Street_2__c;
          ProjNow.City__C = Proj.get(ProjNow.Project_ID__c).Project_City__c;
          ProjNow.State__C = Proj.get(ProjNow.Project_ID__c).Project_State__c;
          ProjNow.Postal_Code__C = Proj.get(ProjNow.Project_ID__c).Project_Postal_Code__c;
          ProjNow.Country__c = Proj.get(ProjNow.Project_ID__c).Project_Country__c;
          ProjNow.Notary__c = Proj.get(ProjNow.Project_ID__c).Notary__c;
          ProjNow.Country__c = Proj.get(ProjNow.Project_ID__c).Project_Country__c;
          ProjNow.Project_Description__C = Proj.get(ProjNow.Project_ID__c).Project_Description__C;
          ProjNow.GC_ID__c = Proj.get(ProjNow.Project_ID__c).Textura_Customer_Number_GC__c;
          UpdateProj.add(ProjNow);
            }
     }
     Update UpdateProj;
   
     Map<String,CPM_Project__c> NewProjMap = new Map<String,CPM_Project__c>();
     FOR(CPM_Project__c AddNewProj : [Select Project_ID__c, ID From CPM_Project__c Where Project_ID__c in :proj.keySet()]){
         NewProjMap.put(AddNewProj.Project_ID__c,AddNewProj);
     }
                                   
//------------------------ Record Linking -------------------------------
                                   
     //  Link Contract to Project and Subcontractors
        List<CPM_Contract__c> LinkCtr = New List<CPM_Contract__c>();
      
     For(CPM_Contract__c LinkC : [SELECT Project_ID__c, Textura_Customer_Number_Sub__c, Report_Date__c, Last_Report_Update__c FROM CPM_Contract__c WHERE Contract_Number__c In :AllCrtIds]){
            IF(NewProjMap.containsKey(LinkC.Project_ID__c)){
                LinkC.CPM_Project__c = NewProjMap.get(LinkC.Project_ID__c).ID;
            }
            IF(NewSubMap.containsKey(LinkC.Textura_Customer_Number_Sub__c)){
                LinkC.Subcontractor__c = NewSubMap.get(LinkC.Textura_Customer_Number_Sub__c).Account__r.ID;
            }
            IF(LinkC.Report_Date__c != Null){
                LinkC.Last_Report_Update__c = LinkC.Report_Date__c;
                LinkC.Report_Date__c = Null;
            }
            IF(ReportID != null){
                LinkC.Report_Date_Record__c = ReportID;
            }
         LinkCtr.add(LinkC);
     }
     Update LinkCtr;
  
     // Link Project to GC
        List<CPM_Project__c> LinkProj = New List<CPM_Project__c>();
     For(CPM_Project__c LinkP : [Select GC_ID__c FROM CPM_Project__c WHERE Project_ID__c in :proj.keySet()]){
            IF(NewGCMap.containsKey(LinkP.GC_ID__c)){
                LinkP.General_Contractor__c = NewGCMap.get(LinkP.GC_ID__c).Account__r.ID;
            }
            LinkProj.add(LinkP);
        }
        Update LinkProj;
    }
  
//------------------------ In Progress Method -------------------------------

    Public Static Void InProgressEntry(Boolean IsUpdate, Boolean IsInsert, Boolean IsDelete, Boolean IsExecuting, Boolean IsBefore, Boolean IsAfter, LIST<sObject> NewList, Map<Id,sObject> NewMap, LIST<sObject> OldList, MAP<Id,sObject> OldMap){
   
    }
}
</pre>
Scott McClungScott McClung
Hi Justin
I'm stumbling across your question a little late so you may have already figured out the answer, but for anyone else who runs into this issue here is the solution.
The order of execution in an upsert is to execute the Before/After Insert and then the Before/After Update events.  The program flow will enter your Dispatch class for all four of those events.
The execution context is the same for all four of those events, however, so when your TriggerObject After Insert condition is true and you set activeclass to an instance of CPMeContractProcess it retains that value as the program flow enters the Dispatch class for the Before/After Update events.  As a result the program flow is diverted to your CPMeContractProcess.InProgressEntry method.
The easiest way to resolve this is to set activeclass back to null.

if(TriggerObject == 'CPM_Contract__c') {
  if(IsAfter && (IsInsert || IsUpdate)) {
    activeclass = new CPMeContractProcess();
    activeclass.MainEntry(IsUpdate, IsInsert, IsDelete, IsExecuting, IsBefore, IsAfter, NewList, NewMap, OldList, OldMap);
    activeclass = null;
  }
}



Hope that helps