Enable Database Log on all Parameter- and Group-Tables

I want to make sure that I know who changed what and when on all parameter- and group-tables.

The following script will enable the database log on all those tables:

static void enableDatabaselogOnParameterTables(Args _args)
{
    #AOT
    DatabaseLog         databaseLog;
    TreeNode            treeNode;
    SysDictTable        sysDictTable;
    Name                name;
    ;
    ttsbegin;
    treeNode = TreeNode::findNode(#TablesPath);
    treeNode = treeNode.AOTfirstChild();
    while (treeNode)
    {
        name = treeNode.AOTname();
        sysDictTable = SysDictTable::newTableId(treeNode.applObjectId());
        if((sysDictTable.tableGroup() == TableGroup::Parameter || sysDictTable.tableGroup() == TableGroup::Group)
            && SysQueryForm::hasValidCountryCode(sysDictTable.id()))
        {
            select firstOnly databaseLog where databaseLog.logTable == sysDictTable.id(); //do not modify existing settings
            if(!databaseLog)
            {
                databaseLog.LogTable = sysDictTable.id();
                databaseLog.LogField = 0;
                databaseLog.LogType = DatabaseLogType::Update;
                databaseLog.insert();
                databaseLog.LogType = DatabaseLogType::EventUpdate;
                databaseLog.insert();
                if(sysDictTable.tableGroup() != TableGroup::Parameter)
                {
                    databaseLog.LogType = DatabaseLogType::Delete;
                    databaseLog.insert();
                    databaseLog.LogType = DatabaseLogType::EventDelete;
                    databaseLog.insert();
                    databaseLog.LogType = DatabaseLogType::RenameKey;
                    databaseLog.insert();
                    databaseLog.LogType = DatabaseLogType::EventRenameKey;
                    databaseLog.insert();
                    databaseLog.LogType = DatabaseLogType::Insert;
                    databaseLog.insert();
                    databaseLog.LogType = DatabaseLogType::EventInsert;
                    databaseLog.insert();
                }
            }
        }
        treeNode = treeNode.AOTnextSibling();
    }
    ttscommit;
    SysFlushDatabaseLogSetup::main();
}

How to get radio buttons on a dialog

There is no dialog.addRadioButtonContol(…) function so how do you do it?

static void Job1(Args _args)
{
    Dialog                dialog;
    FormRadioControl      formRadioControl;
    FormBuildRadioControl formBuildRadioControl;
    FormBuildGroupControl formBuildGroupControl;
    int                   formBuildRadioControlId;
    ;
    //Build dialog with radio buttons
    dialog = new Dialog("Test Dialog");
    formBuildGroupControl = dialog.mainFormGroup();
    formBuildRadioControl = formBuildGroupControl.addControl(FormControlType::RadioButton,'radiobuttons');
    formBuildRadioControlId = formBuildRadioControl.id();
    //set number of buttons
    formBuildRadioControl.items(3);
    //add descriptions
    formBuildRadioControl.item(1);
    formBuildRadioControl.text("Radiobutton 1");
    formBuildRadioControl.item(2);
    formBuildRadioControl.text("Radiobutton 2");
    formBuildRadioControl.item(3);
    formBuildRadioControl.text("Radiobutton 3");
 
    if(dialog.run())
    {
        if(formBuildRadioControl)
        {
            //get control
            formRadioControl = dialog.formRun().control(formBuildRadioControlId);
            //get index
            info(strfmt("Radiobutton %1 selected",formRadioControl.selection()+1));
        }
    }
}

Find Datatypes

I like reusing/extending data types that already exist, however it is not always easy to find them. The following job lets you search the existing data types for a keyword:

static void findEDT(Args _args)
{
    Dialog              dialog = new Dialog('Find EDT');
    SearchString        searchString;
    DialogField         dialogField = dialog.addField('SearchString');
    void searchNodes(boolean _extendedDataTypes)
    {
        TreeNode            treeNode;
        TreeNodeIterator    treeNodeIterator;
        SysDictType         sysDictType;
        SysDictEnum         sysDictEnum;
        ;
        if(_extendedDataTypes)
        {
            treeNode = TreeNode::findNode('\\Data Dictionary\\Extended Data Types');
        }
        else
        {
            treeNode = TreeNode::findNode('\\Data Dictionary\\Base Enums');
        }
        treeNodeIterator = treenode.AOTiterator();
        treeNode = treeNode.AOTfirstChild();
        treeNode = treeNodeIterator.next();
        while(treeNode)
        {
            if(treeNode.treeNodeName() like "*" + searchString + "*")
            {
                if(_extendedDataTypes)
                {
                    sysDictType = sysDictType::newTreeNode(treeNode);
                }
                if(sysDictType)
                {
                    if (sysDictType.extend() && sysDictType.enumId())
                    {
                        info(strfmt("%1 (%2 - %3 -> %4)",treeNode.treeNodeName(), sysDictType.baseType()
                            , extendedTypeId2name(sysDictType.extend()), enumId2Name(sysDictType.enumId()) ));

                    }
                    if(sysDictType.extend())
                    {
                        info(strfmt("%1 (%2 - %3)",treeNode.treeNodeName(), sysDictType.baseType()
                            , extendedTypeId2name(sysDictType.extend()) ));

                    }
                    else if (sysDictType.enumId())
                    {
                        info(strfmt("%1 (%2 - %3)",treeNode.treeNodeName(), sysDictType.baseType()
                            , enumId2Name(sysDictType.enumId()) ));

                    }
                    else
                    {
                        info(strfmt("%1 (%2)",treeNode.treeNodeName(), sysDictType.baseType()));
                    }
                }
                else
                {
                    info(strfmt("%1",treeNode.treeNodeName()));
                }
            }
            treeNode = treeNodeIterator.next();
        }
    }
    ;
    if(dialog.run())
    {
        searchString = dialogField.value();
        info(strfmt("Find %1",searchString));
        if(searchString)
        {
            setPrefix('Extended Data Types');
            searchNodes(true);
            setPrefix('Base Enums');
            searchNodes(false);
        }
    }
}

Identify country specific functionality

Add the following to SysCountryRegionCode::isLegalEntityInCountryRegion

Idea by Kim Steffensen (Microsoft Escalation engineer)

public static boolean isLegalEntityInCountryRegion(container _isoCountryCodes, selectableDataArea _selectableDataArea = curext())
{
    #Define.DEBUG_ALL(true)                 //set true to get infolog for every country evaluated
    #Define.DEBUG_SINGLECOUNTRY(false)      //set true to get infolog when active country is evaluated
    int                             i;
    str                             callingPath;
    int                             line;

    if(#DEBUG_ALL || #DEBUG_SINGLECOUNTRY)
    {   //initialize context
        callingPath = subStr(conPeek(xSession::xppCallStack(),3),4,999);
        line = conPeek(xSession::xppCallStack(),4);
    } 

    if(#DEBUG_ALL && ! #DEBUG_SINGLECOUNTRY)
    {   //print context of every country evaluated
        for(i=1; i <= conLen(_isoCountryCodes); i++)
        {
            info(strFmt("%1 %2 %3",conPeek(_isoCountryCodes,i),callingPath,line),"",SysInfoAction_Editor::newLineColumn(callingPath,line));
        }
    }
    if (conFind(_isoCountryCodes, SysCountryRegionCode::countryInfo(_selectableDataArea)))
    {
        if(#DEBUG_SINGLECOUNTRY)
        {   //print context of active country evaluated
            info(strFmt("%1 %2 %3",SysCountryRegionCode::countryInfo(_selectableDataArea),callingPath,line),"",SysInfoAction_Editor::newLineColumn(callingPath,line));
        }
        return true;
    }

    return false;
}

List of predefined AX 2012 Workflows

Category Workflow Description
Accounts payable Vendor bank remittance journal workflow Use this type to create approval workflows for vendor bank remittance journals
Accounts payable Vendor disbursement journal workflow Use this type to create approval workflows for vendor disbursement journals
Accounts payable Vendor draw promissory note journal workflow Use this type to create approval workflows for vendor draw promissory note journals
Accounts payable Vendor invoice approval journal workflow Use this type to create approval workflows for vendor invoice approval journals
Accounts payable Vendor invoice journal workflow Use this type to create approval workflows for vendor invoice recording journals
Accounts payable Vendor invoice line workflow Use this type to create review workflows for vendor invoice lines
Accounts payable Vendor invoice register journal workflow Use this type to create approval workflows for vendor invoice register journals
Accounts payable Vendor invoice workflow Use this type to create review workflows for vendor invoices
Accounts payable Vendor redraw promissory note journal workflow Use this type to create approval workflows for vendor redraw promissory note journals
Accounts payable Vendor settle promissory note journal workflow Use this type to create approval workflows for vendor settle promissory note journals
Accounts receivable Customer bank remittance workflow Use this type to create approval workflows for customer bank remittance journals
Accounts receivable Customer draw bill of exchange workflow Use this type to create approval workflows for customer draw bill of exchange journals
Accounts receivable Customer free text invoice workflow Use this type to create approval workflows for free text invoices
Accounts receivable Customer payment workflow Use this type to create approval workflows for customer payment journals
Accounts receivable Customer protest bill of exchange workflow Use this type to create approval workflows for customer protest bill of exchange journals
Accounts receivable Customer recurring invoice workflow Use this type to create approval workflows for recurring invoices
Accounts receivable Customer redraw bill of exchange workflow Use this type to create approval workflows for customer redraw bill of exchange journals
Accounts receivable Customer settle bill of exchange workflow Use this type to create approval workflows for customer settle bill of exchange journals
Advanced ledger entry Advanced ledger entry workflow Use this type to create approval workflows for advance ledger entries
Bank Bank reconciliation journal approval workflow Use this type to create approval workflows for Bank Reconciliation journals
Budget plan Budget plan workflows Use this type to create and review workflows for budget plans
Budget register entries Budget account entry workflow Use this type to create review workflows for budget account entries
Budget register entries Budget register entry workflow Use this type to create review workflows for budget register entries
Budget register entries Commitments approval Use this template to create approval workflows for commitment documents
Case management Case management workflow Use this type to create a workflow for cases
Case management Document handling Workflow type for document handling
Fixed assets Ledger fixed assets budget journal workflow Use this type to create approval workflows for fixed asset budget journals
Fixed assets Ledger post fixed assets journal workflow Use this type to create approval workflows for post fixed asset journals
General ledger Ledger allocations journal workflow Use this type to create approval workflows for allocation journals
General ledger Ledger daily journal workflow Use this type to create approval workflows for daily journals
General ledger Ledger eliminations journal workflow Use this type to create approval workflows for eliminations journal
Procurement and sourcing Catalog import approval Use this type to create review workflows for imported catalogs
Procurement and sourcing Catalog import product approval Use this type to create review workflows for imported catalog products
Procurement and sourcing Delivery due date notification workflow Use this type to create delivery due date notification workflows for unconfirmed product receipts
Procurement and sourcing Invoice received notification workflow Use this type to create invoice received notification workflows for unconfirmed product receipts
Procurement and sourcing Product receipt failed notification workflow Use this type to create notifications workflows for failed product receipts
Procurement and sourcing Purchase order line workflow Use this type to create review- and approval workflows for purchase order lines
Procurement and sourcing Purchase order workflow Use this type to create review- and approval workflows for purchase orders
Procurement and sourcing Purchase requisition line review Use this type to create review workflows for purchase requisition lines
Procurement and sourcing Purchase requisition review Use this type to create review workflows for purchase requisitions
Procurement and sourcing Unconfirmed product receipt rejection notification workflow Use this type to create notification workflows for rejected unconfirmed product receipts
Project Review budget revision workflow Use this type to review a budget revision
Project Review original budget workflow Use this type to review an original budget
Project Review project invoice proposals Use this type to review project invoice proposals
Project Review project quotations Use this type to review project quotations
Purchase agreement approval workflow Purchase agreement approval workflow Use this type to create approval workflows for purchase agreements
Retail catalog workflow category Retail catalog approval workflow Retail catalog approval workflow type
Signing limits Signing limits workflow Use this template to create a workflow for review of signing limit requests
Time and attendance Time and attendance days total workflow Use this type to create approval workflows for time and attendance days total records
Time and attendance Time and attendance journal registration workflow Use this type to create approval workflows for time and attendance journal registration records
Timesheet Review timesheet line workflow Use this type to review a timesheet line
Timesheet Review timesheet workflow Use this type to review a timesheet
Travel and expense Cash advance request Use this type to create approval workflows for cash advance requests
Travel and expense Dispute management Use this type to create workflows for credit card dispute management
Travel and expense Expense line item Use this type to create line item approvals for expense reports
Travel and expense Expense line item auto posting Use this type to create line item automatic posting workflows for expense reports
Travel and expense Expense report Use this type to create document approvals for expense reports
Travel and expense Expense report auto posting Use this type to create document automatic posting workflows for expense reports
Travel and expense Travel requisition Use this type to create approval workflows for travel requisitions
Travel and expense VAT tax recovery Use this type to create approval workflows for VAT tax recovery
User management Inactivate user request workflow Use this type to create user inactivation workflows for inactivate user requests
User management User request workflow Use this type to create user provisioning workflows for user requests
Vendor request management Vendor add application workflow Use this type to create approval workflows for vendor add application requests
Vendor request management Vendor add justification workflow Use this type to create approval workflows for vendor add justification requests
Vendor request management Vendor category application workflow Use this type to create approval workflows for vendor category application requests
Vendor request management Vendor category justification workflow Use this type to create approval workflows for vendor category justification requests
Vendor request management Vendor status change request workflow Use this type to create approval workflows for vendor status change requests

This list was exported using the following job:
static void workFlowDescription(Args _args)
{
#AOT
Treenode                workflowTypesNode, workFlowNode;
int                     i;
int                     nodeCount;
str                     workflowName;
SysDictWorkflowType     sysDictWorkflowType;
SysDictWorkflowCategory sysDictWorkflowCategory;
;

workflowTypesNode = treenode::findNode(#WorkflowTypesPath);
nodeCount = workflowTypesNode.AOTchildNodeCount();

workFlowNode = workflowTypesNode.AOTfirstChild();
for (i=1; i<=nodeCount; ++i)
{
workflowName = workFlowNode.AOTgetProperty("Name");
try
{
sysDictWorkflowType = SysDictWorkflowType::newTypeName(workflowName);
sysDictWorkflowCategory = new SysDictWorkflowCategory(sysDictWorkflowType.category());
info(sysDictWorkflowCategory.label() + ";"
+ sysDictWorkflowType.label() + ";"
+ sysDictWorkflowType.help());
}
catch ( Exception::Error)
{
exceptionTextFallThrough();
}
workFlowNode = workFlowNode.AOTnextSibling();
}
}

AX 2012 CU7 – Send documents to e-mail addresses defined on the customer.

Probably every AX consultancy has programmed a module to send customer documents by email using addresses defined on the customer. With CU7 you can finally can do this in Standard AX:

Define a primary e-mail on the customerclip_image002

In the print dialog select “Customer primary contact”clip_image004

Result: The e-mail is sent to the primary e-mail address defined on the customer.

The settings are now saved in the print destinations and do not need to be changed anymore. When the primary e-mail address is changed, the next e-mail will automatically be sent to the new address.

Even better, once the print settings have been saved, all sales orders will pick up their respective customer emails without further settings needed.

Follow the instructions here http://blogs.msdn.com/b/axsupport/archive/2013/02/05/emailing-customer-invoices-from-a-batch.aspx, you will be able to automatically send you confirmations and invoices by email using email addresses defined on the customer.

Even better: Define e-mail addresses for different documents by applying customizable purposes:clip_image006

Select purpose in the print dialog:
clip_image008

Final Note: If the defined e-mail is missing you will get the following error.clip_image002[5]