You need to sign in to do that
Don't have an account?
Prevent duplicate records from being created with opportunity trigger
Hi,
I have been staring at this trigger trying to figure out how to include some logic that allows it to only create one record per opportunity. The trigger runs when a deal is closed won and has service. Basically what the trigger does is create an ESU record on the account, what we've been seeing is that sometimes when the trigger is fired it creates two records per opportunities. I need to somehow add some logic into the trigger to allow only one record per opportunity.
I read somewhere that I should do a "map" to pull the oppty ID into it and check t see if the record exists if not create a new one if it does then update it. So each opppty will have only one ESU tied to it. The ESU record has a relationship to the oppty. The trigger is below as a comment (exceeeded character limite!)
Can someone help me with this please or show me how would I go about adding this into the existing trigger.
Thank you
trigger createProServRecords on Opportunity (after update)
{
List<ID> oppIDs = new List<ID>();
List<OpportunityLineItem> tmpOLIs = new List<OpportunityLineItem>();
Set<Id> pbeIDs = new Set<ID>();
Map<ID, Opportunity> oppInfo = new Map<ID, Opportunity>();
Map<ID, List<OpportunityLineItem>> oppProducts = new Map<ID, List<OpportunityLineItem>>();
Map<ID, String> pbeNames = new Map<ID, String>();
Opportunity tmpOpp = new Opportunity();
Service_Unit__c tmpSU = new Service_Unit__c();
ProService_Order__c tmpPSO = new ProService_Order__c();
List<Service_Unit__c> newSURecords = new List<Service_Unit__c>();
List<ProService_Order__c> newPSORecords = new List<ProService_Order__c>();
Decimal qty1U = 0;
Decimal qty5U = 0;
Decimal qty10U = 0;
Decimal qty20U = 0;
Decimal totalUnits = 0;
Decimal amt1U = 0.00;
Decimal amt5U = 0.00;
Decimal amt10U = 0.00;
Decimal amt20U = 0.00;
Decimal totalAmount = 0.00;
Decimal units = 0;
String skuName;
Date today = System.today();
// Make a list of Closed/Won Opportunities in this trigger that previously weren't Closed/Won
for (Opportunity thisOpp : trigger.new)
if(thisOpp.StageName == 'Closed Won' && Trigger.oldMap.get(thisOpp.id).StageName != 'Closed Won')
oppIDs.add(thisOpp.ID);
if(!oppIDs.isEmpty())
{
// Get Stage and AccountID for these Opportunities
for (Opportunity loopOpp : [SELECT ID, StageName, AccountID FROM Opportunity WHERE ID IN :oppIDs])
oppInfo.put(loopOpp.ID,loopOpp.clone());
// Make a map of Line Items (and a set of PriceBookEntry IDs) for these Opportunities
for (OpportunityLineItem loopOLI : [SELECT PriceBookEntryId, SmartCalc_Class__c, Quantity, extAcqAmt__c, OpportunityID FROM OpportunityLineItem where OpportunityID IN :oppIDs])
{
// Only bother if it's a PS SKU
if(loopOLI.SmartCalc_Class__c == 'Professional Service')
{
pbeIDs.add(loopOLI.PriceBookEntryId);
tmpOLIs.clear();
// Check if Key exists in Map
if (oppProducts.containsKey(loopOLI.OpportunityID))
{
tmpOLIs = oppProducts.get(loopOLI.OpportunityID);
}
// Add the new OLI into the list
tmpOLIs.add(loopOLI);
// A Put will always overwrite the Pair Returned, so use a copy
oppProducts.put(loopOLI.OpportunityID,tmpOLIs.clone());
}
}
// Make a map of PriceBookEntryIds to Product Names
for (PriceBookEntry loopPBE : [SELECT Id, Name FROM PriceBookEntry WHERE ID in :pbeIDs])
pbeNames.put(loopPBE.ID, loopPBE.Name);
//System.Debug('OppIDs:'+oppIDs+':');
//System.Debug('PBEIDs:'+pbeIDs+':');
//System.Debug('OppInfo:'+oppInfo+':');
//System.Debug('OppProducts:'+oppProducts+':');
//System.Debug('PBENames:'+pbeNames+':');
// Skip all calculations if no PS Products
if(!oppProducts.isEmpty())
{
// Get list of Opp Line Items for each Opp
for(ID loopOppId : oppIDs)
{
// Reset tmpSU record (only one per Opp)
tmpSU.clear();
// Reset ESU info for each Opp
totalUnits = 0;
totalAmount = 0.00;
tmpOLIs = oppProducts.get(loopOppId);
// Go through list of Line Items and create records if need be
for(OpportunityLineItem tmpOLI: tmpOLIs)
{
// Reset tmpPSO record (could be multiple per Opp)
tmpPSO.clear();
skuName = pbeNames.get(tmpOLI.PriceBookEntryId);
System.Debug('SKU:'+skuName+':');
if (skuName.startsWith('PS-ESU-'))
{
// Determine SKU Units from SKU Name
units = Decimal.valueOf(skuName.replace('PS-ESU-',''));
if(units == 1)
{
qty1U += tmpOLI.Quantity;
amt1U += tmpOLI.extAcqAmt__c;
}
else if(units == 5)
{
qty5U += tmpOLI.Quantity;
amt5U += tmpOLI.extAcqAmt__c;
}
else if(units == 10)
{
qty10U += tmpOLI.Quantity;
amt10U += tmpOLI.extAcqAmt__c;
}
else if(units == 20)
{
qty20U += tmpOLI.Quantity;
amt20U += tmpOLI.extAcqAmt__c;
}
totalUnits += (units * tmpOLI.Quantity);
totalAmount += tmpOLI.extAcqAmt__c;
}
else
{
tmpOpp = oppInfo.get(loopOppId);
tmpPSO.Account__c = tmpOpp.AccountID;
tmpPSO.Opportunity__c = tmpOpp.Id;
tmpPSO.Part_Number__c = skuName;
tmpPSO.P_O_Amount__c = tmpOLI.extAcqAmt__c;
tmpPSO.Quantity__c = tmpOLI.Quantity;
tmpPSO.Date_Entered__c = today;
tmpPSO.Status__c = 'New';
newPSORecords.add(tmpPSO.clone());
}
}
if (totalUnits > 0)
{
tmpOpp = oppInfo.get(loopOppId);
tmpSU.Account__c = tmpOpp.AccountID;
tmpSU.Opportunity__c = tmpOpp.Id;
tmpSU.P_O_Amount__c = totalAmount;
tmpSU.Total_Units_Purchased__c = totalUnits;
tmpSU.Date_Entered__c = today;
tmpSU.Status__c = 'New';
tmpSU.X1_Unit_Qty__c = qty1U;
tmpSU.X5_Unit_Qty__c = qty5U;
tmpSU.X10_Unit_Qty__c = qty10U;
tmpSU.X20_Unit_Qty__c = qty20U;
tmpSU.X1_Unit_Total__c = amt1U;
tmpSU.X5_Unit_Total__c = amt5U;
tmpSU.X10_Unit_Total__c = amt10U;
tmpSU.X20_Unit_Total__c = amt20U;
newSURecords.add(tmpSU.clone());
}
}
try
{
System.Debug('newSUs:'+newSURecords+':');
System.Debug('newPSOs:'+newPSORecords+':');
insert newSURecords;
insert newPSORecords;
}
catch (Exception e)
{
System.Debug('ERROR! :'+e);
}
}
}
}