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 

Apex Trigger to issue updating two objects

Right now I have a custom object called CPM Contracts.  I have another custom object called CPM Projects.  The contract relates up to the project in a non-master detail lookup and the project relates up to the Account in a non-master detail lookup.

 

My process has users upload records to the Contracts object using the custom object upload wizard.  The records being uploaded have all the information needed to take the once contract record and create 2 accounts, 1 project and 1 user plus unique IDs to match their relationship up.  All the code I have works fine until the end when I create the relationships.  I get the following error;

 

CPMeContractUpdate: execution of AfterUpdate caused by: System.DmlException: Update failed. First exception on row 0 with id a2BS0000000AoQFMA0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, CPMeContractUpdate: execution of AfterUpdate caused by: System.NullPointerException: Attempt to de-reference a null object Trigger.CPMeContractUpdate: line 216, column 1: []: Trigger.CPMeContractUpdate: line 212, column 1

 

It seems to have a problem updating the lookup fields on the Contract and the project.  I messed around with this and I can updated the contract lookups or the project lookup but not both.  What sort of apex principle am I missing here?

 

trigger CPMeContractUpdate on CPM_Contract__c (after insert, after update) {
    
//------------------------ Initialized Variables --------------------------- 
    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>();
    
    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>();    
        
    Set<String> AllCrtIds = new Set<String>();
    Set<String> AllGCIds = new Set<String>();
    Set<String> AllSubIds = new Set<String>();
    Set<String> AllUserIds = new Set<String>();
    Set<String> AllProjIds = new Set<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<CPM_Project__c> LinkSub = new List<CPM_Project__c>();
    list<CPM_Project__c> LinkProj = new List<CPM_Project__c>();
    list<CPM_Contract__c> LinkCtr = new List<CPM_Contract__c>();
    
    String ARTID = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Textura').getRecordTypeId();
    String CRTID = Schema.SObjectType.Contact.getRecordTypeInfosByName().get('Textura Contact').getRecordTypeId();

//------------------------ Starting Trigger For Loop ----------------------- 
    
    // This first for loop catches all the contract records that have a modified date of TODAY().  
    // It sets certain parts of each record into either a map or list to be iterated through later.
    for (CPM_Contract__c SetCtr: Trigger.New){
        if(FirstPassCheck.IsFirstPass()){
            //Map of GC Org ID and the related Contract object to be used for later
            GC.put(SetCtr.Textura_Customer_Number_GC__c,SetCtr);
            //Map of Sub Org ID and the related Contract object to be used for later
            Sub.put(SetCtr.Textura_Customer_Number_Sub__c,SetCtr);
            //Map of Project number and the Contract object to be used for later
            Proj.put(SetCtr.Project_ID__c,SetCtr);
            //Map of Project number and the Contract object to be used for later
            User.put(SetCtr.User_ID__c,SetCtr);
            AllCrtIds.add(SetCtr.Contract_Number__c);
            AllGCIds.add(SetCtr.Textura_Customer_Number_GC__c);
            AllSubIds.add(SetCtr.Textura_Customer_Number_Sub__c);
            AllUserIds.add(SetCtr.User_ID__c);
            AllProjIds.add(SetCtr.Project_ID__c);
        }
    }
    
//------------------------ 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 : AllGCIds]){
        OldGCMap.put(AddOldGC.ID__c,AddOldGC);
    }
    
    //Add missing Accounts
    For(CPM_Contract__c NewA1 : GC.values()){
        IF(!OldGCMap.containsKey(NewA1.Textura_Customer_Number_GC__c)){
            Account A1 = new Account();
            A1.Name = NewA1.Company_Name_GC__c;
            A1.RecordTypeID = ARTID;
            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;
            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()]){
        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;
        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 : AllGCIds]){
        NewGCMap.put(AddNewGC.ID__c,AddNewGC);
    }
    
//------------------------ 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 : AllProjIds]){
        OldProjMap.put(AddOldProj.Project_ID__c,AddOldProj);
    }
    
    //Add missing Projects
    For(CPM_Contract__c NewP : Proj.values()){
        IF(!OldProjMap.containsKey(NewP.Project_ID__c)){
        CPM_Project__c P = new CPM_Project__c();
            P.Project_Name__C = NewP.Project_Name__c;
            P.Project_ID__c = NewP.Project_ID__c;
            P.GC_ID__c = NewP.Textura_Customer_Number_GC__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()]){
        ProjNow.Project_Name__c = Proj.get(ProjNow.Project_ID__c).Project_Name__c;
        ProjNow.GC_ID__c = Proj.get(ProjNow.Project_ID__c).Textura_Customer_Number_GC__c;
        UpdateProj.add(ProjNow);
        Proj.remove(ProjNow.Project_ID__c);
    }
    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 : AllProjIds]){
        NewProjMap.put(AddNewProj.Project_ID__c,AddNewProj);
    }
    
//------------------------ 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 : AllSubIds]){
        OldSubMap.put(AddOldSub.ID__c,AddOldSub);
    }
    
    //Add missing Accounts
    For(CPM_Contract__c NewA2 : Sub.values()){
        IF(!OldSubMap.containsKey(NewA2.Textura_Customer_Number_Sub__c)){
            Account A2 = new Account();
            A2.Name = NewA2.Company_Name_Sub__c;
            A2.RecordTypeID = ARTID;
            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;
            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()]){
        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.Company_Name__c = Sub.get(SubNow.ID__c).Company_Name_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 : AllSubIds]){
        NewSubMap.put(AddNewSub.ID__c,AddNewSub);
    }
    /*
//------------------------ User Handling -----------------------------------
    
    Map<String,User_ID__c> OldUserMap = new Map<String,User_ID__c>([Select External_System_ID__c from User_ID__c where Solution__c = 'CPM' AND External_System_ID__c in :AllUserIds]);
    
    //Add missing Accounts
    For(CPM_Contract__c NewU : User.values()){
        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 = OldSubMap.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()]){
        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>([Select External_System_ID__c from User_ID__c where Solution__c = 'CPM' AND External_System_ID__c in :AllUserIds]);
    
//------------------------ Linking -----------------------------------------
*/
    FirstPassCheck.FirstPassFalse();
    
    //  Link Contract to Project and Subcontractors
    For(CPM_Contract__c LinkC : [SELECT Project_ID__c, Textura_Customer_Number_Sub__c, CPM_Project__c FROM CPM_Contract__c WHERE Contract_Number__c in :AllCrtIds]){
        LinkC.CPM_Project__c = NewProjMap.get(LinkC.Project_ID__c).ID;
        LinkC.Subcontractor__c = NewSubMap.get(LinkC.Textura_Customer_Number_Sub__c).Account__r.ID;
        LinkCtr.add(LinkC);
    }
    Update LinkCtr;
    
    // Link Project to GC
    For(CPM_Project__c LinkP : [Select GC_ID__c FROM CPM_Project__c]){
        LinkP.General_Contractor__c = NewGCMap.get(LinkP.GC_ID__c).Account__r.ID;
        LinkProj.add(LinkP);
    }    
    Update LinkProj;
    
     
}

 

 

Justin.WilliamsJustin.Williams
I figured out how to make it work. My last SOQL did not include any filters like the SOQL does above. Why that should matter I don't know but it does. I appended that last SOQL with 'WHERE Project_ID__C in : AllProjIds' That did the trick. Again, I'm not sure why. Whats the difference if it pulls back all the projects or just one project.