You are on page 1of 8

Microsoft D365 F&O / Dynamics AX 2012

Place of knowledge

WORKFLOWS

Modifying Existing Work Flow through


X++With Example

Date: November 15, 2017 Author: dynamicsaxtechs 1 Comment

Introduction:

This blog starts with explaining the table involved Dynamics AX Work Flow engine and their entity
relation between these tables of Work Flow engine. In the la�er half of the blog we will cover an example
of adding inventory site in an existing workflow.

Work flow tables

Table Purpose
WorkflowTable Contains information of the base record of work flow
Contains the version details of work flow and record that is currently
WorkflowVersion Table
enabled
WorkflowElementTable Contains the information about work flow branch parallel and steps
WorlflowStepTable Contains the setups information of steps include in workflow
ExpressionTable Contains the workflow steps configuration
ExpressionProjectionDatasource Contains data source information of element expression
Contains information of data source field and field type that is to be
ExpressionProjectField
matched
ExpressionPredict Contains information of expression values that is to be matched
ExpressionElement Contains expression information defined in steps
WorkflowTimespanTable Contains information of time allo�ed for step to be completed
WorkFlowEscalationTable Contains information of escalation of on a step
WorkflowAssignmentTable Contains information of assignment on a step
WorkFlowElementLinkTable Contains information of link with workflow version
WorkFlowMessageText Contains information of step its name

Work Flow table field mapping

Source Table Source Field Destination Table Destination Field


WorkflowTable RecID WorkflowVersion Table WorkflowTable
WorkflowVersion Table ConfigurationId WorkflowElementTable ConfigurationId
WorkflowElementTable ElementId WorlflowStepTable ElementId
WorlflowStepTable ExecucationStepId ExpressionTable ExpressionId
ExpressionTable RecId ExpressionElement ExpressionElement
ExpressionProjectionDatasource ExpressionTable ExpressionTable RecId
ExpressionProjectField ExpressionDatasource ExpressionProjectDatasource RecId
ExpressionPredictLHS/
ExpressionPredict ExpressionProjectField RecId
ExpressionPredictRHS

ExpressionElement RecId ExpressionPredict ExpressionElement


WorlflowStepTable RecID WorkflowTimespanTable WorkflowStepTable
WorlflowStepTable RecID WorkFlowEscalationTable WorkflowStepTable
WorlflowStepTable RecID WorkflowAssignmentTable WorkflowStepTable
WorkflowVersion
WorkflowVersion Table RecID WorkFlowElementLinkTable
Table
TxeRecId –
WorlflowStepTable RecID – tableid WorkFlowMessageText
TxtTableID

Work Flow example data hierarchy

Table Example Data


WorkflowTable 000051 – Inventory adjustment workflow
WorkflowVersion Table 1.3.9.0
WorkflowElementTable SL_InventoryAdJrAppr
WorlflowStepTable AM 5011
ExpressionTable SL_InventoryAdJrTypeDocument
ExpressionProjectionDatasource InventJournalTable
ExpressionProjectField Site
ExpressionPredict AE5011
ExpressionElement AND-OR-PREDICTING VALUE
WorkflowTimespanTable 1 Day
WorkFlowEscalationTable None
WorkflowAssignmentTable moosa.kh
WorkFlowElementLinkTable All elements linked to current version of WF
WorkFlowMessageText Demo Subject, Demo Instructions

Sample scenario to add a new step in existing workflow

Scenario:

We need to add a new inventory site in our existing work flow ‘Inventory adjustment workflow’ for the
assignment of cost journal to its respective site having step name ‘AM 5011’, subject ‘Approval for
Inventory Adjustment’ and instruction ‘Approval for Inventory Adjustment’

Assignment type should be set to User Type and User with user id of ‘akramm’. User can approve it
within 1 day and completion policy set to all approvers and condition set to Site id value should contain
‘AE5011’ and escalation is not required.

Source code:
// Variable initialization
WorkflowTable workflowTable;
WorkflowVersionTable workflowVersionTable;
WorkflowElementTable workflowElementTable;
WorkflowStepTable workflowStepTable,stepTmp;
WorkflowAssignmentTable workflowAssignmentTable;
UserInfo userInfo;
WorkflowTimeSpanTable workflowTimeSpanTable;
WorkflowEscalationTable workflowEscalationTable;
WorkflowMessageText workflowMessageText;
ExpressionPredicate expressionPredicate;
ExpressionProjectionField expressionProjectionField;
ExpressionProjectionDatasource expressionProjectionDatasource,expDStmp;
ExpressionTable expressionTable,expTmp;
ExpressionElement expressionElement;

// Select existing workflow with its number seq


select firstOnly * from workflowTable where
workflowTable.SequenceNumber=='000051';

// Select latest version of workflow that is currently enabled


select firstOnly * from workflowVersionTable
where workflowVersionTable.WorkflowTable == workflowTable.RecId
&& workflowVersionTable.Enabled == NoYes::Yes;

// Select the workflow element based on configuration id of version table.


This workflow has single element
select firstOnly * from workflowElementTable
where
workflowElementTable.ConfigurationId==workflowVersionTable.ConfigurationId
&& workflowElementTable.ElementType==WorkflowElementType::Approval;

// Select buffer of existing setup in the workflow to fetch configurations


select firstOnly * from workflowStepTable
order by workflowStepTable.Sequence desc
where workflowStepTable.ElementId == workflowElementTable.ElementId;

// Select execution id of existing step


select * from expressionTable
where expressionTable.ExpressionId == workflowStepTable.ExecuteStepId;

// Create a new expression id that is to be linked with our step


expTmp.ExpressionId = newGuid();
expTmp.QueryClassName = expressionTable.QueryClassName;
expTmp.XPathQuery= expressionTable.XPathQuery;
expTmp.insert();

// Selecting expression datasource for existing execution id


select * from expressionProjectionDatasource
where expressionProjectionDatasource.ExpressionTable
==expressionTable.RecId;

// Creating and defining Expression DataSource for our expression id


expDStmp.ExpressionTable = expTmp.RecId;
expDStmp.DisplayName = expressionProjectionDatasource.DisplayName;
expDStmp.Name = expressionProjectionDatasource.Name;
expDStmp.ParentDatasource = expressionProjectionDatasource.ParentDatasource;
expDStmp.TableName = expressionProjectionDatasource.TableName;
expDStmp.Type = expressionProjectionDatasource.Type;
expDStmp.insert();
// Create step information in step table buffer
stepTmp.CompletionPolicy=WorkflowStepCompletionPolicy::All;
stepTmp.DEL_EscalationType=WorkflowEscalationType::Action;
stepTmp.ElementId = workflowElementTable.ElementId;
stepTmp.ExecuteStep=WorkflowConditionType::OnlyIf;
stepTmp.ExecuteStepId =expTmp.ExpressionId;
stepTmp.Name = 'AM 5011';
stepTmp.Sequence = workflowStepTable.Sequence+1;
stepTmp.StepId = newGuid();
stepTmp.insert();

//Step subject and Instructions


select Language from userInfo where userInfo.Id == curuserid();
workflowMessageText.initValue();
workflowMessageText.Name = 'Subject';
workflowMessageText.TxtTableId = stepTmp.TableId;
workflowMessageText.TxtRecId = stepTmp.RecId;
workflowMessageText.Txt = 'Demo Subject';
workflowMessageText.LanguageId = userInfo.Language;
workflowMessageText.insert();

workflowMessageText::createMessageText(WorkflowConfigMessageTextType::Instruction
,'Demo Instruction',stepTmp);

//Step Assignment
workflowAssignmentTable.ActorValue =
WorkflowActorType::Originator;
workflowAssignmentTable.AssignmentType = WorkflowPersonType::User;
workflowAssignmentTable.HierarchyFilterType =
WorkflowHierarchyFilterType::No;
workflowAssignmentTable.HierarchyProviderName
='WorkflowLimitHierarchyProvider';
workflowAssignmentTable.HierarchyTokenName = 'BlockUserId';
workflowAssignmentTable.ParticipantProviderName =
'WorkflowRoleParticipantProvider';
workflowAssignmentTable.ParticipantTokenName ='ActivityManager';
workflowAssignmentTable.QueueProviderName =
'WorkflowWorkItemQueueCustomProvider';
workflowAssignmentTable.QueueTokenName ='Conditional queue';
workflowAssignmentTable.UserValue ='akramm';
workflowAssignmentTable.WorkflowStepTable = stepTmp.RecId;
workflowAssignmentTable.insert();

//Step Condition
select RecId from stepTmp
where stepTmp.Sequence == workflowStepTable.Sequence+1
&& stepTmp.ElementId==workflowElementTable.ElementId;

//crete ExpressionElement
expressionElement.ExpressionTable = expTmp.RecId;
expressionElement.ParentElement = 0;
expressionElement.Type = ExpressionElementType::Or;
expressionElement.insert();

expressionElement.ExpressionTable = expTmp.RecId;
expressionElement.ParentElement = expressionElement.RecId;
expressionElement.Type = ExpressionElementType::And;
expressionElement.insert();

expressionElement.ExpressionTable = expTmp.RecId;
expressionElement.ParentElement = expressionElement.RecId;
expressionElement.Type = ExpressionElementType::Predicate;
expressionElement.insert();

expressionProjectionField.ExpressionDatasource = expDStmp.RecId;
expressionProjectionField.DisplayName = 'Inventory journal
table.Site';
expressionProjectionField.Category =
ExpressionFieldCategory::Field;
expressionProjectionField.ExtendedDataType = 'InventSiteId';
expressionProjectionField.Name = 'InventSiteId';
expressionProjectionField.Type =
ExpressionFieldType::String;
expressionProjectionField.insert();

expressionPredicate.ExpressionElement = expressionElement.RecId;
expressionPredicate.ExpressionFieldLHS = expressionProjectionField.RecId;
expressionPredicate.ComparisonType = ExpressionComparisonType::Value;
expressionPredicate.DateOperatorType = ExpressionDateOperatorType::Plus;
expressionPredicate.DateType = ExpressionDateType::Relative;
expressionPredicate.Operator = ExpressionOperator::Contains;
expressionPredicate.StartDayType = ExpressionStartDayType::Today;
expressionPredicate.StringValue = 'AE5011';
expressionPredicate.insert();

//Time
workflowTimeSpanTable.DailyCalendarProvider = 'None';
workflowTimeSpanTable.DailyIncludeMonday = NoYes::Yes;
workflowTimeSpanTable.DailyIncludeTuesday = NoYes::Yes;
workflowTimeSpanTable.DailyIncludeWednesday = NoYes::Yes;
workflowTimeSpanTable.DailyIncludeThursday = NoYes::Yes;
workflowTimeSpanTable.DailyIncludeFriday = NoYes::Yes;
workflowTimeSpanTable.DailyIncludeSaturday = NoYes::Yes;
workflowTimeSpanTable.DailyIncludeSunday = NoYes::Yes;
workflowTimeSpanTable.DailyUseNonCalendar = NoYes::No;
workflowTimeSpanTable.DailyValue = 1;

workflowTimeSpanTable.DateType =
WorkflowConfigDurationCategory::Days;
workflowTimeSpanTable.HourCalendarProvider = 'None';
workflowTimeSpanTable.HourIncludeMonday = NoYes::Yes;
workflowTimeSpanTable.HourIncludeTuesday = NoYes::Yes;
workflowTimeSpanTable.HourIncludeWednesday = NoYes::Yes;
workflowTimeSpanTable.HourIncludeThursday = NoYes::Yes;
workflowTimeSpanTable.HourIncludeFriday = NoYes::Yes;
workflowTimeSpanTable.HourIncludeSaturday = NoYes::Yes;
workflowTimeSpanTable.HourIncludeSunday = NoYes::Yes;
workflowTimeSpanTable.HoursAvailable = 8;
workflowTimeSpanTable.HourStartTime = 28800;//08:00:00 am;
workflowTimeSpanTable.HourUseNonCalendar = NoYes::No;
workflowTimeSpanTable.HourValue = 1;
workflowTimeSpanTable.MonthlyDayOfWeek =
WorkflowConfigDaysOfWeek::Monday;
workflowTimeSpanTable.MonthlyWeekInMonth =
WorkflowConfigWeekInMonth::First;
workflowTimeSpanTable.WeeklyValue = 1;
workflowTimeSpanTable.WorkflowStepTable = stepTmp.RecId;
workflowTimeSpanTable.YearlyMonthInYear = WorkflowConfigMonthInYear::Jan;
workflowTimeSpanTable.insert();

//Step Escalation
workflowEscalationTable.EscalationType = WorkflowEscalationType::None;
workflowEscalationTable.WorkflowStepTable = stepTmp.RecId;
workflowEscalationTable.insert();

info(strFmt("Inventory site %1 has been added to work


flow.",workflowStepTable.Name));

Conclusion

This blog explained the table architecture of the Dynamics AX 2012 Workflow engine with an example of
adding workflow step in an existing workflow. In next blog we will be covering how to track the workflow
entries in dynamics AX records with X++.

Contributed by

Muhammad Moosa Khan & Muhammad Salman Siddiqui

Sponsored Content
Full-Floor Penthouse At Ri�- Nightly Routine Helps Restore LeBron James Lists $20.5 Million
Carlton Residences Sells: Itʹs A Vision At Any Age (Weird but Los Angeles Mansion Mansion G
Dream House Mansion Global | Effective). healthyeyes.live | Spon lobal | Sponsored
Sponsored sored

How to get a second income by Gal Gadotʹs Wedding Dress Is Liposuction In Mexico: Prices
investing $ 250 in companies like Still Turning Heads Investing.co May Surprise You! Liposuction in
Amazon Top Invest Advisor | Sp m | Sponsored Mexico | Sponsored | Sponsored
onsored

63 Everyday Things Kate This Cheap Helicopter Drone [Photos] 55 Years Later - Man
Middleton Is Not Allowed To Might Be The Best Selling Gift Who Escaped Alcatraz Sends FBI
Do Bleacher Breaker | Sponsored In Bogor StealthHawk Pro | Spon This Note Explored Planet | Spon
sored sored

Published by dynamicsaxtechs

View all posts by dynamicsaxtechs

One thought on “Modifying Existing Work Flow through


X++With Example”

Add Comment

1. Ali Azim says:


March 28, 2018 at 11:42 am
Nice post

Reply

© 2023 MICROSOFT D365 F&O / DYNAMICS AX 2012

BLOG AT WORDPRESS.COM.

You might also like