+ Start a Discussion
Chris EdwardsChris Edwards 
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));

        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.

The following formula will calculate the number of working days (inclusive) between 2 dates. A working day is defined as Monday to Friday. Even if the start or end dates are a weekend, these are accommodated.

IF(AND((5 - (CASE(MOD( Start_Date__c - DATE(1900, 1, 6), 7), 0, 0, 1, 5, 2, 5, 3, 4, 4, 3, 5, 2, 6, 1, 0)) < (CASE(MOD(  End_Date__c  - DATE(1900, 1, 6), 7), 0, 0, 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 0)) ),
((( End_Date__c  -   Start_Date__c ) + 1) < 7)),
((CASE(MOD(  End_Date__c  - DATE(1900, 1, 6), 7), 0, 0, 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 0)) - (5 - (CASE(MOD(  Start_Date__c  - DATE(1900, 1, 6), 7), 0, 0, 1, 5, 2, 5, 3, 4, 4, 3, 5, 2, 6, 1, 0)))),
(((FLOOR((( End_Date__c  -  Start_Date__c ) - (CASE(MOD(  Start_Date__c  - DATE(1900, 1, 6), 7), 0, 0, 1, 6, 2, 5, 3, 4, 4, 3, 5, 2, 6, 1, 0))) / 7)) * 5) +
(CASE(MOD(  Start_Date__c  - DATE(1900, 1, 6), 7), 0, 0, 1, 5, 2, 5, 3, 4, 4, 3, 5, 2, 6, 1, 0)) +
(CASE(MOD(  End_Date__c  - DATE(1900, 1, 6), 7), 0, 0, 1, 0, 2, 1, 3, 2, 4, 3, 5, 4, 6, 5, 0))))

The Start Date and End Date fields are custom in the above example and can be replaced as required. If use of a DateTime field is required then the DATEVALUE function will be required.

I also recommend a simple field validation rule is added to check that the End Date is after the Start Date.
Best Answer chosen by Admin (Salesforce Developers) 

This formula seems to work when calculating bt 2 different days. What about taking into account for same day and returns result shoud be a "0"? My result shows a "5" when I entered 9/10/09 and 9/10/09 for both start and end dates. Is there one formula that can include this possiblity?




Felix QuinonesFelix Quinones 

Hello All, 

I'm trying to create a formula field (Yearly Compliance) for a custom object named Compliance. The formula should add the compliance for the quarter (i.e. Q1_c__c), if not left blankand, and divide those by the number of complete fields. I'm trying to calculate the percent of compliance. The problem is that any of those four number fields could be left on black.

I tried the following formulas in where any of the Qs (i.e. Q1_c__c)  could be a number or could be left blank.

   (Q1_c__c =0, 
    Q1_c__c = 0, 
    Q1_c__c = 0, 
   Q1_c__c = 0
(Q1_c__c + Q2_c__c + Q3_c__c + Q4_c__c)/4)



NULL,(Q1_c__c + Q2_c__c + Q3_c__c + Q4_c__c)/4)

Here is a picture of the pay layout . 

  • If the quarter is left black, means that do not apply.
  • I'm trying to calculate the percent of Yearly Compliance. Here the Yearly Compliance should be 100% divided by 3. This is because the quarter empty (Q1) do not count for this year compliance. Also, the other two quarters are in 0%. 


Yearly compliance should be 33.33%
Best Answer chosen by Felix Quinones
Swati PawarSwati Pawar

Below mentioned formula might help you.  Make sure to check "Treat blank fields as blanks" option in your formula field.

Formula :
(Q1__c = 0 ||ISBLANK(Q1__c)) && (Q2__c = 0 || ISBLANK(Q2__c)) && (Q3__c = 0 || ISBLANK(Q3__c)) && (Q4__c = 0 || ISBLANK(Q4__c)) ,
0 ,
((IF(ISBLANK(Q1__c),0,Q1__c) +
IF(ISBLANK(Q2__c),0,Q2__c) +
IF(ISBLANK(Q3__c),0,Q3__c) +
IF(ISBLANK(Q4__c),0,Q4__c) ) )/ 
(IF(ISBLANK(Q1__c),0,1)+ IF(ISBLANK(Q2__c),0,1) +
IF(ISBLANK(Q3__c),0,1) + IF(ISBLANK(Q4__c),0,1))

User-added image

If it works for you then mark it as a best answer.

Thanks !!

I'm doing a REST API call to get the global value set and trying to deserialize the JSON result to get the picklist values in a List<String>.

Here is the JSON:

  "size": 1,
  "totalSize": 1,
  "done": true,
  "queryLocator": null,
  "entityTypeName": "GlobalValueSet",
  "records": [
      "attributes": {
        "type": "GlobalValueSet",
        "url": "/services/data/v53.0/tooling/sobjects/GlobalValueSet/0Nt59000000AAAAAAA"
      "Metadata": {
        "customValue": [
            "color": null,
            "default": false,
            "description": null,
            "isActive": null,
            "label": "USA",
            "urls": null,
            "valueName": "USA"
            "color": null,
            "default": false,
            "description": null,
            "isActive": null,
            "label": "Canada",
            "urls": null,
            "valueName": "Canada"
        "description": null,
        "masterLabel": "US States & Territories",
        "sorted": false,
        "urls": null
      "Id": "0Nt59000000AAAAAAA"
I need help in fixing the error and also how to get valueNames in a List<String>

Error: System.JSONException: Malformed JSON: Expected '{' at the beginning of an object.

Here is what I have tried so far:

    public class GlobalValueSetWrapper{
        Metadata metadata;

    public class Metadata {
        public List<CustomValue> customValue;
    public class CustomValue {
        public String label;  
        public String valueName;

//calling API to get the JSON result
HttpResponse res = GlobalValueSetAPIHandler.getResponse('Countries');
GlobalValueSetWrapper wrapper = (GlobalValueSetWrapper) JSON.deserialize(res.getBody(), GlobalValueSetWrapper.class);
Best Answer chosen by RJ12

I'm able to fix it.

public class GlobalValueSetWrapper{
    public List<Records> records;

    public class Records {
        public Metadata metadata;
    public class Metadata {
        public List<CustomValue> customValue;

    public class CustomValue {
        public String label;
        public String valueName;    

    public static List<String> getPicklistValues(HttpResponse response){
        List<String> picklistValues = new List<String>();
        GlobalValueSetWrapper wrapper = (GlobalValueSetWrapper) System.JSON.deserialize(response.getBody(), GlobalValueSetWrapper.class);
        for(GlobalValueSetWrapper.customValue value : wrapper.records[0].metadata.customValue){
        system.debug('Piclist Values: ' + picklistValues);
        return picklistValues;
Ross SutherlandRoss Sutherland 


Trying to create a row level formula that looks to see if any columns has a blank so I have something like, 

IF(ISBlank(fHCM2__Team_Member__c.fHCM2__Birth_Date__c),"Blank","Not Blank")   which is fine.

But I want to add OR so I want to include OR IF ,
fHCM2__Team_Member__c.fHCM2__Manager__c is blank
OR IF, FK_fHCM2__Employment__c.UDFEmployment_Detail__c is blank

FK_fHCM2__Employment__c.UDFEmployment_Detail__c   is a picklist field so not sure how to add that in also.

Any ideas?



Best Answer chosen by Ross Sutherland
IF(IOR( ISBlank(fHCM2__Team_Member__c.fHCM2__Birth_Date__c),
ISBlank(TEXT(FK_fHCM2__Employment__c.UDFEmployment_Detail__c)) ),"Blank","Not Blank")
Amrender sainiAmrender saini 
Howdy Salesforce developers
I'm getting this error often. I'm running my batches in queue.
Any one have any idea how can we prevent this error. This error occur when Single record try to update by 2 jobs at same time.

Update failed. First exception on row 0 with id a145000000C6g5HAAR; first error: UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record or 1 records: a145000000C6g5HAAR: []
Best Answer chosen by Amrender saini
Akhil AnilAkhil Anil
Hi Amrender,

When you have multiple jobs running that update the same set of records, it's recommended to lock the records using the FOR UPDATE keyword. It will ensure that the record is locked and no other job can update the same record at that point in time. The conflicting job will then wait untill the locking on the record is released and then perform the required operaiton. This will avoid conflicts between jobs that are running concurrently and will not throw up this exception. You can refer the below link to learn more about record locking.


kindly mark it as an answer if that resolves your query !
Steve Houghtalen 2Steve Houghtalen 2 
When I try to set my domain, I get this error message
It looks like your network doesn’t allow you to access these domains.

    • https://d1i000003gqvcuac.my.salesforce.com
    • https://d1i000003gqvcuac--c.documentforce.com

Best Answer chosen by Steve Houghtalen 2
Steve Houghtalen 2Steve Houghtalen 2
When I went to set my domain, the subsequent screen looks like the attached. It appears that my domain got set, not sure how, perhaps by Salesforce.The only choice was to "Keep Current  Domain"  which didn't  make any sense.  The error messages and recommended actions also didn't make any sense. I clicked on "Keep Current Domain" and the following screen allowed you to name my domain.  Not exactly user friendly.User-added image
Shaolin MasterShaolin Master 
I want to know how to parse the URL params from a get request
I want to parse the url params in the class below
    global static void getStatus() {
        RestRequest request = RestContext.request;

Please help!
Best Answer chosen by Shaolin Master
Maharajan CMaharajan C

You have to write like below to parse the request:
global static void getStatus() {
    RestRequest req = RestContext.request;
    String subject = req.params.get('subject');
    String status = req.params.get('status');
    String priority = req.params.get('priority');
    String origin = req.params.get('origin');
    system.debug('subject --> ' + subject  + ' status --> ' + status + 'priority --> ' + priority + 'origin --> ' + origin);


Inez TaylorInez Taylor 
There are many application are available in the internet for the conversion of lotus notes to outlook PST file format. There are two methods are available for the migration of NSF to PST, first method you can convert manually and second is use any third party software. Here I am discuss any third party application. There are many third party tools are available in the market todays but I would suggest you try to use NSF to PST  converter without pay any charges. So If you are interested to download NSF to PST Converter software from the google.

Best Answer chosen by Inez Taylor
john cena 11john cena 11
I would like to suggest GainTools NSF to PST converter tool to migrate Lotus Notes to Outlook. You can move all mailbox items like emails, task, notes, contacts etc. from Lotus notes NSF file to PST for MS Outlook.
YiQin HeYiQin He 

I created a lightning component as a quick action button. In the component, I have a cancel button that I want it closed when user clicks.
User-added image

But the problem is that I cannot find any document explain how to close the modal dialog. This is the ui code:
<aura:component controller="ContactController" implements="force:lightningQuickActionWithoutHeader,force:hasRecordId" >
        .changeRecordTypeRow {
        margin-top: 1.5rem;
        margin-bottom: 0;
        margin-left: 0;
        margin-right: 0;
        .changeRecordTypeLeftColumn {
        float: left;
        text-align: right;
        padding-right: 1.5rem;
        width: 35%;
        font-size: .8125rem;
        color: rgb(84, 105, 141);
        .changeRecordTypeRightColumn {
        float: right;
        text-align: left;
        width: 65%;
        	height:auto !important;
        .forceChatterLightningComponent .bodyWrapper{height:100%;width:100%;padding:0;box-sizing:border-box}
    <div class="modal-header slds-modal__header">
        <h2 class="title slds-text-heading--medium" >Change Contact Type</h2>
    <div class="scrollable slds-modal__content slds-p-around--medium">
        <div class="changeRecordTypeRow">
            <fieldset class="slds-form-element">
                <div class="changeRecordTypeLeftColumn">
                    <legend class="form-element__legend slds-form-element__label">Select a record type</legend>
                <div class="changeRecordTypeRightColumn slds-form-element__control">

                    <span class="slds-radio">
                        <input type="radio" id="radio_PrimaryContact" name="recordType" />
                        <label class="slds-radio__label" for="radio_PrimaryContact">
                            <span class="slds-radio--faux"></span>
                            <span class="slds-form-element__label">Primary Contact</span>
                    <span class="slds-radio">
                        <input type="radio" id="radio_SecondaryContact" name="recordType" />
                        <label class="slds-radio__label" for="radio_SecondaryContact">
                            <span class="slds-radio--faux"></span>
                            <span class="slds-form-element__label">Secondary Contact</span>
    <div class="modal-footer slds-modal__footer">
    	<div class="forceChangeRecordTypeFooter">
        	<button type="button" class="slds-button slds-button--neutral .slds-modal__close" aura:id="btnCancel" >
            <button type="button" class="slds-button slds-button--brand" aura:id="btnSave">
Does anyone have similar experience? Thanks in advance.
Best Answer chosen by YiQin He
YiQin HeYiQin He
Hi Karthik,

Thanks for the reply. I've already found the solution.
Call this method $A.get("e.force:closeQuickAction").fire() will close the modal dialog.