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
cbrocbro 

Disallow New Contract Record for Accounts with existing 'Active'/'Pending' Contracts

I have a few questions, as I am very new to building triggers, dev work...

 

This is mostly to get all of what I need out on the table, and I understand this is a large amount of work...  I just don't even know where to start.  

 

Any help would be greatly appreciated!

 

 

My problems: 

  • I need to make sure there can be only one 'Active'/'Pending' Contract per Account.
  • I need to make sure I can have multiple Opportunities associated with that one Contract in 'Active'/'Pending' Status.
  • I need to make sure I cannot create a new Contract from an Opportunity (or from anywhere else) if an 'Active'/'Pending' Contract already exists for an Account.
  • If there is an 'Active'/'Pending' Contract associated with an Account for which a new Opportunity is made, I need that Contract Number to auto-fill in a field on any new Opportunity (Opportunity.Current_Contract__c)
  • If there is an 'Expired' Contract, I need the most recent 'Expired' Contract to auto-fill in a lookup field on the new Contract - that it is replacing the old 'Expired' Status Contract (Contract.Expired_Contract__c).
  • I can have multiple Contracts in 'Expired' status - but I should not be able to add 'Assets' or associate Opportunities to these 'Expired' Contracts.

 

Thanks again in advance for any help at all!

Chris

ReidCReidC

Probably a few ways to handle this.

If I were you, I would start by:

* drawing a small diagram that shows the relationships between the objects

* draw a flow for each one of these restrictions -- where does the restriction start, what objects does it touch, what fields does it affect

* implement a little at a time so the job doesn't feel so big.

* repeat until you have what you need.

 

For some of the detailed requirements, 

I need to make sure there can be only one 'Active'/'Pending' Contract per Account.

- I would make this a before insert before update trigger on Contract and reject the new record if it violates the restriction

I need to make sure I can have multiple Opportunities associated with that one Contract in 'Active'/'Pending' Status.

 

- Default, right?

I need to make sure I cannot create a new Contract from an Opportunity (or from anywhere else) if an 'Active'/'Pending' Contract already exists for an Account.

- Seems like the as the first one, although you might have some nuances around your contract status here.

 

etc.

HTH

cbrocbro

Okay, 

 

So starting slowly (1 piece at a time) - I am simply wanting to add the related Contract (which is not 'Expired') to the Account for which the Contract is Active 

(Account.Contract_Lookup__c).

 

2nd piece - how do I add the restriction, if you know?

 

I am getting the following error.  

 

What am I missing?

 

"ContractNumberOnAccount: execution of BeforeUpdate caused by: System.NullPointerException: Attempt to de-reference a null object: Trigger.ContractNumberOnAccount: line 20, column 1"

 

trigger ContractNumberOnAccount on Contract (before insert, before update) {

{
    Map <Id, Contract> oldmap = new Map <Id, Contract>();
    Map <Id, Contract> newmap = new Map <Id, Contract>();
    List <Account> newAccountList = new List <Account>();
 
 System.debug('------ Contract First Run-----------'+Constants.Contract_First_Run);

    if(Constants.CONTRACT_FIRST_RUN)  
    {
        Map<Id, Account> accountMap = new Map<Id, Account>();

        for(Contract c: Trigger.new) 
        {
            if(c.Status <> 'Expired') // Contract has an Account record and is Expired.
            {
                Account a = accountMap.get(c.Id);

                a.ContractLookup__c = c.Id;
                newAccountList.add(a);
            }
            
        }
        Constants.CONTRACT_FIRST_RUN = False;
        if(newAccountList.size()>0)
    {
    //System.debug('Chris has values to insert = '+ newConList.size());
    try
     {
        upsert newAccountList;
     }
     catch (System.Dmlexception e)  
     {
        system.debug (e); 
     }
}    }
}
}

 

SurpriseSurprise

Below given is before update trigger which which will ensure if contract' status edited to active or pending then it gives an error .However, u have to see how it is going to work with new inserts.You also need to trigger.old to make sure sure that when status was changed to active or pending ,trigger.old had neither pending nor active in the status field.

 

trigger newcontract on Contract (before update ) {
set<id> accs=new set<id>();
for(contract c:trigger.new)
   {

        accs.add(c.accountid);        
        
   }
 
map<id,contract> m=new map<id,contract>([select id,accountid,status from contract where accountid in:accs]);
for(contract z:trigger.new)
{
if(z.status=='active'|| z.status=='pending')
{
        
        contract c=m.get(z.id);
        if(m.size()>0 && c!=null)
        {
        
        z.adderror('Sorry there is already and exisitn contact with status either pending or active');
        
        }
}

SurpriseSurprise

Below given trigger will solve your Bulleted points 1 and 3.

 

Trigger newcontract on Contract (before insert,before update )
{
    if(trigger.isinsert)
    {
              
    set<id>first=new set<id>();
    for(contract c:trigger.new)    
       {
        
            first.add(c.accountid);    
    
      }
    map<id,contract> mp=new map<id,contract>([select id,accountid,status from contract where accountid in:first]);
    for(contract z:trigger.new)
        {
         if(z.status=='pending' || z.status=='active')
             {
             
            contract p=mp.get(z.id);                
            if(mp.size()>0||p!=null)
                {
                 
                 z.adderror('There is an error in it');
                                  
                }
                         
            }
    
        }
    
}     
    else
    
            if(trigger.isupdate)
                {  
                
                contract c10;
                //contract c=trigger.oldmap.keyset();      
                set<id> accs=new set<id>();
                for(contract c:trigger.new)
                   {

                        accs.add(c.accountid);        
        
                   }
 map<id,contract> m=new map<id,contract>([select id,accountid,status from contract where accountid in:accs]);
                   for(contract z:trigger.new)
                   {

                    if(z.status=='active'|| z.status=='pending')
                        {
                        
                         if(trigger.oldmap.get(z.id).status!=trigger.newmap.get(z.id).status)        
                           {
                           
                               c10=m.get(z.id);
                               
                           }
                            if(m.size()>0 && c10!=null)
                            {
        
                                z.adderror('Sorry there is already and exisitn contact with status either pending or active');
        
                            }
                        }
   
                    }
}
}

cbrocbro

Thank you Surprise, for your help thus far.  I will have to revisit this soon.  I am knee deep in something else for the moment, but this looks like a great place to start.  I will let you know how it turns out soon.