Custom
workflow creation in Dynamics 365 for finance and operations
Here
example, Creating custom workflow for custom document
Steps:
Workflow creation for existing document in application without Overlaying on canSubmitToWorkflow method
Suggested workaround solution: (This can be achieve without overlay)
1. Create new table with unique field from custTable and WorkflowStatus Field alone.
2. Add newly created table in to form dataSource and link with primary custTable dataSource in FORM: CustTable using extension.
Note: Using outer join for join Type, Inner join type works only when there is no record in primary table.
3. Override canSubmitToWorkflow method in newly table created above.
4. Create new method for FormDataSourceEvent : OnWritten for Primary dataSource (custTable) and create new values for newly created table when record created in primary table.
5. UpdateWorfklowStatus method should update status both child Table (New table) and CustTable
6. Write method on Datasource On-initialized event method of New table datasource in existing form
Steps:
- Create
new BASE ENUM (Named: Dev_WorkflowStatus)
- Create
Extension class for Table (“CustTable”)
- Add
newly created ENUM in to Table (“CustTable”)
- Add
new method on CustTable
Note: CanSubmitToWorkflow here added as overlay method.
It is not advisable from Microsoft.
Currently canSubmitToWorkflow method through extension is not working as expected in PU12
Note:
-> PU22 (December 2018) - MS Enabled Chain of Command to target method overrides that have not been implemented to tables (now we can use it for canSubmitToWorkflow method).
o
CanSubmitToWorkflow
Code:
public boolean
canSubmitToWorkflow(str _workflowType = '')
{
boolean ret = false;
ret
= this.DEV_WorkflowStatus ==
DEV_WorkflowStatus::Draft;
return ret;
}
o
UpdateWorkflowStatus
Code:
public static void
updateWorkflowStatus(RecId _documentRecId, DEV_WorkflowStatus
_status)
{
CustTable record;
ttsbegin;
update_recordset
record setting DEV_WorkflowStatus = _status
where record.RecId == _documentRecId;
ttscommit;
}
- ·
Create
new query for workflow with data source as CustTable (Named:
Dev_CustTableWf_Query)
- ·
Create
new workflow category and mention name & label property
- ·
Create
new workflowType and mention property of DocumentMenuItem, Query,
WorklfowCategory, then system create all default objects for workflow type
- ·
Add
pre-requisite method in Submit Manager class
Code:
/// <summary>
/// The Dev_Customer_WfTypeSubmitManager menu item action event handler.
/// </summary>
public class Dev_Customer_WfTypeSubmitManager
{
public static void main(Args _args)
{
// Executes when a work item is submitted.
RecId recId = _args.record().RecId;
WorkflowSubmitDialog workflowSubmitDialog;
// Opens the submit to workflow dialog.
workflowSubmitDialog = WorkflowSubmitDialog::construct(_args.caller().getActiveWorkflowConfiguration());
workflowSubmitDialog.run();
if (workflowSubmitDialog.parmIsClosedOK())
{
try
{
ttsbegin;
// Activate the workflow.
Workflow::activateFromWorkflowType(workFlowTypeStr(<WorkflowType>), recId, workflowSubmitDialog.parmWorkflowComment(), NoYes::No);
//TODO write logic for ur Workflow document table status field update
ttscommit;
}
catch(exception::Error)
{
info('Workflow activation failed');
}
// Refresh the caller form.
FormDataSource callerDS = FormDataUtil::getFormDataSource(_args.record());
callerDS.reread();
callerDS.refresh();
_args.caller().updateWorkflowControls();
}
}
}
- Add
pre-requisite method in ReSubmit Manager class
/// The Dev_Customer_WfTypeReSubmitManager menu item action event handler.
public class Dev_Customer_WfTypeReSubmitManager
{
public static void main(Args _args)
{
// Executes when a work item is resubmitted.
RecID recID = _args.record().RecId;
WorkflowWorkItemTable workItem = _args.caller().getActiveWorkflowWorkItem();
if (workItem)
{
try
{
// Opens the resubmit to workflow dialog.
WorkflowWorkItemActionDialog dialog = WorkflowWorkItemActionDialog::construct(
workItem,
WorkflowWorkItemActionType::Resubmit,
new MenuFunction(_args.menuItemName(),_args.menuItemType()));
dialog.run();
if (dialog.parmIsClosedOK())
{
ttsbegin;
workItem = _args.caller().getActiveWorkflowWorkItem();
WorkflowWorkItemActionManager::dispatchWorkItemAction(
workItem,
dialog.parmWorkflowComment(),
dialog.parmTargetUser(),
WorkflowWorkItemActionType::Resubmit,
_args.menuItemName());
//TODO write logic for ur workflow document class status update logic
ttscommit;
}
}
catch(exception::Error)
{
info('Workflow resubmission failed');
}
}
// Refresh the caller form.
FormDataSource callerDS = FormDataUtil::getFormDataSource(_args.record());
callerDS.reread();
callerDS.refresh();
_args.caller().updateWorkflowControls();
}
}
- ·
Go
to event handler created from workflow Type and follow below code
public class
Dev_Customer_WfTypeEventHandler implements
WorkflowCanceledEventHandler,
WorkflowCompletedEventHandler, WorkflowStartedEventHandler
{
public void
started(WorkflowEventArgs _workflowEventArgs)
{
RecId documentRecId =
_workflowEventArgs.parmWorkflowContext().parmRecId();
CustTable::updateWorkflowStatus(documentRecId,
DEV_WorkflowStatus::Submitted);
}
public void
canceled(WorkflowEventArgs _workflowEventArgs)
{
RecId documentRecId =
_workflowEventArgs.parmWorkflowContext().parmRecId();
CustTable::updateWorkflowStatus(documentRecId,
DEV_WorkflowStatus::Rejected);
}
public void
completed(WorkflowEventArgs _workflowEventArgs)
{
RecId documentRecId =
_workflowEventArgs.parmWorkflowContext().parmRecId();
CustTable::updateWorkflowStatus(documentRecId,
DEV_WorkflowStatus::Approved);
}
}
- ·
Create
new workflow approval
- ·
Add
logic on workflow approval event handler class
For demo purpose, we have added code only for cancelled, completed,
Change Request Methods
Code:
/// <summary>
/// The Dev_Customer_WfAppEventHandler workflow outcome event handler.
/// </summary>
public final class Dev_Customer_WfAppEventHandler implements
WorkflowElementCanceledEventHandler,
WorkflowElemChangeRequestedEventHandler,
WorkflowElementCompletedEventHandler,
WorkflowElementReturnedEventHandler,
WorkflowElementStartedEventHandler,
WorkflowElementDeniedEventHandler,
WorkflowWorkItemsCreatedEventHandler
{
public void
canceled(WorkflowElementEventArgs _workflowElementEventArgs)
{
RecId documentRecId =
_workflowElementEventArgs.parmWorkflowContext().parmRecId();
CustTable::updateWorkflowStatus(documentRecId,
DEV_WorkflowStatus::Rejected);
}
public void
completed(WorkflowElementEventArgs _workflowElementEventArgs)
{
RecId documentRecId =
_workflowElementEventArgs.parmWorkflowContext().parmRecId();
CustTable::updateWorkflowStatus(documentRecId,
DEV_WorkflowStatus::Approved);
}
public void
denied(WorkflowElementEventArgs _workflowElementEventArgs)
{
//
TODO: Write code to execute once the
workflow is denied.
}
public void
changeRequested(WorkflowElementEventArgs _workflowElementEventArgs)
{
RecId
documentRecId = _workflowElementEventArgs.parmWorkflowContext().parmRecId();
CustTable::updateWorkflowStatus(documentRecId,
DEV_WorkflowStatus::RequestChange);
}
}
- ·
Add
newly created workflow approvals to Workflow type created for this custom
document workflow
Note: Like this we can add automated Task
and mapping line item workflow as per your requirement.
·
Assign
workflowType, workflowEnable and WorkflowDatasource on Document FORM
Note:
If properties enabled in FORM means,
Assign there itself
Default Application Suite is Hard locked, no more overlay and currently
system is not allowing to edit form design property in Form:CustTable through
extensibility also.
Or else written code on Form Document
datasource OnInitialized
Method as follow
class Dev_Customer_Wf_EventHandler
{
/// <summary>
/// </summary>
/// <param
name="sender"></param>
/// <param
name="e"></param>
[FormDataSourceEventHandler(formDataSourceStr(CustTable, CustTable),
FormDataSourceEventType::Initialized)]
public static void
CustTable_OnInitialized(FormDataSource sender, FormDataSourceEventArgs e)
{
sender.formRun().design().workflowDatasource("CustTable");
sender.formRun().design().workflowEnabled(true);
sender.formRun().design().workflowType("Dev_Customer_WfType");
}
}
- ·
Navigate
to document, Verify new workflow for customer document.
- ·
Added
new field in to document form
- ·
Project
Elements (New Workflow)
- Navigate
to workflow configuration on Module/Setup/Workflows and create new by selecting
new workflow type
- Create
new customer to verify workflow
- Rebuild solution