【问题标题】:What is wrong with my code on Trailhead challenge Developer Beginner > Apex Triggers > Bulk Apex Triggers我在 Trailhead 挑战中的代码有什么问题 Developer Beginner > Apex Triggers > Bulk Apex Triggers
【发布时间】:2026-01-14 12:45:01
【问题描述】:

这是挑战:

要完成此挑战,您需要为机会添加触发器。触发器会将任务添加到任何插入或更新的“已结束赢得”阶段的机会。任务的主题必须是“跟进测试任务”。

  • Apex 触发器必须称为“ClosedOpportunityTrigger”
  • “ClosedOpportunityTrigger”处于活动状态时,如果插入或更新机会为“Closed Won”阶段,它将创建一个主题为“Follow Up Test Task”的任务。
  • 要将任务与机会相关联,请在“WhatId”字段中填写机会 ID。
  • 此挑战专门在一次操作中测试 200 条记录。

这是我的代码

trigger ClosedOpportunityTrigger on Opportunity (before insert, before update) {
List<Opportunity> opportunities = [SELECT Id, StageName
                                   FROM Opportunity
                                   WHERE Id
                                   IN :Trigger.New];
List<Task> tasksToUpdate = new List<Task>();
System.debug('##### OPS' + opportunities);
for(Opportunity o : opportunities){
    System.debug('##### ' + o.StageName);
    if(o.StageName == 'Closed Won'){
        Task thisTask = new Task(WhatId = o.Id, Subject = 'Follow Up Test Task');
        tasksToUpdate.add(thisTask);
        System.debug('##### ' + tasksToUpdate);
    }
}
insert tasksToUpdate;

}

当我尝试通过 trailhead 进行验证时,它给出了“挑战尚未完成......这是错误的: 对触发器执行未按预期工作。”错误。

我添加了一些调试打印,似乎表明 soql 语句没有提取任何结果,因此它没有进入 if 语句。对我来说,这似乎是一个非常简单的 soql 语句,但我一定遗漏了一些东西。无论我添加或更新项目,都会发生这种情况。

提前致谢

【问题讨论】:

    标签: salesforce apex


    【解决方案1】:

    在触发器上下文中,您不需要使用 SOQL 查询来检索正在插入或更新的记录。

    此外,使用before insert 触发器,记录还不会在数据库中,因此它们不会定义任何 ID。这就是查询没有返回任何内容的原因。

    相反,您将希望使用 Trigger Context Variables 来处理记录。

    特别是,您可以使用Trigger.new 来获取正在插入或更新的记录集合。尝试循环访问此集合,而不是在触发器中使用 SOQL 查询。

    【讨论】:

      【解决方案2】:
        trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
              List<Task> taskListToInsert = new List<Task>();
      
              for(Opportunity opp : [Select Id,StageName from Opportunity 
                                        where Id in :Trigger.New AND StageName = 'Closed Won'])
              {
                      taskListtoInsert.add(new Task(Subject ='Follow Up Test Task',WhatId = opp.Id));
      
              }
      
          if(taskListtoInsert.size()>0)
          {
              insert taskListtoInsert;
          }
      }
      

      【讨论】:

      • 虽然此代码可以回答问题,但提供有关 如何为什么 解决问题的附加上下文将提高​​答案的长期价值。
      【解决方案3】:

      您的代码的问题是您在插入/更新之前运行,其中元素还没有 ID。因此下面的代码:

      Task thisTask = new Task(WhatId = o.Id, Subject = 'Follow Up Test Task');
      

      插入一个没有通过测试的空 WhatId 任务。只需更改为插入后/更新触发事件后即可。

      【讨论】:

        【解决方案4】:

        好吧,由于任务问题,我在这个挑战中遇到了麻烦,似乎它只是 salesforce 的默认对象!

        您的问题是您的代码量不够大,就像跟踪中显示的那样。

        trigger ClosedOpportunityTrigger on Opportunity (after insert, after update) {
        
            List<Opportunity> closedOpp = [Select id from opportunity
                                          where id IN :Trigger.New
                                          AND StageName = 'Closed Won'];
        
            List<Task> triggeredTasks = new List<Task>();
        
            for (Opportunity o : closedOpp){
        
                Task tache = new Task (Subject = 'Follow Up Test Task',
                                      WhatId = o.ID);
                triggeredTasks.add(tache);
            }
        
            insert triggeredTasks;
        }
        

        【讨论】:

          【解决方案5】:

          这是有效的代码:

          在机会上触发 ClosedOpportunityTrigger(插入后,更新后){

          List<Task> OpTasklist = new List<Task>();
          
          // Iterate over opportunities that are in this trigger and have a stage of "Closed Won"
          for (Opportunity op: [SELECT id FROM Opportunity 
                                WHERE Id IN :Trigger.New AND
                                StageName =: 'Closed Won']) {
          
                                    if ((Trigger.IsUpdate && Trigger.oldMap.get(op.Id).StageName != 'Closed Won')) OR 
                                        (Trigger.IsInsert) {
                                            OpTaskList.add(new Task (Subject='Follow Up Test Task', 
                                                                     WhatId = op.Id)); }          
                                }
          
          If (OpTaskList.size() > 0) { 
              Insert OpTaskList ;
          }   
          

          }

          【讨论】:

            【解决方案6】:

            在机会上触发 ClosedOpportunityTrigger(插入后,更新后){

            List oppty = [从机会中选择 id,其中 id IN :Trigger.New AND St​​ageName = 'Closed Won'];

            List<Task> new_task = new List<Task>();
            
            for (Opportunity opp : oppty){
            
                Task thistask = new Task (Subject = 'Follow Up Test Task',WhatId = opp.ID);
                new_task.add(thistask);
            }
            
            insert new_task;
            

            }

            【讨论】:

            • 我也尝试了其他一些方法,但我看到当您使用列表上的查询时,您会直接声明您需要包含舞台名称的最新记录,因为已关闭,这会给您答案。托努