• Justin.Williams
  • NEWBIE
  • 0 Points
  • Member since 2012

  • Chatter
    Feed
  • 0
    Best Answers
  • 2
    Likes Received
  • 0
    Likes Given
  • 14
    Questions
  • 14
    Replies
Anyone know what the CSS is for styling content to look like the updated service cosole?  Specifically like how related lists look like on a side component.  It has a clean, white look without much borders.  I would like to use such a CSS for my Flow's that I am planning on making.
I have been trying to write test code recently that seems to not work like it used to.  In the test class I would create a record and insert it, then make a change and update it.  That used to work fine now it is as if only the insert is recognized and the code related to the update doesn't get checked.

<pre>
public class AccountTeamManage Implements Dispatch.ITriggerEntry{
   
    public static list<AccountTeamMember> MemberList = null;
    public static list<AccountShare> RulesList = null;
    public static list<AccountTeamMember> RemovalList = null;
    public static map<Id,AccountTeamMember> CurrentTeam = null;
   
    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,Account>NewAccount = (Map<Id,Account>)NewMap;
        Map<Id,Account>OldAccount = (Map<Id,Account>)OldMap;       
        MemberList = new List<AccountTeamMember>();
        RulesList = new List<AccountShare>();   
        RemovalList = new list<AccountTeamMember>();       
        CurrentTeam = new map<Id,AccountTeamMember>();
       
        for(AccountTeamMember Team : [SELECT UserId, AccountID, TeamMemberRole FROM AccountTeamMember WHERE AccountId IN:NewAccount.keySet()]){
            CurrentTeam.put(Team.UserId, Team);
        }
       
        for(Account a : NewAccount.values()){
            if(IsInsert){               
                if(a.CPMb_Sales__c != null){CreateTeam('CPMB Sales Consultant', a.Id, a.CPMb_Sales__c, a.OwnerId);}
                if(a.CPMb_Support__c != null){CreateTeam('CPMB Solution Consultant', a.Id, a.CPMb_Support__c, a.OwnerId);}
                if(a.SubEx_Sales__c != null){CreateTeam('Submittal Exchange Sales Consultant', a.Id, a.SubEx_Sales__c, a.OwnerId);}
                if(a.SubEx_NBR__c != null){CreateTeam('Submittal Exchange NBR', a.Id, a.SubEx_NBR__c, a.OwnerId);}
                if(a.SubEx_Support__c != null){CreateTeam('Submittal Exchange CRC', a.Id, a.SubEx_Support__c, a.OwnerId);}               
                if(a.Gradebeam_Sales__c != null){CreateTeam('Gradebeam Sales Consultant', a.Id, a.Gradebeam_Sales__c, a.OwnerId);}
                if(a.PQM_Sales__c != null){CreateTeam('PQM Sales Consultant', a.Id, a.PQM_Sales__c, a.OwnerId);}
                if(a.BidOrganizer_Sales__c != null){CreateTeam('BidOrganizer Sales Consultant', a.Id, a.BidOrganizer_Sales__c, a.OwnerId);}
                if(a.PlanSwift_Sales__c != null){CreateTeam('PlanSwift Sales Consultant', a.Id, a.PlanSwift_Sales__c, a.OwnerId);}               
            }else if(IsUpdate){
                Account oldAcct = OldAccount.get(a.Id);               
                UpdateTeam('CPMB Sales Consultant', a.Id, OldAcct.CPMb_Sales__c, a.CPMb_Sales__c, OldAcct.OwnerId, a.OwnerId);
                UpdateTeam('CPMB Solution Consultant', a.Id, OldAcct.CPMb_Support__c, a.CPMb_Support__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('Submittal Exchange Sales Consultant', a.Id, OldAcct.SubEx_Sales__c, a.SubEx_Sales__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('Submittal Exchange NBR', a.Id, OldAcct.SubEx_NBR__c, a.SubEx_NBR__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('Submittal Exchange CRC', a.Id, OldAcct.SubEx_Support__c, a.SubEx_Support__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('Gradebeam Sales Consultant', a.Id, OldAcct.Gradebeam_Sales__c, a.Gradebeam_Sales__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('PQM Sales Consultant', a.Id, OldAcct.PQM_Sales__c, a.PQM_Sales__c, OldAcct.OwnerId, a.OwnerId);
                UpdateTeam('BidOrganizer Sales Consultant', a.Id, OldAcct.BidOrganizer_Sales__c, a.BidOrganizer_Sales__c, OldAcct.OwnerId, a.OwnerId);
                UpdateTeam('PlanSwift Sales Consultant', a.Id, OldAcct.PlanSwift_Sales__c, a.PlanSwift_Sales__c, OldAcct.OwnerId, a.OwnerId);
            }
        }
       
        if(RemovalList.size() > 0){
            delete RemovalList;
        }       
        if(MemberList.size() > 0){
            upsert MemberList;
        }       
        if(RulesList.size() > 0){
         upsert RulesList;
        }
    }
   
    private static void CreateTeam(string TeamName, Id AccId,Id NewMember,Id NewOwner){
        accountTeamMember ATeam = new AccountTeamMember(AccountId = AccId,TeamMemberRole = TeamName,UserId =NewMember);
        MemberList.add(ATeam);
        if(NewMember != NewOwner){
            AccountShare ATeamRules = new AccountShare(AccountId=AccId,OpportunityAccessLevel='Read',CaseAccessLevel='Read',AccountAccessLevel='Edit',UserOrGroupId=NewMember);
            RulesList.add(ATeamRules);
        }
    }
   
    private static void UpdateTeam(string TeamName, Id AccId, Id OldMember, Id NewMember, Id OldOwner, Id NewOwner){
        if(NewMember == null && OldMember != null){
            RemoveTeam(OldMember, TeamName);
        }
       
        if(NewMember != null){
            if(NewMember != OldMember){
                RemoveTeam(OldMember, TeamName);
            }
           
            if(!CurrentTeam.containsKey(NewMember)){
                CreateTeam(TeamName, AccId, NewMember, NewOwner);
            }else{
                if(CurrentTeam.get(NewMember).TeamMemberRole != TeamName){
                    CreateTeam(TeamName, AccId, NewMember, NewOwner);
                }else if(OldOwner != NewOwner && NewMember == OldOwner){
                    AccountShare ATeamRules = new AccountShare(AccountId=AccId,OpportunityAccessLevel='Read',CaseAccessLevel='Read',AccountAccessLevel='Edit',UserOrGroupId=NewMember);
              RulesList.add(ATeamRules);                   
                }
            }
        }
    }
   
    private static void RemoveTeam(Id OldMember, String TeamName){
        if(CurrentTeam.containsKey(OldMember)){
            if(CurrentTeam.get(OldMember).TeamMemberRole == TeamName){RemovalList.add(CurrentTeam.get(OldMember));}
        }
    }
   
    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>
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>

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;
    
     
}

 

 

Running my first 'beforeupdate' trigger. Not even sure which would be better for my process, before or after.  Anyway my original code seemed too simple like it wasn't handling bulkification enough.  So I added an soql at the beginning and then did a for loop off of that.  It worked before I added the soql/for loop combination, now it saves the code fine but nothing happens.

 

Its a nested SOQL statement because I plan on referencing the opportunitycontactrole data in later versions to see if they have contacts of a certain type.

 

trigger CPMeStageChange on Opportunity (before insert, before update) {

    list<Opportunity> o = [select id, StageName, Prior_Stage__c, Date_Stage_Last_Updated__c, Engagement_Letter_Signed__c, X80_Gate_Status__c, X70_Gate_Status__c, X50_Gate_Status__c, X40_Gate_Status__c, X30_Gate_Status__c, X20_Gate_Status__c, X10_Gate_Status__c,
                           (select opportunityID, Contact.FirstName from OpportunityContactRoles where Role = 'Internal Supporter') from opportunity where id in:trigger.new];
    
    for (Opportunity CPMOpp: o) {
        if ( CPMOpp.Engagement_Letter_Signed__c==null){
               if (CPMOpp.StageName !='Engagement' && CPMOpp.X80_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Engagement';
               } else if(CPMOpp.StageName !='Verbal Agreement - Date Agreed' && CPMOpp.X70_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Verbal Agreement - Date Agreed';
               } else if(CPMOpp.StageName !='Verbal Agreement - No Date' && CPMOpp.X50_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Verbal Agreement - No Date';
               } else if(CPMOpp.StageName !='Pilot Project' && CPMOpp.X40_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Pilot Project';
               } else if(CPMOpp.StageName !='Negotiation - No Date' && CPMOpp.X30_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Negotiation - No Date';
               } else if(CPMOpp.StageName !='Owner Mandated' && CPMOpp.X20_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Owner Mandated';
               } else if(CPMOpp.StageName !='Sales Process' && CPMOpp.X10_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Sales Process';
               }
            }
        }

 

Can't seem to get this to work.  I have a left outer join query but it doesn't like the relationship syntax:

 

for (Account acct:[SELECT Id,(SELECT Solution__c FROM Org_ID__r)FROM Account WHERE Id in :list_Accts.ID]) {

 

It says it doesn't understand the relationship from Org_ID__r but I check and thats the name of the child object as shown in the lookup field.  

 

Here is what i'm trying to do.  I have a related list under the Account that is lookup, not master-detail.  It holds different external IDs an account could possibly have (duplicates).  There is a field on the account that functions the same and is the old way we did it when it was a one to one relationship.  To speed things up for our service teams to enter accounts they just put the account number on the account and a trigger decides if a new entery in the related list needs to be added or not.

 

1. user enteres a number in a text field to represent an external Key.

2. If that number doesn't match any of the numbers in the related list then create a new one, else leave it alone.

 

Is the Left Outer Join the way to go?  I did something like this on another trigger but that was a master-detail and also standard objects so I don't know if my syntax is correct.

 

Here is the old code with the nested SOQL that I am trying to fix:

trigger CPMOrgIDCreate on Account (after insert, after update) {
    try {
        // List of account IDs
        List<Id> list_Accts = new List<Id>();

        // Add to the list all opps associated with an agreement in the trigger that has been signed
        for (Account AcctID: Trigger.New) {
            if ((trigger.isInsert && AcctID.CPM_Org_ID__c != NULL)|| ( trigger.isUpdate && AcctID.CPM_Org_ID__c != NULL && trigger.oldMap.get(AcctID.id).CPM_Org_ID__c != AcctID.CPM_Org_ID__c )){
                list_Accts.add(AcctID.ID); 
            }
        }

    
        // Loop through all accounts who were added to the list previously
        for (Account acct:[SELECT Id, CPM_Org_ID__c FROM Account WHERE Id in :list_Accts]) {

        
            // Check to see if a project already exists that is related to the opportunity
            List<ORG_ID__c> list_OrgIDs = new List<ORG_ID__c>();
            for (ORG_ID__c SystemID:[SELECT Id FROM ORG_ID__c WHERE ID__c = :acct.CPM_Org_ID__C AND Account__c = :acct.id]) {
                list_OrgIDs.add(SystemID);
            }
        
            if (list_OrgIDs.size() == 0) {
                // If ID does not exist, create one
                ORG_ID__c OID = new ORG_ID__c();
                OID.Account__c = acct.Id;
                OID.ID__c = acct.CPM_Org_ID__c;
                OID.Solution__c = 'CPM';
            
                // Create the new project
                insert OID;
            }            
        }
    } catch (Exception e) {Trigger.new[0].addError(e.getMessage());}   
}

 

I am trying to get this trigger to be as efficient as possible.  I can get it to work enough but to get the code coverage I change it slightyly in a way that causes too many SOQL queries.  Its pretty obvious why as I have three for statemenets nested with SOQL queries in them.  Up till now thats the only way I know how to do it.  I think I am supposed to move those queires to Maps but I don't know how to conceptually work with maps.

 

WHAT IT DOES:

When some fields are filled in on the opp it takes those values and insertes them into a new record related to the contact record listed as primary contact on the opp. 

HOW I SEE THE PROCESS

1. Trigger an opp cause the Credit Card fields are filled in

2. find the contact ID listed as priamry contact on the Opportunity Contact Roles

3. Create a new payment method record, fill values from the opp and set the ContactID to whoever was the primary contact Role on the Opp.

 

I think I need to approach my code totally differently.

trigger PaymentMethodCreate on Opportunity (after update) {
 
    try {
        List<Id> list_Opps = new List<Id>();
 
        List<Id> Prime_Contact = new List<Id>();
        ID PrimeContact;
        List<pymt__Payment_Method__c> NewMethod = new List<pymt__Payment_Method__c>();
        
        for (Opportunity NewCard: Trigger.New) {
            if ((NewCard.CC__c != Null && 
                NewCard.CC_Expiration_Month__c != Null &&
                NewCard.CC_Expiration_Year__c !=Null) &&
                (trigger.oldmap.get(NewCard.Id).CC__c != NewCard.CC__c ||
                trigger.oldmap.get(NewCard.Id).CC_Expiration_Month__c != NewCard.CC_Expiration_Month__c ||
                trigger.oldmap.get(NewCard.Id).CC_Expiration_Year__c != NewCard.CC_Expiration_Year__c)){
                    list_Opps.add(NewCard.ID);
                }
        }
 
        for (Opportunity CardInfo:[SELECT Id, Credit_Card_Notes__c, CC__c, Card_Type__c, Name_On_CC__c, CC_Expiration_Month__c, CC_Expiration_Year__c FROM Opportunity WHERE Id in :List_Opps]) {
            for(OpportunityContactRole PrimaryContact:[SELECT ContactId FROM OpportunityContactRole WHERE OpportunityId = :CardInfo.Id]){
                Prime_Contact.add(PrimaryContact.ContactID);
                IF(Prime_Contact.size() < 1 ){
                    CardInfo.Credit_Card_Notes__c = 'There are no primary contacts listed in the Opportunity Contact Role section to apply a payment method.';
                    update CardInfo;
                } else {
                    for(Contact Payee:[SELECT Id, MailingStreet, MailingCity, MailingState, MailingPostalCode, MailingCountry, Phone, Email FROM Contact WHERE Id = :PrimaryContact.ContactId]){
                        //This section sets a name to the TempC__c field if it is null because 
                        //it won't work if it is null.
                        String FullName;
                        IF(CardInfo.Name_On_CC__c == null){
                            FullName = 'NoName';
                        } else {
                            FullName = CardInfo.Name_On_CC__c;
                        }
            
                        //The rest of the variables that will be used are set here.
                        Integer Index = FullName.indexOf(' ',0);
                        String Prefix;
                        String FName;
                        String LName;
                        String SubName;            
            
                        //First check if a common salutation is on the name to pull it out and set the Prefix variable with it. 
                        //Then strip it of the prefix to create a substring of the name without the prefix.
                        IF((FullName.left(Index) == 'Mr.') || 
                           (FullName.left(Index) == 'Mr') || 
                           (FullName.left(Index) == 'Mrs.') || 
                           (FullName.left(Index) == 'Mrs') || 
                           (FullName.left(Index) == 'Ms.') || 
                           (FullName.left(Index) == 'Ms') || 
                           (FullName.left(Index) == 'Dr.') || 
                           (FullName.left(Index) == 'Dr')){
                               Prefix = FullName.left(Index);
                               SubName = FullName.substring(Index + 1,FullName.length());
                               Index = SubName.indexOf(' ',0);
                    
                               //This sub-IF statement exists to process different logic depending 
                               //if there is one or more words after scurbbing the salutation.
                               IF(SubName.contains(' ')){
                                   FName = SubName.left(Index);
                                   LName = SubName.substring(Index,SubName.length());
                                   } else{
                                       FName = '';
                                       LName = SubName;
                                   }
                    
                               //This other half of the if statement processes like the other but 
                               //without the logic to deal with a salutation since there ins't one.
                               //However there may actually be a salutation if it is not one of the 
                               //common ones included in the first If Statement.
                           } else {
                               Prefix = '';
                               IF(FullName.contains(' ')){
                     
                                   FName = FullName.left(Index);
                                   LName = FullName.substring(Index,FullName.length());
                               } else{
                                   FName = '';
                                   LName = FullName;
                               }
                           }
            
                        //Now that the variables for the name has been procecced for different situations the 
                        //next code will create a new payment method record.
                        pymt__Payment_Method__c Method = new pymt__Payment_Method__c();
                        Method.Name = CardInfo.Card_Type__c + ' (' + CardInfo.CC__C.right(4) + ')';
                        Method.pymt__Contact__c = Payee.Id;
                        Method.pymt__Type__c = 'Credit Card';
                        Method.pymt__Card_Type__c = CardInfo.Card_Type__c;
                        Method.pymt__Billing_Salutation__c = Prefix;
                        Method.pymt__Billing_First_Name__c = FName;
                        Method.pymt__Billing_Last_Name__c = LName;
                        Method.pymt__Last_4_Digits__c = CardInfo.CC__C.right(4);
                        Method.ccrd__Card_Number__c = CardInfo.CC__C;
                        Method.pymt__Expiration_Month__c = CardInfo.CC_Expiration_Month__c;
                        Method.pymt__Expiration_Year__c = CardInfo.CC_Expiration_Year__c;
                        Method.pymt__Billing_Street__c = Payee.MailingStreet;
                        Method.pymt__Billing_City__c = Payee.MailingCity;
                        Method.pymt__Billing_State__c = Payee.MailingState;
                        Method.pymt__Billing_Postal_Code__c = Payee.MailingPostalCode;
                        Method.pymt__Billing_Country__c = Payee.MailingCountry;
                        Method.pymt__Billing_Phone__c = Payee.Phone;
                        Method.pymt__Billing_Email__c = Payee.Email;
                        Method.pymt__Default__c = true;
                        NewMethod.add(Method);
                    }
                    insert NewMethod;
                       
                        
                    //Now that the card info is securly stored inside the payment method record and is encryped
                    //we can clear out the exposed CC info on the opportunity.
                    CardInfo.CC__C = '';
                    CardInfo.Name_On_CC__c = '';
                    CardInfo.CC_Expiration_Month__c = '';
                    CardInfo.CC_Expiration_Year__c = '';
                    CardInfo.Card_Type__c = '';
                    CardInfo.Credit_Card_Notes__c = 'Credit Card was stored in a related Payment Method and is ready to use.  Go to the Payment Terminal and apply the existing payment method';
                                 Update CardInfo;
            }
        }
    }
}catch (Exception e) {Trigger.new[0].addError(e.getMessage());}
}

 

 

I have a new sales team and would like to have a button on the opp create a product with the right pricebook and price.  I could see the value where each button click creates a single product and so they click the button multiple times to add more products OR the click the button and the price book and product are selected and they land on the multi line edit page where they can add quantitiy to a single line item.  Either way works.

 

I tried URL hacking but have been having no luck.  I haven't tried java buttons yet so thats over my head for now.

When a service rep creates a case from an account they may create a contact by using the Quick Craete  button.  We know this quick create feature coes not allow the user to select an account.  I have a trigger that should grab the Account id and contact IDs on the case and add the Account on the case to the newly created contact.  I finally got past the errors but nw nothing happens.

trigger QuickContactUpdate on Case (after insert, after update) {
    String CPMCase = 'CPM Case';
    Map<String, Schema.RecordTypeInfo>  CaseType = new Map<String, Schema.RecordTypeInfo>();
    CaseType = Schema.SObjectType.Case.getRecordTypeInfosByName();
    String CaseTypeId = CaseType.get(CPMCase).getRecordTypeId();
        
    List<ID> CaseList = new list<ID>();
    for (Case c : Trigger.new) {
        IF(c.RecordTypeID == CaseTypeID && c.contact != NULL && c.account != NULL){
            CaseList.add(c.id);
        }
    }
    
    Map<string,string> ConID = New Map<string,string>();
    FOR(Case CaseConnect:[SELECT ContactID, AccountID FROM Case WHERE AccountID != NULL AND contact.AccountID = null AND ID IN :CaseList]){
        ConID.put(CaseConnect.ContactID,CaseConnect.AccountID);
    
        FOR(Contact ConCorrect:[SELECT ID, AccountID FROM Contact WHERE ID in :ConID.KeySet()]){
            ConCorrect.AccountID = ConID.get(ConCorrect.ID);
            UPDATE ConCorrect;
        }
    }
}

  Any thoughts on what I'm missing?

Created a trigger for the service team to easily create a lead and contact if one doesnt exist. (basicaly create a lead then auto convert).  I recently ran a lead inport using the out of the box wizzard and got a error.

 

"

Apex script unhandled trigger exception by user/organization: -------------------------

CPMNewContact: System.LimitException: Too many SOQL queries: 101"

 

I'm guessing I didn't bulkify or put the query in the right spot.  Any thoughts? 

trigger CPMNewContact on Lead (after insert) {
    for (Lead l : Trigger.new) {
        
        Id rtId = [select Id, name from RecordType where name = 'CPM Support Contact' and SObjectType = 'Lead' limit 1].id;

        if (l.isConverted == false && l.recordtypeid == rtId) //to prevent recursion
        {
            Database.LeadConvert lc = new Database.LeadConvert();
            lc.setLeadId(l.Id);
            lc.setDoNotCreateOpportunity(true);
            
            LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
            lc.setConvertedStatus(convertStatus.MasterLabel);
            
            Database.LeadConvertResult lcr = Database.convertLead(lc);
            System.assert(lcr.isSuccess());
            
            //String A = [SELECT ConvertedAccountId FROM Lead WHERE Id =:l.Id].ConvertedAccountId;
            //String C = [SELECT ConvertedContactId FROM Lead WHERE Id =:l.Id].ConvertedContactId;
            //String Org = [SELECT CPM_Org_ID__c FROM Lead WHERE Id =:l.Id];
            
            //Case NewCase = new Case(AccountId=A, ContactId=C);
            //insert NewCase;
        }
    }
}

 

I have a convet lead trigger that creates an account, contact, and case.  I have values in the lead that I want to apply to the account and case.  What syntax do I use to grab data from the converted lead to put in a variable so I can applie it to the other records later.

 

(I need to do this to the account because the standard lead mapping is already mapping to the contact and I need it to map to both account and contact... its a pick list value)

All my lead conversion triggers to date leave the user on the screen that shows what records have been created from the conversion.  In most cases this is not really a problem.  My newest trigger I have a different need.

 

In my conversion I convert the lead into an acocunt and contact but no Oppty.  I also create a new case with the new account and contact as being related to the case.  The trigger is 'after insert' so as soon as they hit save the first time I want the trigger to run and have the user looking at the new case created by the trigger.  I get everything to work except the last part to re-direct the user to the new Case record.  How can I do that?  Can they be directed to the Case in edit mode?  Thanks all.

May have a bulkify issue.  I thought the code below was bulkified but its preventing me from insterting opportunities over 1 at a time.  At least I think its the below code, from what little I know about using debug logs and the developer console.  I filtered on the phrase "Insert Failed" and I saw this trigger come up.

 

The error I get with the data loader when its higher than 1 record is this

 

Insert failed. First exception on row 0 with id a047000000G0BaFAAV; first error: INVALID_FIELD_FOR_INSERT_UPDATE, cannot specify Id in an insert call: [Id]

 

trigger UpdateSalesScoreEvents on Opportunity (After update) {
   
   try { 
 
    // List of variables to be used later.
       List<Sales_Score__c> ScoreEvents = new list<Sales_Score__c>();   
       List<Opportunity> OldStage = New list<Opportunity>();
       ScoreEventHelper.resetCreatedScores();


    // 
    for (Opportunity Opp: Trigger.New) {
        if ((Opp.Company_Division__c == 'Textura') && (Opp.StageName != trigger.oldMap.get(Opp.id).StageName) && (!ScoreEventHelper.hasAlreadyCreatedScores())){

            //
            Sales_Score__c OldEvent = new Sales_Score__c();
            OldEvent.Opportunity__c = opp.id;
            OldEvent.Direction__c = 'Leaving Stage';
            OldEvent.Movement_Date__c = system.Today();
            OldEvent.Stage__c = Trigger.oldMap.get(opp.ID).StageName;
            // Add to ScoreEvent list
            ScoreEvents.add(OldEvent);
            
            //
            Sales_Score__c Event = new Sales_Score__c();
            Event.Opportunity__c = opp.id;
            Event.Direction__c = 'Entering Stage';
            Event.Movement_Date__c = system.Today();
            Event.Stage__c = opp.StageName;
            // Add to ScoreEvent list
            ScoreEvents.add(Event);
                                   

        }
        ScoreEventHelper.setAlreadyCreatedScores();
        insert ScoreEvents;
    }   
   } catch (Exception e) {Trigger.new[0].addError(e.getMessage());}   
}

 

I have an ETL that is loading in Leads.  They suddenly have been missing the email.  The IT developer has been passing emails to my leads but they haven't been loading.  With what i've looked into it seems that it is most likely a trigger or class that strips the email before insert. 

 

How can I serach my many triggers and classes to find the cuplrit?  any good tools or tricks out there other than going through them one by one?

Anyone know what the CSS is for styling content to look like the updated service cosole?  Specifically like how related lists look like on a side component.  It has a clean, white look without much borders.  I would like to use such a CSS for my Flow's that I am planning on making.
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>

I have been trying to write test code recently that seems to not work like it used to.  In the test class I would create a record and insert it, then make a change and update it.  That used to work fine now it is as if only the insert is recognized and the code related to the update doesn't get checked.

<pre>
public class AccountTeamManage Implements Dispatch.ITriggerEntry{
   
    public static list<AccountTeamMember> MemberList = null;
    public static list<AccountShare> RulesList = null;
    public static list<AccountTeamMember> RemovalList = null;
    public static map<Id,AccountTeamMember> CurrentTeam = null;
   
    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,Account>NewAccount = (Map<Id,Account>)NewMap;
        Map<Id,Account>OldAccount = (Map<Id,Account>)OldMap;       
        MemberList = new List<AccountTeamMember>();
        RulesList = new List<AccountShare>();   
        RemovalList = new list<AccountTeamMember>();       
        CurrentTeam = new map<Id,AccountTeamMember>();
       
        for(AccountTeamMember Team : [SELECT UserId, AccountID, TeamMemberRole FROM AccountTeamMember WHERE AccountId IN:NewAccount.keySet()]){
            CurrentTeam.put(Team.UserId, Team);
        }
       
        for(Account a : NewAccount.values()){
            if(IsInsert){               
                if(a.CPMb_Sales__c != null){CreateTeam('CPMB Sales Consultant', a.Id, a.CPMb_Sales__c, a.OwnerId);}
                if(a.CPMb_Support__c != null){CreateTeam('CPMB Solution Consultant', a.Id, a.CPMb_Support__c, a.OwnerId);}
                if(a.SubEx_Sales__c != null){CreateTeam('Submittal Exchange Sales Consultant', a.Id, a.SubEx_Sales__c, a.OwnerId);}
                if(a.SubEx_NBR__c != null){CreateTeam('Submittal Exchange NBR', a.Id, a.SubEx_NBR__c, a.OwnerId);}
                if(a.SubEx_Support__c != null){CreateTeam('Submittal Exchange CRC', a.Id, a.SubEx_Support__c, a.OwnerId);}               
                if(a.Gradebeam_Sales__c != null){CreateTeam('Gradebeam Sales Consultant', a.Id, a.Gradebeam_Sales__c, a.OwnerId);}
                if(a.PQM_Sales__c != null){CreateTeam('PQM Sales Consultant', a.Id, a.PQM_Sales__c, a.OwnerId);}
                if(a.BidOrganizer_Sales__c != null){CreateTeam('BidOrganizer Sales Consultant', a.Id, a.BidOrganizer_Sales__c, a.OwnerId);}
                if(a.PlanSwift_Sales__c != null){CreateTeam('PlanSwift Sales Consultant', a.Id, a.PlanSwift_Sales__c, a.OwnerId);}               
            }else if(IsUpdate){
                Account oldAcct = OldAccount.get(a.Id);               
                UpdateTeam('CPMB Sales Consultant', a.Id, OldAcct.CPMb_Sales__c, a.CPMb_Sales__c, OldAcct.OwnerId, a.OwnerId);
                UpdateTeam('CPMB Solution Consultant', a.Id, OldAcct.CPMb_Support__c, a.CPMb_Support__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('Submittal Exchange Sales Consultant', a.Id, OldAcct.SubEx_Sales__c, a.SubEx_Sales__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('Submittal Exchange NBR', a.Id, OldAcct.SubEx_NBR__c, a.SubEx_NBR__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('Submittal Exchange CRC', a.Id, OldAcct.SubEx_Support__c, a.SubEx_Support__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('Gradebeam Sales Consultant', a.Id, OldAcct.Gradebeam_Sales__c, a.Gradebeam_Sales__c, OldAcct.OwnerId, a.OwnerId);               
                UpdateTeam('PQM Sales Consultant', a.Id, OldAcct.PQM_Sales__c, a.PQM_Sales__c, OldAcct.OwnerId, a.OwnerId);
                UpdateTeam('BidOrganizer Sales Consultant', a.Id, OldAcct.BidOrganizer_Sales__c, a.BidOrganizer_Sales__c, OldAcct.OwnerId, a.OwnerId);
                UpdateTeam('PlanSwift Sales Consultant', a.Id, OldAcct.PlanSwift_Sales__c, a.PlanSwift_Sales__c, OldAcct.OwnerId, a.OwnerId);
            }
        }
       
        if(RemovalList.size() > 0){
            delete RemovalList;
        }       
        if(MemberList.size() > 0){
            upsert MemberList;
        }       
        if(RulesList.size() > 0){
         upsert RulesList;
        }
    }
   
    private static void CreateTeam(string TeamName, Id AccId,Id NewMember,Id NewOwner){
        accountTeamMember ATeam = new AccountTeamMember(AccountId = AccId,TeamMemberRole = TeamName,UserId =NewMember);
        MemberList.add(ATeam);
        if(NewMember != NewOwner){
            AccountShare ATeamRules = new AccountShare(AccountId=AccId,OpportunityAccessLevel='Read',CaseAccessLevel='Read',AccountAccessLevel='Edit',UserOrGroupId=NewMember);
            RulesList.add(ATeamRules);
        }
    }
   
    private static void UpdateTeam(string TeamName, Id AccId, Id OldMember, Id NewMember, Id OldOwner, Id NewOwner){
        if(NewMember == null && OldMember != null){
            RemoveTeam(OldMember, TeamName);
        }
       
        if(NewMember != null){
            if(NewMember != OldMember){
                RemoveTeam(OldMember, TeamName);
            }
           
            if(!CurrentTeam.containsKey(NewMember)){
                CreateTeam(TeamName, AccId, NewMember, NewOwner);
            }else{
                if(CurrentTeam.get(NewMember).TeamMemberRole != TeamName){
                    CreateTeam(TeamName, AccId, NewMember, NewOwner);
                }else if(OldOwner != NewOwner && NewMember == OldOwner){
                    AccountShare ATeamRules = new AccountShare(AccountId=AccId,OpportunityAccessLevel='Read',CaseAccessLevel='Read',AccountAccessLevel='Edit',UserOrGroupId=NewMember);
              RulesList.add(ATeamRules);                   
                }
            }
        }
    }
   
    private static void RemoveTeam(Id OldMember, String TeamName){
        if(CurrentTeam.containsKey(OldMember)){
            if(CurrentTeam.get(OldMember).TeamMemberRole == TeamName){RemovalList.add(CurrentTeam.get(OldMember));}
        }
    }
   
    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>
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>

Today we’re excited to announce the new Salesforce Developers Discussion Forums. We’ve listened to your feedback on how we can improve the forums.  With Chatter Answers, built on the Salesforce1 Platform, we were able to implement an entirely new experience, integrated with the rest of the Salesforce Developers site.  By the way, it’s also mobile-friendly.

We’ve migrated all the existing data, including user accounts. You can use the same Salesforce account you’ve always used to login right away.  You’ll also have a great new user profile page that will highlight your community activity.  Kudos have been replaced by “liking” a post instead and you’ll now be able to filter solved vs unsolved posts.

This is, of course, only the beginning  and because it’s built on the Salesforce1 Platform, we’re going to be able to bring you more features faster than ever before.  Be sure to share any feedback, ideas, or questions you have on this forum post.

Hats off to our development team who has been working tirelessly over the past few months to bring this new experience to our community. And thanks to each of you for helping to build one of the most vibrant and collaborative developer communities ever.
 

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;
    
     
}

 

 

Running my first 'beforeupdate' trigger. Not even sure which would be better for my process, before or after.  Anyway my original code seemed too simple like it wasn't handling bulkification enough.  So I added an soql at the beginning and then did a for loop off of that.  It worked before I added the soql/for loop combination, now it saves the code fine but nothing happens.

 

Its a nested SOQL statement because I plan on referencing the opportunitycontactrole data in later versions to see if they have contacts of a certain type.

 

trigger CPMeStageChange on Opportunity (before insert, before update) {

    list<Opportunity> o = [select id, StageName, Prior_Stage__c, Date_Stage_Last_Updated__c, Engagement_Letter_Signed__c, X80_Gate_Status__c, X70_Gate_Status__c, X50_Gate_Status__c, X40_Gate_Status__c, X30_Gate_Status__c, X20_Gate_Status__c, X10_Gate_Status__c,
                           (select opportunityID, Contact.FirstName from OpportunityContactRoles where Role = 'Internal Supporter') from opportunity where id in:trigger.new];
    
    for (Opportunity CPMOpp: o) {
        if ( CPMOpp.Engagement_Letter_Signed__c==null){
               if (CPMOpp.StageName !='Engagement' && CPMOpp.X80_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Engagement';
               } else if(CPMOpp.StageName !='Verbal Agreement - Date Agreed' && CPMOpp.X70_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Verbal Agreement - Date Agreed';
               } else if(CPMOpp.StageName !='Verbal Agreement - No Date' && CPMOpp.X50_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Verbal Agreement - No Date';
               } else if(CPMOpp.StageName !='Pilot Project' && CPMOpp.X40_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Pilot Project';
               } else if(CPMOpp.StageName !='Negotiation - No Date' && CPMOpp.X30_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Negotiation - No Date';
               } else if(CPMOpp.StageName !='Owner Mandated' && CPMOpp.X20_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Owner Mandated';
               } else if(CPMOpp.StageName !='Sales Process' && CPMOpp.X10_Gate_Status__c == 'Complete'){
                   CPMOpp.Prior_Stage__c = CPMOpp.StageName;
                   CPMOpp.Date_Stage_Last_Updated__c = System.today();
                   CPMOpp.StageName = 'Sales Process';
               }
            }
        }

 

Can't seem to get this to work.  I have a left outer join query but it doesn't like the relationship syntax:

 

for (Account acct:[SELECT Id,(SELECT Solution__c FROM Org_ID__r)FROM Account WHERE Id in :list_Accts.ID]) {

 

It says it doesn't understand the relationship from Org_ID__r but I check and thats the name of the child object as shown in the lookup field.  

 

Here is what i'm trying to do.  I have a related list under the Account that is lookup, not master-detail.  It holds different external IDs an account could possibly have (duplicates).  There is a field on the account that functions the same and is the old way we did it when it was a one to one relationship.  To speed things up for our service teams to enter accounts they just put the account number on the account and a trigger decides if a new entery in the related list needs to be added or not.

 

1. user enteres a number in a text field to represent an external Key.

2. If that number doesn't match any of the numbers in the related list then create a new one, else leave it alone.

 

Is the Left Outer Join the way to go?  I did something like this on another trigger but that was a master-detail and also standard objects so I don't know if my syntax is correct.

 

Here is the old code with the nested SOQL that I am trying to fix:

trigger CPMOrgIDCreate on Account (after insert, after update) {
    try {
        // List of account IDs
        List<Id> list_Accts = new List<Id>();

        // Add to the list all opps associated with an agreement in the trigger that has been signed
        for (Account AcctID: Trigger.New) {
            if ((trigger.isInsert && AcctID.CPM_Org_ID__c != NULL)|| ( trigger.isUpdate && AcctID.CPM_Org_ID__c != NULL && trigger.oldMap.get(AcctID.id).CPM_Org_ID__c != AcctID.CPM_Org_ID__c )){
                list_Accts.add(AcctID.ID); 
            }
        }

    
        // Loop through all accounts who were added to the list previously
        for (Account acct:[SELECT Id, CPM_Org_ID__c FROM Account WHERE Id in :list_Accts]) {

        
            // Check to see if a project already exists that is related to the opportunity
            List<ORG_ID__c> list_OrgIDs = new List<ORG_ID__c>();
            for (ORG_ID__c SystemID:[SELECT Id FROM ORG_ID__c WHERE ID__c = :acct.CPM_Org_ID__C AND Account__c = :acct.id]) {
                list_OrgIDs.add(SystemID);
            }
        
            if (list_OrgIDs.size() == 0) {
                // If ID does not exist, create one
                ORG_ID__c OID = new ORG_ID__c();
                OID.Account__c = acct.Id;
                OID.ID__c = acct.CPM_Org_ID__c;
                OID.Solution__c = 'CPM';
            
                // Create the new project
                insert OID;
            }            
        }
    } catch (Exception e) {Trigger.new[0].addError(e.getMessage());}   
}

 

I am trying to get this trigger to be as efficient as possible.  I can get it to work enough but to get the code coverage I change it slightyly in a way that causes too many SOQL queries.  Its pretty obvious why as I have three for statemenets nested with SOQL queries in them.  Up till now thats the only way I know how to do it.  I think I am supposed to move those queires to Maps but I don't know how to conceptually work with maps.

 

WHAT IT DOES:

When some fields are filled in on the opp it takes those values and insertes them into a new record related to the contact record listed as primary contact on the opp. 

HOW I SEE THE PROCESS

1. Trigger an opp cause the Credit Card fields are filled in

2. find the contact ID listed as priamry contact on the Opportunity Contact Roles

3. Create a new payment method record, fill values from the opp and set the ContactID to whoever was the primary contact Role on the Opp.

 

I think I need to approach my code totally differently.

trigger PaymentMethodCreate on Opportunity (after update) {
 
    try {
        List<Id> list_Opps = new List<Id>();
 
        List<Id> Prime_Contact = new List<Id>();
        ID PrimeContact;
        List<pymt__Payment_Method__c> NewMethod = new List<pymt__Payment_Method__c>();
        
        for (Opportunity NewCard: Trigger.New) {
            if ((NewCard.CC__c != Null && 
                NewCard.CC_Expiration_Month__c != Null &&
                NewCard.CC_Expiration_Year__c !=Null) &&
                (trigger.oldmap.get(NewCard.Id).CC__c != NewCard.CC__c ||
                trigger.oldmap.get(NewCard.Id).CC_Expiration_Month__c != NewCard.CC_Expiration_Month__c ||
                trigger.oldmap.get(NewCard.Id).CC_Expiration_Year__c != NewCard.CC_Expiration_Year__c)){
                    list_Opps.add(NewCard.ID);
                }
        }
 
        for (Opportunity CardInfo:[SELECT Id, Credit_Card_Notes__c, CC__c, Card_Type__c, Name_On_CC__c, CC_Expiration_Month__c, CC_Expiration_Year__c FROM Opportunity WHERE Id in :List_Opps]) {
            for(OpportunityContactRole PrimaryContact:[SELECT ContactId FROM OpportunityContactRole WHERE OpportunityId = :CardInfo.Id]){
                Prime_Contact.add(PrimaryContact.ContactID);
                IF(Prime_Contact.size() < 1 ){
                    CardInfo.Credit_Card_Notes__c = 'There are no primary contacts listed in the Opportunity Contact Role section to apply a payment method.';
                    update CardInfo;
                } else {
                    for(Contact Payee:[SELECT Id, MailingStreet, MailingCity, MailingState, MailingPostalCode, MailingCountry, Phone, Email FROM Contact WHERE Id = :PrimaryContact.ContactId]){
                        //This section sets a name to the TempC__c field if it is null because 
                        //it won't work if it is null.
                        String FullName;
                        IF(CardInfo.Name_On_CC__c == null){
                            FullName = 'NoName';
                        } else {
                            FullName = CardInfo.Name_On_CC__c;
                        }
            
                        //The rest of the variables that will be used are set here.
                        Integer Index = FullName.indexOf(' ',0);
                        String Prefix;
                        String FName;
                        String LName;
                        String SubName;            
            
                        //First check if a common salutation is on the name to pull it out and set the Prefix variable with it. 
                        //Then strip it of the prefix to create a substring of the name without the prefix.
                        IF((FullName.left(Index) == 'Mr.') || 
                           (FullName.left(Index) == 'Mr') || 
                           (FullName.left(Index) == 'Mrs.') || 
                           (FullName.left(Index) == 'Mrs') || 
                           (FullName.left(Index) == 'Ms.') || 
                           (FullName.left(Index) == 'Ms') || 
                           (FullName.left(Index) == 'Dr.') || 
                           (FullName.left(Index) == 'Dr')){
                               Prefix = FullName.left(Index);
                               SubName = FullName.substring(Index + 1,FullName.length());
                               Index = SubName.indexOf(' ',0);
                    
                               //This sub-IF statement exists to process different logic depending 
                               //if there is one or more words after scurbbing the salutation.
                               IF(SubName.contains(' ')){
                                   FName = SubName.left(Index);
                                   LName = SubName.substring(Index,SubName.length());
                                   } else{
                                       FName = '';
                                       LName = SubName;
                                   }
                    
                               //This other half of the if statement processes like the other but 
                               //without the logic to deal with a salutation since there ins't one.
                               //However there may actually be a salutation if it is not one of the 
                               //common ones included in the first If Statement.
                           } else {
                               Prefix = '';
                               IF(FullName.contains(' ')){
                     
                                   FName = FullName.left(Index);
                                   LName = FullName.substring(Index,FullName.length());
                               } else{
                                   FName = '';
                                   LName = FullName;
                               }
                           }
            
                        //Now that the variables for the name has been procecced for different situations the 
                        //next code will create a new payment method record.
                        pymt__Payment_Method__c Method = new pymt__Payment_Method__c();
                        Method.Name = CardInfo.Card_Type__c + ' (' + CardInfo.CC__C.right(4) + ')';
                        Method.pymt__Contact__c = Payee.Id;
                        Method.pymt__Type__c = 'Credit Card';
                        Method.pymt__Card_Type__c = CardInfo.Card_Type__c;
                        Method.pymt__Billing_Salutation__c = Prefix;
                        Method.pymt__Billing_First_Name__c = FName;
                        Method.pymt__Billing_Last_Name__c = LName;
                        Method.pymt__Last_4_Digits__c = CardInfo.CC__C.right(4);
                        Method.ccrd__Card_Number__c = CardInfo.CC__C;
                        Method.pymt__Expiration_Month__c = CardInfo.CC_Expiration_Month__c;
                        Method.pymt__Expiration_Year__c = CardInfo.CC_Expiration_Year__c;
                        Method.pymt__Billing_Street__c = Payee.MailingStreet;
                        Method.pymt__Billing_City__c = Payee.MailingCity;
                        Method.pymt__Billing_State__c = Payee.MailingState;
                        Method.pymt__Billing_Postal_Code__c = Payee.MailingPostalCode;
                        Method.pymt__Billing_Country__c = Payee.MailingCountry;
                        Method.pymt__Billing_Phone__c = Payee.Phone;
                        Method.pymt__Billing_Email__c = Payee.Email;
                        Method.pymt__Default__c = true;
                        NewMethod.add(Method);
                    }
                    insert NewMethod;
                       
                        
                    //Now that the card info is securly stored inside the payment method record and is encryped
                    //we can clear out the exposed CC info on the opportunity.
                    CardInfo.CC__C = '';
                    CardInfo.Name_On_CC__c = '';
                    CardInfo.CC_Expiration_Month__c = '';
                    CardInfo.CC_Expiration_Year__c = '';
                    CardInfo.Card_Type__c = '';
                    CardInfo.Credit_Card_Notes__c = 'Credit Card was stored in a related Payment Method and is ready to use.  Go to the Payment Terminal and apply the existing payment method';
                                 Update CardInfo;
            }
        }
    }
}catch (Exception e) {Trigger.new[0].addError(e.getMessage());}
}

 

 

When a service rep creates a case from an account they may create a contact by using the Quick Craete  button.  We know this quick create feature coes not allow the user to select an account.  I have a trigger that should grab the Account id and contact IDs on the case and add the Account on the case to the newly created contact.  I finally got past the errors but nw nothing happens.

trigger QuickContactUpdate on Case (after insert, after update) {
    String CPMCase = 'CPM Case';
    Map<String, Schema.RecordTypeInfo>  CaseType = new Map<String, Schema.RecordTypeInfo>();
    CaseType = Schema.SObjectType.Case.getRecordTypeInfosByName();
    String CaseTypeId = CaseType.get(CPMCase).getRecordTypeId();
        
    List<ID> CaseList = new list<ID>();
    for (Case c : Trigger.new) {
        IF(c.RecordTypeID == CaseTypeID && c.contact != NULL && c.account != NULL){
            CaseList.add(c.id);
        }
    }
    
    Map<string,string> ConID = New Map<string,string>();
    FOR(Case CaseConnect:[SELECT ContactID, AccountID FROM Case WHERE AccountID != NULL AND contact.AccountID = null AND ID IN :CaseList]){
        ConID.put(CaseConnect.ContactID,CaseConnect.AccountID);
    
        FOR(Contact ConCorrect:[SELECT ID, AccountID FROM Contact WHERE ID in :ConID.KeySet()]){
            ConCorrect.AccountID = ConID.get(ConCorrect.ID);
            UPDATE ConCorrect;
        }
    }
}

  Any thoughts on what I'm missing?

Can anyone suggest, how ca we delete apex class from production.

please provide step-step process to delete it from prod. through Force.com Eclipse.

  • October 29, 2010
  • Like
  • 1