function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
wcwill978wcwill978 

Auto Create custom object on opportunity when updated

Hi I am trying to create a trigger that will auto create a new custom object when the SatgeName field is set to Closed Lost. So far I have created the custom object and the API name is "Win_Loss_Analysis__c". When the upportunity satge is saved I want the trigger to create a new object so we can later have workflow rules that will email the user to update and complete so we can keep track of why we lost that opportunity. So far this is what I have for the trigger:

 

trigger AutoCreateWinLossAnalysis on Opportunity (after update, after insert) {
Map<ID,Win_Loss_Analysis__c> mapRec = new Map<ID,Win_Loss_Analysis__c>();
    for(RecordType r: [Select r.Name, r.ID From RecordType where r.SobjectType = "Win_Loss_Analysis__c"]){
        mapRec.put(r.Name,r.ID)
    }
    List<Win_Loss_Analysis__c> lstWinLoss = new List<Win_Loss_Analysis__c>();
    for(Opportunity Loan:Trigger.New){
        if(StageName =='Closed Lost'){
            Win_Loss_Analysis__c wl = new Win_Loss_Analysis__c();
            if(mapRec.containsKey(opp.Loss_Analysis__c)){
                wl.o.RecordTypeId = mapRec.get(opp.Loss_Analysis__c)
            }
            
            lstWinLoss.add(wl);
        }
        
    }
    if(lstWinLoss.size()>0)
        insert lstWinLoss;
}

 

When I save I get the following error: Error: Compile Error: line 3:81 no viable alternative at character '"' at line 3 column 81.I have record types in the custom object that have page layouts assigned to them so when the opportunity is closed there is another required dependent field called Loss Analysis with values such as Price, Relationship, Product Feature, etc. After the opportunity is saved I would like it to triger the new custom object to create and if price was selected on the Loss Analysis field to show the page layout attached to that record type.

 

Thanks in advanced...

bob_buzzardbob_buzzard

There's a couple of issues:

 

(1) you are using double quotes for the string literal, whereas SOQL expects single quotes

(2) You don't need the r. prefix for the fields unless you alias your recordtype to r.  

 

Try changing to:

 

 

 

   for(RecordType r: [Select Name, ID From RecordType where SobjectType = 'Win_Loss_Analysis__c']){

 

 

 

wcwill978wcwill978

Hi I changed the line to represent what you suggested:

 

trigger AutoCreateWinLossAnalysis on Opportunity (after update, after insert) {
Map<ID,Win_Loss_Analysis__c> mapRec = new Map<ID,Win_Loss_Analysis__c>();
    for(RecordType r: [Select Name, ID From RecordType where SobjectType = 'Win_Loss_Analysis__c']){
        mapRec.put(r.Name,r.ID);

    List<Win_Loss_Analysis__c> lstWinLoss = new List<Win_Loss_Analysis__c>();
    for(Opportunity Loan:Trigger.New){
        if(StageName =='Closed Lost'){
            Win_Loss_Analysis__c wl = new Win_Loss_Analysis__c();
            if(mapRec.containsKey(opp.Loss_Analysis__c)){
                wl.o.RecordTypeId = mapRec.get(opp.Loss_Analysis__c);
            
            lstWinLoss.add(wl);
        }
        
    }
    if(lstWinLoss.size()>0)
        insert lstWinLoss;
}
}
}

 

The above is wha i have, but now I get Error: Compile Error: Variable does not exist: StageName at line 8 column 12. StageName is the field name of stage, a standard SFDC field in the opportunity, this is the field that i want to trigger the new object, when this field is changed to Closed lost i want this to fire. Please help!

 

Thank you

bob_buzzardbob_buzzard

StageName on its own doesn't mean anything to the compiler.  You need to tell it which object to retrieve the field from:

 

 

 

 for(Opportunity Loan:Trigger.New){
        if(Loan.StageName =='Closed Lost'){

 

 

wcwill978wcwill978

Hi,

 

I finally got the trigger working and its creating the object as it should we ended up adding some logginc as it was creating dupes when a record type changed, but its good now. Can you help me with the test case for this I have never created one, and have heard that you need at least 75% coverage in order to deploy in production:

 

 

trigger AutoCreateWinLossAnalysisOnOpportunityCSL on Opportunity (after update) 
{

  List<Opportunity> closedOps = new List<Opportunity>();
  List<Win_Loss_Analysis__c> newwinLossObjects = new List<Win_Loss_Analysis__c>();  
  List<Win_Loss_Analysis__c> updatewinLossObjects = new List<Win_Loss_Analysis__c>();
  
  List<RecordType> recordTypesForOppty = new List<RecordType>();
  recordTypesForOppty = [Select Name, ID From RecordType where SobjectType = 'Win_Loss_Analysis__c'];
    List<Id> ExistingIds = new List<Id>();
    
     
    Integer  count = Trigger.new.size(); 
    for(Opportunity newvalue : Trigger.new)
    {
      Opportunity oldvalue = Trigger.oldMap.get(newvalue.Id);
        if(oldvalue.StageName != newvalue.StageName || oldvalue.Loss_Analysis__c != newvalue.Loss_Analysis__c)  
       {
           if(newvalue.StageName == 'Closed Lost'){
            if(newvalue.Loss_Analysis__c == 'Price' 
              || newvalue.Loss_Analysis__c == 'Product Feature/Functionality' 
              || newvalue.Loss_Analysis__c =='Relationship')
            {
               closedOps.add(newvalue);
                 ExistingIds.add(newvalue.Id);
       
            }
          }
       }
    }
    system.debug('Found : ' + closedOps.size() + ' Opps that need analysis records created');
    if (closedOps.size() > 0)  
    { 
      List<Win_Loss_Analysis__c> existing = [SELECT Id,Opportunity_Name__c FROM Win_Loss_Analysis__c WHERE  Opportunity_Name__c  in :ExistingIds];
      system.debug('Found : ' + existing.size() + ' Existing Win Loss Records');
      string LossAnalysis = null;
      for (Opportunity oppty : closedOps)
      {       
              // get the recordTypeId
              Id WinLossObjectRecordTypeId = null;
              string typeName;
              LossAnalysis = oppty.Loss_Analysis__c.toLowerCase();
          for (RecordType recordType : recordTypesForOppty)
          {
            typeName = recordType.Name.toLowerCase();
            if (LossAnalysis == 'price' && typeName == 'price') 
            {
              WinLossObjectRecordTypeId = recordType.Id;
            }
            if (LossAnalysis == 'product feature/functionality' && typeName == 'productfeature') 
            {
              WinLossObjectRecordTypeId = recordType.Id;
            }
            if (LossAnalysis == 'relationship' && typeName == 'relationship') 
            {
              WinLossObjectRecordTypeId = recordType.Id;
            }
          }
          system.debug('Record type id: ' + WinLossObjectRecordTypeId + ' found for oppt id' + WinLossObjectRecordTypeId );
              // construct the new custom object with the required fields set
              
              Win_Loss_Analysis__c wL = new Win_Loss_Analysis__c();
              wL.Opportunity_Name__c = oppty.Id;
              wL.RecordTypeId = WinLossObjectRecordTypeId;
              wL.Account_Name__c = oppty.AccountId;
              if(existing.size() > 0)
              {
                   for(Win_Loss_Analysis__c exist : existing)
                {
                  if(exist.Opportunity_Name__c == oppty.Id)
                  {
                    wL.Id = exist.Id;
                    break;  
                  }              
                }
              }
              
              if(wL.Id == null)
              {
                newwinLossObjects.add(wL);
              }
              else
              {
                updatewinLossObjects.add(wL);
              }
              
      }
    }
    system.debug('Inserting ' + newwinLossObjects.size() + ' new Win Loss Objects' );
    system.debug('Updating ' + updatewinLossObjects.size() + '  Win Loss Objects' );
    if(newwinLossObjects.size() > 0)
         insert newwinLossObjects;
   
    if(updatewinLossObjects.size() > 0)
         update updatewinLossObjects;

}