You need to sign in to do that
Don't have an account?
Opportunity trigger not working correctly in certain scenarios
Hi,
I wonder if someone could help please. I know very little about APEX…I probably need a developer but trying this first.
We use Salesforce for giving out grants – the main part being Organisations & Opportunities (Accounts renamed to Organisations and Opportunities renamed to Grant Requests). Opportunities have two custom fields: Grant Amount and a Decision Date. EG £5,000 12/07/2005
Organisations can apply every year and the Apex code we have had written, lists in a rich text field on the latest grant request the previous grants (ie previous to this grant on the same account) and updates a currency field named: Total of Previous Grants. Eg:
£2,500 2004-2005
£1,500 2010-2011
£3,400 2014-2015
Total of Previous Grants: £7,400
As far as I can tell the code is triggered in two ways:
When a new Grant Request (Opportunity) is created – Works perfectly
When the “Populate Previous Grants” button on a Grant Request is clicked – this has an issue...
The issue with the button seems to be that if an old grant request is added (we are entering old ones) that it does not picked if the “Populate Previous Grants” is clicked. However if I just clone the new grant request, the old grant is picked up. If I then clear down the lists of previous grants and total, save, and then click the button it works fine, which I find a bit odd.
I can therefore reproduce the problem but cannot work out what the issue may be. I have put the code below.
Any pointers/suggestiosn would be helpful, thanks, Rob
Button Code
{!REQUIRESCRIPT("/soap/ajax/29.0/connection.js")}
{!REQUIRESCRIPT("/soap/ajax/29.0/apex.js")}
var accId="{!Opportunity.AccountId}";
if( accId != null && accId != '') {
var result = sforce.apex.execute("PopulatePreviousGrantsController","populatePreviousGrants",{oppId:"{!Opportunity.Id}"});
if(result=="Success") {
alert("Previous Grants value updated successfully");
}else {
alert(result);
}
location.reload();
} else {
alert('Opportunity must be associated with a Account');
}
Opportunity Trigger
trigger PopulatePreviousGrants on Opportunity (before insert) {
Set<Id> accIdSet=new Set<Id>();
Map<Id,List<Opportunity>> oldAccIdAndOppMap=new Map<Id,List<Opportunity>>();
Map<Id,List<Opportunity>> newAccIdAndOppMap=new Map<Id,List<Opportunity>>();
List<Opportunity> updateOppList=new List<Opportunity>();
List<String> args = new String[]{'0','number','###,###,##0.00'};
for(Opportunity opp:Trigger.New) {
accIdSet.add(opp.AccountId);
if( opp.AccountId != NULL && !newAccIdAndOppMap.containsKey(opp.AccountId)) {
newAccIdAndOppMap.put(opp.AccountId,new List<Opportunity>());
}
newAccIdAndOppMap.get(opp.AccountId).add(opp);
}
for(Opportunity opp:[SELECT Id,AccountId,Grant_Amount__c,Grant_Payment_Period__c,Previous_Grants_Total__c,Decision_Date__c From Opportunity WHERE AccountId IN :accIdSet ORDER BY Decision_Date__c ]) {
if( opp.AccountId != NULL && !oldAccIdAndOppMap.containsKey(opp.AccountId)) {
oldAccIdAndOppMap.put(opp.AccountId,new List<Opportunity>());
}
oldAccIdAndOppMap.get(opp.AccountId).add(opp);
}
for(Id accId :newAccIdAndOppMap.keySet()) {
for(Opportunity newOpp:newAccIdAndOppMap.get(accId)) {
if(oldAccIdAndOppMap.containsKey(accId)) {
String previousGrants='';
Decimal previousGrantsTotal=0;
for(Opportunity oldOpp:oldAccIdAndOppMap.get(accId)) {
if(oldOpp.Grant_Amount__c > 1) {
String period=oldOpp.Grant_Payment_Period__c==NULL?'':oldOpp.Grant_Payment_Period__c;
previousGrants+=period+' £'+String.format(oldOpp.Grant_Amount__c.format(), args)+'<br>';
previousGrantsTotal+=oldOpp.Grant_Amount__c;
}
}
newOpp.Previous_Grants__c=previousGrants;
newOpp.Previous_Grants_Total__c=previousGrantsTotal;
}
if(!oldAccIdAndOppMap.containsKey(accId)) {
oldAccIdAndOppMap.put(accId,new List<Opportunity>());
oldAccIdAndOppMap.get(accId).add(newOpp);
} else {
List<Opportunity> tempOldOpp=new List<Opportunity>();
boolean flag=false;
for(Opportunity oldOpp:oldAccIdAndOppMap.get(accId)) {
if(newOpp.Decision_Date__c<oldOpp.Decision_Date__c && flag == false) {
tempOldOpp.add(newOpp);
flag=true;
}
tempOldOpp.add(oldOpp);
}
if(flag==false) {
tempOldOpp.add(newOpp);
}
oldAccIdAndOppMap.get(accId).clear();
oldAccIdAndOppMap.get(accId).addAll(tempOldOpp);
System.debug('<--------------------------------->'+tempOldOpp.size());
}
}
}
}
It seems the code fired from the button is not picking up 1 of the other grants. The 'button' code is a little different from the 'trigger' code in that it looks for grants that were entered into Salesforcebefore the Grant from which the button is clicked. Whereas the trigger code does not include this criteria.
So if my theory is correct, the missing grant (1980-1999 £3,750) was created after the grant that you clicked the button from, and the logic in the button code is excluding it. Could you please verify that?
All Answers
The button is calling some other code, a method called 'populatePreviousGrants' in a class called 'PopulatePreviousGrantsController':
So I think this is where the code is not working as expected. Are you able to share that piece of code please?
Cheers
JD
Yes of course - thank you, here it is, Rob
global class PopulatePreviousGrantsController {
webService static String populatePreviousGrants(Id oppId) {
try {
List<String> args = new String[]{'0','number','###,###,##0.00'};
List<Opportunity> currentOppList=[SELECT Id,CreatedDate,AccountId FROM Opportunity WHERE Id= :oppId ];
List<Opportunity> oppList=[SELECT Id,Grant_Payment_Period__c,Grant_Amount__c,Previous_Grants_Total__c,Decision_Date__c,CreatedDate FROM Opportunity WHERE AccountId = :currentOppList.get(0).AccountId AND CreatedDate <= :currentOppList.get(0).CreatedDate ORDER BY Decision_Date__c];
String previousGrants='';
Decimal previousGrantsTotal=0;
if(oppList != NULL && oppList.size() > 0) {
for(Opportunity opp :oppList) {
if(opp.Grant_Amount__c > 0 && opp.Id != oppId) {
String period=opp.Grant_Payment_Period__c == NULL ? '' :opp.Grant_Payment_Period__c;
previousGrants+=period+' £'+String.format(opp.Grant_Amount__c.format(), args)+'<br>';
previousGrantsTotal+=opp.Grant_Amount__c;
}
}
}
Opportunity opp=new Opportunity();
opp.Id=oppId;
opp.Previous_Grants__c=previousGrants;
opp.Previous_Grants_Total__c=previousGrantsTotal;
update opp;
return 'Success';
}catch(Exception e) {
System.debug('<--------------ERROR LOG------------------>'+e);
return e.getMessage();
}
}
}
1 Clicking on the 'Populate Previous Grants' button - the listing is incorrect
2 Creating (cloning) the Grant Request - the listing is correct.
They are rather long - shall I paste it into this blog or send to you?
Yes it is a Non Profit - but I work for another NonProfit and occasionally do work for other Nonprofits but not entirely free some of the time.. A little complicated to explain I sometime think.
Many thanks, Rob
johndavies1968@gmail.com
It seems the code fired from the button is not picking up 1 of the other grants. The 'button' code is a little different from the 'trigger' code in that it looks for grants that were entered into Salesforcebefore the Grant from which the button is clicked. Whereas the trigger code does not include this criteria.
So if my theory is correct, the missing grant (1980-1999 £3,750) was created after the grant that you clicked the button from, and the logic in the button code is excluding it. Could you please verify that?
Yes you were correct that the missing grant (1980-1999 £3,750) was created after the grant that you clicked the button from, and the logic in the button code is excluding it. As you said the class was looking at created date - all created date entries in class changed to decision date and works fine now.
Many thanks for your help, much appreciated
Rob