I have the trigger class below and I would like it to fire only when an Opportunity Stage is changed to Closed Won. Can anyone help me figure out how to do this? I have an if
statement, but it fires any time an Opportunity
that is Closed Won is edited, and when I tried to add another condition it gives me the error message:
Error: Compile Error: Field expression not allowed for generic SObject at line 12 column 85.
I only want it to fire when the Stage is initially changed. Thanks.
Trigger:
trigger MainTriggerOpportunity on Opportunity (after update) {
ClassRenewalOppClone updater13 = new ClassRenewalOppClone();
updater13.cloneOpp(Trigger.new);
}
Trigger Class:
public class ClassRenewalOppClone {
public void cloneOpp(List<Opportunity> cloneOpp) {
String recordTypeName = 'Renewals';
Map<String, Schema.RecordTypeInfo> rtMapByName = Schema.SObjectType.Opportunity.getRecordTypeInfosByName();
Schema.RecordTypeInfo rtInfo = rtMapByName.get(recordTypeName);
id recType = rtInfo.getRecordTypeId();
FOR(Opportunity opp1 : cloneOpp) {
IF(opp1.StageName.contains('Closed Won') && trigger.OldMap.get(opp1.Id).isclosed == false && opp1.RecordTypeId == recType) {
String OppId = opp1.Id;
//Clone the Opportunity that is associated with the handoff and all createable fields
/* query Opportunity and then clone it */
String soql = RecClone.getCreatableFieldsSOQL('Opportunity', 'Id =: OppId');
Opportunity opp = (Opportunity)Database.query(soql);
Opportunity opp2 = opp.clone(false, true);
insert opp2;
List<OpportunityLineItem> itemList = (List<OpportunityLineItem>)Database.query(RecClone.getCreatableFieldsSOQL('OpportunityLineItem', 'OpportunityId =: OppId'));
List<OpportunityLineItem> newItemList = new List<OpportunityLineItem>();
for (OpportunityLineItem item : itemList) {
OpportunityLineItem ol = item.clone(false, true);
ol.totalprice = null;
ol.opportunityid = opp2.id;
newItemList.add(ol);
}
insert newItemList;
}
}
}
}
Best Answer
You need to adjust your IF() statement to something like this
Also need to ensure you have trigger.oldMap
trigger
Utility Class
You have a few issues with the trigger that you may also that are not best practice. You have SOQL within a For loop as well as DML statements within a For loop, so you are likely to run into some governor issues very soon.
I would try to utilize collections (Lists, Sets, and Maps) to move your SOQL and DML outside of the for loop.
See below for some best practices
https://developer.salesforce.com/page/Apex_Code_Best_Practices
https://developer.salesforce.com/page/Trigger_Frameworks_and_Apex_Trigger_Best_Practices
General trigger bulkification - best practices
http://blog.jeffdouglas.com/2011/01/06/fun-with-salesforce-collections/