Hello everyone,
I have the below code that has different rules to prevent saving the WO if the user did not completed all his tasks:
var isValidationNeeded = true; var preventEventSave = true; var SaveMode = { Save: 1, SaveAndClose: 2, SaveAndNew: 59, Autosave: 70 }; function preventSave(executionContext) { debugger; //getting save mode from event var saveMode = executionContext.getEventArgs().getSaveMode(); var formContext = executionContext.getFormContext(); var formType = formContext.ui.getFormType(); console.log(formType); if(formType != 1){ //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; } if (!isValidationNeeded) { isValidationNeeded = true; return; } var ruleThree = false; rule3(executionContext).then(function(data) { ruleThree = data; if (!ruleThree) { if (saveMode === SaveMode.Save || saveMode === SaveMode.SaveAndClose) { Xrm.Navigation.openAlertDialog({ text: "Current work order can't be closed because the incident type is visit and contains products!" }); return; } } else { var boolRule1 = false; var formContext = executionContext.getFormContext(); var status = formContext.getAttribute("msdyn_systemstatus").getValue(); // getting the status the value console.log(status); // Completed Status // status is not close posted if (status === 690970004 || status === 690970003) { var ruleOne = false; var ruleTwo = false; if (status === 690970004) { rule1(executionContext).then(function(data) { ruleOne = data; if (!ruleOne) { if (saveMode === SaveMode.Save || saveMode === SaveAndClose) { Xrm.Navigation.openAlertDialog({ text: "Current work order can't be saved because it's linked to canceled agreement!" }); return; } } else { isValidationNeeded = false; formContext.data.save().then(function() { }, function(error) { var errorMessage = error.message; console.log(errorMessage); }); } }, function(errorMessage) { Xrm.Navigation.openAlertDialog({ text: errorMessage }); }); } if (status === 690970003) { rule2(executionContext).then(function(data) { ruleTwo = data; if (!ruleTwo) { Xrm.Navigation.openAlertDialog({ text: "Current work order can't be closed because not all the service tasks are done!" }); return; } else { isValidationNeeded = false; formContext.data.save().then(function() { }, function(error) { var errorMessage = error.message; console.log(errorMessage); }); } }, function(errorMessage) { Xrm.Navigation.openAlertDialog({ text: errorMessage }); }); } } else { isValidationNeeded = false; console.log(preventEventSave); if (preventEventSave) { formContext.data.save().then(function() { }, function(error) { var errorMessage = error.message; console.log(errorMessage); }) } } } }, function(errorMessage) { Xrm.Navigation.openAlertDialog({ text: errorMessage }); }); } } // if rule1 is passed then check rule3 function rule1(executionContext) { // 1. Prevent the user to close posted the work order if the linked agreement is canceled. var formContext = executionContext.getFormContext(); var agreement = formContext.getAttribute("msdyn_agreement").getValue(); executionContext.getEventArgs().preventDefault(); var promiseRule1 = new Promise(function(resolve, reject) { var boolRule1 = true; if (agreement != null && agreement.length > 0) { var id = agreement[0].id; var result = Xrm.WebApi.retrieveRecord("msdyn_agreement", id, "?$select=msdyn_systemstatus").then( function success(result) { if (result["msdyn_systemstatus"] === 690970003) { //Xrm.Navigation.openAlertDialog({text:"Current work order can't be saved because of Cancelled agreement"}); boolRule1 = false; } resolve(boolRule1); }, function(error) { //Xrm.Navigation.openAlertDialog({ text: error.message }); reject(error.message); } ); } else { resolve(boolRule1); } }) return promiseRule1; } function rule2(executionContext) { //2.Prevent the user from completing the work order if not all the service tasks are done. executionContext.getEventArgs().preventDefault(); var promiseRule2 = new Promise(function(resolve, reject) { var boolRule2 = true; var serviceTaskValidation = true; var formContext = executionContext.getFormContext(); //get current WO id var workOrderId = formContext.data.entity.getId().replace("{", "").replace("}", ""); //var valInc = formContext.getAttribute("msdyn_primaryincidenttype").getValue(); var woStatus = formContext.getAttribute("msdyn_systemstatus").getValue(); var woType = formContext.getAttribute("msdyn_workordertype").getValue(); //close the WO or not //console.log(valInc); if (woType != null && woType.length > 0) { var woTypeName = woType[0].name; } if (woStatus != null && woStatus === 690970003 && woTypeName === "Installation" ) { // If the System status is equal to Completed //get active related service task Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderservicetask", "?$select=msdyn_name,msdyn_percentcomplete,statecode,haceb_responsevalueyesno&$filter=statecode eq 0 and msdyn_workorder/msdyn_workorderid eq " workOrderId).then( function success(result) { for (var i = 0; i < result.entities.length; i ) { console.log(result.entities[i].msdyn_name); console.log(result.entities[i].msdyn_percentcomplete); console.log(result.entities[i].haceb_responsevalueyesno); if (result.entities[i].haceb_responsevalueyesno == false) { serviceTaskValidation = false; break; } } if (!serviceTaskValidation) { boolRule2 = false; } resolve(boolRule2); }, function(error) { reject(error.message); } ) } }); return promiseRule2; } function rule3(executionContext) { // Prevent Closing WO if primary incident is visit and WO contains products var promiseRule3 = new Promise(function(resolve, reject) { var boolRule3 = true; var woProdValidation = true; var formContext = executionContext.getFormContext(); var woID = formContext.data.entity.getId().replace("{", "").replace("}", ""); var valInc = formContext.getAttribute("msdyn_primaryincidenttype").getValue(); if (valInc != null && valInc.length > 0) { var name = valInc[0].name; if (name == "Visit") { executionContext.getEventArgs().preventDefault(); Xrm.WebApi.retrieveMultipleRecords("msdyn_workorderproduct", "?$select=msdyn_name&$filter=msdyn_workorder/msdyn_workorderid eq " woID " and statecode eq 0").then( function success(result) { console.log(result); // perform operations on on retrieved records if (result.entities != null && result.entities.length > 0) { woProdValidation = false; } else { } if (!woProdValidation) { boolRule3 = false; } resolve(boolRule3); }, function(error) { reject(error.message); // handle error conditions } ) } else { preventEventSave = false; resolve(boolRule3); } } else { preventEventSave = false; resolve(boolRule3); } }); return promiseRule3; }
The issue is only with function Rule2 (Line 167) in the above code which is about (Prevent saving the WO if the Work order type is equal to "Installation" and Wo Status equal to "Completed" and if any of the service task in the same WO is/are not completed using a custom field eq false)
While testing & debugging rule2 for a WO that don't match the above condition the form is saving due to the promise is always returning status "Pending" after the API call and the Web API call is not returning any data.
I tested the api call in a new tab by using the below query same as the code and it is working fine:
The expected result for Rule2 and for the scenario I tested is to throw the below error message and avoid saving the form:
The other rules are working perfectly with no issue. It is really strange why Rule2 is not working.
What I am doing wrong? Can please someone check the code and provide the new updated version?
Kindly note that supported me previously on the same topic but I made a change only for rule2 by adding a condition to check for WOType is eq to installation.
community.dynamics.com/.../plugin---work-order-onupdate-validation
Any help is highly appreciated.
Thank you!