0

I have built a Trigger which first creates an Asset and then a Case when an Opportunity is Closed/Won. I however need to fill a field on Case, Asset.Id, with the ID of the Asset created in the same Trigger. How can I accomplish this?

I have tried going over the newly created List with another for loop, so for(Asset as : ast) {}, but then I just have the ID's in a List again. I also tried using trigger.newMap.keySet(), but then I will have them in a Map and I don't know how to acces them in the for loop of the Cases. I feel that there is an easy way to do this, I just don't know it yet.

Any help is greatly appreciated :)

My code:

trigger CreateAssetonClosedWon on Opportunity (after insert, after update) {
     for(Opportunity o: trigger.new){ 
      if(o.isWon == true && o.HasOpportunityLineItem == true){

         String opptyId = o.Id;
         OpportunityLineItem[] OLI = [Select Id, Quantity, PricebookEntry.Product2.Family, PricebookEntry.Product2Id, PricebookEntry.Product2.Name, Description, Converted_to_Case__c, Converted_to_Asset__c  
                                      From OpportunityLineItem 
                                      where OpportunityId = :opptyId  AND (Converted_to_Asset__c = false OR Converted_to_Case__c = false)];
         Asset[] ast = new Asset[]{};
         Asset a = new Asset();

         Case[] css = new Case[]{};
         Case c = new Case();

         for(OpportunityLineItem ol: OLI){
         if(ol.Converted_to_Asset__c == false){
            a = new Asset();
            a.AccountId = o.AccountId;
            a.Product2Id = ol.PricebookEntry.Product2Id;
            a.Quantity = ol.Quantity;
            ast.add(a);
            ol.Converted_to_Asset__c = true;
           }

           if(ol.Converted_to_Case__c == false){
            c = new Case();
            c.AccountId = o.AccountId;
            c.Opportunity__c = o.Id;  
            css.add(c);
            ol.Converted_to_Case__c = true;
           }

          insert ast;
          insert css;
          update OLI;
       }
     }
    }
2

I have few recommendations to your code:

  • do not do SOQL or DML in loop;
  • ol.Converted_to_Asset__c == false equivalent to !ol.Converted_to_Asset__c;
  • declare new variables in places, where they will be used; for example, Case c = new Case(); is declared to early, as you are going to use it only after if condition

if you would have external id on your assets, you would use Creating Parent and Child Records in a Single Statement Using Foreign Keys. but this is not current case. So you need first to insert new assets, relate them to OpprtunityLineItem and this relationship will allow to get correct Asset Id for Case related to OpprtunityLineItem. This relationship is implemented by means of assetsByOLIIdMap Map.

trigger CreateAssetonClosedWon on Opportunity (after insert, after update){
    Set<Id> filteredOppIds = new Set<Id>();
    for(Opportunity opp :trigger.new){
        if(opp.isWon && opp.HasOpportunityLineItem){
            filteredOppIds.add(opp.Id);
        }
    }
    List<OpportunityLineItem> olis = [
        select Id, OpportunityId, Quantity, PricebookEntry.Product2.Family, PricebookEntry.Product2Id, PricebookEntry.Product2.Name, Description, Converted_to_Case__c, Converted_to_Asset__c  
        from OpportunityLineItem 
        where OpportunityId = :filteredOppIds
            and (
                Converted_to_Asset__c = false 
                or
                Converted_to_Case__c = false
                )
        ];

    List<Case> casesToInsert = new List<Case>();
    Map<Id, Asset> assetsToInsertByOLIIdMap = new Map<Id, Asset>();

    for(OpportunityLineItem oli :olis){
        if(!oli.Converted_to_Asset__c){
            Asset newAsset = new Asset();
            newAsset.AccountId = Trigger.newMap.get(oli.OpportunityId).AccountId;
            newAsset.Product2Id = oli.PricebookEntry.Product2Id;
            newAsset.Quantity = oli.Quantity;
            oli.Converted_to_Asset__c = true;
            assetsToInsertByOLIIdMap.put(oli.Id, newAsset);
        }
    }
    insert assetsToInsertByOLIIdMap.values();

    for(OpportunityLineItem oli :olis){
        if(!oli.Converted_to_Case__c){
            Case newCase = new Case();
            newCase.AccountId = Trigger.newMap.get(oli.OpportunityId).AccountId;
            newCase.Opportunity__c = oli.OpportunityId;
            if(assetsToInsertByOLIIdMap.containsKey(oli.Id)){
                newCase.Asset__c = assetsToInsertByOLIIdMap.get(oli.Id).Id;
            }
            casesToInsert.add(newCase);
            oli.Converted_to_Case__c = true;
        }
    }
    insert casesToInsert;
    update olis;
}

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.