0

I have after insert Trigger and I'm trying to test it with this logic (for bulk testing). It's a little test from Execute Anonymous Window:

List<Lib__c> lb = new List<Lib__c>();
string s = '2019-09-09 08:25:00.14Z';

for(Integer i=0; i<100; i++){
    Lib__c b = new Lib__c(Name = 'Lib', WhenToStart__c = Datetime.valueOf(s));
    lb.add(b);
}
insert lb;

But I'm getting an error: Trigger: execution of AfterInsert caused by: System.ListException: Before Insert or Upsert list must not have two identically equal elements What am I doing wrong?

    trigger Trig on Lib__c (after insert) { 
    if(Trigger.isAfter && Trigger.isInsert) {
        triggerHelper.updTriggerHelper(Trigger.new); 
    }
}

Helper:

    public static void updTriggerHelper(List<Lib__c> libs){
    Map<Id, Tool__c> mapToConnect = new Map<Id, Tool__c>();
    List<Tool__c> listToUpsert = new List<Tool__c>();
    List<Id> oppIds = new List<Id>();
    List<Date> dates = new List<Date>();

    for(Lib__c l : libs){
        oppIds.add(l.Opportunity__c);
        if(l.WhenToStart__c != null){
            dates.add(date.newinstance(l.WhenToStart__c.year(), l.WhenToStart__c.month(), l.WhenToStart__c.day()));
        }
    }

    List<Tool__c> neededTools = [SELECT Name, WhenToFinish__c, Lib__r.Opportunity__c, Price__c FROM Tool__c
                  WHERE Lib__r.Opportunity__c IN : oppIds AND DAY_ONLY(WhenToFinish__c) IN : dates];

    if(neededTools.size() > 0){
        for(Tool__c t : neededTools){
            mapToConnect.put(t.Lib__r.Opportunity__c, t);
        }
    }

    if(!mapToConnect.isEmpty()){
        for(Lib__c lb : libs){
            Id oppId = lb.Opportunity__c;                
            if(mapToConnect.containsKey(oppId) && lb.Price__c != null){ 
                mapToConnect.get(oppId).Price__c = String.valueOf(lb.Price__c);
                listToUpsert.add(mapToConnect.get(oppId));
            }
        }
    }

    if (listToUpsert.size() > 0){
        try {
            upsert listToUpsert Id;
        } catch (DmlException e) {
            ApexPages.addMessages(e);
            System.debug('Error: ' + e);
        }
    }
}
5
  • Issue is not in the given code. Is this whole code to be executed? What is in thigger?
    – kurunve
    Commented Jul 31, 2019 at 15:14
  • I'm guessing the problem is in the trigger logic. Nothing should be wrong here.
    – sfdcfox
    Commented Jul 31, 2019 at 15:22
  • Name = 'Lib' + i doesn't help. Here is no unique fields. Commented Jul 31, 2019 at 15:41
  • Updated with code Commented Jul 31, 2019 at 15:56
  • Undoubtedly, this line here listToUpsert.add(mapToConnect.get(oppId)); is adding duplicate Tool__c records/objects to listToUpsert. I don't have time to break it down further, but I'm sure someone will.
    – pchittum
    Commented Jul 31, 2019 at 16:28

1 Answer 1

1

This:

mapToConnect.put(t.Lib__r.Opportunity__c, t);

will only keep one of the potentially many Tool__c objects so is logically questionable but not the problem.

Multiple Lib__c objects can reference the same Opportunity, so this loop is the probable cause:

    for(Lib__c lb : libs){
        Id oppId = lb.Opportunity__c;                
        if(mapToConnect.containsKey(oppId) && lb.Price__c != null){ 
            mapToConnect.get(oppId).Price__c = String.valueOf(lb.Price__c);
            listToUpsert.add(mapToConnect.get(oppId));
        }
    }

so to avoid the error:

    Set<Id> oppIdsHandled = new Set<Id>();
    for(Lib__c lb : libs){
        Id oppId = lb.Opportunity__c;
        if (!oppIdsHandled.contains(oppId)) {  
            oppIdsHandled.add(oppId);     
            if(mapToConnect.containsKey(oppId) && lb.Price__c != null){ 
                mapToConnect.get(oppId).Price__c = String.valueOf(lb.Price__c);
                listToUpsert.add(mapToConnect.get(oppId));
            }
        }
    }

or maybe better:

Map<Id, Tool__c> toUpsert = new Map<Id, Tool__c>();
for(Lib__c lb : libs){
    Id oppId = lb.Opportunity__c;
    Tool__c t = mapToConnect.get(oppId);
    if (t != null) {
        toUpsert.put(t.Id, t);
    }
}
upsert toUpsert.values();

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .