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
Tanmay SahaiTanmay Sahai 

I want to create an opportunity from an event using a trigger and also want the event to be mapped/added to the created opportunity

Hello All,

I am looking for a functionality wherein I am creating an opportunity from the event. The condition is that the oppty will only be created when the Event-Type is Demo and the Status ( a custom picklist field on the Event) = Complete.
I have created a trigger to achieve this requirement. Below is the code:

trigger EventTrigger on Event (after update){

    List<Opportunity> opportunities = new List<Opportunity>();
    List<Id> idAccountList = new List<Id>();
    List<Event> eventToProcessList = new List<Event>();
    String eventType;
    
    for(Event event :Trigger.new) {

        eventType = event.Type;
        if(!eventType.containsIgnoreCase('demo') || eventType.Demo_Status__c != 'Completed') continue;

        if(event.WhatId.getSObjectType() != Account.SObjectType) continue;
        
        idAccountList.add(event.WhatId);
        eventToProcessList.add(event);
        
    }
    
    if(idAccountList.isEmpty()) return;
    
    Map<Id, Account> accountMap = [SELECT Id, Name FROM Account WHERE Id IN :idAccountList];
    
    for(Event event : eventToProcessList){
        
        Opportunity opp = new Opportunity(
            Name = accountMap.get(event.WhatId).Name + '|RP|' + event.Seats__c,
            //Name = 'Test Opp'+ 'Amount'+'(event.Id).Contact_Lookup__c',
            CloseDate = Date.Today()+ 90,
            Type = 'New Business',
            //Notes__c = Trigger.newMap.get(event.Id).Notes__c,
            Notes__c = event.Notes__c,
            //fill other mandatory fields comma seperated as shown above
            AccountId = event.WhatId,
            //Contact_Lookup__c = Trigger.newMap.get(event.Id).Contact_Lookup__c,
            StageName = 'Pre-Qualified',
            Referring_SDR__c= event.OwnerId,
            Contact_Name__c = event.Related_Contact_Name__c,
            Opportunity_Owner__c= event.Assigned_AE__c,
            Amt__c= event.Amount__c,
            Seat_Number__c= event.Seats__c,
            LeadSource= event.Lead_Source__c,
            New_Lead_Source__c= event.New_Lead_Source__c
         );
         opportunities.add(opp);
    }

    if(!opportunities.isEmpty()){
        insert opportunities;
    }
}

But I am getting the below compile error:
" Error: Compile Error: Variable does not exist: Demo_Status__c at line 11 column 63 "
Not sure why this is coming as the API name is correct as per my knowledge.

Also, additionally I am looking to map this event to the opportunity that gets created via trigger for this event on the basis of EventId/ActivityId so that we can create a report to track the number of events that got converted into opportunities.

Any quick help will be highly appreciated.  Thanks in advance!
Best Answer chosen by Tanmay Sahai
Narender Singh(Nads)Narender Singh(Nads)
Hi Tanmay,

Use this code:
trigger EventTrigger on Event (after update){

    List<Opportunity> opportunities = new List<Opportunity>();
    list<string> idAccountList = new list<string>();
    List<Event> eventToProcessList = new List<Event>();
    String eventType;
    
    for(Event event :Trigger.new) {
        eventType = event.Type;
        if(eventType.containsIgnoreCase('demo') && event.Demo_Status__c != 'Completed'){
        //if(eventType!=NULL && eventType.containsIgnoreCase('email') ){
            if(event.WhatId!=NULL && event.WhatId.getSObjectType() == Account.SObjectType ){
                eventToProcessList.add(event);
                if(!idAccountList.contains(event.whatid))
                    idAccountList.add(event.WhatId);
             }
        }
	}
    
    Account[] AccNames=[select name from account where id in :idAccountList];
    map<string,string> AcccountMap= new map<string,string>();
    for(integer i=0;i<AccNames.size();i++){
        AcccountMap.put(idAccountList[i],AccNames[i].name );
    }
    
    for(Event event : eventToProcessList){
        
        //system.debug(AcccountMap.get(event.whatid));
        //Creating Oppty
        Opportunity op = new Opportunity();
            op.Name =AcccountMap.get(event.whatid)+ '|RP|'+ event.Seats__c;
            //Name = 'Test Opp'+ 'Amount'+'(event.Id).Contact_Lookup__c',
            op.CloseDate = Date.Today()+ 90;
            //op.Type = 'New Business';
            //Notes__c = Trigger.newMap.get(event.Id).Notes__c,
            //op.Notes__c = event.Notes__c;
            //fill other mandatory fields comma seperated as shown above
            op.AccountId = event.WhatId;
            //Contact_Lookup__c = Trigger.newMap.get(event.Id).Contact_Lookup__c,
            op.StageName = 'Prospecting';
            //op.Referring_SDR__c= event.OwnerId;
            //op.Contact_Name__c = event.Related_Contact_Name__c;
            //op.Opportunity_Owner__c= event.Assigned_AE__c;
            //op.Amt__c= event.Amount__c;
            //op.Seat_Number__c= event.Seats__c;
            //op.LeadSource= event.Lead_Source__c;
            //op.New_Lead_Source__c= event.New_Lead_Source__c;
        
         opportunities.add(op);
    }
    //system.debug('List of Records to be Created: '+opportunities);
    
    if(opportunities.size()>0){
        insert opportunities;
    }
    
    
}

I have tested the code on my org. It sucessfully creates the oppty on the associated account. Manipulate the code according to your requirement after Creating Oppty Comment.

Thanks.

All Answers

Tanmay SahaiTanmay Sahai
Hi All,

I am also getting the below error as well:
" Illegal assignment from List to Map ".
 Guys kindly share inputs on the same.

Thanks & Best Regards
Narender Singh(Nads)Narender Singh(Nads)
Hi Tanmay,

 if(!eventType.containsIgnoreCase('demo') || eventType.Demo_Status__c != 'Completed') continue;

In this line of your code you're dereferencing a string type variable i.e 'eventType'. In your code you have declared this variable as string type. If you have created a custom field on activity object then use event.Demo_Status__c.

Let me know if it helps.
Thanks!
Raj2019ssRaj2019ss
Hi Tanmay Sahai,
Try the below one
for(Event event :Trigger.new) {

      //  eventType = event.Type;
        if(!event.Type.containsIgnoreCase('demo') || event.Type.Demo_Status__c != 'Completed');

 
Tanmay SahaiTanmay Sahai
Hello Narendra & Rajesh,

Thanks for your quick response guys but this is still not working.
If I use Narender's logic, I get the below error:

" Error: Compile Error: Illegal assignment from List<Account> to Map<Id,Account> at line 22 column 22" which means the logic works but is failing for my SOQL Query.

If I use Rajesh's code, I get the below error:
Error: Compile Error: Unexpected token ';'. at line 11 column 95

Also, how to achieve the requirement of mapping/adding the event to the opportunity that gets created via trigger for this event on the basis of EventId/ActivityId so that we can create a report to track the number of events that got converted into opportunities.

Any help will be highly obliged. Thanks!
 
Narender Singh(Nads)Narender Singh(Nads)
This compilation is occuring because you are trying to assign a list to a map. SOQL query returns a list of records not a map of records.
Your code should be like:
list<Account> accountMap = [SELECT Id, Name FROM Account WHERE Id IN :idAccountList];
But if you really need a map then for that you will have to iterate on the list returned by SOQL and assign to map. For that your code should look something like this:
map<id,account> accountmap= new map<id,account>();

for(account a : [SELECT Id, Name FROM Account WHERE Id IN :idAccountList ]){

   accountmap.put(a.id, a);

}

This should resolve your error.
Thanks!
Tanmay SahaiTanmay Sahai
Hello Narender,

The code is working now. However, when I am trying to update the event record, I am getting the below error:

" Error:Apex trigger EventTrigger caused an unexpected exception, contact your administrator: EventTrigger: execution of AfterUpdate caused by: System.NullPointerException: Attempt to de-reference a null object: ()"

Here is my entire trigger:

trigger EventTrigger on Event (after update){

    List<Opportunity> opportunities = new List<Opportunity>();
    List<Id> idAccountList = new List<Id>();
    List<Event> eventToProcessList = new List<Event>();
    String eventType;
    
    for(Event event :Trigger.new) {

        eventType = event.Type;
        if(!eventType.containsIgnoreCase('demo') || event.Demo_Status__c != 'Completed') continue;

        if(event.WhatId.getSObjectType() != Account.SObjectType) continue;
        
        idAccountList.add(event.WhatId);
        eventToProcessList.add(event);
        
    }
    map<id,account> accountmap= new map<id,account>();

for(account a : [SELECT Id, Name FROM Account WHERE Id IN :idAccountList ]){

   accountmap.put(a.id, a);

}
    if(idAccountList.isEmpty()) return;
    //list<Account> accountMap = [SELECT Id, Name FROM Account WHERE Id IN :idAccountList];
    
    //Map<Id, Account> accountMap = [SELECT Id, Name FROM Account WHERE Id IN :idAccountList];
    
    for(Event event : eventToProcessList){
        
        Opportunity opp = new Opportunity(
            Name = accountMap.get(event.WhatId).Name + '|RP|' + event.Seats__c,
            //Name = 'Test Opp'+ 'Amount'+'(event.Id).Contact_Lookup__c',
            CloseDate = Date.Today()+ 90,
            Type = 'New Business',
            //Notes__c = Trigger.newMap.get(event.Id).Notes__c,
            Notes__c = event.Notes__c,
            //fill other mandatory fields comma seperated as shown above
            AccountId = event.WhatId,
            //Contact_Lookup__c = Trigger.newMap.get(event.Id).Contact_Lookup__c,
            StageName = 'Pre-Qualified',
            Referring_SDR__c= event.OwnerId,
            Contact_Name__c = event.Related_Contact_Name__c,
            Opportunity_Owner__c= event.Assigned_AE__c,
            Amt__c= event.Amount__c,
            Seat_Number__c= event.Seats__c,
            LeadSource= event.Lead_Source__c,
            New_Lead_Source__c= event.New_Lead_Source__c
         );
         opportunities.add(opp);
    }

    if(!opportunities.isEmpty()){
        insert opportunities;
    }
}

Kindly help with the exlusion of the error. Thanks in advance!
Tanmay SahaiTanmay Sahai
Below is the screenshot for your reference:

User-added image
Narender Singh(Nads)Narender Singh(Nads)
Hi Tanmay,
Can you please also share the the screenshot of Custom fields you have created on Activity object(if any) and also the picklist values of 'Event Type' Field.
Tanmay SahaiTanmay Sahai
Hi Narender,
Sure. Below is the screenshot of all the Activity Custom fields:

Activity Custom fields

Here is the screenshot of the Event Type (custom Activity pikclist field) picklist values:

User-added image

So basically, when the picklist value for Event Type = Demo and Status = Complete, it should trigger an oppty creation. Additionally, I want to add the event ID to the created oppty.

Kindly let me know if you need any additional information.

Thanks!
Narender Singh(Nads)Narender Singh(Nads)
Hi Tanmay,
In your for loop:
for(Event event :Trigger.new) {

        eventType = event.Type;
        if(!eventType.containsIgnoreCase('demo') || event.Demo_Status__c != 'Completed') continue;

        if(event.WhatId.getSObjectType() != Account.SObjectType) continue;
        
        idAccountList.add(event.WhatId);
        eventToProcessList.add(event);
        
    }

You need to have a NULL check because there may be events without any account associated with them. Something like:
for(Event event :Trigger.new) {
    
    if(event.whatid!=NULL){
       eventType = event.Type;
        if(!eventType.containsIgnoreCase('demo') || event.Demo_Status__c != 'Completed')
        continue;

        if(event.WhatId.getSObjectType() != Account.SObjectType)
        continue;
        
        idAccountList.add(event.WhatId);
        eventToProcessList.add(event); 
    }
}

This should help with the NULL reference error.

Thanks!
Tanmay SahaiTanmay Sahai
Hi Narender,

Thanks again for the quick response. The solution you provided is working now. My trigger doesn't throw any errors but it is not creating the opportunity and I am not getting any error in the debug logs as well which is kinda stange. Can you please re-check?

Thanks in advance!
Narender Singh(Nads)Narender Singh(Nads)
Hi Tanmay,
Try this code and let me know if it works for you or not.
trigger EventTrigger on Event (after update){

    List<Opportunity> opportunities = new List<Opportunity>();
    List<Id> idAccountList = new List<Id>();
    List<Event> eventToProcessList = new List<Event>();
    String eventType;
    
    for(Event event :Trigger.new) {
        if(event.WhatId!=NULL){
            eventType = event.Type;
        	if(!eventType.containsIgnoreCase('demo') || event.Demo_Status__c != 'Completed') continue;

        	if(event.WhatId.getSObjectType() != Account.SObjectType) continue;
        
        	idAccountList.add(event.WhatId);
        	eventToProcessList.add(event);
        }
	}
    for(Event event : eventToProcessList){
        account a=[select name from account where id =:event.whatid]
        
        Opportunity opp = new Opportunity(
            Name = a.Name + '|RP|' + event.Seats__c,
            //Name = 'Test Opp'+ 'Amount'+'(event.Id).Contact_Lookup__c',
            CloseDate = Date.Today()+ 90,
            Type = 'New Business',
            //Notes__c = Trigger.newMap.get(event.Id).Notes__c,
            Notes__c = event.Notes__c,
            //fill other mandatory fields comma seperated as shown above
            AccountId = event.WhatId,
            //Contact_Lookup__c = Trigger.newMap.get(event.Id).Contact_Lookup__c,
            StageName = 'Pre-Qualified',
            Referring_SDR__c= event.OwnerId,
            Contact_Name__c = event.Related_Contact_Name__c,
            Opportunity_Owner__c= event.Assigned_AE__c,
            Amt__c= event.Amount__c,
            Seat_Number__c= event.Seats__c,
            LeadSource= event.Lead_Source__c,
            New_Lead_Source__c= event.New_Lead_Source__c
         );
         opportunities.add(opp);
    }
    system.debug('List of Records to be Created: '+opportunities);
    if(!opportunities.isEmpty()){
        insert opportunities;
    }
    
}

Thanks.
Narender Singh(Nads)Narender Singh(Nads)
Hey tanmay,
Minor correction in the code above.
for(Event event : eventToProcessList){
        //account a=[select name from account where id =:event.whatid]; //Comment out this line
        
        Opportunity opp = new Opportunity(
            Name = e.what.Name + '|RP|' + event.Seats__c, //Changed the 'a.name' to e.what.name
Thanks.
Tanmay SahaiTanmay Sahai
Hello Narender,

Thanks again for your help. I have used your code and there were few compile errors which I was able to resolve. However, the trigger is not automating the oppty. I mean the oppty is not being created from the event.

Also, if I try to change the status from Open to Complete or from Complete to Open and again complete, it throws an error.

What could be the reason according to you. Await your response.

Thanks!
Narender Singh(Nads)Narender Singh(Nads)
Hi Tanmay,

Use this code:
trigger EventTrigger on Event (after update){

    List<Opportunity> opportunities = new List<Opportunity>();
    list<string> idAccountList = new list<string>();
    List<Event> eventToProcessList = new List<Event>();
    String eventType;
    
    for(Event event :Trigger.new) {
        eventType = event.Type;
        if(eventType.containsIgnoreCase('demo') && event.Demo_Status__c != 'Completed'){
        //if(eventType!=NULL && eventType.containsIgnoreCase('email') ){
            if(event.WhatId!=NULL && event.WhatId.getSObjectType() == Account.SObjectType ){
                eventToProcessList.add(event);
                if(!idAccountList.contains(event.whatid))
                    idAccountList.add(event.WhatId);
             }
        }
	}
    
    Account[] AccNames=[select name from account where id in :idAccountList];
    map<string,string> AcccountMap= new map<string,string>();
    for(integer i=0;i<AccNames.size();i++){
        AcccountMap.put(idAccountList[i],AccNames[i].name );
    }
    
    for(Event event : eventToProcessList){
        
        //system.debug(AcccountMap.get(event.whatid));
        //Creating Oppty
        Opportunity op = new Opportunity();
            op.Name =AcccountMap.get(event.whatid)+ '|RP|'+ event.Seats__c;
            //Name = 'Test Opp'+ 'Amount'+'(event.Id).Contact_Lookup__c',
            op.CloseDate = Date.Today()+ 90;
            //op.Type = 'New Business';
            //Notes__c = Trigger.newMap.get(event.Id).Notes__c,
            //op.Notes__c = event.Notes__c;
            //fill other mandatory fields comma seperated as shown above
            op.AccountId = event.WhatId;
            //Contact_Lookup__c = Trigger.newMap.get(event.Id).Contact_Lookup__c,
            op.StageName = 'Prospecting';
            //op.Referring_SDR__c= event.OwnerId;
            //op.Contact_Name__c = event.Related_Contact_Name__c;
            //op.Opportunity_Owner__c= event.Assigned_AE__c;
            //op.Amt__c= event.Amount__c;
            //op.Seat_Number__c= event.Seats__c;
            //op.LeadSource= event.Lead_Source__c;
            //op.New_Lead_Source__c= event.New_Lead_Source__c;
        
         opportunities.add(op);
    }
    //system.debug('List of Records to be Created: '+opportunities);
    
    if(opportunities.size()>0){
        insert opportunities;
    }
    
    
}

I have tested the code on my org. It sucessfully creates the oppty on the associated account. Manipulate the code according to your requirement after Creating Oppty Comment.

Thanks.
This was selected as the best answer