Sunday, February 16, 2014

Creating Workflow in Ax 2012

Example for Workflow creation in Customer details form

1. Create query 'CustApprWorkflowQry' for custtable.

2. Create Enum 'CustApprWorkflowState' for Workflow Status.

3. Add the above enum in Custtable table.

4. Add the modified override method 'canSubmitToWorkflow' in custtable table.

//BP Deviation Documented
public boolean canSubmitToWorkflow(str _workflowType = '')
{
    boolean ret;
 
    ret = this.RecId != 0 && this.CustApprWorkflowState == CustApprWorkflowState::NotSubmitted;
   
    return ret;
}

5. Add the new method 'UpdateCustWorkflowState' in custtable table.

//BP Deviation documented
public static void UpdateCustWorkflowState(RefRecId _recId, CustApprWorkflowState _state)
{
    CustTable custTable = CustTable::findRecId(_recId, true);

    ttsBegin;

    custTable.CustApprWorkflowState = _state;
    custTable.update();

    ttsCommit;
}

6. Create Workflow Type 'CustWFApprovalDemo' using wizard.

All the required classes and menuitems will be created automatically. Do the following changes.

In CustWFApprovalDemoEventHandler Class, 
add code in Canceled method
//BP Deviation Documented
public void canceled(WorkflowEventArgs _workflowEventArgs)
{
CustTable::UpdateCustWorkflowState(_workflowEventArgs.parmWorkflowContext().parmRecId(),   CustApprWorkflowState::PendingCancellation);
}
add code in Completed method
//BP Deviation Documented
public void completed(WorkflowEventArgs _workflowEventArgs)
{
    CustTable::UpdateCustWorkflowState(_workflowEventArgs.parmWorkflowContext().parmRecId(), CustApprWorkflowState::Completed);
}
add code in Started method
//BP Deviation Documented
public void started(WorkflowEventArgs _workflowEventArgs)
{
    CustTable::UpdateCustWorkflowState(_workflowEventArgs.parmWorkflowContext().parmRecId(), CustApprWorkflowState::Submitted);
}

In CustWFApprovalDemoDocument Class, add the above created queryname in getQueryName method
public queryName getQueryName()
{
    return querystr(CustApprWorkflowQry);
}

7. Create Workflow Approval 'CustWFApprovalDemo' using wizard.

All the required classes and menuitems will be created automatically. Do the following changes.

//BP Deviation Documented
public void canceled(WorkflowElementEventArgs _workflowElementEventArgs)
{
        CustTable::UpdateCustWorkflowState(_workflowElementEventArgs.parmWorkflowContext().parmRecId(),  CustApprWorkflowState::PendingCancellation);
}
//BP Deviation Documented
public void changeRequested(WorkflowElementEventArgs _workflowElementEventArgs)
{
        CustTable::UpdateCustWorkflowState(_workflowElementEventArgs.parmWorkflowContext().parmRecId(),  CustApprWorkflowState::ChangeRequest);
}
//BP Deviation Documented
public void completed(WorkflowElementEventArgs _workflowElementEventArgs)
{
CustTable::UpdateCustWorkflowState(_workflowElementEventArgs.parmWorkflowContext().parmRecId(), CustApprWorkflowState::Approved);
}
//BP Deviation Documented
public void returned(WorkflowElementEventArgs _workflowElementEventArgs)
{
    CustTable::UpdateCustWorkflowState(_workflowElementEventArgs.parmWorkflowContext().parmRecId(),  CustApprWorkflowState::Returned);
}
//BP Deviation Documented
public void started(WorkflowElementEventArgs _workflowElementEventArgs)
{
    CustTable::UpdateCustWorkflowState(_workflowElementEventArgs.parmWorkflowContext().parmRecId(),   CustApprWorkflowState::Submitted);
}

8. Create new Class 'WorkflowSubmitManager' for Submit / Re-Submit

//Generic class which can be used for all workflow activation on submit/resubmit
public class WorkflowSubmitManager
{
    WorkflowSubmitDialog  workFlowSubmitDialog;
    Common                workflowConfiguration;
    RefRecId              recordRecId;
    WorkflowCorrelationId workFlowCorrelationId;
    WorkflowTypeName      workFlowTypeName;
    WorkflowComment       note;

    WorkflowVersionTable  workflowVersionTable;
    WorkflowWorkItemTable workflowWorkItemTable;
    FormDataSource        callerDS;
    FormRun               callerForm;
    Common                callerRecord;

    boolean               isSubmit;
}
private boolean canSubmit()
{
    boolean ret = true;

    if (CustTable::findRecId(recordRecId).address() == "")
    {
        ret = checkFailed("Customer Address not defined");
    }

    return ret;
}
private void init(Args _args)
{
    ;

    callerForm            = _args.caller();
    callerRecord          = _args.record();
    callerDS              = callerRecord.dataSource();
    recordRecId           = callerRecord.RecId;
    workflowVersionTable  = callerForm.getActiveWorkflowConfiguration();
    WorkflowWorkItemTable = callerForm.getActiveWorkflowWorkItem();

    // Construct dialog to prompt user to enter submit comments/note
    workFlowSubmitDialog = WorkflowSubmitDialog::construct(workflowVersionTable);

    isSubmit = this.isCalledFromSubmitMenuItem(_args.menuItemName());
}
private boolean isCalledFromSubmitMenuItem(str _menuItemName)
{
    str name = _menuItemName;
    ;

    if (strScan(name, "Resubmit", 1, strLen(name)) > 0)
    {
        return false;
    }
    else
    {
        return true;
    }

}
public RefRecId parmRecordRecId(RefRecId _recordRecId = recordRecId)
{
    recordRecId = _recordRecId;

    return recordRecId;
}
private void refreshCallerWorkflowControls()
{
    ;

    if (callerDS)
    {
        ttsBegin;
        this.updateWorkflowState();
        ttsCommit;

        callerDS.reread();
        callerDS.refresh();
    }

    //Refresh/update workflow controls on called form
    callerForm.updateWorkflowControls();
}
private void reSubmit()
{
    ;

    Workflow::cancelWorkflow(workflowWorkItemTable.CorrelationId);
}
public void run(Args _args)
{
    ;

    // Initializing params from caller argument object
    this.init(_args);

    //Bydefault canSubmit returns true always, you can add validations here if any
    if (this.canSubmit())
    {
        workFlowSubmitDialog.run();

        //User enters note and clicked Ok for document processing
        if (workFlowSubmitDialog.parmIsClosedOK())
        {
            note = workFlowSubmitDialog.parmWorkflowComment();

            // Activate workflow i,e submit document for processing
            if (isSubmit)
            {
                this.submit();
            }
            else
            {
                this.reSubmit();
            }

            //Update workflow state for caller record and refresh to reflect new state
            this.refreshCallerWorkflowControls();
        }
    }

}
private void submit()
{
    ;

    ttsBegin;

    try
    {
        workFlowCorrelationId = Workflow::activateFromWorkflowConfigurationId(workflowVersionTable.ConfigurationId, recordRecId, note, false);
    }
    catch(Exception::Error)
    {
        throw error ("Error on workflow activation.");
    }

    ttsCommit;
}
private void updateWorkflowState()
{
    ;
    //Add case for each caller table and update workflow state accordingly
    switch (callerRecord.TableId)
    {
        case tableNum(custTable):
            CustTable::UpdateCustWorkflowState(callerRecord.RecId, CustApprWorkflowState::Submitted);
            break;
    }
}
public static WorkflowSubmitManager constructWith(RefRecId _recId)
{
    WorkflowSubmitManager submitManager = new WorkflowSubmitManager();
    ;

    submitManager.parmRecordRecId(_recId);

    return submitManager;

}
public static void main(Args args)
{
    WorkflowSubmitManager submitManager = new WorkflowSubmitManager();


    submitManager.run(args);

}

Add this class with the WF Type menuitem 'CustWFApprovalDemoSubmitMenuItem' object property and with WF Approval menuitem 'CustWFApprovalDemoSubmitMenuItem' object property.

9. Add the workflow for Customer details form.

Change WorkflowEnabled property to Yes, Workflow Datasource property to Custtable and Workflow Type to 'CustWFApprovalDemo' in CustTableListPage form Design property.

10. Create new record. Workflow bar will be displayed.


No comments:

Post a Comment