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
shobana shobana 1shobana shobana 1 

whenever Opportunity is "closed won" create an order and orderitem

My task is when opportunity is "closed won"  automaticlly it should create order(populate opportunity fields) and orderitems(all opportunitylineitem products should be created in it).

I am pretty new to Salesforce development. Can anyone give me suggestion to do this.
trigger name on Opportunity (after update) {
set<id> ids = new set<id>();
for(opportunity O:trigger.new) {
if(O.StageName =='ClosedWon'){
ids.add(O.id);
}}
orderItem orl = new orderItem(); 
Opportunity opp = [select id,AccountId,CloseDate,(select Name,ProductCode,Quantity,OpportunityId 
                                  from OpportunityLineItems)
                           from Opportunity 
                           where  id in:Trigger.NewMap.keySet() AND Opportunity.StageName =: 'Closed Won'];


Order ord = new Order();
  ord.OpportunityId=opp.id;
  ord.AccountId =opp.AccountId;
  ord.EffectiveDate = opp.CloseDate;
  ord.Status= 'Draft'; 
  insert ord;
for(OpportunityLineItem opl : opp.OpportunityLineItems){
   orl.Order= ord; 
  orl.Quantity=opl.Quantity;

  
  }
  
  insert orl;
  
                                              
}



 
Best Answer chosen by shobana shobana 1
Mahesh DMahesh D
Hi Shobhana,

Please find the below trigger:
trigger OpportunityTriggerForOrder on Opportunity (after insert, after update) {
    Set<Id> oppIdSet = new Set<Id>();
    List<Order> ordList = new List<Order>();
    
    for(Opportunity opp: Trigger.new) {
        if(opp.StageName == 'Closed Won' && (Trigger.isInsert || opp.StageName != Trigger.oldMap.get(opp.Id).StageName)){
            if(opp.AccountId != null) {
                oppIdSet.add(opp.Id);
                Order ord = new Order();
                ord.OpportunityId = opp.Id;
                ord.AccountId = opp.AccountId;
                ord.EffectiveDate = opp.CloseDate;
                ord.Status= 'Draft';
                ord.Pricebook2Id = opp.Pricebook2Id;
                ordList.add(ord);
            }
        }
    }
    
    if(!ordList.isEmpty()) {
        insert ordList;
        Map<Id, Order> ordMap = new Map<Id, Order>();
        List<OrderItem> oiList = new List<OrderItem>();
        for(Order ord: ordList) {
            ordMap.put(ord.OpportunityId, ord);
        }
        
        for(Opportunity opp: [Select Id, AccountId, CloseDate, (select Id, Name, ProductCode, Quantity, PricebookEntryId, UnitPrice, OpportunityId from OpportunityLineItems) from Opportunity where Id IN: oppIdSet]) {
            for(OpportunityLineItem oli: opp.OpportunityLineItems) {
                OrderItem oi = new OrderItem();
                oi.OrderId = ordMap.get(opp.Id).Id;
                oi.Quantity = oli.Quantity;
                oi.PricebookEntryId = oli.PricebookEntryId;
                oi.UnitPrice = oli.UnitPrice;
                oiList.add(oi);
            }
        }
        
        if(!oiList.isEmpty()) {
            insert oiList;
        }
    }
}
I also tested the above code in DE environment and everything is working fine.

Note: On Opportunity Account is required to create Order and Order Item records.

Please do let me know if it helps.

Regards,
Mahesh

All Answers

ManojjenaManojjena
HI Sobana,

Try like below and add mandatory fields .
trigger name on Opportunity (after update) {
    List<Order> ordList=new List<Order>();
    List<OrderItem> ordItemList=new List<OrderItem>();
    for(opportunity opp:trigger.new) {
        if(opp.StageName != Trigger.oldMap.get(opp.Id).StageName && opp.StageName == 'Closed Won'){
            Order ord = new Order();
                ord.OpportunityId=opp.id;
                ord.AccountId =opp.AccountId;
                ord.EffectiveDate = opp.CloseDate;
                ord.Status= 'Draft';  
        }
    }
    if(!ordList.isEmpty()){
       Insert ordList;
        For(Order ord: ordList){
          OrderItem ordItem = new OrderItem();
          //Add Mandatory fields here 
            ordItem.OrderId=ord.Id;
            ordItemList.add(ordItem);
       }if(ordItemList.isEmpty()){
         insert ordItemList;
       }
    }
}

Let me know if any helps you need !!
Thanks 
Manoj
Mahesh DMahesh D
Hi Shobhana,

Please find the below trigger:
trigger OpportunityTriggerForOrder on Opportunity (after insert, after update) {
    Set<Id> oppIdSet = new Set<Id>();
    List<Order> ordList = new List<Order>();
    
    for(Opportunity opp: Trigger.new) {
        if(opp.StageName == 'Closed Won' && (Trigger.isInsert || opp.StageName != Trigger.oldMap.get(opp.Id).StageName)){
            if(opp.AccountId != null) {
                oppIdSet.add(opp.Id);
                Order ord = new Order();
                ord.OpportunityId = opp.Id;
                ord.AccountId = opp.AccountId;
                ord.EffectiveDate = opp.CloseDate;
                ord.Status= 'Draft';
                ord.Pricebook2Id = opp.Pricebook2Id;
                ordList.add(ord);
            }
        }
    }
    
    if(!ordList.isEmpty()) {
        insert ordList;
        Map<Id, Order> ordMap = new Map<Id, Order>();
        List<OrderItem> oiList = new List<OrderItem>();
        for(Order ord: ordList) {
            ordMap.put(ord.OpportunityId, ord);
        }
        
        for(Opportunity opp: [Select Id, AccountId, CloseDate, (select Id, Name, ProductCode, Quantity, PricebookEntryId, UnitPrice, OpportunityId from OpportunityLineItems) from Opportunity where Id IN: oppIdSet]) {
            for(OpportunityLineItem oli: opp.OpportunityLineItems) {
                OrderItem oi = new OrderItem();
                oi.OrderId = ordMap.get(opp.Id).Id;
                oi.Quantity = oli.Quantity;
                oi.PricebookEntryId = oli.PricebookEntryId;
                oi.UnitPrice = oli.UnitPrice;
                oiList.add(oi);
            }
        }
        
        if(!oiList.isEmpty()) {
            insert oiList;
        }
    }
}
I also tested the above code in DE environment and everything is working fine.

Note: On Opportunity Account is required to create Order and Order Item records.

Please do let me know if it helps.

Regards,
Mahesh
This was selected as the best answer
shobana shobana 1shobana shobana 1
Hi Mahesh D

Thank you for your help it's working good but i have changed the  5th line 
if(Trigger.OldMap.get(opp.Id).StageName != 'Closed Won' && opp.StageName == 'Closed Won' ).
 
Mahesh DMahesh D
Hi Shibana,

You can below code only if the trigger is on update action:
 
if(Trigger.OldMap.get(opp.Id).StageName != 'Closed Won' && opp.StageName == 'Closed Won' )

In insert action, Trigger.OldMap will be null and we will get NullPointerException.

If the trigger is on both insert and update action:
 
if(opp.StageName == 'Closed Won' && (Trigger.isInsert || opp.StageName != Trigger.oldMap.get(opp.Id).StageName))

Regards,
Mahesh
shobana shobana 1shobana shobana 1
Hi mahesh
 Thank you for your reply. i need the action only for an updation action only.
vishal yadav 86vishal yadav 86
Can we achieve this through process builder?
Nilesh Shende 6Nilesh Shende 6
Thank you so much. its working good