+ Start a Discussion
Chris EdwardsChris Edwards 

Where am I going wrong? Trailhead: Bulk Apex Triggers

Hello developer heroes!

I'm working through the Apex modules on Trailhead and can't seem to get past this one: https://developer.salesforce.com/en/trailhead/force_com_programmatic_beginner/apex_triggers/apex_triggers_bulk.

Hopefully this doesn't read like a 'please complete the course for me' kinda post, but I have written a trigger that I believe meets the criteria but it isn't passing the check, so I wanted to seek the guidance of the experts.

The challenge is to do this:

Create an Apex trigger for Opportunity that adds a task to any opportunity set to 'Closed Won'.

To complete this challenge, you need to add a trigger for Opportunity. The trigger will add a task to any opportunity inserted or updated with the stage of 'Closed Won'. The task's subject must be 'Follow Up Test Task'.The Apex trigger must be called 'ClosedOpportunityTrigger'

- With 'ClosedOpportunityTrigger' active, if an opportunity is inserted or updated with a stage of 'Closed Won', it will have a task created with the subject 'Follow Up Test Task'.
- To associate the task with the opportunity, fill the 'WhatId' field with the opportunity ID.
- This challenge specifically tests 200 records in one operation.


And here is the trigger I have come up with, which compiles OK and stands up to a manual (though admittedly unbulkified) test:
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {

    List<Task> taskList = new List<Task>();
    
    for (Opportunity opp : [SELECT Id, StageName FROM Opportunity WHERE StageName = 'Closed Won' AND Id IN :Trigger.new]){
                    
            taskList.add(new Task(Subject = 'Follow Up Test Task',
                                  WhatId = opp.Id));
       
    }

    if(taskList.size()>0){
        
        insert taskList;
        
    }
    
}
I have tried replacing the SOQL with a straightforward 'for (Opportunity opp : Trigger.new)' and having the taskList.add inside an IF that checks for Closed Won - no luck. I also thought about checking to see if the stage was being changed to Closed Won, rather than the trigger firing on every edit, but I don't think this is what the module is asking for.

Where do you think I'm going wrong?

Huge thanks in advance!
Best Answer chosen by Chris Edwards
Adam Purkiss 99Adam Purkiss 99
Hi Chris,

It's possible for something else in your DE org to cause an assessment to fail. For example, if you had a workflow, validation rule or another trigger that threw an error during the course of testing, the Trailhead assessment would be unable to finish its execution. We're making a change to Trailhead to provide more detailed information about unexpected errors to help resolve these issues, which should be released soon. But in general, it's best to use a fresh DE org to avoid such conflicts.

Thanks!

All Answers

AmulAmul
Hi Chris,

use following below code.


trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {

    List<Task> taskList = new List<Task>();
    
    
        
    for(opportunity opp: Trigger.New){
    
        if(opp.StageName!=trigger.oldMap.get(opp.id).stageName)
        {
            
            taskList.add(new Task(Subject = 'Follow Up Test Task',
                                  WhatId = opp.Id));
        }
    
    }

    
    if(taskList.size()>0){
        
        insert taskList;
        
    }
    
}


please mail me at amulhai@gmail.com. if it wont works for you. thanks
 
Sumitkumar_ShingaviSumitkumar_Shingavi
Your code should entry criterials like:
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {

    List<Task> taskList = new List<Task>();
    
    for(Opportunity opp : Trigger.new) {
		
		//Only create Follow Up Task only once when Opp StageName is to 'Closed Won' on Create
		if(Trigger.isInsert) {
			if(Opp.StageName == 'Closed Won') {
				taskList.add(new Task(Subject = 'Follow Up Test Task', WhatId = opp.Id));
			}
		}
		
		//Only create Follow Up Task only once when Opp StageName changed to 'Closed Won' on Update
		if(Trigger.isUpdate) {
			if(Opp.StageName == 'Closed Won' 
			&& Opp.StageName != Trigger.oldMap.get(opp.Id).StageName) {
				taskList.add(new Task(Subject = 'Follow Up Test Task', WhatId = opp.Id));
			}
		}       
    }

    if(taskList.size()>0) {        
        insert taskList;        
    }    
}

PS: if this answers your question then hit Like and mark it as solution!
Chris EdwardsChris Edwards
Thanks very much for your answers, Amul and Sumitkumar.

They make sense to me, but I have tried both of them and no joy. The check is still failing. To be clear - I have no doubt these triggers would work in real life, it is just that Trailhead isn't validating them. 

I also tried moving to (after insert, before update) but still nope. 

Could it just be an issue with the Trailhead checking mechanism (as with https://developer.salesforce.com/forums/#!/feedtype=SINGLE_QUESTION_SEARCH_RESULT&id=906F0000000AnOCIA0), or does anyone else have any suggestions?
Sumitkumar_ShingaviSumitkumar_Shingavi
Can you tell me what TrailHead says? It should work as it is!
Chris EdwardsChris Edwards
Sure - this is probably the most frustrating part, as the error is so generic as to be useless:
Trailhead Generic Error
Sumitkumar_ShingaviSumitkumar_Shingavi
I will suggest you to run same trigger in an new developer org (you might need to create one if you don't have it already) which is separate than trailhead. You might get towards more correct solution but this requirement is fairly straight.
Chris EdwardsChris Edwards
The trigger is already in my dev org. I don't particularly want to spin up a new one just for the purposes of getting Trailhead to work, especially as my dev org ID is how Trailhead knows I am me.

And I don't quite understand why the same trigger being checked by the same system would work simply because it is in a different org. 

But anyway, thank you for your assistance and for trying to help. I appreciate it!
Sumitkumar_ShingaviSumitkumar_Shingavi
Oh got it! Put some debug logs and see the result after your testing. If you still see things working in dev org then TrailHead might make it a GO in it's next synch or something.
Chris EdwardsChris Edwards
Have set up a debug log and checked the log but no obvious hints. All seems to have happened as expected. 
Adam Purkiss 99Adam Purkiss 99
Hi Chris,

It's possible for something else in your DE org to cause an assessment to fail. For example, if you had a workflow, validation rule or another trigger that threw an error during the course of testing, the Trailhead assessment would be unable to finish its execution. We're making a change to Trailhead to provide more detailed information about unexpected errors to help resolve these issues, which should be released soon. But in general, it's best to use a fresh DE org to avoid such conflicts.

Thanks!
This was selected as the best answer
Sandeep BhanotSandeep Bhanot
Chris - first of all, apologies on behaof of the Trailhead team that you're having trouble with this challenge. I just tried your code in an own DE Org and was able to pass the challenge successfully. As Adam mentioned earlier, this means that there must be some code or config in your DE Org (probably related to the Opportunity object) that is causing the challenge to fail for you.
The fastest path for you is to try the challenge in a fresh DE Org as Adam recommended. I do understand that it is painful to spin up a new DE, but as you can imagine, it is impossible for us to write challenges that work in every possible combination of code/config in a DE Org. As Adam also said, we're working on improving our error reporting functionality as well so that its easier for you to know that something unexpected occured (vs the generic error that you're seeing now).
Aplogies again for these "challenges" (sorry, I couldn't resist!), but thank you for trying Trailhead and sending us your feedback.

Sandeep
Chris EdwardsChris Edwards
Thank you very much Adam and Sandeep!

I didn't like the thought of spinning up a new DE since even if it worked it would mean that my 'real' DE still didn't get the green tick for that challenge, so I hunted high and low for another trigger, VR and WFR that could have been tripping me up. Didn't find any. But then... I found it was a new process I'm building with the Process Builder that was causing the issue! So I deactivated it and passed the check.

Great to hear that the error messages are going to be improved. That will be a huge win. 

Thanks a lot for your help everyone! 
Adam Purkiss 99Adam Purkiss 99
Great to hear, Chris! Thanks for letting us know!
Sandeep BhanotSandeep Bhanot
Great to know Chris! Also remember that you can login to Trailhead with one DE login so that your profile gathers all the points and badges in one place, but you can attempt challenges in different DE Orgs. The points/badges would still acrrue to the profile/login that you logged into Trailhead with. Hope this isn't too confusing. You can watch the short video associated with the '?' icon to the right of the Challenge section to see how login and challenges work in Trailhead. Happy trails! 
Chris EdwardsChris Edwards
Ah, cool - I didn't know that! That's a big help. Thanks Sandeep!
Satyanarayana PusuluriSatyanarayana Pusuluri
Hi,

The below code working fine.

trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {

    List<Task> taskList = new List<Task>();
    
    for(Opportunity opp : Trigger.new) {
        
        if(Trigger.isInsert) {
            if(Opp.StageName == 'Closed Won') {
                taskList.add(new Task(Subject = 'Follow Up Test Task', WhatId = opp.Id));
            }
        }
        
        if(Trigger.isUpdate) {
            if(Opp.StageName == 'Closed Won' && Opp.StageName != Trigger.oldMap.get(opp.Id).StageName) {
                taskList.add(new Task(Subject = 'Follow Up Test Task', WhatId = opp.Id));
            }
        }       
    }

    if(taskList.size()>0) {        
        insert taskList;        
    }    
}

Thanks & Regards,
Satya P
Kishan MalepuKishan Malepu
Hi ,
 This code is working for me..

trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
   List<Task> taskList = new List<Task>();
    for (Opportunity o :[SELECT Id,StageName FROM Opportunity WHERE StageName ='Closed Won' AND Id IN :Trigger.New]) 
    {
        if(o.StageName == 'Closed Won')    
        {
            taskList.add(new task (Subject ='Follow Up Test Task' , WhatId=o.Id));
        }
            
    }
    if(taskList.size() > 0){
         insert taskList;
   }
}

Regards,
Kishan
Venkat K 27Venkat K 27
Chris's original code worked for me
Chris Kim 9Chris Kim 9
I was able to complete the challenge using the 'or' operator for the trigger 'isInsert' and 'isUpdate'.  See below.
 
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
	List <Task> todoList = new List <Task>();
   
    for (Opportunity opp :Trigger.new){
        if(Trigger.isInsert || Trigger.isUpdate) {
            if(opp.StageName == 'Closed Won') {
                todoList.add(new Task(Subject = 'Follow Up Test Task', WhatId = opp.Id));
            }
        }
    }
    if(todoList.size()>0) {
        insert todoList;
    }
}

 
Ashraful Islam 19Ashraful Islam 19
Hi @Chris Edwards

Try once using : (colon) in 'WHERE' clause.

 for (Opportunity opp : [SELECT Id, StageName FROM Opportunity WHERE StageName =: 'Closed Won' AND Id IN :Trigger.new]){


Thanks
Ashraful
sankalp tripathi 3sankalp tripathi 3
TRY WITH THIS

trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {

    List<Task> tl = new List<Task>();
    
    for(Opportunity op : Trigger.new) {
        
        
        if(Trigger.isInsert) {
            if(Op.StageName == 'Closed Won') {
                tl.add(new Task(Subject = 'Follow Up Test Task', WhatId = op.Id));
            }
        }
        
        
        if(Trigger.isUpdate) {
            if(Op.StageName == 'Closed Won' 
            && Op.StageName != Trigger.oldMap.get(op.Id).StageName) {
                tl.add(new Task(Subject = 'Follow Up Test Task', WhatId = op.Id));
            }
        }       
    }

    if(tl.size()>0) {        
        insert tl;        
    }    
}
Prem Kumar Gupta 8Prem Kumar Gupta 8
Easiest Approch:

trigger ClosedOpportunityTrigger on Opportunity (after insert,after update) {
    List<Opportunity> oppo = Trigger.new;
    system.debug('oppo----'+oppo);
    List<Task> taskList = new List<Task>();
    for(Opportunity o : oppo){
        if(o.StageName =='Closed Won'){
            Task task = new task();
            task.WhatId = o.id;
            task.Subject = 'Follow Up Test Task';
            task.status = 'Not Started';
            task.description = 'New  Work';
            taskList.add(task);
        }
    }
    if(taskList.size()>0)
        insert taskList;
}
Sindhura ManthapuriSindhura Manthapuri
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
    List<Task> t = new List<Task>();
    for(Opportunity o : Trigger.new) {
        if(o.StageName == 'Closed Won'){
            Task task = new task();
            task.WhatId = o.id;
            task.Subject = 'Follow Up Test Task';
            task.status = 'Not Started';
            task.description = 'New  Work';
            t.add(task);
       }
    }
if(t.size()>0)
    insert t;
}

This Worked for me.
Verma, ManishVerma, Manish
Hi,

Use the code below, it works perfectly:
 
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {

    List <Task> tasks = new List<Task>();
    for(Opportunity opp : [SELECT Id, StageName FROM Opportunity WHERE StageName='Closed Won' 
                           AND Id IN :Trigger.new]){
        tasks.add(new Task(Subject = 'Follow Up Test Task' , WhatId = opp.Id));
    }
    
    if(tasks.size() > 0){
        insert tasks;
    }
}

Hope this helps!!
 
Muhammad AlaaMuhammad Alaa
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
    //adds a 'Follow Up Test Task' to any opportunity set to 'Closed Won'
    List<Task> lstTask = new List<Task>();
    //Iterate over Opptys that are in this trigger and Closed Won
    for (Opportunity o : [SELECT Id, StageName FROM Opportunity WHERE Id IN :Trigger.New AND StageName = 'Closed Won']){
        //add Follow Up Task to this Oppty
        lstTask.add(new Task(Subject = 'Follow Up Test Task',
                            WhatId = o.Id));
    }
    
    if (lstTask.size() > 0)
        insert lstTask;
}

 
naresh shettynaresh shetty
Way to use standard way 
trigger ClosedOpportunityTrigger on Opportunity (after insert,after update) {

 List<Opportunity> relatedOpps = [SELECT Id,OwnerId,StageName FROM Opportunity WHERE id in :Trigger.New]; 
   List<Task> tasks = new List<Task>();
   for(Opportunity opp : relatedOpps) {
    if(opp.StageName == 'Closed Won')
    {
     
      Task tsk = new Task(whatID = Opp.ID, Ownerid = Opp.OwnerId, Subject='Follow Up Test Task'); tasks.add(tsk); 
         
    }   
   
  } 
  insert tasks;

}
Ruchir SinghalRuchir Singhal

I am getting this error

 

" There was an unexpected error in your org which is preventing this assessment check from completing: System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Discount_Percent__c]: [Discount_Percent__c] '

Can someone help

Below is the code used

trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
    
    List<Task> taskList = new List<Task>();

    for(Opportunity opp : Trigger.new) {
        
        if(Trigger.isInsert) {

            if(Opp.StageName == 'Closed Won') {

                taskList.add(new Task(Subject = 'Follow Up Test Task', WhatId = opp.Id));

            }

            //Only create Follow Up Task only once when Opp StageName changed to 'Closed Won' on Update

        if(Trigger.isUpdate) {

            if(Opp.StageName == 'Closed Won' && Opp.StageName != Trigger.oldMap.get(opp.Id).StageName) 
            {

                taskList.add(new Task(Subject = 'Follow Up Test Task', WhatId = opp.Id));

            }

        }
        }
        
        if(taskList.size()>0) {       

        insert taskList;       

    }
    }
            
    

}
 

 

Ruchir SinghalRuchir Singhal
Fixed it.. Had a Discount_Percent__c as a compulsory variable. Post removal of mandatory field it works
lorenzo d'aleolorenzo d'aleo
Hi all, i do this and perfectly work 
trigger ClosedOpportunityTrigger on Opportunity (before insert, before update) {
	list<task> a =new list<task>();
    for(Opportunity o: Trigger.New)
        if(o.stagename=='Closed Won')
        	a.add(new Task(Subject='Follow Up Test Task', WhatId=o.Id));
    insert a;
}

I hope it will be useful
santosh_sahanisantosh_sahani
Thank you @Satyanarayana Pusuluri .It workes for me.
RabindranathRabindranath

Thanks Sandeep Bhanot,Adams and Chris.

The only reason the trigger was failing in the trailhead was a Process builder  named Opportunity Management which was created in earlier topics
Saumyajit Mishra 9Saumyajit Mishra 9
The main issue with the above answers was no one has checked the 200 record limit. Please refer the below code to solve the trailhead challenge.

trigger ClosedOpportunityTrigger on Opportunity (after insert,after update)
{
    List<Task> l = new List<Task>();
    for(Opportunity o:[SELECT Id, StageName FROM Opportunity WHERE StageName = 'Closed Won' AND Id IN :Trigger.new])
    {
        
            Task t = new Task();
            t.subject='Follow Up Test Task';
            t.WhatId=o.id;
            l.add(t);
     }
    if(l.size()>0 && l.size()-1<=200)
    {
        insert l;
    }
}
Luis Angel Granados Cuello 2Luis Angel Granados Cuello 2
In my case i solved the problem by including "OwnerId=Opp.OwnerId" in the new task. In the Task Object the OwnerId is mandatory.
Luis Angel Granados Cuello 2Luis Angel Granados Cuello 2
trigger ClosedOpportunityTrigger on Opportunity (before insert, before update) {
    
    List<Task> NewTasks=new List<task>();
    For(opportunity selectedOpps : Trigger.new){
        NewTasks.add(new task(WhatId=selectedOpps.id, Subject = 'Follow Up Test Task', OwnerId=selectedOpps.OwnerId));
    }
    if(NewTasks.size()>0){
        insert NewTasks;
    }
}

Complete Code
pulak biswaspulak biswas
Hi,
I have done the trail head and tested it okay. New task being created with 'Closed Won' opportunity. However the challenge has failed. Showing the following error description:
"Challenge Not yet complete... here's what's wrong: 
There was an unexpected error in your org which is preventing this assessment check from completing: System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Discount_Percent__c]: [Discount_Percent__c]"

My code is as below -->
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
    
    
    List<Task> listTask = new List<Task>();
    Try{
    for (Opportunity opp:[select Id,AccountId,StageName,Name,CloseDate,Discount_Percent__c,(select WhatId from tasks) from Opportunity 
                          where Id in:Trigger.New and StageName='Closed Won']){
        if(opp.tasks.size()==0){
        listTask.add( new task(subject='Follow Up Test Task',
                               WhatId=opp.id,
                              Priority='Normal',
                              Status='In Progress' ));
        
        }
                          }
    insert listTask;
    }catch (exception e)
    {system.debug('exception is '+ e.getTypeName());
     system.debug('exception cause is '+ e.getCause());
     system.debug('exception line is '+ e.getLineNumber());}

}

-----------------------------
This is a bit frustrating. Can any one help?
Note : this same has happened with other trail head challenges too.
Ben RowleyBen Rowley
The instructions actually say description but if you check the assertion failures in the debug logs it will likely say assertion failed when running a query for 'where subject = 'Follow up test task'.

Below should do it for you. 

trigger ClosedOpportunityTrigger on Opportunity (after insert,after update) {
     
    List<Task> tasksToInsert = new List<Task>();
    
    for(Opportunity o: Trigger.new){
        if(o.StageName == 'Closed won'){
           tasksToInsert.add(new Task(Subject = 'Follow Up Test Task',
                                      whatId = o.id,
                                      Priority = 'High',
                                      Status = 'Complete'));
        }
    }
       if(tasksToInsert.size() >0)
    insert tasksToInsert;
}
Ben RowleyBen Rowley
Also remember you don't need to requery the opportunity object for the ID as you already have this from Trigger.new
Christian BäthgeChristian Bäthge
Hello,

after some work the coe is now fine. Watch out for the Process in the Processbuilder

trigger ClosedOpportunityTrigger on Opportunity (after insert, after update)
{
    List <Task> newTask = new List <Task>();

    for(Opportunity opp :Trigger.new)
    {       newtask.add(new Task(  Subject='Follow Up Test Task', Priority='Normal',Status='Completed'));        }
        
    If (newTask.size()>0)
    {        insert newtask;    }
}
 
chaitanya motupallichaitanya motupalli
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
   List<Task> taskList = new List<Task>();
    for (Opportunity o :[SELECT Id,StageName FROM Opportunity WHERE StageName ='Closed Won' AND Id IN :Trigger.New]) 
    {
      taskList.add(new task (Subject ='Follow Up Test Task' , WhatId=o.Id));
    }
    upsert taskList;
}

I just simplified Kishan Malepu work. thank you ALL.
it is working fine.
Jonnika Kubert 8Jonnika Kubert 8
Thank you all for your answers here. They helped me get my badge! The Bulk Apex Triggers unit made zero sense to me. Any recommendations on resources that break down triggers using layman terms for those of us that are not developer minded?
Sidhant JainSidhant Jain
this is what i wrote and it is working remember don't insert inside for loop and don't query inside for loop
trigger ClosedOpportunityTrigger on Opportunity (after insert,after update) {
    List<Task> taskList=new List<Task>();
    for(Opportunity objOpp :Trigger.New){
        if(objOpp.StageName =='Closed Won'){
            taskList.add(new Task(Subject ='Follow Up Test Task',WhatId =objOpp.Id));
        }
    }
    if(taskList.size()>0)
        insert taskList;
}
Alex Valavanis 10Alex Valavanis 10
I thought this was a module for beginners !

It would be highly appreciated if the module was a bit more "User Friendly" for those who know peanuts about Apex Triggers....
venkata Daggubativenkata Daggubati
Please Try this Can try both ways .Working fine

To complete this challenge, you need to add a trigger for Opportunity. The trigger will add a task to any opportunity inserted or updated with the stage of 'Closed Won'. The task's subject must be 'Follow Up Test Task'.
venkata Daggubativenkata Daggubati
trigger ClosedOpportunityTrigger on Opportunity (After insert, After Update) {

/*list<opportunity> opplist=new list<Opportunity> ([Select id, name, StageName from 
                         Opportunity Where (ID in :trigger.New AND  StageName='Closed Won') ]);
    
    list <Task> T=new List<Task>();
    
    for(Opportunity op:Opplist)
    {
        
        Task T1=new Task();
        T1.WhatId=op.id;
        T1.Subject='Follow Up Test Task';
        T.add(T1);
    }
 Insert T;
*/
    
 list<Opportunity> Op=New List<Opportunity>([SELECT ID, NAME ,(Select Subject from Tasks ) 
                                               From Opportunity Where (ID in :trigger.New AND  StageName='Closed Won') ]);
   
    List<Task> tasklist=new list<Task>();
    for(Opportunity Oplist:  Op)
    {
        if(oplist.Tasks.size()==0)
        {
           Task T=new Task(Subject='Follow Up Test Task', Whatid=Oplist.Id);
           Tasklist.add(T) ;           
        }
    }
    Insert Tasklist;
   
}
Krishnan MishraKrishnan Mishra
Hi Chris,
I had similar problem,try checking out the query you used in SOQL, there must be a simple error. YOu can first search your query in query editor and the ncopy past it in the apex code
sunil mali 11sunil mali 11
Working for code for this challenge:
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
    List<Task> taskList = new List<Task>();
    
    for(Opportunity opp : Trigger.new) {
        //create Follow Up Task only when Opportunity StageName is equal to 'Closed Won' on Create/Update
        if(Trigger.isInsert || Trigger.isUpdate) {
            if(opp.StageName == 'Closed Won') {
            taskList.add(new Task(Subject='Follow Up Test Task', WhatId =opp.Id));
        }
        }
        
    }
    if(taskList.size() > 0) {
        insert taskList;
    }
}
Mikhail RzhevskyMikhail Rzhevsky
I think that correct one is my version, but trailhead consider that correct commented lines.

trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {

    List<Task> taskList = new List<Task>(); 
    Opportunity[] opps = [SELECT Id,Name,StageName FROM Opportunity
        WHERE Id IN :Trigger.New];
    //for(opportunity opp: Trigger.New){
    	//if(opp.StageName=='Closed Won')
    	if(opps[0].StageName=='Closed Won')
        {
            
            taskList.add(new Task(Subject = 'Follow Up Test Task',
                                  //WhatId = opp.Id));
                                  WhatId = opps[0].Id));
        }   
    //}  
    if(taskList.size()>0){       
        insert taskList;       
    }
}

 
Vishal Sharma 126Vishal Sharma 126
What is the meaning of these lines?
1--- Opp.StageName != Trigger.oldMap.get(opp.Id).StageName) 
2---  WhatId = opp.Id
setiaman lee (Dev)setiaman lee (Dev)
I managed to clear this challenge after setting Discount Percentage field in the opportunity to not required. 
Gurdeep Rahi 3Gurdeep Rahi 3
Tried few different code examples from this thread but it did not work until I changed the field Discount_Percent to NOT Required as per the suggestion here.  It worked fine after the change.
 
Admin User 7969Admin User 7969
Hi guys
I got an issue with my trigger trailhead, I could find a lot of explanations but I want to understand why my SOQL request doesn't 'work' ;
Because I tried previously to fill a List, before looping on it, and System.debug the size of the List --> 0...
Here is my code,
Thanks by advance for your help / explanations :)
 
trigger ClosedOpportunityTrigger on Opportunity (before insert, before update) {
    // liste de Task ou ajouter les elements a updater / inserer
    List <Task> TaskToUpdate = new List <Task>();
 
    for (Opportunity op : [SELECT id FROM opportunity WHERE (stageName= 'Closed Won'
                                                             AND id IN :trigger.new)]) {
        // ajout d'une new task a liste de task (avec subject, et l'id de l'op)
        TaskToUpdate.add(new task(whatId=op.Id,
                                  Subject='Follow Up Test Task'));    
    }
    
    // upsert if usefull
    if (TaskToUpdate.size() > 0) {
        upsert TaskToUpdate;
    } 
}

 
Admin User 7969Admin User 7969
(sorry, I put my code inside the <> balise but it seems not to work ... An idea of why ?

Thanks !! )
Admin User 7969Admin User 7969
Ok, my mistake was just that I configured the trigger on BEFORE and it's a AFTER !!

Well done :)
xuer zoxuer zo
My experience is that Task.OwnerId has to be defined, this works for me:
trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
    Task[] tasklist = new List<Task>();
    for (Opportunity opp : [SELECT Id, Name, OwnerId FROM Opportunity WHERE Id IN :Trigger.New AND StageName = 'Closed Won']) {
        tasklist.add(new Task(WhatId = opp.Id, Subject = 'Follow Up Test Task', OwnerId = opp.OwnerId));
        System.debug('inserted records: ' + opp.Id);
    }
    if (tasklist.size() > 0) {
    insert tasklist;
    }
}
Vivek HIngorani 2Vivek HIngorani 2
@xuer zo: Thanks for the solution. It was Owner Id that solved the issue.