web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Service | Customer Service, Contact Center, Fie...
Suggested Answer

Issue with javascript retrieveMultipleRecords

(0) ShareShare
ReportReport
Posted on by 2,909

I am trying to retrieve all the workorder service tasks in the field service bookable resource booking form.

I have left code with various commented out lines that I tried simplify to identify where it was failing however it never seems to enter into the function call.

When I debug it just goes straight past the entire block and I don't have any idea why.

I tried to debug by running the code in the console and noticed that when it was debugging it had pending however once out of the script would return the rows as per below images

pastedimage1658641998492v2.png

pastedimage1658641934269v1.png

The current code I am using is from the CRM rest builder any ideas where my error lies?

function completecheck(executionContext) {

    var formContext = executionContext.getFormContext(); // get formContext
    var gridContext = formContext.getControl("FsWorkOrderServiceTasksGrid"); // returns null
    var wo = formContext.getAttribute('msdyn_workorder').getValue()[0].id; // returns GUID
    var tasks = 0;
    if (formContext.getAttribute("bookingstatus") != null && formContext.getAttribute("bookingstatus") != undefined) 
    {
        var status = formContext.getAttribute("bookingstatus").getValue()[0].name;
        if(status == "Completed")
        {
                // Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", "?$select=msdyn_percentcomplete,_msdyn_workorder_value&$filter=_msdyn_workorder_value eq 7ea364a4-6952-4008-bb4e-7291c34180f9 and  msdyn_percentcomplete ne 100").then(
                // Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", "?$select=msdyn_percentcomplete,_msdyn_workorder_value&$filter=_msdyn_workorder_value eq "   woguid   " and  msdyn_percentcomplete ne 100").then(
                Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", "?$select=msdyn_percentcomplete,_msdyn_workorder_value").then(    
                function success(results) {
                    for (var i = 0; i < results.entities.length; i  ) {
                        tasks = results.entities.length;
                        console.log(results.entities[i]["_msdyn_workorder_value"]);
                    }
                },
                function(error) {
                    Xrm.Utility.alertDialog(error.message);
                }
            );
           
            var faultcategory = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").getValue();
            var incidenttype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_primaryincidenttype").getValue()[0].name;
            var workordertype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_workordertype").getValue()[0].name;

            if (status == "Completed" && (incidenttype == "Breakdown" || incidenttype == "Trapped Passenger" || incidenttype == "Repairs") && faultcategory == null) {
                executionContext.getEventArgs().preventDefault(); // Stop the Save
                formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").setRequiredLevel("required")
            }
            else if (status == "Completed" && tasks > 0 && workordertype == "Maintenance")
            {
                executionContext.getEventArgs().preventDefault();
                formContext.ui.setFormNotification("All WO service tasks need to be complete", "ERROR", "DurationErrorMessageId");
            }
            else
            {
                formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").setRequiredLevel("none")
                formContext.ui.clearFormNotification("DurationErrorMessageId")
            }
        }
    }
}

I have the same question (0)
  • Suggested answer
    antc Profile Picture
    2,909 on at

    Forgot this is asynchronous so I will likely need to use await for the retrieve method.

  • Community Member Profile Picture
    on at

    Hi antc,

    Yes, that's correct. Or you can move your business code into your callback function like this:

    function completecheck(executionContext) {
    
        var formContext = executionContext.getFormContext(); // get formContext
        var gridContext = formContext.getControl("FsWorkOrderServiceTasksGrid"); // returns null
        var wo = formContext.getAttribute('msdyn_workorder').getValue()[0].id; // returns GUID
        var tasks = 0;
        if (formContext.getAttribute("bookingstatus") != null && formContext.getAttribute("bookingstatus") != undefined) 
        {
            var status = formContext.getAttribute("bookingstatus").getValue()[0].name;
            if(status == "Completed")
            {
                    // Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", "?$select=msdyn_percentcomplete,_msdyn_workorder_value&$filter=_msdyn_workorder_value eq 7ea364a4-6952-4008-bb4e-7291c34180f9 and  msdyn_percentcomplete ne 100").then(
                    // Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", "?$select=msdyn_percentcomplete,_msdyn_workorder_value&$filter=_msdyn_workorder_value eq "   woguid   " and  msdyn_percentcomplete ne 100").then(
                    Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", "?$select=msdyn_percentcomplete,_msdyn_workorder_value").then(    
                    function success(results) {
                        for (var i = 0; i < results.entities.length; i  ) {
                            tasks = results.entities.length;
                            console.log(results.entities[i]["_msdyn_workorder_value"]);
    						var faultcategory = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").getValue();
    						var incidenttype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_primaryincidenttype").getValue()[0].name;
    						var workordertype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_workordertype").getValue()[0].name;
    
    						if (status == "Completed" && (incidenttype == "Breakdown" || incidenttype == "Trapped Passenger" || incidenttype == "Repairs") && faultcategory == null) {
    							executionContext.getEventArgs().preventDefault(); // Stop the Save
    							formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").setRequiredLevel("required")
    						}
    						else if (status == "Completed" && tasks > 0 && workordertype == "Maintenance")
    						{
    							executionContext.getEventArgs().preventDefault();
    							formContext.ui.setFormNotification("All WO service tasks need to be complete", "ERROR", "DurationErrorMessageId");
    						}
    						else
    						{
    							formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").setRequiredLevel("none")
    							formContext.ui.clearFormNotification("DurationErrorMessageId")
    						}
                        }
                    },
                    function(error) {
                        Xrm.Utility.alertDialog(error.message);
                    }
                );
            }
        }
    }
    

  • antc Profile Picture
    2,909 on at

    I have this working both online and offline however when using save and close button it runs through some system scripts post my script and allows the booking/WO to be saved and closed. Just using the Save button works as expected and prevents save. When using save and close I do see the notification appear before it closes.

    Any thoughts?

    function completecheck(executionContext) {
    
        var formContext = executionContext.getFormContext(); // get formContext
        var gridContext = formContext.getControl("FsWorkOrderServiceTasksGrid"); // returns null
        var wo = formContext.getAttribute('msdyn_workorder').getValue()[0].id; // returns GUID
    
        let fetchXml = "?fetchXml=";
    
        var tasks = 0;
        if (formContext.getAttribute("bookingstatus") != null && formContext.getAttribute("bookingstatus") != undefined) 
        {
            var status = formContext.getAttribute("bookingstatus").getValue()[0].name;
            if(status == "Completed")
            {
                    
                    
                
                    async function ServiceCheck() {
                        var servicetasks = await getServiceTasks();
                        console.log("3");
                        tasks = servicetasks.entities.length;
                        console.log("2");
                        var faultcategory = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").getValue();
                        var incidenttype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_primaryincidenttype").getValue()[0].name;
                        var workordertype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_workordertype").getValue()[0].name;
    
                        if (status == "Completed" && (incidenttype == "Breakdown" || incidenttype == "Trapped Passenger" || incidenttype == "Repairs") && faultcategory == null) {
                            executionContext.getEventArgs().preventDefault(); // Stop the Save
                            formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").setRequiredLevel("required")
                            console.log("5");
                        }
                        else if (status == "Completed" && tasks > 0 && workordertype == "Maintenance")
                        {
                            executionContext.getEventArgs().preventDefault();
                            formContext.ui.setFormNotification("All WO service tasks need to be complete", "ERROR", "DurationErrorMessageId");
                        }
                        else
                        {
                            formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").setRequiredLevel("none")
                            formContext.ui.clearFormNotification("DurationErrorMessageId")
                        }
    
                    }
    
                    async function getServiceTasks() {
                        var results = await Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", fetchXml);
                        console.log("4");
                        return results;
                    }
                    console.log("1");
                     ServiceCheck();
                    
                
            }
                   
                
        }
    }

  • antc Profile Picture
    2,909 on at

    I don't completely understand why however I believe that the Save and Close button fails because of the async method and the close obviously gets processed prior to the .preventDefault().

    I'm aware of the Async Save Handler however I believe that it will just throw a script error rather than set the notification and prevent save / close.

    I have read some information on adding the preventDefault() prior to the retrieve call then if I want to allow save then implement the original request i.e. Save or Save&Close.

    Any thoughts?

  • Suggested answer
    antc Profile Picture
    2,909 on at

    The code below is working in online and offline mode.

    Also credit to Steve for pointing me in right direction and Andrew Butenko for the code in this post which I modified slightly.

    var BookingForm = (function () {
    
        var SaveMode = {
            Save: 1,
            SaveAndClose: 2,
            SaveAndNew: 59,
            Autosave: 70
        };
    
        //this is variable that shows if validation was successfully passed or not
        var isValidationNeeded = true;
        
        function OnSave(executionContext) {
            //so if there are several save handlers and one of previous already called preventDefault
            //there is no need to do any validations anymore
            if (executionContext.getEventArgs().isDefaultPrevented()) {
                return;
            }
    
            //getting save mode from event
            var saveMode = executionContext.getEventArgs().getSaveMode();
    
            //if savemode is not one of listed - just quit the execution and let the record to be saved
            if (saveMode !== SaveMode.Save &&
                saveMode !== SaveMode.SaveAndClose &&
                saveMode !== SaveMode.SaveAndNew &&
                saveMode !== SaveMode.Autosave) {
                return;
            }
    
            //so if validation was successfully passed - flag is reset
            //and code just leaves the form alone and allows changes to be saved
            if (!isValidationNeeded) {
                isValidationNeeded = true;
                return;
            }
    
            //getting of the form context from execution context object
            var formContext = executionContext.getFormContext();
    
            
            // Get WO Guid
            var wo = formContext.getAttribute('msdyn_workorder').getValue()[0].id; // returns GUID
    
            
            // Fetch will return any service tasks that are incomplete and related to WO. Using FetchXml allows us to use same querey in online and offline mode
            let fetchXml = "?fetchXml=";
    
    
        var tasks = 0;
        if (formContext.getAttribute("bookingstatus") != null && formContext.getAttribute("bookingstatus") != undefined) 
        {
            var status = formContext.getAttribute("bookingstatus").getValue()[0].name;
            if(status == "Completed")
            {
                var faultcategory = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").getValue();
                var incidenttype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_primaryincidenttype").getValue()[0].name;
                var workordertype = formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("msdyn_workordertype").getValue()[0].name;
    
                if (status == "Completed" && (incidenttype == "Breakdown" || incidenttype == "Trapped Passenger" || incidenttype == "Repairs") && faultcategory == null) {
                    // executionContext.getEventArgs().preventDefault(); // Stop the Save
                    formContext.ui.tabs.get(3).sections.get(0).controls.get(0).getAttribute("eye_faultcategory").setRequiredLevel("required");
                }
                //preventing of the save operation before async operation is started
                executionContext.getEventArgs().preventDefault();
                Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", fetchXml).then(    
                            function success(results) {
                                tasks = results.entities.length;
                                if(results.entities.length !== 0)
                                {
                                    console.log(`In retrieve call ${tasks}`);
                                    formContext.ui.setFormNotification("All WO service tasks need to be complete", "ERROR", "DurationErrorMessageId");
                                }
                                else
                                {
                                    //othervice validation flag is set to "Passed"
                                    isValidationNeeded = false;
                                    //and save event is called again and notification cleared
                                    formContext.ui.clearFormNotification("DurationErrorMessageId");
                                    if (saveMode === SaveMode.Save || saveMode === SaveMode.Autosave) {
                                        formContext.data.entity.save();
                                    } else if (saveMode === SaveMode.SaveAndClose) {
                                        formContext.data.entity.save("saveandclose");
                                    } else {
                                        formContext.data.entity.save("saveandnew");
                                    }
                                }
                            },
                            function (error) {
                                //if something went wrong - error message is shown to user
                                Xrm.Navigation.openAlertDialog({ text: error.message });
                            }
                         );
               } else {
                    // Booking status not complete so clear notifications and allow save
                    formContext.ui.clearFormNotification("DurationErrorMessageId");
                    return;
               }
                    }
                 }
                
                return {
                    OnSave: OnSave
                };
            } // BookingForm Function
        ) // BookingForm
    ();

  • antc Profile Picture
    2,909 on at

    Also submitted in general forum.

    I spoke to soon all works except when I try to Save a Booking with Incident Type Breakdown and Fault Category is not null, it just gets an infinite loop.

    In the debugger it runs through hits this:

    isValidationNeeded = false;

    It then re-enters the OnSave function and exits when it hits

    if (!isValidationNeeded) {

               isValidationNeeded = true;

               return;

           }

    It is then when it just seems to loop through this section.

    I expected that as executionContext.getEventArgs().preventDefault(); is further down it should just exit and Save.

    When it is the service Tasks and WO is not Incident Type Breakdown it works perfectly and gracefully exits.

    Could the new Async Save setting be effecting this?

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > Service | Customer Service, Contact Center, Field Service, Guides

#1
Tom_Gioielli Profile Picture

Tom_Gioielli 53 Super User 2025 Season 2

#2
Daniyal Khaleel Profile Picture

Daniyal Khaleel 27 Most Valuable Professional

#3
Soundari Profile Picture

Soundari 15

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans