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
Jay Parikh 36Jay Parikh 36 

Hi -- Urgent Req apex trigger

Hi -- I have one xyz custom object and which is related with account object now i have req where on account object there will be 3 or 4 xyz object records and i want to create a new fields which is called first record and latest record checkbox which is based on created date of xyz records how will i achieve ??
for example :: on account there will be xyz object has a , b , c records based on creation date it will checked a record first records box true and same with the latest one ?????
Best Answer chosen by Jay Parikh 36
HARSHIL U PARIKHHARSHIL U PARIKH
Hello Jay,

finally !! We have nailed this one down!

Here is how,

1) Relationship: = Parent Object: Account and Child Object: Contact
2) Two Fields on parent (Account) object named: First Contact Id, and Latest Contact Id. (These are simple text fields and make them locked at page layout and hidden if you want)
3) Two formula fields on Child (Contact) object named First Contact, and Latest Contact. Both of them would be a formula fields with return type as checkbox.
Formulas for both fields:
For First_Contact__c field    
IF( Id = Account.First_Contact_Id__c , TRUE, FALSE)
For Latest_Contact__c field
IF( Id = Account.Latest_Contact_Id__c , TRUE, FALSE)
4) Now, have this following trigger on Child (Contact) object.
Trigger Code:
Trigger UpdateFirstAndLastCon On Contact(After Insert, After Update, After Delete, After UnDelete){
    
    List<Id> accountIds = New List<Id>();
    
    If(Trigger.IsInsert || Trigger.IsUpdate || Trigger.IsUnDelete){
        For(Contact con : Trigger.New){
            If(con.AccountId != null){
                accountIds.add(con.AccountId);
            }
        }
    }
    If(Trigger.IsDelete){
        For(Contact con : Trigger.old){
            If(con.AccountId != Null){
                accountIds.add(con.AccountId);
            }
        }
    }
    
    List<Account> actFinalList = New List<Account>();
    
    For(Account act : [Select Id, First_Contact_Id__c, Latest_Contact_Id__c,
                                (Select Id, CreatedDate FROM Contacts WHERE CreatedDate != NULL ORDER BY CreatedDate Desc)
                                  FROM Account WHERE Id =:accountIds])
    {
        List<Id> comingConsIds = New List<Id>();
        
        Integer I = 0;
        For(Contact EveryCon : act.Contacts){
            comingConsIds.add(EveryCon.Id);
            I++;
        }
        
        If(!comingConsIds.IsEmpty())
        {            
            act.Latest_Contact_Id__c = String.ValueOf(comingConsIds[0]).substring(0,15);
            act.First_Contact_Id__c  = String.ValueOf(comingConsIds[I - 1]).substring(0,15);
            actFinalList.add(act);
        }
        
        
    }
    try{
        If(!actFinalList.IsEmpty()){
            update actFinalList;
        }
    }
    catch(Exception e){
        System.debug('Thwon exception for UpdateFirstAndLastCon Trigger Is:: ' + e.getMessage());
    }
    
}
See it in Action:

User-added image

This trigger would work in all conditions such as When you insert the Contact, update it or delete it and even undelete it.

Hope this helps jay and if it solves the puzzle then please mark it as Best Answer so it can help others with the similar issue.

Thank You Sir!


 

All Answers

om gupta(sfdc)om gupta(sfdc)
you mean a account contains child (a,b,c) . so a checked as records first and c checked as latest. and b having both field false right ?
Jay Parikh 36Jay Parikh 36
yes
om gupta(sfdc)om gupta(sfdc)
i didn't see so much code but may you use before instead of after . 
Jay Parikh 36Jay Parikh 36
Hi in my code at line 27 i am gerring correct value but it in not updating that field value on object 
om gupta(sfdc)om gupta(sfdc)
i am not 100 % sure but i my openion using after in trigger you have to manually update . and  when you use before you have not to do . plz give me few more min to create a new code basis on this
 
Jay Parikh 36Jay Parikh 36
Ok
om gupta(sfdc)om gupta(sfdc)
trigger FirstLpCal on Lead_Products__c (after insert , after update) {
	List <id> accountids = new list <id>();
	if (trigger.isinsert || trigger.isupdate){
		for (Lead_Products__c  ls : trigger.new){
			if(ls.account__c!= null){
			  accountids.add(ls.account__c);  
			}
		} 
	}  
	Map<String,Integer> childSizeByAccountId = new Map<String,Integer>();
	Map<String,Integer> originalchildSizeByAccountId = new Map<String,Integer>();
	list <account> accountfinallist = [select id ,(select id , createddate from Lead_Products__r ORDER BY createddate ASC) from account where id in : accountids];
	for(account acc : accountfinallist){
		childSizeByAccountId.put(acc.Id,acc.Lead_Products__r.size());
		originalchildSizeByAccountId.put(acc.Id,acc.Lead_Products__r.size());
	}
	//here we always get the records in created order thats why not applied filter
	for(Lead_Products__c lp : Trigger.new){
		String accId = lp.account__c;
		Integer size = childSizeByAccountId.get(accId);
		if(size != null){
			lp.First_Lead_Product__c = originalchildSizeByAccountId.get(accId) == size;
			lp.Latest_Lead_Product__c = size == 1;
		    childSizeByAccountId.put(accId,--size);
		}
	}

}

if this solve you problem plz maked as best answer . i didn't get a single one . if any issue i will again reply 
Asif Ali MAsif Ali M
Hi Jay,

I refactored your for loop . Please try the code and let me know if it works.
 
List<Lead_Products__c> recordToUpdate = new List<Lead_Products__c>();
for (account act : [select id, (select id, createddate, Last_Lead_Product__c, First_Lead_Product__c from Lead_Products__r ORDER BY createddate ASC) from account where id in :accountids]) {

    // child record exists?
    if (act.Lead_Products__r != null && act.Lead_Products__r.size() > 0) {
        Integer childCount = act.Lead_Products__r.size();
        Lead_Products__c childRecord = new Lead_Products__c();

        // Set First Record Flag
        childRecord = act.Lead_Products__r[0];
        childRecord.First_Lead_Product__c = true;
        recordToUpdate.add(childRecord);

        // Set Last Record Flag
        if (childCount > 1) {
            childRecord = act.Lead_Products__r[childCount - 1];
            childRecord.Last_Lead_Product__c = true;
            recordToUpdate.add(childRecord);
        }

        // Reset all other records between first & last
        for (Integer childIndex = 1; childIndex < childCount - 1; childIndex++) {
            childRecord = act.Lead_Products__r[childIndex];
            childRecord.First_Lead_Product__c = false;
            childRecord.Last_Lead_Product__c = false;
            recordToUpdate.add(childRecord);
        }
    }
}


if (recordToUpdate.size() > 0) {
    system.debug('Total Record to Update' + recordToUpdate.size());
    update recordToUpdate;
}


 
Jay Parikh 36Jay Parikh 36
trigger FirstLpCal on Lead_Products__c (after insert , after update) {
List <id> accountids = new list <id>();
    if (trigger.isinsert || trigger.isupdate){
        for (Lead_Products__c  ls : trigger.new){
            if(ls.account__c!= null){
              accountids.add(ls.account__c);  
              system.debug('-------1'+ls);

            }
        } 
    }  
  List<Lead_Products__c> recordToUpdate = new List<Lead_Products__c>();
for (account act : [select id, (select id, createddate, First_Lead_Product__c from Lead_Products__r ORDER BY createddate ASC) from account where id in :accountids]) {

    // child record exists?
    if (act.Lead_Products__r != null && act.Lead_Products__r.size() > 0) {
        Integer childCount = act.Lead_Products__r.size();
        Lead_Products__c childRecord = new Lead_Products__c();

        // Set First Record Flag
        childRecord = act.Lead_Products__r[0];
        childRecord.First_Lead_Product__c = true;
        recordToUpdate.add(childRecord);

        // Set Last Record Flag
        if (childCount > 1) {
            childRecord = act.Lead_Products__r[childCount - 1];
          //  childRecord.Last_Lead_Product__c = true;
            recordToUpdate.add(childRecord);
        }

        // Reset all other records between first & last
        for (Integer childIndex = 1; childIndex < childCount - 1; childIndex++) {
            childRecord = act.Lead_Products__r[childIndex];
            childRecord.First_Lead_Product__c = false;
           // childRecord.Last_Lead_Product__c = false;
            recordToUpdate.add(childRecord);
        }
    }
}


if (recordToUpdate.size() > 0) {
    system.debug('Total Record to Update' + recordToUpdate.size());
    update recordToUpdate;
}
}

I am using this code but it is getting

CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, FirstLpCal: maximum trigger depth exceeded 

this error
om gupta(sfdc)om gupta(sfdc)
have you tried my one
Asif Ali MAsif Ali M
ahh,  your trigger is on the Lead_Products__c. Seperate the logic into a future handler so you dont end up with recursive trigger issue. 
HARSHIL U PARIKHHARSHIL U PARIKH
I would suggest the following:
I am not sure this suggesation would still lead to recursion though...

First have a two fields on parent obeject named EarliestChildId, and LatestChildId.

Rememer this trigger below, which was updaitng Latest_Purchased__c& Early_Purchased__c on Account object..? Very similar way get the Id of those records into EarliestChildId, and LatestChildI fields.
Trigger EarlyLatestDates on Product__c(After Insert, After Update, After Delete, After UnDelete){
    
    List<Id> accountIds = New List<Id>();
    
    If(Trigger.IsInsert || Trigger.IsUpdate || Trigger.IsUnDelete)
    {
        For(Product__c prod : Trigger.New)
        {
            If(Prod.Account_Name__c != null)
            {
                accountIds.add(Prod.Account_Name__c);
            }
        }
    }
    If(Trigger.IsDelete)
    {
        For(Product__c Prod : Trigger.Old)
        {
            If(Prod.Account_Name__c != null)
            {
                accountIds.add(Prod.Account_Name__c);
            }
        }
    }
    
    List<Account> accountFinalList = New List<Account>();
    
    For(Account act : [Select Id, Early_Purchased__c, Latest_Purchased__c,
                                (Select Id, Purchase_Date__c FROM Products__r WHERE Purchase_Date__c != null ORDER BY Purchase_Date__c DESC)
                                        FROM Account WHERE Id =:accountIds ])
    {
        List<Date> datesPerAccount = New List<Date>();
        Integer I = 0;
        For(Product__c EveryProd : act.Products__r){
            datesPerAccount.add(EveryProd.Purchase_Date__c );
            I += 1;
        }
        
        act.Latest_Purchased__c = datesPerAccount[0];
        act.Early_Purchased__c  = datesPerAccount[I - 1];
        
        accountFinalList.add(act);
       
    }
    
    try{
        If(!accountFinalList.IsEmpty()){
            update accountFinalList;
        }
    }
    Catch(Exception e){
        system.debug('Thrown Exception for EarlyLatestDates Trigger Is:: ' + e.getMessage());
    }
    
}
Now have a processbuilder on Account which would update only those records whoes IDS are on EarliestChildId, and LatestChildId field.

Again, this is just an idea sharing..
HARSHIL U PARIKHHARSHIL U PARIKH
Hello Jay,

finally !! We have nailed this one down!

Here is how,

1) Relationship: = Parent Object: Account and Child Object: Contact
2) Two Fields on parent (Account) object named: First Contact Id, and Latest Contact Id. (These are simple text fields and make them locked at page layout and hidden if you want)
3) Two formula fields on Child (Contact) object named First Contact, and Latest Contact. Both of them would be a formula fields with return type as checkbox.
Formulas for both fields:
For First_Contact__c field    
IF( Id = Account.First_Contact_Id__c , TRUE, FALSE)
For Latest_Contact__c field
IF( Id = Account.Latest_Contact_Id__c , TRUE, FALSE)
4) Now, have this following trigger on Child (Contact) object.
Trigger Code:
Trigger UpdateFirstAndLastCon On Contact(After Insert, After Update, After Delete, After UnDelete){
    
    List<Id> accountIds = New List<Id>();
    
    If(Trigger.IsInsert || Trigger.IsUpdate || Trigger.IsUnDelete){
        For(Contact con : Trigger.New){
            If(con.AccountId != null){
                accountIds.add(con.AccountId);
            }
        }
    }
    If(Trigger.IsDelete){
        For(Contact con : Trigger.old){
            If(con.AccountId != Null){
                accountIds.add(con.AccountId);
            }
        }
    }
    
    List<Account> actFinalList = New List<Account>();
    
    For(Account act : [Select Id, First_Contact_Id__c, Latest_Contact_Id__c,
                                (Select Id, CreatedDate FROM Contacts WHERE CreatedDate != NULL ORDER BY CreatedDate Desc)
                                  FROM Account WHERE Id =:accountIds])
    {
        List<Id> comingConsIds = New List<Id>();
        
        Integer I = 0;
        For(Contact EveryCon : act.Contacts){
            comingConsIds.add(EveryCon.Id);
            I++;
        }
        
        If(!comingConsIds.IsEmpty())
        {            
            act.Latest_Contact_Id__c = String.ValueOf(comingConsIds[0]).substring(0,15);
            act.First_Contact_Id__c  = String.ValueOf(comingConsIds[I - 1]).substring(0,15);
            actFinalList.add(act);
        }
        
        
    }
    try{
        If(!actFinalList.IsEmpty()){
            update actFinalList;
        }
    }
    catch(Exception e){
        System.debug('Thwon exception for UpdateFirstAndLastCon Trigger Is:: ' + e.getMessage());
    }
    
}
See it in Action:

User-added image

This trigger would work in all conditions such as When you insert the Contact, update it or delete it and even undelete it.

Hope this helps jay and if it solves the puzzle then please mark it as Best Answer so it can help others with the similar issue.

Thank You Sir!


 
This was selected as the best answer