Blog

Name is Anant Dubey and the intent to create this blog is to discuss the problems and issues that developer face in the dynamics AX development and to share the new things that come up with the new version of AX.

Thursday, 30 January 2014

how to add another user in Alert in ax 2012

public void execute(
    EventRule   eventRule,
    EventType   eventType,
    Common      buffer,
    EventInbox inbox,
    // note: for due date events, the time and date on which the alert
    // is considered to be created is when the due date batch
    // started to run
    EventAlertCreatedDateTime alertCreatedDateTime = DateTimeUtil::newDateTime(systemDateGet(),timeNow(),DateTimeUtil::getUserPreferredTimeZone())
    )
{
    EventInboxId            inboxId;
    EventInboxData          inboxData;
    EventAlertField         eventAlertField;
    WorkflowRecordCaptionGenerator recordCaptionGenerator;

    container c;

    List                    list;
    SysUserInfo userInfo1;
    SysUserInfo userInfo = SysUserInfo::find(eventRule.UserId);
    if(userInfo)
    {

        inboxId = EventInbox::nextEventId();

        inbox.initValue();
        inbox.initFromEventRule(eventRule);

        inbox.InboxId           = inboxId;

        inbox.AlertCreatedDateTime = alertCreatedDateTime;

        recordCaptionGenerator = WorkflowRecordCaptionGenerator::construct(buffer);
        inbox.AlertedFor        = recordCaptionGenerator.caption();

        if (userInfo && ((userInfo.EventPopUpDisplayWhen == EventPopupShowDefineMode::AllRules) ||
            (userInfo.EventPopUpDisplayWhen == EventPopupShowDefineMode::DefinedOnRule && eventRule.ShowPopup == true)))
            inbox.Visible = false;

        list                = SysDictTable::getUniqueIndexFields(buffer.TableId);
        if (list)
        {
            inbox.keyFieldList(list.pack());
            inbox.keyFieldData(SysDictTable::mapFieldIds2Values(list,buffer).pack());
        }

        if (eventRule.alertField())
        {
            eventAlertField = eventRule.alertField();
            if (eventAlertField != null && eventAlertField.parmAlertField().FieldRelationPath)
            {
                inbox.ExtendedDataType = eventAlertField.parmAlertField().FieldRelationPathExtendedDataType;
                inbox.EnumType = eventAlertField.parmAlertField().FieldRelationPathEnumType;
            }
        }


        if (userInfo)
        {
            // if email send settings are forced
            if (userInfo.EventEmailAlertsWhen == EventEmailSendDefineMode::AllRules)
                inbox.SendEmail = true;
            else if (userInfo.EventEmailAlertsWhen == EventEmailSendDefineMode::NoRules)
                inbox.SendEmail = false;

            if (inbox.SendEmail)
                inbox.EmailRecipient = eventRule.emailRecipient();
        }

        inbox.insert();

        // insert packed EventType class
        c = eventType.pack();
        inboxData.InboxId = inboxId;
        inboxData.DataType = EventInboxDataType::TypeData;
        inboxData.Data = c;
        inboxData.insert();

        // insert packed context information for drill down
        inboxData.InboxId   = inboxId;
        inboxData.DataType  = EventInboxDataType::Context;
        inboxData.Data      = eventRule.contextInfo();
        inboxData.insert();
    }

    eventRule.UserId    = eventRule.UserId1;
    userInfo1 = SysUserInfo::find(eventRule.UserId1);
    if(userInfo1)
    {
        userInfo    =   userInfo1;
        inboxId = EventInbox::nextEventId();

        inbox.initValue();
        inbox.initFromEventRule(eventRule);

        inbox.InboxId           = inboxId;

        inbox.AlertCreatedDateTime = alertCreatedDateTime;

        recordCaptionGenerator = WorkflowRecordCaptionGenerator::construct(buffer);
        inbox.AlertedFor        = recordCaptionGenerator.caption();

        if (userInfo && ((userInfo.EventPopUpDisplayWhen == EventPopupShowDefineMode::AllRules) ||
            (userInfo.EventPopUpDisplayWhen == EventPopupShowDefineMode::DefinedOnRule && eventRule.ShowPopup == true)))
            inbox.Visible = false;

        list                = SysDictTable::getUniqueIndexFields(buffer.TableId);
        if (list)
        {
            inbox.keyFieldList(list.pack());
            inbox.keyFieldData(SysDictTable::mapFieldIds2Values(list,buffer).pack());
        }

        if (eventRule.alertField())
        {
            eventAlertField = eventRule.alertField();
            if (eventAlertField != null && eventAlertField.parmAlertField().FieldRelationPath)
        {
            inbox.ExtendedDataType = eventAlertField.parmAlertField().FieldRelationPathExtendedDataType;
            inbox.EnumType = eventAlertField.parmAlertField().FieldRelationPathEnumType;
        }
        }

        if (userInfo)
        {
            // if email send settings are forced
            if (userInfo.EventEmailAlertsWhen == EventEmailSendDefineMode::AllRules)
                inbox.SendEmail = true;
            else if (userInfo.EventEmailAlertsWhen == EventEmailSendDefineMode::NoRules)
                inbox.SendEmail = false;

            if (inbox.SendEmail)
                inbox.EmailRecipient = eventRule.emailRecipient();
            }

            inbox.insert();

            // insert packed EventType class
            c = eventType.pack();
            inboxData.InboxId = inboxId;
            inboxData.DataType = EventInboxDataType::TypeData;
            inboxData.Data = c;
            inboxData.insert();

            // insert packed context information for drill down
            inboxData.InboxId   = inboxId;
            inboxData.DataType  = EventInboxDataType::Context;
            inboxData.Data      = eventRule.contextInfo();
            inboxData.insert();
    }
}

Friday, 24 January 2014

How to open Form through Code in ax 2012

Hi Guys,

      Today we are going to open a form using code..just try following code


 if(inventtable.Family == family::MettalicCore)
   {
   new MenuFunction(MenuItemDisplayStr(Attributes1),MenuItemType::Display).run();
    }
    else
    {
     new MenuFunction(MenuItemDisplayStr(Attributes),MenuItemType::Display).run();
     }
Here we are opening a form of Attributes1 and Attributes form its a simple way.Block Super()

Here is another way take a look


static void OpenFormByCodeB()
{ FormRun formRun;
Args args = new Args();
;
args.name(formstr(CustTable));
args.record(CustTable::find('ABC'));

formRun = ClassFactory.formRunClass(args);
formRun.init();
formRun.run();
formRun.wait();
}

Now if we tweak this a little bit, we can add our code
Like this:

static void OpenFormByCodeB()
{ Object formRun;
Args args = new Args();
;
args.name(formstr(CustTable));
args.record(CustTable::find('ABC'));

formRun = ClassFactory.formRunClass(args);
formRun.init();

formRun.yourmethodgoeshere(); /* !!

formRun.run();
formRun.wait();
}

By changing the type of formRun from class FormRun to class Object, we can implement and execute extra methods on our destination form! This gives us extra possibilities for customizations. You can pass along extra parameters for example.
Only drawback: While programming, your method doesn't show up in the IntelliSense, showing all the available methods. So be carefull of typo's. 

Monday, 20 January 2014

Generate Txt File on clicked in ax 2012

void clicked()
{
     LedgerJournalTrans   ledgerJournalTrans1;
    BinData     binData;
    TextBuffer  textBuffer;
    ;

    textBuffer = new TextBuffer();
    textBuffer.setText('');
        ledgerJournalTrans1 = LedgerJournalTrans_ds.getFirst(1);
    while(ledgerJournalTrans1) //where custTable.AccountNum < '40020'
    {

        textBuffer.appendText(strfmt('%1 %2 %3 %4 %5',ledgerJournalTrans1.LedgerDimension, ledgerJournalTrans1.Txt, ledgerJournalTrans1.AmountCurDebit, ledgerJournalTrans1.OffsetAccountType, ledgerJournalTrans1.OffsetLedgerDimension));
        ledgerJournalTrans1 = LedgerJournalTrans_ds.getNext();
    }

    textBuffer.getText();

    binData = new BinData();
    binData.setStrData(textBuffer.getText());
    binData.saveFile(@"d:\iban.txt");

}

Monday, 13 January 2014

Worker Phone With Name Filter in ax 2012

static void S_WorkerPhone(Args _args)
{
    TreeNode                    treeNode;
    Query                       q;
    QueryBuildDataSource        qbds,qbds1,qbds2,qbds3;
    QueryRun                    qr;
    QueryBuildRange             qbr;
    HcmWorker                   hcmWorker;
    DirPerson                   dirPerson;
    DirPartyTable               dirPartyTable;
    LogisticsElectronicAddress  logisticsElectronicAddress;
    str                         queryname = "S_WorkerPhone";
    str                         projectName = "A_DemoQuery";
    ;
    #AOT
    // Delete the query from the AOT, if the query exists.

    treeNode = TreeNode::findNode(#QueriesPath);
    //treeNode = treeNode::findNode(#ProjectPrivatePath);
    treeNode = treeNode.AOTfindChild(queryname);
    //treeNode = treeNode.AOTfindChild(queryname);
    if (treeNode)
    {
        //treeNode.AOTDuplicate();
        //treeNode.newObjectName(queryname);
        treeNode.AOTdelete();
    }

    treeNode = TreeNode::findNode(#QueriesPath);
    //treeNode = treeNode::findNode(#ProjectPrivatePath);
    //treeNode = treeNode.AOTfindChild(projectName);
    //treeNode = treeNode.AOTfindChild(queryname);
    treeNode.AOTadd(queryname);
    q                   = treeNode.AOTfindChild(queryname);
    //q                   = treeNode.AOTfindChild("S_WorkerPhone");
    qbds                = q.addDataSource(tableNum(DirPerson));
    qbds1               = qbds.addDataSource(tableNum(DirPartyTable));
    qbds2               = qbds1.addDataSource(tableNum(LogisticsElectronicAddress));
    //qbds3               = qbds1.addDataSource(tableNum(LogisticsElectronicAddress));
    //qbr                 = qbds.addRange(fieldNum(HcmWorker,personnelNumber));
    //qbds1.addLink(fieldNum(DirPartyTable,RecId),
    //              fieldNum(DirPerson,RecId));
    qbds1.addLink(fieldNum(DirPerson,RecId),
                  fieldNum(DirPartyTable,RecId));
    qbds2.addLink(fieldNum(LogisticsElectronicAddress,RecId),
                  fieldNum(DirPartyTable,PrimaryContactEmail));
                 /* && fieldNum(DirPartyTable,primaryContactPhone),
                     fieldNum(LogisticsElectronicAddress,RecId));*/
    //qbds2.addDynalink(fieldNum(LogisticsElectronicAddress,RecId),
    //                  fieldNum(DirPartyTable,primaryContactEmail));
    //qbds2.addLink(fieldNum(LogisticsElectronicAddress,RecId),
    //              fieldNum(DirPartyTable,primaryContactemail));
    //            (fieldNum(DirPartyTable,RecId)));
    //qbds3.addLink(fieldNum(DirPartyTable,primaryContactPhone),
    //              fieldNum(LogisticsElectronicAddress,RecId));
    q.AOTcompile(1);
    q.AOTsave();
    qr = new QueryRun("S_WorkerPhone");
    while(qr.next())
    {
        dirPerson                    = qr.GetNo(1);
        dirPartyTable                = qr.getNo(2);
        logisticsElectronicAddress   = qr.getNo(3);
        //logisticsElectronicAddress   = qr.getNo(4);
        //hcmWorker       = qr.get(tableNum(HcmWorker));
        info(strFmt("%1, %2, %3",dirPerson.Name,logisticsElectronicAddress.Locator,dirPartyTable.primaryPhone()));
    }
}

Monday, 6 January 2014

Failed to create a session, confirm that the user has the proper privileges to log on to Microsoft Dynamics in ax 2012

While running system Administration > Setup > Workflow > Workflow
infrastructure configuration

Error:- Failed to create a session, confirm that the user has the proper privileges to log on to Microsoft Dynamics.

To resolve this:- Confirm that user is logged in as a administrator.
go to the user relation in system Administration > Common > User relation
and set user admin to a person.
and save this. jst close application and start again.


"or"

A closer look into this learned that this is linked to the new partitions feature.

It seems the UserInfo table is not correctly updated and the partition administrator is not updated correctly when you restore an existing DB or the Demo database.
To fix this, you can do the following.

To fix this, you can do the following.

Stop the AOS
Restore the database again
Start the AOS
Start a client and complete the partition initialiasation checklist
Close the client and execute the script below on the SQL database
Restart the client and reimport your license (if you were restoring the Microsoft demo data, the demo license is back in there)
Then compile / generate CIL / DB sync and you should be on track again!

Worker phone with name by query in ax 2012

static void S_WorkerPhone(Args _args)
{
    TreeNode                    treeNode;
    Query                       q;
    QueryBuildDataSource        qbds,qbds1,qbds2,qbds3;
    QueryRun                    qr;
    QueryBuildRange             qbr;
    HcmWorker                   hcmWorker;
    DirPerson                   dirPerson;
    DirPartyTable               dirPartyTable;
    LogisticsElectronicAddress  logisticsElectronicAddress;
    str                         queryname = "S_WorkerPhone";
    str                         projectName = "A_DemoQuery";
    ;
    #AOT
    // Delete the query from the AOT, if the query exists.

    treeNode = TreeNode::findNode(#QueriesPath);
    //treeNode = treeNode::findNode(#ProjectPrivatePath);
    treeNode = treeNode.AOTfindChild(queryname);
    //treeNode = treeNode.AOTfindChild(queryname);
    if (treeNode)
    {
        //treeNode.AOTDuplicate();
        //treeNode.newObjectName(queryname);
        treeNode.AOTdelete();
    }

    treeNode = TreeNode::findNode(#QueriesPath);
    //treeNode = treeNode::findNode(#ProjectPrivatePath);
    //treeNode = treeNode.AOTfindChild(projectName);
    //treeNode = treeNode.AOTfindChild(queryname);
    treeNode.AOTadd(queryname);
    q                   = treeNode.AOTfindChild(queryname);
    //q                   = treeNode.AOTfindChild("S_WorkerPhone");
    qbds                = q.addDataSource(tableNum(DirPerson));
    qbds1               = qbds.addDataSource(tableNum(DirPartyTable));
    qbds2               = qbds1.addDataSource(tableNum(LogisticsElectronicAddress));
    //qbds3               = qbds1.addDataSource(tableNum(LogisticsElectronicAddress));
    //qbr                 = qbds.addRange(fieldNum(HcmWorker,personnelNumber));
    //qbds1.addLink(fieldNum(DirPartyTable,RecId),
    //              fieldNum(DirPerson,RecId));
    qbds1.addLink(fieldNum(DirPerson,RecId),
                  fieldNum(DirPartyTable,RecId));
    qbds2.addLink(fieldNum(LogisticsElectronicAddress,RecId),
                  fieldNum(DirPartyTable,PrimaryContactEmail));
                 /* && fieldNum(DirPartyTable,primaryContactPhone),
                     fieldNum(LogisticsElectronicAddress,RecId));*/
    //qbds2.addDynalink(fieldNum(LogisticsElectronicAddress,RecId),
    //                  fieldNum(DirPartyTable,primaryContactEmail));
    //qbds2.addLink(fieldNum(LogisticsElectronicAddress,RecId),
    //              fieldNum(DirPartyTable,primaryContactemail));
    //            (fieldNum(DirPartyTable,RecId)));
    //qbds3.addLink(fieldNum(DirPartyTable,primaryContactPhone),
    //              fieldNum(LogisticsElectronicAddress,RecId));
    q.AOTcompile(1);
    q.AOTsave();
    qr = new QueryRun("S_WorkerPhone");
    while(qr.next())
    {
        dirPerson                    = qr.GetNo(1);
        dirPartyTable                = qr.getNo(2);
        logisticsElectronicAddress   = qr.getNo(3);
        //logisticsElectronicAddress   = qr.getNo(4);
        //hcmWorker       = qr.get(tableNum(HcmWorker));
        info(strFmt("%1, %2, %3",dirPerson.Name,logisticsElectronicAddress.Locator,dirPartyTable.primaryPhone()));
    }
}

Workflow in ax 2012 complete

 WORKFLOW

Objectives
The objectives are:
•  Identify the components required prior to using workflow
•  Specify which application module a workflow is applicable to using
a workflow category
•  Create a new workflow template
•  Link tables to workflows using a workflow document
•  Define what happens when the workflow is approved or denied.
•  Apply a workflow to a form
•  Create Event Handlers and apply them to a workflow
•  Configure a workflow
•  Submit a record for workflow processing
•  Use the workflow processor

Introduction
Workflow is a module in Microsoft Dynamics®
AX 2012, that allows flexible
task and approval routes for documents created by users. For example, a purchase
requisition may need to be approved by a number of different employees
according to the requisition's total amount, and each employee has to approve it
before the next employee in the approval route.
A Workflow in Microsoft Dynamics AX uses a combination of AOT elements
created by IT, and configuration that may be set up by a user. This lesson
introduces the development side of creating an workflow, for which you will
need to use skills developed from this class and the Morph X development class.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Isaac, the systems developer, has been asked to create a new workflow that will
be used to approve a new sales order for a customer that has reached their credit
limit. The requirement is that when a new sales order is entered that takes the
customer over their credit limit, the sales order should be submitted to the
Accounts Receivable (AR) manager. They will either approve or deny the sales
order. Until it is approved, the sales order cannot be picked, packed or invoiced.
Workflow Installation
A number of the workflow system components are required to be installed before
you can begin to create and configure workflows in Microsoft Dynamics AX.
•  Workflow website. This is an IIS website that controls the flow of
the workflows.
•  Workflow accounts. There are two accounts used - a system account
used to provide access to the workflow tables, and an execution
account that is used to execute business logic.
•  Microsoft Dynamics AX workflow server component. This is the
workflow engine and is installed using the Microsoft Dynamics AX
installation files. The website and the accounts are required to run
this installation.
NOTE: This course does not cover the installation of the workflow system
components; however you need to be aware of the requirements. For more
information about workflow installation,refer to the Administrator Guide.

Create a Workflow Category
A workflow category defines the module in which the workflow will be
available. Modules are defined by the SysModule enum.

Demonstration: Creating a Workflow Category
This demonstration shows you how to create a category that allows the workflow
to be configured from the Projects module.
1.  Open the AOT
2.  Expand the Workflow node
3.  Right-click on the Workflow Category node and select New
Workflow Category. A new workflow category called Workflow
Category1 will be created.
4.  Right-click on the newly created workflow category and select
Properties
5.  Change the name property to SalesCreditLimitApproval
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-3
6.  Change the label property to Sales credit limit approval.
7.  Change the Module property to Cust.
8.  Right-click on the newly created workflow category and select Save.

FIGURE 11.1
Create a Workflow Template
A workflow template brings all the different elements of the workflow together.
Workflow configurations are created based on a template, and many
configurations can be based on the sametemplate. The template defines which
actions are allowed and which are required.

Demonstration: Creating a Workflow Template
This demonstration creates a workflow template and binds it to the workflow
category created in the previous demonstration.
1.  Open the AOT.
2.  Expand the Workflow node.
3.  Right-click on the Workflow Templates node and select New
Workflow Template. A new workflow template named
WorkflowTemplate1 will be created.
4.  Right-click on the newly created workflow template and select
Properties.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

5.  Change the name property to SalesCreditLimitApproval.
6.  Change the label property to Sales credit limit approval.
7.  Change the category property to SalesCreditLimitApproval.
8.  Right-click on the newly created workflow template and select Save.
FIGURE 11.2

Create a Workflow Document
A workflow document defines what data is affected by the workflow. It can
define one or more tables and all or selectedfields on that table. This is done by
using a query.

Demonstration: Creating a Workflow Document
A query defines what tables are used to determine that a workflow can be
initiated. Use a class to bind thatquery to the workflow template.
1.  Open the AOT.
2.  Right-click on the Query node and select New Query.
3.  Rename the query to SalesCreditLimitApproval.
4.  Expand the newly created query.
5.  Open another AOT window.
6.  Expand Data Dictionary > Tables.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement

Chapter 11: Workflow
11-5
7.  Find the table SalesTable.
8.  Drag the SalesTable table to the Data Sources node of the
SalesCreditLimitApproval query.
9.  Right click on the SalesCreditLimitApproval query and select Save.
10. In the AOT, right-click on the Classes node and select New Class.
11. Copy the following code into the ClassDeclaration.
12. Press F8 to save the method
13. Right-click on the class and select override method >
getQueryName.
14. Copy the following code in to the method.
15. Press F8 to save the method
16. Find the SalesCreditLimitApproval workflow template in the AOT.
17. Right-click on the workflow template and select Properties.
18. In the document property, enter SalesCreditLimitApproval.
19. Right-click on the workflow template and select Save.

class ProjTimeApproval extends workFlowDocument
{
}
QueryName getQueryName()
{
return queryStr(SalesCreditLimitApproval);
}

Create a Workflow Approval
An approval route may contain a number of outcomes. It may be approved,
rejected, returned or a change may be requested. The Workflow Approval
element determines which of these outcomes is allowed and what happens in the
event of each outcome.
Each outcome can trigger specific code by specifying a menu item for each item.

Demonstration: Creating a Workflow Approval
This demonstration creates a workflow approval and specifies how the approval
route can be defined.
1.  Open the AOT.
2.  Expand the workflow node.
3.  Right-click on approvals and select New Approval.
4.  Right-click on the newly created approval and select properties.
5.  Change the Name property to SalesCreditLimitApproval.
6.  Change the Document property to SalesCreditLimitApproval.
7.  Change the ParticipantProvider property to
WorkflowUserGroupParticipantProvider.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
8.  Change the DueDateProvider to
WorkflowWorkCalendarDueDateProvider.
9.  Change the HierarchyProvider to WorkflowLimitHierarchyProvider.
10. Change the DocumentMenuItem to SalesTable.
The Providers specify classes that enable rules to be defined for the workflow.
These providers are standard application classes but can be overridden and
modified, or other providers can be used in their place.

Demonstration: Creating Approval Outcomes
Use a standard class that acts as an engine for all approval outcomes.
You are not required to do anything but set the workflow to either Approved or
Denied, therefore call the same class from two different menu items. The two
menu items simply allow you to use two different labels. In more complex
workflows it may be necessary to override or copy and modify this class rather
than use it directly.
1.  Open the AOT.
2.  Expand Menu Items.
3.  Right-click on Action and select New Menu Item.
4.  Right-click on the newly created Action item and select Properties.
5.  Change the Name property to SalesCreditLimitApprove.
6.  Change the Label property to Approve.
7.  Change the ObjectType property to Class.
8.  Change the Object property to WorkflowWorkItemActionManager.
9.  Right-click on the SalesCreditLimitApprove menu item and select
Save.
10. Right-click on Action and select New Menu Item.
11. Right-click on the newly created Action item and select Properties.
12. Change the Name property to SalesCreditLimitReject.
13. Change the Label property to Reject.
14. Change the ObjectType property to Class.
15. Change the Object property to WorkflowWorkItemActionManager.
16. Right-click on the SalesCreditLimitReject menu item and select
Save.
17. In the AOT, expand Workflow > Approvals >
SalesCreditLimitApproval > Outcomes.
18. Right-click on the Approve node and select Properties.
19. Change the ActionMenuItem property to SalesCreditLimitApprove.
20. Right-click on the Reject node and select Properties.
21. Change the ActionMenuItem property to SalesCreditLimitReject.
22. Right-click on the Deny node and select Properties.
23. Change the Enabled property to No.
24. Right-click on the RequestChange node and select Properties.
25. Change the Enabled property to No
26. Right-click on the SalesCreditLimitApproval approval node and
select Save.

Demonstration: Attaching an Approval to a Template
The approval needs to be attached to the template. This demonstration shows you
how to attach an approval to a template.
1.  Open the AOT.
2.  Expand Workflow > Workflow Templates >
SalesCreditLimitApproval.
3.  Open another AOT window.
4.  Expand Workflow > Approvals.
5.  Find SalesCreditLimitApproval.
6.  Drag the SalesCreditLimitApproval approval to the Required
Elements node of the SalesCreditLimitApproval template.
7.  Right-click on the SalesCreditLimitApproval workflow template and
select save.
Enable Workflow on a Form
Now that the workflow template is defined, you can specify which forms will use
this template.
Demonstration: Add a WorkflowState Field
Any form that uses the same table in the datasource as is specified in a workflow
document is able to use that document for workflow. This demonstration shows
how to enable workflow on the Project Hours journal form.
You can specify conditions under which a workflow is eligible for submission.
One of these conditions must be that it has not already been submitted. To test
this condition, use a new field on the SalesTable table.
1.  Open the AOT.
2.  Expand Data Dictionary.
3.  Right-click on Base Enums and select New
4.  Rename the new enum to SalesCreditLimitApprovalStatus
5.  Add four elements to the Enum called NotSubmitted, Submitted,
Approved, Rejected.
6.  Expand Tables > SalesTable.
7.  Right-click on Fields and select New > Enum.
8.  Right-click on the newly created field and select Properties.
9.  Change the Name property to CreditLimitApprovalStatus.
10. Change the EnumType property to SalesCreditLimitApprovalStatus.
11. Right-click on the SalesTable node and select Save.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-9
Demonstration: Enable Workflow on the Form
Workflow on the form is enabled using properties on the design node, and by
overiding a form method. This demonstration shows you how to enable workflow
on a form.
1.  Open the AOT.
2.  Expand Tables > SalesTable.
3.  Create a new method and add the first method in the following code.
4.  Save the changes made to the table.
5.  Expand Forms > SalesTable > Designs.
6.  Right-click on the design node and select Properties.
7.  Change the WorkflowEnabled property to Yes.
8.  Change the WorkflowDatasource property to SalesTable.
9.  Right-click on the form Methods node and select Override
Method > canSubmitToWorkflow.
10. Copy the second method in the following code into the method.
boolean canSubmitToWorkflow()
{
amountMST creditBalance;
custTable custTable;
;
if (!this.CreditLimitApprovalStatus ==
SalesCreditLimitApprovalStatus::NotSubmitted)
return false;
custTable = this.custTable_InvoiceAccount();
if (!custTable.CreditMax)
return false;
creditBalance = custTable.CreditMax -
custTable.balanceMST();
if (this.amountRemainSalesFinancial() +
this.amountRemainSalesPhysical() < creditBalance)
return false;
return true;
}
public boolean canSubmitToWorkflow()
{
return salesTable.canSubmitToWorkflow();
}
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Development IV in Microsoft Dynamics
®
AX2009
11-10
The canSubmitToWorkflow method returns true if the ProjJournalTable record
has not already been submitted and the total hours entered in the transactions is
greater than 40.
Demonstration: Create a Submit to Workflow Class
To submit a document to workflow, call standard code to prompt the user for a
comment and to process the submisson. This demonstration shows you how to
create a submit to workflow class.
1.  Open the AOT and create a new class.
2.  Copy the following code in to the classDeclaration, submit method
and the main method.
3.  Press F8 to save and compile the code.
4.  Open another AOT and expand Menu Items.
5.  Drag the SalesCreditLimitSubmit class to the Actions node.
6.  Right-click on the newly created Actions node and select Properties.
7.  Change the Label property to Submit.
8.  Right-click on the SalesCreditLimitSubmit menu item and select
Save.
9.  Locate the workflow template node in the AOT.
10. Right-click and select Properties.
11. Change the SubmitToWorkFlowMenuItem property to
SalesCreditLimitSubmit.
class SalesCreditLimitSubmit
{
}
void submit(Args args)
{
// Variable declaration.
recId recId = args.record().RecId;
WorkflowCorrelationId workflowCorrelationId;
// Hardcoded template name
WorkflowTemplateName workflowTemplateName =
workflowtemplatestr(SalesCreditLimitApproval);
// Initial note is the information that users enter
when they
// submit the document for workflow.
WorkflowComment note ="";
WorkflowSubmitDialog workflowSubmitDialog;
SalesTable SalesTable;
;
// Opens the submit to workflow dialog.
workflowSubmitDialog =
WorkflowSubmitDialog::construct(args.caller().getActiveWork
flowConfiguration());
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-11
workflowSubmitDialog.run();
if (workflowSubmitDialog.parmIsClosedOK())
{
recId = args.record().RecId;
SalesTable = args.record();
// Get comments from the submit to workflow dialog.
note = workflowSubmitDialog.parmWorkflowComment();
try
{
ttsbegin;
workflowCorrelationId =
Workflow::activateFromWorkflowTemplate(workflowTemplateName
,
recId,
note,
NoYes::No);
SalesTable.CreditLimitApprovalStatus =
SalesCreditLimitApprovalStatus::Submitted;
// Send an Infolog message.
info("Submitted to workflow.");
ttscommit;
}
catch(exception::Error)
{
info("Error on workflow activation.");
}
}
args.caller().updateWorkFlowControls();
}
public static void main(Args _args)
{
SalesCreditLimitSubmit SalesCreditLimitSubmit
= new SalesCreditLimitSubmit();
;
SalesCreditLimitSubmit.submit(_args);
}
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Development IV in Microsoft Dynamics
®
AX2009
11-12
Create Event Handlers
Event handlers are used to execute business logic at specific events in the
workflow. They can be implemented at the workflow level, for example when the
workflow is started or completed, or at an element level, for example when
anyone approves or rejects a step in the approval.
Event handlers are implemented by creating a class that implements one or more
of the EventHandler interfaces. The interfaces at the workflow level are as
follows:
Event  Description
WorkflowStartedEventHandler  This event raises when the
workflow instance starts.
WorkflowCompletedEventHandler  This event raises when the
workflow instance ends after it
is completed.
WorkflowCanceledEventHandler   This event raises when the
workflow instance ends after it
is canceled. Use this event
handler to perform any clean
up operations needed.
WorkflowConfigDataChangeEventHandler This event raises when the
workflow configuration data
changes. Use this event
handler to identify when a
configuration has changed. For
example, if you create an
association between the
application data and a
workflow configuration, this
event handler would raise if
the configuration was deleted
or updated.
Demonstration: Add Workflow Level Event Handlers
This demonstration shows you how to add workflow level event handlers.
1.  Create a new class. Add the following ClassDeclaration and
methods.
2.  Open the properties form for the SalesCreditLimitApproval
workflow template.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-13
3.  Set StartedEventHandler, CompletedEventHandler and
CanceledEventHandler properties toSalesCreditLimitEventHandler
class SalesCreditLimitEventHandler implements
WorkflowStartedEventHandler,
WorkflowCanceledEventHandler,
WorkflowCompletedEventHandler
{
}
public void cancelled(WorkflowEventArgs _workflowEventArgs)
{
SalesTable SalesTable;
;
ttsbegin;
select forupdate SalesTable
where SalesTable.RecId ==
_workflowEventArgs.parmWorkflowContext().parmRecId();
SalesTable.CreditLimitApprovalStatus =
SalesCreditLimitApprovalStatus::NotSubmitted;
SalesTable.update();
ttscommit;
}
public void completed(WorkflowEventArgs _workflowEventArgs)
{
SalesTable SalesTable;
;
ttsbegin;
select forupdate SalesTable
where SalesTable.RecId ==
_workflowEventArgs.parmWorkflowContext().parmRecId();
if (salesTable.CreditLimitApprovalStatus ==
SalesCreditLimitApprovalStatus::Submitted)
{
SalesTable.CreditLimitApprovalStatus =
SalesCreditLimitApprovalStatus::Approved;
SalesTable.update();
}
ttscommit;
}
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Development IV in Microsoft Dynamics
®
AX2009
11-14
public void returned(WorkflowEventArgs _workflowEventArgs)
{
SalesTable SalesTable;
;
ttsbegin;
select forupdate SalesTable
where SalesTable.RecId ==
_workflowEventArgs.parmWorkflowContext().parmRecId();
SalesTable.CreditLimitApprovalStatus =
SalesCreditLimitApprovalStatus::Rejected;
SalesTable.update();
ttscommit;
}
public void started(WorkflowEventArgs _workflowEventArgs)
{
SalesTable SalesTable;
;
ttsbegin;
select forupdate SalesTable
where SalesTable.RecId ==
_workflowEventArgs.parmWorkflowContext().parmRecId();
SalesTable.CreditLimitApprovalStatus =
SalesCreditLimitApprovalStatus::Submitted;
SalesTable.update();
ttscommit;
}
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-15
Element Level Event Handlers
The interfaces at the workflow element level are as follows:
Event  Description
WorkflowElementStartedEventHandlerThis event raises when the
task or approval starts.
For approvals, you can use
this event to transition the
workflow document state
from Submitted to
PendingApproval.
WorkflowElementCanceledEventHandlerThis event raises when the
task or approval is canceled.
For approvals, you can use
this event to transition the
workflow document state
from the current state to
Canceled.
WorkflowElementCompletedEventHandler This event raises when the
task or approval is completed.
For approvals, you can use
this event to transition the
workflow document state
from PendingApproval to
Approved.
WorkflowElementReturnedEventHandlerThis event raises when the
task or approval is returned to
the originator.
For approvals, you can use
this event to transition the
workflow document state
from the current state to
RequestChange.
WorkflowElemChangeRequestedEventHandler This event raises when an
approver requests a change to
the task or approval.
For approvals, you can use
this event to transition the
workflow document state
from PendingApproval to
RequestChange.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Development IV in Microsoft Dynamics
®
AX2009
11-16
Demonstration: Add Element Level Event Handlers
This demonstration shows you how to add element level event handlers.
1.  Create a class and add the following ClassDeclaration and methods.
2.  Find the SalesCreditLimitApproval Workflow Approval element
3.  Expand the node and open the properties for the Reject node.
4.  Set the EventHandler property to SalesCreditLimitElementHandler
class SalesCreditLimitElementHandler implements
WorkflowElementCompletedEventHandler,
WorkflowElementCanceledEventHandler,
WorkflowElementReturnedEventHandler,
WorkflowElemChangeRequestedEventHandler,
WorkflowElementStartedEventHandler
{
}
public void returned(WorkflowEventArgs _workflowEventArgs)
{
SalesTable SalesTable;
;
ttsbegin;
select forupdate SalesTable
where SalesTable.RecId ==
_workflowEventArgs.parmWorkflowContext().parmRecId();
SalesTable.CreditLimitApprovalStatus =
SalesCreditLimitApprovalStatus::Rejected;
SalesTable.update();
ttscommit;
}
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-17
Configure a Workflow
Now that you have created a template and enabled it on a form, you can
configure it for use.
Demonstration: Configuring a Workflow
This demonstration shows you how to configure a workflow from the main
menu.
1.  Open the main menu and select Accounts Receivable > Setup >
Workflow configurations.
2.  Click New.
3.  Select Sales credit limit approval and click Create configuration.
4.  Enter "Credit limit approval" as the name.
5.  Click Create Instruction, enter "Please approve" and then click OK.
6.  Click the Detailstab, expand SalesCreditLineApproval, and click on
Step 1.
7.  Under Step details, click on Assignmenttab.
8.  Click the Choosebutton.
9.  Select User based, enter a user in the Select users field and then click
OK.
10. Close the approval form.
11. On the configuration form click Set as active.
12. Click the Overviewtab.
13. Click Set as default.
The workflow is now ready for use.
Demonstration: Test the Workflow
This demonstration shows you how to can test the workflow by creating a
timesheet
1.  Select a customer from the customer table and set a credit limit.
2.  Create a new sales order and create lines such that the balance of the
customer plus the total amount on the lines is greater than the credit
limit.
3.  The workflow submitbutton and dialog should appear.
4.  Click the submitbutton and enter a comment.
5.  Open the AOT.
6.  Expand the Forms node.
7.  Find the form Tutorial_WorkFlowProcessor.
8.  Right-click on this form and select Open.
9.  Click Start.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Development IV in Microsoft Dynamics
®
AX2009
11-18
10. When the form says that it has zero records in queue, click Stopand
go back to the sales table form.
11. Select Actions > History. You will see that the document is waiting
for approval by the person you assigned to approve it.
12. Logon as the user who should approve the sales order
13. Open the sales order form.
14. Click the workflow Actionsbutton and select Approve.
15. Open the Tutorial_WorkflowProcessor form again and click Start,
wait for it to complete and click Stop.
16. The workflow has now been approved.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-19
Lab 11.1 - Add Another Condition to the Submit Action
Scenario
Isaac has been asked to ensure that, once a credit limit has been reached, the sales
order cannot be posted until the workflow has been approved.
Challenge Yourself!
Add conditions to the posting functions on the sales order form that will prevent
posting to picking, packing or invoicing until the workflow has been approved. If
the credit limit has not been reached, then the postings should be allowed.
Step by Step
1.  Add the following method CanPostCreditLimit to the salesTable
table.
2.  Add the following code to the methods canPickingListBeUpdate(),
canPackingSlipBeUpdated() and canInvoiceBeUpdated() in the
salesTableType class.
boolean canPostCreditLimit()
{
amountMST creditBalance;
custTable custTable;
;
if (this.CreditLimitApprovalStatus ==
SalesCreditLimitApprovalStatus::Approved)
return true;
if (this.CreditLimitApprovalStatus ==
SalesCreditLimitApprovalStatus::Rejected
|| this.CreditLimitApprovalStatus ==
SalesCreditLimitApprovalStatus::Submitted)
return false;
custTable = this.custTable_InvoiceAccount();
if (!custTable.CreditMax)
return true;
creditBalance = custTable.CreditMax -
custTable.balanceMST();
if (this.amountRemainSalesFinancial() +
this.amountRemainSalesPhysical() < creditBalance)
return true;
return false;
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Development IV in Microsoft Dynamics
®
AX2009
11-20
}
boolean canPickingListBeUpdated()
{
......
ok = ok && salesTable.canPostCreditLimit();
return ok;
}
boolean canPackingslipBeUpdated()
{
......
ok = ok && salesTable.canPostCreditLimit();
return ok;
}
boolean canInvoiceBeUpdated()
{
......
ok = ok && salesTable.canPostCreditLimit();
return ok;
}
Code Walkthrough: Submitting a workflow
When a record is submitted to workflow, the main()method in the submit to
workflow class is called.
1.  View the ProjTimeApprovalsSTWF.main() method created in the
Create A Submit to Workflow Class demonstration. The user is
prompted for a comment while submitting the workflow
workflowSubmitDialog =
WorkflowSubmitDialog::construct(args.caller().getActiveWork
flowConfiguration());
workflowSubmitDialog.run();
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-21
The record is retrieved from the calling formand the recId is passed to the static
method Workflow::activateFromWorkflowTemplate(), which runs the submit
process.
ProjJournalTable = args.record();
// Get comments from the submit to workflow dialog.
_initialNote = workflowSubmitDialog.parmWorkflowComment();
try
{
ttsbegin;
// Activate the workflow.
_workflowCorrelationId =
Workflow::activateFromWorkflowTemplate(_workflowTemplateNam
e, _recId, _initialNote, NoYes::No);
2.  View the method Workflow::activateFromWorkflowTemplate()
tableId =
Workflow::getDocumentTableId(_workflowTemplateName);
configTable =
Workflow::findWorkflowConfigToActivateForTemplate(_workflow
TemplateName, _recId, tableId);
The tableId that the workflow is to be performed on is retrieved from the query
specified in the workflow document class.
The workFlowContext class holds all the relevant data for the workflow
submission. The SysWorkFlowEventDispatcher class creates records that will be
read by the Workflow Processor class todetermine which actions should be
executed in the next step of the workflow.
workflowContext =
WorkflowContext::newRootWorkflowContext(curext(), tableId,
_recId, correlationId);
try
{
SysWorkflowEventDispatcher::onWorkflowSubmit(workflowContex
t, _submittingUser, configTable.ConfigurationId,
_initialNote, _activatingFromWeb);
}
3.  Return to the ProjTimeApprovalsSTWF.main() method
ProjJournalTable.WorkFlowState = true;
The journal is marked as submitted.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Development IV in Microsoft Dynamics
®
AX2009
11-22
Code Walkthrough: Workflow Processor
All workflows are processed through a batch process. To view a simulation of
how the workflows are processed, use the form Tutorial_WorkflowProcessor.
1.  View the form method doMessageProcessing on the form
Tutorial_WorkflowProcessor.
while select workflowWorkItemTable where
workflowWorkItemTable.Type ==
WorkflowWorkItemType::WorkItem &&
(workflowWorkItemTable.Status ==
WorkflowWorkItemStatus::Pending ||
workflowWorkItemTable.Status ==
WorkflowWorkItemStatus::Delegated) &&
workflowWorkItemTable.DueDateTime <
DateTimeUtil::getSystemDateTime()
{
WorkflowWorkItem::escalateWorkItem(SysWorkflowWorkItemConte
xt::newWorkflowWorkItemContextFromWorkItem(workflowWorkItem
Table));
cntWorkItems++;
}
All records due for processing are retrieved. The
WorkflowWorkItem::escalateWorkItem() is called
2.  View the method WorkflowWorkItem::escalateWorkItem()
try
{
workItemId =
SysWorkflowEventDispatcher::onWorkItemEscalation(_workItemC
ontext);
}
3.  View the method
SysWorkflowEventDispatcher::onWorkItemEscalation()
workItemTable =
WorkflowWorkItemTable::findPendingActivityInstanceId(_workI
temContext.parmWorkflowActivityInstanceKey().parmWorkflowAc
tivityInstanceId(), true);
The workItemTable record is retrieved. This is the next pending activity on the
workflow, based on the configuration.
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-23
The action to be performed is examined
switch (stepTable.EscalationType)
{
case WorkflowEscalationType::Action:
workItemInstanceId = workItemTable.Id;
The next step is completed.
workItemTable.Status =
SysWorkflowEventDispatcher::completeWorkItem(
_workItemContext,
workItemTable,
stepTable.EscalationAction,
workItemTable.UserId,
workflowTable.Originator, // always set the auto-escalate user to the workflow originator
"@SYS110277");
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Development IV in Microsoft Dynamics
®
AX2009
11-24
Lab 11.2 - Enable Resubmit
Scenario
Issac is required to ensure the workflowcan be resubmitted after it has been
rejected.
Challenge Yourself!
When a workflow is rejected, it should be able to be resubmitted. Modify the
Submit to Workflow class so that it can resubmit the workflow after a rejection
Use the PurchReqWorkflow class as inspriration.
Step by Step
1.  Create a new action menu item called SalesCreditLimitResubmit
2.  Set the ObjectTypePropety to class, the Object property to
SalesCreditLimitSubmit and the Label property to Resubmit.
3.  Modify the Main method on the SalesCreditLimitSubmit class and
add a new method Resubmit as follows:
4.  On the SalesCreditLimitApproval approval element, set the
ResubmitMenuItem property to SalesCreditLimitResubmit
public static void main(Args _args)
{
SalesCreditLimitSubmit SalesCreditLimitSubmit
= new SalesCreditLimitSubmit();
;
if (_args.menuItemName() ==
menuitemactionstr(SalesCreditLimitSubmit))
{
SalesCreditLimitSubmit.submit(_args);
}
else
{
SalesCreditLimitSubmit.resubmit(_args);
}
}
void resubmit(Args args)
{
// Variable declaration.
recId _recId = args.record().RecId;
WorkflowCorrelationId _workflowCorrelationId;
// Hardcoded template name
WorkflowTemplateName _workflowTemplateName =
workflowtemplatestr(SalesCreditLimitApproval);
Microsoft Official Training Materials for Microsoft Dynamics ®
Your use of this content is subject to your current services agreement
Chapter 11: Workflow
11-25
// Initial note is the information that users enter
when they
// submit the document for workflow.
WorkflowComment _initialNote ="";
WorkflowWorkItemActionDialog
WorkflowWorkItemActionDialog;
SalesTable SalesTable;
;
// Opens the submit to workflow dialog.
workflowWorkItemActionDialog =
WorkflowWorkItemActionDialog::construct(
args.caller().getActiveWorkflowWorkItem(),
WorkflowWorkItemActionType::Resubmit,
new
MenuFunction(menuitemactionstr(PurchReqReSubmit),
MenuItemType::Action));
workflowWorkItemActionDialog.run();
if (WorkflowWorkItemActionDialog.parmIsClosedOK())
{
_recId = args.record().RecId;
SalesTable = args.record();
// Get comments from the submit to workflow dialog.
_initialNote =
workflowWorkItemActionDialog.parmWorkflowComment();
try
{
ttsbegin;
WorkflowWorkItemActionManager::dispatchWorkItemAction(
args.caller().getActiveWorkflowWorkItem(),
_initialNote,
curUserId(),
WorkflowWorkItemActionType::Resubmit,
args.menuItemName(),
false);
SalesTable.CreditLimitApprovalStatus =
SalesCreditLimitApprovalStatus::Submitted;
// Send an Infolog message.
info("Resubmitted to workflow.");

Workflow in ax 2012

WORKFLOW in MS Dynamics AX 2012
Workflow Configuration
There are three batch jobs that manage workflow processing. These jobs are all
run on the Application Object Server (AOS) using the Batch system. To set this
up, run System Administration > Setup > Workflow > Workflow
infrastructure configuration. Enter batch groups for each process. Batch groups
can be used to control which AOS instance each workflow batch job is run on.
  Create a Workflow Category
1. Open the AOT.
2. Expand the Workflow node.
3. Right-click on the Workflow Categories node and select New
Workflow Category. A new workflow category called Workflow
Category1 will be created.
4. Right-click on the newly created workflow category and select
Properties.
5. Change the name property to SalesCategory.
6. Change the label property to Sales workflows.
7. Change the Module property to SalesOrder.
8. Right-click on the newly created workflow category and select Save.
Create a Workflow Category (Step by Step with screen shot)
=================================================================================
  Create a Query
1. Open the AOT.
2. Right-click on the Queries node and select New Query.
3. Rename the query to SalesCreditLimitApproval.
4. Expand the newly created query.
5. Open another AOT window.
6. Expand Data Dictionary > Tables.
7. Find the table SalesTable.
8. Drag the SalesTable table to the Data Sources node of the
SalesCreditLimitApproval query.
9. Expand the SalesTable_1 node
10. Right-click on the Fields node and select Properties.
11. Set the Dynamics property to Yes and close the property sheet.
12. Right click on the SalesCreditLimitApproval query and select
Save.
Create a Workflow Category (Step by Step with screen shot)
==================================================================================
  Create a Workflow Type
1. Open the AOT.
2. Expand the Workflow node.
3. Right-click on the Workflow Types node and select Add-ins >
Workflow type wizard.
4. Click Next.
5. Enter SalesCreditLimitAppr in the name.
6. Enter SalesCategory in the Category.
7. Enter SalesCreditLimitApproval in the query.
8. Enter SalesTable in the Document menu item.
9. Click Next.
10. Click Finish. A development project with a number of newly created
elements will be displayed.
Create a Workflow  Type   (Step by Step with screen shot)
==================================================================================
  Enable Workflow on a Form
Add a WorkflowState Field
1. Open the AOT.
2. Expand Data Dictionary.
3. Right-click on Base Enums and select New Base Enum.
4. Rename the new enum to SalesCreditLimitApprovalStatus
5. Add four elements to the Enum called NotSubmitted, Submitted,
Approved, Rejected.
6. Expand Tables > SalesTable.
7. Right-click on Fields and select New > Enum.
8. Right-click on the newly created field and select Properties.
9. Change the Name property to CreditLimitApprovalStatus.
10. Change the EnumType property to
SalesCreditLimitApprovalStatus.
11. Right-click on the SalesTable node and select Save.
Add a WorkflowState Field (Step by Step with screen shot)
Enable Workflow on the Form
1. Open the AOT.
2. Expand Tables > SalesTable.
3. Create a new method and add the method in the following code.
4. Save the changes made to the table.
5. Expand Forms > SalesTableListPage > Designs.
6. Right-click on the design node and select Properties.
7. Change the WorkflowEnabled property to Yes
8. Change the WorkflowDatasource property to SalesTable.
9. Change the WorkflowType property to SalesCreditLimitAppr
10. Save your changes to the form.
boolean canSubmitToWorkflow(str _workflowType = '')
{
amountMST creditBalance;
custTable custTable;
;
if (!this.CreditLimitApprovalStatus ==
SalesCreditLimitApprovalStatus::NotSubmitted)
return false;
custTable = this.custTable_InvoiceAccount();
if (!custTable.CreditMax)
return false;
creditBalance = custTable.CreditMax -custTable.balanceMST();
if (this.amountRemainSalesFinancial() +
this.amountRemainSalesPhysical() < creditBalance)
return false;
return true;
}
Enable Workflow on the form (Step by Step with screen shot)
Create a Submit to Workflow Class
1. Press Ctrl+Shift+P to open the development projects window.
2. Expand Private.
3. Double-click on SalesCreditLimitApprWFType development project.
4. In the development project find the class
SalesCreditLimitApprSubmitManager.
5. Create a new method called submit, and copy the following code for
this method.
6. Modify the code for the main method as shown in the following code.
7. Press F8 to save and compile the code.
8. Find the menu item SalesCreditLimitApprSubmitMenuItem.
9. Change the Label property to Submit.
10. Right-click on the SalesCreditLimitApprSubmitMenuItem menuitem and select Save.
void submit(Args args)
{
// Variable declaration.
recId recId = args.record().RecId;
WorkflowCorrelationId workflowCorrelationId;
// Hardcoded type name
WorkflowTypeName workflowTypeName =workflowtypestr(SalesCreditLimitAppr);
// Initial note is the information that users enter
when they
// submit the document for workflow.
WorkflowComment note ="";
WorkflowSubmitDialog workflowSubmitDialog;
SalesTable SalesTable;
// Opens the submit to workflow dialog.
workflowSubmitDialog = WorkflowSubmitDialog::construct(args.caller().getActiveWorkflowConfiguration());
workflowSubmitDialog.run();
if (workflowSubmitDialog.parmIsClosedOK())
{
recId = args.record().RecId;
SalesTable = args.record();
// Get comments from the submit to workflow dialog.
ttscommit;
}
catch(exception::Error)
{
info("Error on workflow activation.");
}
}
args.caller().updateWorkFlowControls();
}
note = workflowSubmitDialog.parmWorkflowComment();
try
{
ttsbegin;
workflowCorrelationId = Workflow::activateFromWorkflowType(workflowTypeName,recId,note,NoYes::No);
SalesTable.CreditLimitApprovalStatus = SalesCreditLimitApprovalStatus::Submitted;
// Send an Infolog message.
info("Submitted to workflow.");
Create a submit to Workflow Class   (Step by Step with screen shot)
Create a Workflow Approval
1. Open the AOT.
2. Expand the Workflow node.
3. Right-click on Approvals and select Add-ins > Approval wizard.
4. Click Next.
5. Enter SalesCLApproval in Name.
6. Enter SalesCreditLimitApprDocument in Workflow document.
7. Enter Overview in Document preview field group.
8. Enter SalesTableListPage in Document menu item.
9. Click Next.
10. Click Finish. A development project with a number of newly created
elements is displayed.
11. Drag SalesCLApproval approval to the Supported elements node
on the SalesCreditLimitAppr workflow type.
12. Save your changes to the SalesCreditLimitAppr workflow type
Creating a   Workflow Approval  (Step by Step with screen shot)


  Create Event Handlers
Write code for Event Handler
1. Press Ctrl+Shift+P to open the development projects window.
2. Expand Private.
3. Double-click on SalesCreditLimitApprWFType development project.
4. In the development project find the class SalesCreditLimitApprEventHandler.
The following code needs tobe added to the completed method of the
SalesCreditLimitApprEventHandler class.
public void completed(WorkflowEventArgs _workflowEventArgs)
{
SalesTable SalesTable;
select forupdate SalesTable where SalesTable.RecId ==
_workflowEventArgs.parmWorkflowContext().parmRecId();
if(SalesTable.RecId)
{
SalesTable.CreditLimitApprovalStatus =
SalesCreditLimitApprovalStatus::Approved;
SalesTable.write();
}
}
Add Element Level Event Handlers
1. In the AOT locate the class SalesCLApprovalEventHandler. This class was created by the Approval
element wizard.
2. Add the following code in the returned method
3. Save your changes to the class.
4. In the AOT, right-click on the AOT node and select Incremental
CIL generation from X++
public void returned(WorkflowElementEventArgs
_workflowElementEventArgs)
{
SalesTable SalesTable;
ttsbegin;
select forupdate SalesTable
where SalesTable.RecId ==
_workflowElementEventArgs.parmWorkflowContext().parmRecId()
;
SalesTable.CreditLimitApprovalStatus =
SalesCreditLimitApprovalStatus::Rejected;
SalesTable.update();
ttscommit;
}
Author a Workflow
1. The workflow category we created in the first procedure needs to be
added to the main menu. Create a new display menu item called
WorkflowConfigurationSales.
2. Set the label to Sales workflows.
3. Set the object to WorkflowTableListPage.
4. Set the EnumTypeParameter to ModuleAxapta.
5. Set the EnumParameter to SalesOrder.
6. Add the new menu item to SalesAndMarketting > Setup menu.
7. In the property sheet for the new node in the menu, set the property
IsDisplayedInContentArea to Yes.
8. Save your changes to the menu.
9. Open the main menu and select Sales and Marketting > Setup > Sales workflows.
10. Click New.
11. Select SalesCreditLimitApprType and click Create workflow.
The workflow editor window opens.
12. Drag SalesCLApprovalApproval approval from the Workflow elements window to the
Workflow window.
13. Drag the bottom node of the Start box to the top node of the Approval box.
14. Drag the bottom node of the Approval box to the top node of the End box.
15. Double click on the Approval box.
16. Click Step 1
17. Click Assignment.
18. On the Assignment type tab, select User
19. On the User tab, double click on Sammy
20. Click on Basic Settings and then enter a subject and instructions for the approval
21. Click on Close
22. Click on Save and Close
23. Enter some notes for the new workflow if you wish.
24. Select to Activate the new version
25. Click OK.
Authoring a Workflow   (Step by Step with screen shot)


  Test the Workflow
1. In the application workspace, navigate to Accounts receivable > Common > Customers > All
customers.
2. Select a customer and click Edit.
3. In the Credit and collections fasttab, set a credit limit.
4. Close the Customers form.
5. Go to Sales and marketting > Common > Sales orders > All sales orders.
6. Click New sales order. Enter the customer account modified that
you modified the credit limit for and click ok.
7. Enter items and quantities in the sales lines so that the balance of the customer plus the total
amount on the lines is greater than the credit limit.
8. The workflow Submit button and dialog should appear.
9. Click the Submit button and enter a comment.
10. Wait for the batch job to process the workflow request. This should take one to two minutes.
11. Select Actions > History. You will see that the document is waiting for approval by the person
you assigned to approve it.
12. Logon to windows as the Sammy using the Switch User option on the Start menu.
13. Start the Microsoft Dynamics AX client.
14. Open the Sales order form.
15. Click the workflow Actions button and select Approve.
16. Wait one to two minutes for the workflow engine to process the approval.
Workflow in ax 2012 download17. The workflow has now been approved. 

Number Sequence for existing module in ax 2012

 NumberSequence for  the Existing module
To create a numbersequence for  the Existing module.
Suppose in my HRM Module for the Employee Table I have to create the NumberSequence  (EmplTable).
I need to follow these steps to create the NumberSequence  .
 Go to the Classes -> NumberseqReference_HRM (Class) -> LoadMethod

In the load method you have to override the code , need to added the code to which field we are planning to add the code that it can be copied from the exisitng code and modfiy the EDT which we want to add   ( Here My EDT is EmplId)

Let us Assume (Existing Code )
numRef.DataTypeId = typeId2ExtendedTypeId(typeid(HRMApplicationId));


For The Empl Id We have to add the code means

numRef.DataTypeId = typeId2ExtendedTypeId(typeid(EmplId));


After completing the above procedure, we have to go to AOT -> Tables ->HRM Parameters -> Need to Override the code  in the method
Ex: The Overrided code is

static client server NumberSequenceReference numRefEmplId()
{
    return NumberSeqReference::findReference(typeId2ExtendedTypeId(typeid(EmplId)));
}

Same code u copy as per u r requirement in there see the below screen shot

After the above step go to the Empl Form -> Form Level Methods u have to write the number sequence formhandler method have to create the code.
See the below figure.


Class declaration Code
IN the class declaration we have to write the code

NumberSeqFormHandler numberSeqFormHandler;

Numberseqformhandler Code
In the Numberseqformhandler write the below code

NumberSeqFormHandler numberSeqFormHandler()
{
    if (!numberSeqFormHandler)
    {
        numberSeqFormHandler = NumberSeqFormHandler::newForm(HRMParameters::numRefEmplId().NumberSequence,element, EmplTable_ds, fieldnum(EmplTable, EmplId));
    }
    return numberSeqFormHandler;
}

Then we have to Override  the DataSource Methods ( Create, Write ,Delete).

Write Method Code is
element.numberSeqFormHandler().formMethodDataSourceWrite(); ---- After Super

Create Method is
element.numberSeqFormHandler().formMethodDataSourceCreatePre(); - Before Super
super();
  element.numberSeqFormHandler().formMethodDataSourceCreate(); --- > After Super
Delete Method Code Is
element.numberSeqFormHandler().formMethodDataSourceDelete();---- After Super

After completing all the above steps.
Go -> HRM Module -> Setup -> Parameters -> Numbersequence


We have to add the reference for the EMP ID. To add the reference see the below screens .
Task1
Auto-generated document.



Task1 1
Form name: Human Resource parameters 2
Form name: Number sequences 3


1. Click Area Page node: Human Resources -> Setup -> Parameters.

Form name: Human Resource parameters
2. Switch to the Number sequences tab on the Human Resource parameters form.
3. Select the Number sequence code field.
4. Right-click the field to go to the main table.
Form name: Number sequences
5. Create a new record in the Number sequences form.
6. Change Number sequence code from 'Test_001' to 'Acco_42'.
7. Change Name from 'Testing' to 'Acco_42'.
8. Change Largest from '999999' to '99999999'.
9. Change Next from '4' to '1'.
10. Change Format from 'TST_######' to '########_042'.
11. Change In use from 'Yes' to 'No'.
12. Change Number sequence code from '' to 'USR_001'.
13. Change Name from '' to 'EmplTable'.
14. Change Format from '' to 'USR_######'.
15. Switch to the General tab on the Number sequences form.
16. Change Continuous from 'false' to 'true'.
17. Save the record in the Number sequences form.
18. Switch to the Overview tab on the Number sequences form.
19. Close the Number sequences form.
20. Change Number sequence code from 'Test_001' to 'USR_001'.
21. Save the record in the Human Resource parameters form.
22. Close the Human Resource parameters form.
23. Click the Microsoft Dynamics AX -> Tools -> Task Recorder menu item.

How to send SMS through code in ax 2012

public static void sendsms(Args _args)
{
System.Net.WebClient custWebclient;
System.IO.Stream InfoData;
System.IO.StreamReader Streamreader;
System.String URLStr;
Str SMSConfirmID;
str mobileno='983499999';
str message='Test SMS';
;
custWebclient=new System.Net.WebClient();
URLStr="http://www.smszone.in/sendsms.asp?
page=SendSmsBulk&username=87676767645&password=8787&number="+mobileno+"&message="+message;

//URLStr="http://site5.way2sms.com/content/index.html/Login1.action?//username=9910999999&password=26&phone="+mobileno+"&msg="+message;

//URLStr="http://site5.way2sms.com/content/index.html/Login1.action?username=9910999999&password=26&number="+mobileno+"&message="+mess

//URLStr="http://site5.way2sms.com/content/index.html/Login1.action?username=9910999999&password=26&phone=9910711493&msg=hggfjhfhggf";

//URLStr="http://site5.way2sms.com/content/index.html/Login1.action?username=9910999999&password=26&number=9910711493&message=hggfjhfhggf";

InfoData=custWebclient.OpenRead(URLStr);
Streamreader=new System.IO.StreamReader(InfoData);
SMSConfirmID=Streamreader.ReadToEnd();
InfoData.Close();
Streamreader.Close();
}