I am writing a trigger for the beforeInsert
event of the Opportunity
object. What I am trying to achieve is, generating a value for one of the Opportunity's
custom fields(Ref__c
), that is, a concatenation of a field of the Opportunity's Account
(Codigo_Socio__c
) and an 'auto-increment' number(numberCode
), that will increment, based on the quantity of the inserted opportunities for this account.
(e.g An Account with Codigo_Socio__c = 'BCN-0001'
, if two Opportunities are going to be inserted, their Ref__c
fields would have to result to the following values, respectively: BCN0001-1, BCN0001-2
.
Below, is the method I am trying to implement to control the logic for this task.
public void generateRefCode(List<Opportunity> newList)
{
Integer numberCode = 1;
String[] numberCodeParts;
//map-Opportunities with their Accounts
//Key= AccountId ; Value=Opportunity
Map<Id, Opportunity> mapAccountsWithOpps = new Map<Id,Opportunity>();
// Now let's get the accountIds
Set<Id> accountIds = new Set<Id>();
for(Opportunity op : newList){
accountIds.add(op.AccountId);
}
//obtain opportunities from the existing accounts
Map<Id, Opportunity> mapOpps = new Map<Id,Opportunity>([SELECT AccountId, Ref__c FROM Opportunity
Where AccountId in : accountIds]);
//get the existing accounts as well from the database
Map<Id, Account> mapAccounts = new Map<Id,Account> ([Select Id, Codigo_Socio__c, Name FROM Account Where Id in : accountIds]);
//Put them together
for(Id accountId: mapOpps.keySet()){
if(mapAccounts.containsKey(accountId)){
Opportunity op = mapOpps.get(accountId);
mapAccountsWithOpps.put(accountId, op);
}
}
//we iterate over the newly inserted opportunities
for(Opportunity opp: newList)
{
//case 1 :no opps so far for this account
if(!mapAccountsWithOpps.containsKey(opp.AccountId)){
//we obtain the corresponding account via its Id
Account acct = mapAccounts.get(opp.AccountId);
//concatenate strings for the Ref field(CodigoSocio + number)
opp.Ref__c = acct.Codigo_Socio__c + '-' + String.valueOf(numberCode);
numberCode++;
System.debug('@@Ref generated: ' + opp.Ref__c );
//we add the account in the list accountsWithOpps
mapAccountsWithOpps.put(opp.AccountId, opp);
}
else{
Opportunity lastOpp = mapAccountsWithOpps.get(opp.AccountId);
//we obtain the corresponding account via its Id
Account acct = mapAccounts.get(lastOpp.AccountId);
System.debug('@@Last added opp for Account ' + acct.Name + ', oppRef: ' + lastOpp.Ref__c);
if(!String.isEmpty(lastOpp.Ref__c)){
numberCodeParts = lastOpp.Ref__c.split('-');
String numberPart = numberCodeParts[1].trim();
numberCode = Integer.valueOf(numberPart);
numberCode++;
opp.Ref__c = acct.Codigo_Socio__c + '-' + numberCode;
System.debug('@@Ref generated ' + opp.Ref__c);
//we remove the last added opp for this accountId
mapAccountsWithOpps.remove(lastOpp.AccountId);
mapAccountsWithOpps.put(opp.AccountId, opp);
}
}
}
}
I first proceed to this , by querying the existing opportunities and accounts from the database, and map them together in the map Map<Id, Opportunity> mapAccountsWithOpps = new Map<Id,Opportunity>();
so I can keep track of the accounts that already have opportunities. And then on the iteration of newList
(i.e actually, Trigger.new
that I pass it from my trigger handler class) I create the condition, that, if the corresponding opportunity does not have an Account mapped already in the aforementioned map, I add it to the map. Else, I retrieve the last opportunity, added to that Account so I can obtain the numberCode
, increment it and put the new Opportunity
along with its AccountId
key in the map.
One of the problems that I observed my implementation has , whilst running its corresponding test and debugging as well, is that the following lines of code are totally omitted when an insertion happens:
//Put them together
for(Id accountId: mapOpps.keySet()){
if(mapAccounts.containsKey(accountId)){
Opportunity op = mapOpps.get(accountId);
mapAccountsWithOpps.put(accountId, op);
}
}
It has been a while now that I am having a hard time on this one and even though I have tried other implementations and approaches, apart from the aforementioned method logic,(e.g execute an SOQL statement
for Account
that, with a subquery in it, so the Account's Opportunities
could be obtained at the same time),
I am still failing to see clearly, where my head's bug for this trigger lurks!
Any help/suggestion would be much appreciated.
Thank you.