AX 2012: Understanding postal addresses data model

Posted on Updated on

Purpose:

The purpose of this document is to quickly understand the underlying data model which is used by Dynamics AX to store postal addresses for a party. Some examples of party are customer, vendor and company.

Assumptions:

Basic understanding of UML’s crow foot notation for data modeling.

Data model:

 

Postal addresses schema

AX 2012: Automated build deployment process

Posted on Updated on

Purpose:

The purpose of this document is to describe how we can deploy automated builds to different Dynamics AX pre-production environments so that newly developed features could be rolled-out for UAT. The document also illustrates how version controlling by TFS and data migration activities fit into the big picture.

Business requirement:

Ability to release, deploy automated builds to different Dynamics AX pre-production environments to roll-out newly developed features, bug fixes for testing.

Assumptions:

  • Dynamics AX Management Utilities have been installed and configured.
  • Build scripts have been installed and configured.

AX pre-production servers topology:

ax-pre-production-environments

Process:

  1. ISV model server (Optional)
    1. Only applicable when an ISV model needs to be updated in the next build.
    2. TFS Force sync.
    3. Perform full compile, full CIL, DB synchronization.
    4. Export ISV model.
  2. Build server
    1. Must have 2 AOS instances, build and deploy. Both must not be connected to TFS.
    2. Copy ISV model to file system.
    3. Uninstall existing ISV model from build instance.
    4. Uninstall existing ISV model from deploy instance.
    5. Install new ISV model to build instance.
    6. Install new ISV model to deploy instance.
    7. Restart AOS service of build instance.
    8. Restart AOS service of deploy instance.
    9. Perform full compile, full CIL, DB synchronization on build instance.
    10. Perform full compile, full CIL, DB synchronization on deploy instance.
    11. Run build command, buildax.ps1, on build instance.
      1. Output is CUS model file created on the file system.
    12. Run deploy command, deployax.ps1 on deploy instance.
      1. Output is modelstore file created on the file system.
  3. ConsTest server
    1. Copy modelstore file to file system.
    2. Import modelstore file via powershell.
    3. Restart AOS service.
    4. Perform full compile, full CIL, DB synchronization.
  4. Document newly developed features and bug fixes in release notes.
  5. Email the notification and release notes to business stake holders.

AX 2012: Create AIF document service

Posted on Updated on

Purpose:

The purpose of this document is to illustrate how we can develop AIF document service, what are the important methods available that can be overridden to do the customization and finally how we can consume/unit test the document service through an external .NET application.

Business requirement:

Ability to integrate Dynamics AX with external systems.

Assumptions:

Application Integration Framework (AIF) has been configured to process inbound and outbound messages.

Development:

  • Create an AOT query. Prefix it with Axd to follow the naming convention for document service.
  • Run AIF document service wizard to generate/regenerate:
    • Document class (Axd class).
      • Represents whole business document.
      • Used to perform cross-table validations.
      • Serializes/deserializes the document to/from XML.
    • Document object class
      • Object interface to whole business document.
    • Data object classes
      • Object interface to underlying tables involved in the document.
    • AxBC classes, if chosen
      • Wrapper classes for underlying tables involved in the document.
      • Used to perform table-level validations.
        • For example, AxSalesLine.validateWrite method.
        • It then calls validateWrite method of SalesLine table.
      • Used by Axd class to create, read, update, delete data in tables.
    • Service class
      • Contains the service operations in the form of methods.
    • Service node
      • Exposes service operations to inbound/outbound ports
  • Change namespace property of service node (optional).
  • Generate incremental CIL.
  • Register the service
  • Create security privilege for each service operation (optional).
  • Create an enhanced inbound port
  • Choose an adapter
    • File system adapter
    • HTTP
    • ISABEL SEPA credit transfer
    • MSMQ
    • NetTcp
    • Windows Azure Service Bus
  • Choose service operations
  • Activate

Important methods:

  • Axd class
    • prepareForSave/prepareForSaveExtended method
      • Validation code goes here.
      • For example checkSalesTable method in AxdSalesOrder class.
    • updateNow method
      • Business logic to be executed post insert/update of document.
      • For example, post receipt in II7.
    • expandSurrogateForeignKeys method
      • To automatically resolve surrogate foreign keys to natural keys.
    • getSurrogateForeignKeyValue method
      • To manually resolve surrogate foreign keys to natural keys.
  • AxBC class
    • initMandatoryFieldsExemptionList method
      • To make a field optional which is mandatory at the table level.
    • initMandatoryFieldsMap method
      • To make a field mandatory which is optional at the table level.
    • set<Field> method
      • To set default value of a field in service.
      • This method calls parm method to set the default value.
      • For example, setLineNum method of AxSalesLine class.
      • It calls parmLineNum method of AxSalesLine class.

Consuming service:

  • Create console application in Visual Studio
  • Add service reference
  • Sometimes, setting some fields doesn’t work in C#. We use “<Field>Specified” parameters for them.
  • For example:
    • Course.Name = “Name”;
    • Course.NameSpecified = true;
    • Course.Description = “Desc”;
    • Course.DescriptionSpecified = true;

AX 2012: Create AIF custom service

Posted on Updated on

Purpose:

The purpose of this document is to illustrate how we can develop AIF custom service.

Business requirement:

Ability to integrate Dynamics AX with external systems.

Assumptions:

Application Integration Framework has been configured to process inbound and outbound messages.

Development:

  1. Create a data contract class.
    1. Use [DataContractAttribute(‘Name’)] attribute to indicate class represents data contract.
    2. Use [DataMemberAttribute(‘Name’)] attribute to indicate method represents data member.
    3. Use [AifCollectionTypeAttribute] attribute to define parameter and return types.
  2. Create a service class.
    1. Set RunOn property of class to Server.
    2. Create a method attributed with [SysEntryPointAttribute(true)] to designate it as a service operation.
    3. The boolean parameter of attribute defines whether AOSAuthorization property of tables will be checked or not in this method.
  3. Create a service contract by creating service node.
  4. Add service operation.
  5. Create a service group for the basic inbound port.
  6. Deploy the service group.
  7. The inbound port created must be activated now.

AX 2012: Add custom field to standard DIXF target entity

Posted on

Purpose:

The purpose of this document is to describe how we can add custom fields to standard DIXF target entity. While performing data migration for standard entities like customer, we often come across a requirement to load data for customized fields as well. In this post, we will add custom fields of customer master to its standard DIXF entity.

Business requirement:

To load customer master through DIXF along with custom fields.

Assumptions:

1. Custom fields are already added to CustTable table.
2. DIXF component is up and running.
3. ODBC source data format has been configured.
4. Prestaging database and table is ready to fetch data from.

untitled

Development:

1. The following are the custom fields that need to be loaded through standard DIXF entity for customer master:

untitled

2. Add custom fields to DMFCustomerEntity table, which is the standard DIXF staging entity for customer master.

untitled

3. Add the same fields to the DMF field group of DMFCustomerEntity table.
4. Add the same fields to DMFCustomerTargetEntity query.

Queries > DMFCustomerTargetEntity > Data Sources > Customer(CustTable) > Fields

5. Make sure the same fields exist in the target entity, CustTable table.
6. Open Data import export framework > Setup > Target entities
7. Create new target entity as follows. You must create a new target entity to include the newly added fields.

untitled

8. Verify the newly added fields by looking at the mappings.

untitled

9. Create new processing group and select the newly created target entity

untitled

10. Generate source mapping and verify the mappings by clicking Modify source mapping.

untitled

11. You can also preview the source data by clicking Preview source file to validate data is pulling up correctly.

untitled

12. Get staging data

untitled

untitled

13. Copy data to target.

untitled

untitled

14. You can verify loaded customers in All customers list page.

untitled

15. You can also verify custom fields loaded successfully!

untitled

 

AX 2012: Open fiscal periods in X++

Posted on Updated on

Purpose:

The purpose of this document is to describe how we can quickly open fiscal periods through X++.

Development:

// Developed on 28 Dec 2015 by Muhammad Anas Khan
// Blog: dynamicsaxinsight.wordpress.com
// LinkedIn: pk.linkedin.com/in/muhammadanaskhan
// Description: Ability to confirm purchase order
static void MAKOpenFiscalPeriods(Args _args)
{
    FiscalCalendarPeriod       fiscalCalendarPeriod;
    LedgerFiscalCalendarPeriod ledgerFiscalCalendarPeriod;

    ttsBegin;

    //Open fiscal periods
    update_recordSet ledgerFiscalCalendarPeriod
        setting Status = FiscalPeriodStatus::Open
        join fiscalCalendarPeriod
            where fiscalCalendarPeriod.RecId == ledgerFiscalCalendarPeriod.FiscalCalendarPeriod
                && fiscalCalendarPeriod.Type == FiscalPeriodType::Operating;

    ttsCommit;
}

AX 2012: General journal posting in X++

Posted on Updated on

Purpose:

The purpose of this document is to describe how we can quickly post general journals (also known as GL opening balances or simply GL balances) across all the companies in X++.

This particularly comes in handy when GL balances are loaded in bulk through DIXF and the customer wants to post the loaded journals automatically as part of the DIXF load process.

Business requirement:

Ability to post GL balances across all the companies in X++ along with the posting log.

Prerequisites:

Fiscal periods are open for the relevant periods.

Assumptions:

The number sequence for the Journal batch number contains a constant segment “_GL” to designate it as a GL balance entry. Based on this assumption the given code filters GL balance record from the LedgerJournalTable.

Development:

1. Create a posting log table MAKLedgerJournalPostLog with the following fields:

untitled

where,

JournalNum        – uses LedgerJournalId EDT
Posted                  – uses NoYesId EDT
PostingLog          – uses Log EDT
TransactionTime – uses DateTimeExecuted EDT

2. Create an AOT job with the following code:

// Developed on 28 Dec 2015 by Muhammad Anas Khan
// Blog: dynamicsaxinsight.wordpress.com
// LinkedIn: pk.linkedin.com/in/muhammadanaskhan
// Description: Ability to confirm purchase order
static void MAKLedgerJournalPost(Args _args)
{
    LedgerJournalTable      ledgerJournalTable;
    LedgerJournalName       ledgerJournalName;
    LedgerJournalCheckPost  ledgerJournalValiate, ledgerJournalPost;
    Log                     errorMessage;
    SysInfologEnumerator    sysInfologEnumerator;
    MAKLedgerJournalPostLog postingLogTable;

    //Private method
    void insertLog(log _log, ledgerjournalid _journalNum, NoYes _post)
    {
        postingLogTable.clear();
        postingLogTable.PostingLog = _log;
        postingLogTable.JournalNum = _journalNum;
        postingLogTable.TransactionTime = DateTimeUtil::utcNow();
        postingLogTable.Posted = _post;
        postingLogTable.insert();
        infolog.clear();
    }

    delete_from postingLogTable;

    while select crossCompany * from ledgerJournalTable
        where ledgerJournalTable.JournalNum like '*_GL*'
            && ledgerJournalTable.Posted == NoYes::No
    {
        try
        {
            changeCompany(ledgerJournalTable.dataAreaId)
            {
                ledgerJournalName = LedgerJournalName::find(ledgerJournalTable.JournalName);
                ledgerJournalValiate = ledgerJournalCheckPost::newLedgerJournalTable(
                    ledgerJournalTable,
                    NoYes::No);
                
                ledgerJournalValiate.run();

                if (!ledgerJournalValiate.tableErrorLog())
                {
                    ledgerJournalPost = ledgerJournalCheckPost::newLedgerJournalTable(
                        ledgerJournalTable,
                        NoYes::Yes);
                    
                    ledgerJournalPost.run();
                    
                    insertLog(
                        ledgerJournalValiate.tableErrorLog(),
                        ledgerJournalTable.JournalNum,
                        NoYes::Yes);
                }
                else
                {
                    insertLog(
                        ledgerJournalValiate.tableErrorLog(),
                        ledgerJournalTable.JournalNum,
                        NoYes::No);
                }
            }
        }
        catch(Exception::Error)
        {
            sysInfologEnumerator = SysInfologEnumerator::newData(infolog.infologData());
            errorMessage = "";

            while (sysInfologEnumerator.moveNext())
            {
                errorMessage += sysInfologEnumerator.currentMessage() + "; ";
            }

            insertLog(
                errorMessage,
                ledgerJournalTable.JournalNum,
                NoYes::No);
        }
    }

    info("Posting completed. Please check log for posting results.");
}

3. After running the above AOT job, you can find the posting log by querying records in table MAKLedgerJournalPostLog from SQL server client.