0

I have a one to many relationship between Project and Insurance. When a record is created on Insurance object, it needs to get the Project record and then count how many Insurance records are present and it needs to input the value in the Name field of the Insurance record.

The below code does that exactly but it inserts the records based on the order it receives it. When I try to mass upload the Insurance__c using excel, the record that I insert first gets inserted and assigned a reference as INS-001 and so on.

The sequence will be incorrect if the records are not in order. For that reason, I want to sort it by start date field in the Insurance__c object. I don't think this is achievable in before insert trigger since I don't have the record Id's. I am confused as to how to go about it for 2 days now. Can you please help? Many thanks in advance!

Trigger

trigger InsuranceTrigger on Insurance__c (before insert) {
        
    SWITCH ON Trigger.operationType {
        WHEN BEFORE_INSERT{
            InsuranceClass.insuranceAutomation(Trigger.new);
        }
    }
}

Apex Class:

public class InsuranceClass {
    public static void insuranceAutomation(List<Insurance__c> insuranceList){
        Set<Id> insuranceIds = new Set<Id>();
        
        //Get all the project Id for the corresponding new insurance records
        for(Insurance__c i : insuranceList){
            insuranceIds.add(i.Project__c);
            system.debug(insuranceIds);
        }

        //Query the number of insurance records for the corresponding projects
        Map<Id,Milestone1_Project__c> is = new Map<Id,Milestone1_Project__c>([SELECT Id, Cleantech_Reference__c, 
                                                                              (SELECT Id, Project__c, Name FROM Insurance__r) 
                                                                              FROM Milestone1_Project__c WHERE Id in :insuranceIds]);
        
        Map<Id, Integer> newMap = new Map<Id, Integer>();        
        for(Insurance__c i : insuranceList){
            
            //if there is no insurance record associated with the project and if the newMap is empty
            if(is.get(i.Project__c).Insurance__r.isEmpty() && !newMap.containskey(i.Project__c)){
                Integer count = 1;
                i.Name = is.get(i.Project__c).Cleantech_Reference__c+'/'+'INS-'+string.valueOf(count);
                newMap.put(i.Project__c, count);
                
            }
            //if there are insurance records and the newMap is empty
            else if(!is.get(i.Project__c).Insurance__r.isEmpty()&& !newMap.containskey(i.Project__c) )
            {
                Integer count = is.get(i.Project__c).Insurance__r.size()+1;
                i.Name = is.get(i.Project__c).Cleantech_Reference__c+'/'+'INS-'+string.valueOf(count);
                newMap.put(i.Project__c, count);
            }
            //if the newMap is not empty
            else{
                Integer count = newMap.get(i.Project__c)+1;
                i.Name = is.get(i.Project__c).Cleantech_Reference__c+'/'+'INS-'+string.valueOf(count);
                newMap.put(i.Project__c, count);
                
            }
        }   
    }
}

1 Answer 1

2

You can't do this in a before trigger. While in theory you could sort the records in Trigger.new, you have no assurance that that set is the complete set of records that will be committed this transaction because triggers execute in 200-record blocks. Further, you have no assurance that one or more of those records won't be blocked later in the save order, and if the caller has set allOrNone=False, records that do succeed will still go through. That could result in gaps in your numbering.

I don't see a way to do this without building an after trigger, where records will be queryable. You could then obtain both the new and existing records for some parent Project, sort them all, and renumber them, but you will by doing so fire another round of trigger operation. You'll need to be very careful about recursion management; don't use a static Boolean variable.

Alternately, you could bounce the renumbering into a Queueuable job after the transaction has completed, obviating the need to worry about partial success or changes deeper in the order of execution in the original transaction.

2
  • Hi David, thank you for the answer. I am a bit confused. Are you saying that I should convert to after insert trigger instead of before insert trigger and modify the logic to add sorting insert? Can you give me guidance? Thank you. Feb 21, 2021 at 3:48
  • You definitely need to go to after context, where you'll be able to write a query against all of the records (new and old); they do have Ids at that point in time. If it's an absolute requirement that the number sequence be contiguous (no gaps) there might be still more work to do.
    – David Reed
    Feb 22, 2021 at 2:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.