Custom
workflow creation in Dynamics 365 for finance and operations
Here
example, Creating custom workflow for custom document
Steps:
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:
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
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();
}
}
{
// 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
Code:
/// <summary>
/// The Dev_Customer_WfTypeReSubmitManager menu item action event handler.
/// </summary>
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();
{
// 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');
}
}
{
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();
}
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
No comments:
Post a Comment