The sub-status on the RTV form is changing when the form is loaded.

As an example, for the status 'Shipped' there is only one substatus (Shipped).

This is not set as the default status, and when the RTV form is loaded, the substatus field is cleared. This is happening to every status that does not have a default substatus.

If you set a default status, it actually gets worse (imo). Say I have a substatusA as the default, but the current substatus is set as substatusB, the default onload function will then set the substatus to the default substatusA.

As it probably should be handled:

  • if a substatus is set ( msdyn_substatus != null ), leave it alone during form load
  • if msdyn_substatus == null AND there is a default substatus defined for the current msdyn_status, set msdyn_substatus to the default value.

It appears this used to be an issue with RMAs as well, as documented here: RMA sub-status is reset every time I open an RMA

As a solution, I could follow the approach in the above link, but figure that could probably cause some headaches down the road as updates are published by Microsoft.

Since I already had my own onLoad function, I am trying to override the default behavior there.

I read the msdyn_substatus at the start of the function (it is still the original value before the load) and store it in a hidden field new_substatus. 

Then execute the existing code (reading the related RTV products asynchronously).

In the return function, data from the RTV products is added up and written to the RTV form.

After that, the msdyn_substatus is set to the new_substatus saved at the start of the procedure.

function onLoad(executionContext) {
    console.log("RTV: onLoad");

    let formContext = executionContext.getFormContext();

    let wedyn_substatus = formContext.getAttribute("msdyn_substatus").getValue();
    if (wedyn_substatus != null) {
        formContext.getAttribute("new_substatus").setValue(wedyn_substatus);
    }

    // get GUID of the current record
    let fRTVNum = formContext.data.entity.getId();

    // don't process if this is a new record
    if (fRTVNum != null) {
        // strip the curly brackets
        fRTVNum = fRTVNum.replace(/\{|\}/g, "");

        let recOptions = "?$select=wedyn_freightcharge&$filter=_msdyn_rtv_value eq " + fRTVNum;

        Xrm.WebApi.retrieveMultipleRecords("msdyn_rtvproduct", recOptions).then(
            RTVProdResponse,
            RTVProdError
        );
    }

    function RTVProdResponse(result) {
        console.log("In RTV Product Response");

        let totalFreight = 0;
        for (var i = 0; i < result.entities.length; i++) {
            totalFreight = totalFreight + result.entities[i].wedyn_freightcharge;
        }
        formContext.getAttribute("wedyn_freightcharge").setValue(totalFreight);

        let new_substatus = formContext.getAttribute("new_substatus").getValue();
        if (new_substatus != null) {
            formContext.getAttribute("msdyn_substatus").setValue(new_substatus);
        }
    }

    function RTVProdError() {
        console.log("In RTV Product Error");

        let new_substatus = formContext.getAttribute("new_substatus").getValue();
        if (new_substatus != null) {
            formContext.getAttribute("msdyn_substatus").setValue(new_substatus);
        }
    }
}

This appears to work, but I am afraid I'm just getting lucky with the timing.

What would be the better options to resolve this issue?

I posted an idea with the way I think the sub-status should be handled here:

RTV status and substatus handling

Please upvote or feel free to post your ideas for proper handling of the substatus.

Best Regards!