Friday 8 March 2019

D365 - Revise Quote using Workflow - ReviseQuoteRequest

As a result of constant feature rich updates from MS Team, we were able to call actions from workflows which personally if one of my favorites. I am exploring lot of options around the same, one such is revising the Quote via Workflow.

Why should I need this as I already have a ribbon button to achieve this?

Many businesses have their own business specific quote processflow which might not be in sync OOB quote process flow. In such situation we might need this revise option to minimize the coding effort and leverage OOB revision process. 


Lets not wait anymore, diving into the configuration

1. Create a workflow against quote(Set Scope and sync/async)
2. Hit "Add Step" => "Change Status". Set the status to Closed(Lost/Won/Cancelled) as only closed quotes can be revised using "ReviseQuoteRequest". In this case I am setting it to Closed(Cancelled).

3. Hit "Add Step" => "Perform Action". Select "Revise" against Action optionset and "Quote" should be auto selected against Entity optionset.

4. Hit "Set Properties" => select current quote as dynamic value against QuoteId

Happy Learning!


Thursday 7 March 2019

D365 CE - JS Deprecated Methods cheatsheet - Xrm.Page deprecated and replaced by formContext



Its important for every dynamics developer to understand the deprecated functionalities so that we can stay away from them in our current implementations. This would save lot of time and money when it comes to upgrade and rework when the functionalities are obsolete.

JavaScript is a key piece in  Dynamics UI tuning and with D365 there are a wave of updates when it comes to JS and its hard to remember all the deprecated methods/objects so Microsoft has provided a cheat sheet for deprecated methods. I have copy pasted the same below, please make use of it.


Deprecated Client API
Replacement Client API
Comments
Forms: ExecutionContext.getFormContext 
Commands: Send it as the PrimaryControl parameter
Use of the Xrm.Page object as a static access to the primary form context is still supported to maintain backward compatibility with the existing scripts. Based on the feedback, we understand that the usage of Xrm.Page is high, and it won’t be removed as soon as some other client API methods listed in this section. We encourage you to use the new way of getting form content where possible. More information: Client API form context
Although Xrm.Page is deprecated, parent.Xrm.Page will continue to work in case of HTML web resources embedded in forms as this is the only way to access the form context from the HTML web resource.
Xrm.Utility.getGlobalContext
Allows access to the global context without going through the form context.
formContext.data.attributes
The formContext.data.attributes API will make retrieval of non-entity bound data consistent across entity forms, metadata-driven dialogs, and task-based flows. The data will be a combination of custom values sent using the query string and what was specified in the parameters in the openForm method.
globalContext.userSettings.getTimeZoneOffsetMinutes
Moved to globalContext.userSettings
globalContext.userSettings.userId
Moved to globalContext.userSettings
globalContext.userSetings.languageId
Moved to globalContext.userSettings
globalContext.userSettings.userName
Moved to globalContext.userSettings
globalContext.userSettings.securityRoles
Moved to globalContext.userSettings
globalContext.organizationSettings.isAutoSaveEnabled
Moved to globalContext.organizationSettings
globalContext.organizationSettings.languageId
Moved to globalContext.organizationSettings
globalContext.organizationSettings.uniqueName
Moved to globalContext.organizationSettings
No change in the method, but use "typename" instead of type for lookup attributes.

GridRow.data
GridRow is essentially a form context. This change unifies the interface of GridRow with formContext.
GridRowData.entity
GridRowData is form data. This change unifies the interface of GridRowData with formContextData.
Xrm.Mobile.offline
Moved the offline-related methods under Xrm.WebApi.offline

Earlier: An HTML web resource may interact with the Xrm.Page or Xrm.Utility objects within the form by using parent.Xrm.Page or parent.Xrm.Utility. 
Now: parent.Xrm.* will work if the HTML web resource is loaded in a form container. It won't work for HTML web resources that are stand alone, or referenced from the site map or any other places.
addOnKeyPress
Use a custom control

removeOnKeyPress
Use a custom control

showAutoComplete
Use a custom control and corresponding UI

hideAutoComplete
Use a custom control and corresponding UI

Xrm.Navigation.openAlertDialog
The new signature is consistent with other APIs (openForm) and takes a new set of parameters for flexibility.
Xrm.Navigation.openConfirmDialog
The new signature is consistent with other APIs (openForm) and takes a new set of parameters for flexibility.
Xrm.Utility.getEntityMetadata
The isActivityType method is synchronous so it was suitable for ribbon rules. However, the replacement method, getEntityMetadata, is asynchronous, and is not suitable for ribbon rules.
Xrm.Navigation.openForm
Moving navigation actions to Xrm.Navigation
Xrm.Navigation.openForm
Moving navigation actions to Xrm.Navigation
Xrm.Navigation.openWebResource
Moving navigation actions to Xrm.Navigation 
Note: This API returns VOID in Unified Interface.


Sunday 3 March 2019

D365 CE - Quote Revise Approach and Error Troubleshooting - The quote cannot be revised because it is not in closed state.

I have recently faced an error while revising an active quote using ReviseQuoteRequest action via plugin/workflow. Below is the error message

"The quote cannot be revised because it is not in closed state. If you contact support, please provide the technical details."

Root Cause
Its due to the state of Quote. Only the quotes in closed state can be revised, if we are trying to revise a quote in a different state, then its going to error out with above message.

Fix/Approach
  1. First change the Quote status to Closed(Won/Lost/Cancelled). 
  2. Then execute the ReviseQuoteAction which would result in new revised Quote as expected
You can read how to implement the above revise quote with a workflow here.