Custom workflow development in the Dynamics 365 Finance and Operations using x++ code

Custom workflow development in the Dynamics 365 Finance and Operations using x++ code

Hi Reader, In this article, we will learn how to create a custom workflow and configure it in the dynamics 365 F&O apps to automate the process.

What is workflow?

A?workflow?in the dynamics 365 apps is a way that automate business processes without a user interaction. People usually use workflow processes to commence automation that doesn’t require any user involvement.

Let start learning by doing its practical.

  1. Create a project with name "customWorkflow"

No alt text provided for this image

Add a new base enum with name “CustomWorkflowBaseEnum

No alt text provided for this image

Add the elements in the newly created enum by right click on the enum and select “Add Element”.

No alt text provided for this image

Add elements as shown in below figure and make sure submit element must be on top because when you are trying to create a record in the form. By default, first value will be selected on the flow.

No alt text provided for this image

Create a custom table with name “CustomWorkflowTable” and add three fields (Id, name, CustomWorkflowBaseEnum) in the table.

No alt text provided for this image

Add a field group in this table by right click on the field groups and click “New Group”.

No alt text provided for this image

Change the name the field group as “CustomWorkflowFieldGroup” and drag the fields in the field group according to your requirement. For learning perspective, I am drag and drop all the fields in the group.

No alt text provided for this image

Override CanSubmitToWorkflow method of this table

No alt text provided for this image

Add a new method with name "UpdateWorkflowStatus" in this table.

No alt text provided for this image

Write the below code in the above created methods.

public boolean canSubmitToWorkflow(str _workflowType = ''

??? {

??????? boolean ret;

???

??????? ret = super(_workflowType);

?

??????? if(this.CustomWorkflowBaseEnum != CustomWorkflowBaseEnum::Approved)

??????? {

?????????? ret = true;

??????? }

??????? else

??????? {

??????????? ret = false;

??????? }

???

??????? return ret;

??? }

?

??? public static void? updateWorkflowStatus(RefRecId recId , CustomWorkflowBaseEnum status)

??? {

??????? CustomWorkflowTable customWorkflowTable;

?

??????? ttsbegin;

?

??????? select forupdate customWorkflowTable

??????????? where customWorkflowTable.RecId == recId;

?

??????? customWorkflowTable.CustomWorkflowBaseEnum = status;

?

??????? customWorkflowTable.update();

?

??????? ttscommit;

?

??? })        

Add a custom form with name “CustomWorkflowForm

No alt text provided for this image

Add our custom table “CustomWorkflowTable” in the datasource of the form.

Set the form design pattern as "Custom".

Add the action pane and a grid and drag and drop the datasource fields in the grid.

Set allowEdit property of enum control in the grid to No.

No alt text provided for this image

Create a display menu item “CustomWorkflowMenu”.

No alt text provided for this image

Enter the created form name in the object property and set the label of the menu item.

No alt text provided for this image

Now create an extension of Accounts Receivable module in the project

No alt text provided for this image

Drag the menu item in the “InquiriesAndReport” section.

No alt text provided for this image

Create a new query with the name “CustomWorkflowQuery

No alt text provided for this image

Add our table "CustomWorkflowTable" in the datasource of the query and set the dynamics field property to No.

No alt text provided for this image

Build the project with database synchronization.

Add work flow category “CustomWorkflowCategory

No alt text provided for this image

Set module property to “SalesOrder” and also set the label.

No alt text provided for this image

Add a workflow type “CustomWorkflowType

No alt text provided for this image

A new window will appear. ?Enter category name, query name, display menu item name.

No alt text provided for this image

Below classes and action menu items will automatically be created.

No alt text provided for this image
No alt text provided for this image

Change the label of workflow type submit action menu item.

No alt text provided for this image

Change the label of workflow type cancel action menu item

No alt text provided for this image

Add the below code in submit manager class.

/// <summary

/// The CustomWorkflowTypeSubmitManager menu item action event handler.

/// </summary>

public class CustomWorkflowTypeSubmitManager

{

??? public static void main(Args args)

?????? {

???????????? //? TODO:? Write code to execute once a work item is submitted.

?

??????? CustomWorkflowTable???? customWorkflowTable;

??????? WorkflowComment???????? note = "";

??????? WorkflowSubmitDialog??? workflowSubmitDialog;

??????? WorkflowCorrelationId?? workflowCorrelationId;

??????? WorkflowTypeName??????? workflowTypeName = workFlowTypeStr("CustomWorkflowType");

?

?

?

??????? //Opens the submit to workflow dialog.

?

workflowSubmitDialog =??? WorkflowSubmitDialog::construct(args.caller().getActiveWorkflowConfiguration());

?

??????? workflowSubmitDialog.run();

?

??????? if (workflowSubmitDialog.parmIsClosedOK())

??????? {

?

??????????? customWorkflowTable = args.record();

?

??????????? // Get comments from the submit to workflow dialog.

?

??????????? note = workflowSubmitDialog.parmWorkflowComment();

?

??????????? try

??????????? {

?

??????????????? ttsbegin;

?

workflowCorrelationId = Workflow::activateFromWorkflowType(workflowTypeName, customWorkflowTable.RecId, note, NoYes::No);

?

??????????????? customWorkflowTable.CustomWorkflowBaseEnum = CustomWorkflowBaseEnum::Submitted;

?

??????????????? customWorkflowTable.update();

?

??????????????? ttscommit;

?

??????????????? // Send an Infolog message.

?

??????????????? info("Submitted to workflow.");

??????????? }

?

??????????? catch (Exception::Error)

??????????? {

?

??????????????? error("Error on workflow activation.");

??????????? }

??????? }

?

??????? args.caller().updateWorkFlowControls();

?

?????? }

?

}>        

Add the below code in workflow type event handler class

/// The CustomWorkflowTypeEventHandler workflow event handler

/// </summary>

public class? CustomWorkflowTypeEventHandler implements WorkflowCanceledEventHandler,?

WorkflowCompletedEventHandler,

WorkflowStartedEventHandler

{

??? ?? public void started(WorkflowEventArgs _workflowEventArgs)

?????? {

???????????? // TODO:? Write code to execute once the workflow is started.

??????? CustomWorkflowTable::updateWorkflowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(),CustomWorkflowBaseEnum::Submitted);

?????? }

?

??? ?? public void canceled(WorkflowEventArgs _workflowEventArgs)

?????? {

???????????? // TODO:? Write code to execute once the workflow is canceled.

??????? CustomWorkflowTable::updateWorkflowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(),CustomWorkflowBaseEnum::Rejected);

?????? }

?

??? ?? public void completed(WorkflowEventArgs _workflowEventArgs)

?????? {

???????????? // TODO:? Write code to execute once the workflow is completed.

CustomWorkflowTable::updateWorkflowStatus(_workflowEventArgs.parmWorkflowContext().parmRecId(), CustomWorkflowBaseEnum::Approved);

?????? }

?

}        

Change the Workflow Enable property to Yes and add workflow type name on the form design property.

No alt text provided for this image

Build the project with database synchronization.

Now add the workflow approval “CustomWorkflowApproval

No alt text provided for this image

A window will appear.

  1. Select workflow document (It’s the class which was created automatically it returns the query).
  2. Enter field group of the custom table.
  3. Enter display menu item name.

No alt text provided for this image

Some classes and action menus created automatically.

No alt text provided for this image
No alt text provided for this image

Add the below code in workflow approval event handler class.

/// <summary

/// The CustomWorkflowApprovalEventHandler workflow outcome event handler.

/// </summary>

public final class CustomWorkflowApprovalEventHandler implements WorkflowElementCanceledEventHandler,

WorkflowElemChangeRequestedEventHandler,

WorkflowElementCompletedEventHandler,

WorkflowElementReturnedEventHandler,

WorkflowElementStartedEventHandler,

WorkflowElementDeniedEventHandler,

WorkflowWorkItemsCreatedEventHandler

{

??? ?? public void started(WorkflowElementEventArgs _workflowElementEventArgs)

?????? {

???????????? // TODO:? Write code to execute once the workflow is started.

?????? }

?

??? ?? public void canceled(WorkflowElementEventArgs _workflowElementEventArgs)

?????? {

???????????? // TODO:? Write code to execute once the workflow is canceled.

??????? CustomWorkflowTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), CustomWorkflowBaseEnum::Rejected);

?????? }

?

??? ?? public void completed(WorkflowElementEventArgs _workflowElementEventArgs)

?????? {

???????????? // TODO:? Write code to execute once the workflow is completed.

??????? CustomWorkflowTable::updateWorkflowStatus(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), CustomWorkflowBaseEnum::Rejected);

?????? }

}>        

Change the label of workflow approval Approve Action Menu Item.

No alt text provided for this image

Change the label of workflow approval Delegate Action Menu Item

No alt text provided for this image

Change the label of workflow approval Reject Action Menu Item

No alt text provided for this image

Change the label of workflow approval RequestChange Action Menu Item

No alt text provided for this image

Change the label of workflow approval Resubmit Action Menu Item

No alt text provided for this image

Now open workflow type and right click on supported elements section and select “New Workflow Element Reference

No alt text provided for this image

Enter workflow approval name in the Element Name property and also provide a name.

No alt text provided for this image

Change the label of workflow type.

No alt text provided for this image

Now build the project with database synchronization.

Open the form in d365 browser, see there is no workflow button enable. So, we need to configure the custom workflow in the attached module like we setup it in the Accounts Receivable module.

No alt text provided for this image

Go to Accounts Receivable module > Setup > Accounts receivable workflows. Click on the Accounts receivable workflows

No alt text provided for this image

Click on New button.

No alt text provided for this image

Select custom workflow type from the list (It’s the label of workflow type)

No alt text provided for this image

A new window will appear click on “Run” button.

No alt text provided for this image

A new form will open, enter email and password

No alt text provided for this image

If you are not logged in with admin account the below error will appear.

No alt text provided for this image

If you are logged in with admin account the below window will appear; Design the workflow according to your need.

No alt text provided for this image

Click on “Basic settings” and add placeholder.

No alt text provided for this image
No alt text provided for this image

Navigate to assignments and add select “User” option.

No alt text provided for this image

Click on “User” button and add user there.

No alt text provided for this image

Now click on “Basic Settings” Button under assignment window and provide placeholders.

No alt text provided for this image

Now drag workflow approval in the workflow window

No alt text provided for this image

Click on start and drag the connector (Arrow) to the workflow approval function.

Scroll the bar you will find end function.

Click on workflow approval and drag the connector (Arrow) to the end function.

No alt text provided for this image

Click “Save and close” button.

No alt text provided for this image

Click “OK” button and another form will open, click on “Activate” button there to activate the workflow.

Go back and now open the form again and you will see the workflow button visible there.

No alt text provided for this image

Happy Learning,

Syed Amir Ali.

Tatenda Ngorima

Microsoft Dynamics 365 Techno-Functional Consultant | Finance & Operations | Business Central | Security | MCT | .NET Developer | Azure DevOps | Power Apps | Power Automate | Power BI

1 个月
Murat Sa?lam

Software Developer

2 个月

Thanks to you, I can create a workflow from scratch, thank you very much for your efforts, greetings from Turkey

回复
Muhammad Azeem

Full Stack Web Developer | Creative FontEnd Developer | ASP.Net Core | Tech Trainer | SQL Server | ReactJS | LGU '23

3 个月

tell me the importance of field group ?

回复
Giang Le

IT manager at Response VietNam

9 个月

hi is there any way to wrap it into an API then I can call it through another apps like ASP.NET ?

回复
Alwyn Potgieter

Dynamics 365 F&O Developer

1 年

I followed this tutorial to a tee, but I still had one issue. I could submit my record to workflow but the submit button stayed in the workflow dropdown. The Cancel and View History buttons did not appear. I could also submit a record as many times as I wanted to, but the buttons did not switch. At last, I found that the issue was the canSubmitToWorkflow method. It was returning true after it had been submitted and thus did not allow the buttons to switch. Correction: Your canSubmitToWorkflow method should be the following: public boolean canSubmitToWorkflow(str _workflowType = '') ??{ ????boolean ret; ????ret = super(_workflowType); ????if(this.CustomWorkflowBaseEnum != CustomWorkflowBaseEnum::NotSubmitted) ????{ ??????ret = false; ????} ????else ????{ ??????ret = true; ????} ??? ????return ret; ??} The rest of the tutorial is great, thanks.

回复

要查看或添加评论,请登录

社区洞察

其他会员也浏览了