We have a trigger in our org that will clone Opportunities if they meet certain criteria. Due to recent changes in our business though we now have to account for certain record types (i.e we only want an Opportunity to clone itself if it is of a certain record type), but I'm having trouble trying to check the record type.

Here is the code I have so far. Some of it I got from this thread here, but I still can't get the code to clone any opportunities that meet my criteria.

trigger RenewalClone on Opportunity (after update) {

if(SingleExecution.hasAlreadyDone()) return;
// else
// Clone

Set<Id> oppAccountIds = new Set<Id>();
// opportunities we have to clone
Opportunity[] oppsToClone = new Opportunity[]{};
// clones to save
Opportunity[] oppsToSave = new Opportunity[]{};

//Build set of RecordType Ids 
Set<Id> opportunityRecordTypeIds = new Set<Id>(); 
for(Opportunity record : Trigger.new) {

Map<Id, RecordType> recordTypeMap = 
new Map<Id, RecordType>([SELECT Id, DeveloperName, Name 
                       FROM RecordType 
                       WHERE Id IN :opportunityRecordTypeIds]);

// bulkified handling
for (Opportunity record:trigger.new)

  RecordType oppRecordType = recordTypeMap.get(record.RecordTypeId);

  if(oppRecordType.DeveloperName == 'RECORD_TYPE_NAME')
      // make sure the opportunity stage has been changed to Closed Won
      if ((record.StageName == 'Closed Won' 
       && trigger.oldMap.get(record.Id).StageName !=  'Closed Won'
       && record.Order_Type__c == 'New Order' 
       && record.Initial_Terms__c == 12) 
       || (record.StageName == 'Closed Won' 
          && trigger.oldMap.get(record.Id).StageName != 'Closed Won'
          && record.Order_Type__c == 'Renewal' 
          && record.Initial_Terms__c == 12
          && record.Within_Existing_Initial_Renewal_Term__c == false))
            // keep for query
            // keep opps that meet the criteria for further processing



// make sure we only continue , if there are any opps we have to clOne
if (oppsToClone.size() > 0)

    Map<Id,Account> accountMap = new Map<Id,Account>([
        select Id
             , Name
             from Account
             where Id IN: oppAccountIds]);

// clone the opps
for (Opportunity record:oppsToClone)
    Opportunity v = record.clone(false,true);

    // for opportunity name
    Datetime renewalDate = record.Commencement_Date__c.addyears(1);
    Datetime ExpirationDate = record.Commencement_Date__c.addyears(2).adddays(-1);
    String renewaldateString = renewalDate.format('dd MMM yyyy');
    String expirationDateString = ExpirationDate.format('dd MMM yyyy');

    v.CloseDate = record.Commencement_Date__c.addmonths(11);  
    v.OwnerId = record.OwnerId;
    v.order_type__c = 'Renewal';
    v.accountId = record.accountId;
    v.Commencement_Date__c = record.Commencement_Date__c.addYears(1);
    v.Amount = record.Amount;
    v.StageName = '75% - Verbal';
    v.Probability = 75;
    v.Name = v.CloseDate.year() + '-' + v.CloseDate.Month() + ' - ' + accountMap.get(record.AccountId).Name + ' - ' + 'Renewal' + ' - ' +'(' + renewalDateString + ' to ' + expirationDateString + ')'; 
    v.Description = null;
    v.Commitment_Type_picklist__c = null;
    v.Commitment_Year__c = null;
    v.Within_Existing_Initial_Renewal_Term__c = false;
    v.Ready_for_Quote_Generation__c = false;
    v.Opportunity_Manager__c = record.Opportunity_Manager__c;
    v.No_of_Languages_Included__c = record.No_of_Languages_Included__c;
    v.Belongs_to_Reseller__c = record.Belongs_to_Reseller__c;
    v.Region__c = record.Region__c;
    v.Division__c = record.Division__c;
    v.ForecastCategoryName = 'Best Case';
    v.Next_Payment_Number__c = 1;
    v.LeadSource = null;
    v.Lead_Source_Description__c = null;
    v.Lead_Source_Description_Text__c = null;
    v.Ready_for_Approval__c = False;
    //v.Request_for_RFP__c = False;
    v.Stage_of_Completion__c = null;
    v.RFP_Opportuntity__c = False;
    v.Contract_Sale__c = False;
insert oppsToSave;

  • First of all you can avoid a SOQL by replacing it with Describe method to created the Map<ID,Schema.RecordTypeInfo> recordTypeMap = Opportunity.sObjectType.getDescribe().getRecordTypeInfosByName(); – Jarvis Sep 25 '18 at 9:49
  • Fundamentally this should work. Maybe check that your conditions are definitely being met by your testing (a few system.debug()s on the values you are checking against to ensure they are what you expect would help). Also its worth noting that the Recordtype.DeveloperName will be the api name for the recordtype so 'RECORD_TYPE_NAME' will need to match it. This is likely (unless manually changed) to be the record type name with underscores instead of spaces eg 'Some RecordType' ==> 'Some_RecordType'. – Alex255 Sep 25 '18 at 10:12
  • Bennie, I tried replacing my code with yours and unfortunately I got at error "Illegal assignment from Map to Map". – cbarkoczi Sep 25 '18 at 11:16
  • Alex255, just ran some system debugs, and the values are what I expected. – cbarkoczi Sep 25 '18 at 11:17
  • So it is running without throwing any errors but the cloned record isn't appearing? I would pepper a few system.debugs at various points as pseudo-breakpoints, to ensure that the applicable Opportunity is added to 'oppsToClone', to make sure the 'if (oppsToClone.size() > 0)' block is executed, to make sure the new Opp is added to oppsToSave etc - this may help you to narrow down the problem area. If these all seem fine then perhaps there is something else at play, are there any other active triggers/workflow etc which may be removing or modifying the cloned Opp? – Alex255 Sep 26 '18 at 8:22

Right, I've figured out the problem. After doing some digging I found out that we have a process that switches an Opportunity's record type after it's been closed won.

That process was causing my checks for the record type to not work. Everything works now that I've altered the process.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.