Friday, June 11, 2010

Customize AX 2009 Workflow to select the approver at runtime

In standard AX2009 workflow, theres is no provision to select the approver at runtime. But we can do this with a small amount of customization.

Here, we are going to customize the Fixed Asset Posting workflow.

1. Add a new element to ‘WorkflowWorkItemActionType’ enum
Name: Submit
Label: Submit


2. Create a new table to store the details of approver selected at runtime
Table name: WorkflowRuntimeApprover
Add the following fields,
RefTableId - ExtendsRefTableId
RefRecId - ExtendsRefRecId
ActionType – WorkflowWorkItemActionType
Approver – UserId

Add a new method to fetch the approver
public static UserId getApprover(RefTableId _refTableId,
RefRecId _refRecId)
{
WorkflowRuntimeApprover workflowRuntimeApprover;
;

select firstonly Approver from workflowRuntimeApprover
where workflowRuntimeApprover.RefTableId == _refTableId
&& workflowRuntimeApprover.RefRecId == _refRecId;

return workflowRuntimeApprover.Approver;
}


3. Customize the Submit class ‘LedgerJournalWFApprSubmitToWF’ to use ‘WorkflowWorkitemActionDialog’ object instead of ‘WorkflowSubmitDialog’ object.
Comment the existing codes to open submit dialog and write the codes to run the action dialog.
Declare the variables for WorkflowWorkItemActionDialog, WorkfloWorkItemTable and WorkflowRuntimeApprover objects.
/*
workflowSubmitDialog = WorkflowSubmitDialog::construct(_args.caller().getActiveWorkflowConfiguration());
workflowSubmitDialog.run();

if (workflowSubmitDialog.parmIsClosedOK())
{
try
{
ttsbegin;
workflowCorrelationId = Workflow::activateFromWorkflowSequenceNumber(ledgerJournalName.Configuration, recId, comment, NoYes::No);

LedgerJournalWFApprovalStatusManager::submitFromForm(ledgerJournalTable);
ttscommit;
}
*/
workflowWorkItemActionDialog = WorkflowWorkItemActionDialog::construct( WorkfloWorkItemTable ,
WorkflowWorkItemActionType::Submit,
new MenuFunction(_args.menuItemName(),
_args.menuItemType()));
workflowWorkItemActionDialog.run();

if (workflowWorkItemActionDialog.parmIsClosedOK())
{
try
{
ttsbegin;
workflowCorrelationId = Workflow::activateFromWorkflowSequenceNumber(ledgerJournalName.Configuration, recId, comment, NoYes::No);
LedgerJournalWFApprovalStatusManager::submitFromForm(ledgerJournalTable);

workflowRuntimeApprover.RefTableId = ledgerJournalTable.TableId;
workflowRuntimeApprover.RefRecId = ledgerJournalTable.RecId;
workflowRuntimeApprover.Approver= workflowWorkItemActionDialog.parmTargetUser();
workflowRuntimeApprover.ActionType = WorkflowWorkItemActionType::Submit;
workflowRuntimeApprover.insert();

ttscommit;
}

4. Modify the run() method in ‘WorkflowWorkItemActionDialog’ form and add one more condition in the if.. else.

if (workItemTable.RecId != 0)
{
………
}
else if (workflowWorkItemActionDialog.parmWorkItemActionType()==WorkflowWorkItemActionType == Submit)
{
groupUser.visible(true);
}
else
{
.......
}

Modify the closeOk() method to add one more condition for 'Status in if..else condition.

if ((this.parmWorkflowWorkItemActionDialog().parmWorkItemActionType() == WorkflowWorkItemActionType::Delegate)
(this.parmWorkflowWorkItemActionDialog().parmWorkItemActionType() == WorkflowWorkItemActionType::RequestChange)
(this.parmWorkflowWorkItemActionDialog().parmWorkItemActionType() == WorkflowWorkItemActionType::Submit))
{
this.parmWorkflowWorkItemActionDialog().parmTargetUser(user.valueStr());
}


5. Modify onWorkItemCreate() method in ‘SysWorkflowEventDispatcher' class and add the following codes just before inserting the records into ‘WorkflowWorkItemTable’
If(workItem.RefTableId == tablenum(LedgerJournalTble)
{
workItem.UserId = WorkflowRuntimeApprover::getApprover(workItem.RefTableId, workItem.RefRecId);
}
Now run the workflow and you get a window shown below
























Select the user (approver) and press on 'Ok' button to submit the request to the selected user for approval.