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
ForceRookieForceRookie 

How to avoid duplicating related record on Opportunity?

I have an Opportunity record and it has Product (OpportunityLineItem) related list and Placement related list.
if Opportunity is Closed Won and it has Product record, the trigger should create a Placement record (its fields are based on Opportunity and Product fields).

It is creating a record BUT the problem is:
For example existing Product record is “Book”, so it creates 1 Placement record.
if I add another Product again, for example “Album”, the Opportunity will update and create another Placement record from Book and creates 1 Placement record for Album. If I add Product again, and once the Opportunity updates, it creates another 1 Placement record again for Book and Album.

how can I prevent it from creating duplicate records?
Here’s my code:
trigger CreatePlacement on Opportunity (after insert, after update) {
	Set <Id> oppIds = new Set<Id>();
    for (Opportunity opty : Trigger.new) {
        oppIds.add(opty.Id);
    }

    List<Opportunity> oLst = [SELECT Id, Account.Name, IsClosed, IsWon, CloseDate FROM Opportunity WHERE Id IN :oppIds];
    List<OpportunityLineItem> oliList = [SELECT Id, ProductP.Name, TotalPrice, Quantity, Opportunity.Name FROM OpportunityLineItem WHERE OpportunityId IN :oppIds]; 
    List<Placement__c> pList = new List<Placement__c>();
    for (Opportunity o : oLst) {
            if (o.IsClosed == True && o.IsWon == True) {
                for (OpportunityLineItem li : oliList) {
                    Placement__c p = new Placement__c();
                    p.Name = o.Account.Name +' '+ li.Product2.Name;
                    p.Opportunity__c = o.Id;
                    p.Product__c = li.ProductP.Name;
                    p.Qty__c = li.Quantity;
                    pList.add(p);
                }
            }
    }
    if (pList.size() > 0) {
        upsert pList;
    }
}

Please reply. Nobody seems helping here..
Amit Chaudhary 8Amit Chaudhary 8
Try to use oldMap to avoide executing same trigger multiple times.

NOTE:- Now this trigger will only execute at the time one closed won. and only once
trigger CreatePlacement on Opportunity (after insert, after update) {
	Set <Id> oppIds = new Set<Id>();
    for (Opportunity opty : Trigger.new) {
		if ( o.IsClosed == True && o.IsWon == True && o.IsClosed != Trigger.oldMap(o.id).IsClosed ) {
			oppIds.add(opty.Id);
		}
    }

	if(oppIds.size() > 0 ){
		List<OpportunityLineItem> oliList = [SELECT Id,OpportunityId,ProductP.Name, TotalPrice, Quantity, Opportunity.Name,Opportunity.Account.Name FROM OpportunityLineItem WHERE OpportunityId IN :oppIds]; 
		
		List<Placement__c> pList = new List<Placement__c>();
		for (OpportunityLineItem li : oliList) {
			Placement__c p = new Placement__c();
			p.Name = li.Account.Name +' '+ li.Product2.Name;
			p.Opportunity__c = li.Id;
			p.Product__c = li.ProductP.Name;
			p.Qty__c = li.Quantity;
			pList.add(p);
		}
		if (pList.size() > 0) {
			upsert pList;
		}	
	}

}

Let us know if this will help you
 
Raj VakatiRaj Vakati
trigger CreatePlacement on Opportunity (after insert, after update) {
	Set <Id> oppIds = new Set<Id>();
    for (Opportunity opty : Trigger.new) {
		if ( o.IsClosed == True && o.IsWon == True && o.IsClosed != Trigger.oldMap(o.id).IsClosed ) {
			oppIds.add(opty.Id);
		}
    }

	if(oppIds.size() > 0 ){
		List<OpportunityLineItem> oliList = [SELECT Id,OpportunityId,ProductP.Name, TotalPrice, Quantity,
		Opportunity.Name,Opportunity.Account.Name FROM OpportunityLineItem
		WHERE OpportunityId IN :oppIds]; 
	
Set<String> str = new Set<String>() ; 
	List<Placement__c> pls = [Select Id ,Name from Placement__c where Id in :oppIds];
	
	for(Placement__c p :pls){
		str.add(p.Name) ; 
	}
	
	
		List<Placement__c> pList = new List<Placement__c>();
		for (OpportunityLineItem li : oliList) {
			If(!str.contacts(li.Account.Name +' '+ li.Product2.Name)){
			Placement__c p = new Placement__c();
			p.Name = li.Account.Name +' '+ li.Product2.Name;
			p.Opportunity__c = li.Id;
			p.Product__c = li.ProductP.Name;
			p.Qty__c = li.Quantity;
			pList.add(p);
			}
		}
		if (pList.size() > 0) {
			upsert pList;
		}	
	}

}

 
edanna kedanna k
Working code is here:

trigger CreatePlacement on Opportunity (after insert, after update) {
    Set <Id> oppIds = new Set<Id>();
    for (Opportunity opty : Trigger.new) {        
        if(Trigger.isUpdate){            
            if ( opty.IsClosed == True && opty.IsWon == True ) {
                oppIds.add(opty.Id);
            }
        }
    }    
    if(oppIds.size() > 0 ){        
        List<Opportunity> oLst = [SELECT Id, Account.Name, IsClosed, IsWon, CloseDate FROM Opportunity WHERE Id IN :oppIds];
        
        List<OpportunityLineItem> oliList = [SELECT Id,OpportunityId,Product2.Name, TotalPrice, Quantity,
                                             Opportunity.Name,Opportunity.Account.Name FROM OpportunityLineItem
                                             WHERE OpportunityId IN :oppIds];        
        Set<String> str = new Set<String>() ; 
        List<Placement__c> pls = [Select Id ,Name from Placement__c where Opportunity__c in :oppIds];        
        for(Placement__c p :pls){
            str.add(p.Name) ; 
        }     
        List<Placement__c> pList = new List<Placement__c>();
        for (Opportunity o : oLst) {            
            for (OpportunityLineItem li : oliList) {                
                If(Trigger.isUpdate && oliList.size() > 1 ){                    
                    If(!str.contains(o.Account.Name+' '+ li.Product2.Name)){
                        Placement__c p = new Placement__c();
                        p.Name =o.Account.Name +' '+ li.Product2.Name;
                        p.Opportunity__c = o.Id;
                        p.Product__c = li.Product2.Name;
                        p.Qty__c = li.Quantity;
                        pList.add(p);
                    }
                }                
                If(Trigger.isUpdate && oliList.size() == 1){                    
                    Placement__c p = new Placement__c();
                    p.Name = o.Account.Name+' '+ li.Product2.Name;
                    p.Opportunity__c = o.Id;
                    p.Product__c = li.Product2.Name;
                    p.Qty__c = li.Quantity;
                    pList.add(p);
                }                
            }
        }
        if (pList.size() > 0) {
            upsert pList;
        }    
    }    
}

Please let me know if you need any clarification!