Translate

Wednesday, September 19, 2012

Update Customer/Vendor dimensions | AX 2012

Upload using csv which contains columns customer account number and all active dimension, if particular dimension is not applicable for a customer/vendor then it has to be left as blank.

Read full post at : http://dynamicsnavax.blogspot.com.au/2012/07/import-default-dimension-into-table-eg.html



static void ImportCustomerDimension(Args _args)
{
    AsciiIO     asciiIO;
    Filename    filename;
    NoYesId     skipFirstLine;
    Container   line;
    Dialog      dialog;
    DialogField dialogFileName, dialogSkipFirstLine;
    DimensionAttribute              dimAttr;
    DimensionAttributeSetItem       dimAttrSetItem;
    DimensionEnumeration            dimensionSetId;
    Container                       combinedContainer;
    CustTable                       custTable;
    CustAccount                     custAccount;
    Counter                         counter;
    DimensionAttributeValue         dimAttributeValue;
    //Dialog
    dialog                  = new Dialog("Import Default Dimension");
    dialogFileName          = dialog.addField(extendedTypeStr(Filenameopen), "File name");
    dialogSkipFirstLine     = dialog.addField(extendedTypeStr(NoYesId), "Skip first line");

    if (dialog.run())
    {
        filename      = dialogFileName.value();
        skipFirstLine = dialogSkipFirstLine.value();
    }
    asciiIO = new AsciiIO(filename, 'R');
    if (!asciiIO || asciiIO.status() != IO_Status::Ok )
    {
        throw error (strfmt("@SYS19312",filename));
    }

    asciiIO.inRecordDelimiter('\r\n');
    asciiIO.inFieldDelimiter(',');
    if (skipFirstLine)
        line = asciiIO.read();
    while (asciiIO.status() == IO_status::Ok)
    {
        line = asciiIO.read();
        if (line)
        {
            //get customer account number
            custAccount = conpeek(line,1);
            counter = 1; //Dimension starting point
            combinedContainer = conNull();
            dimAttributeValue = null;
            
            //Build dimension container
            dimensionSetId = DimensionCache::getDimensionAttributeSetForLedger();
            while select dimAttr
                order by Name
                    where dimAttr.Type != DimensionAttributeType::MainAccount
                join RecId from dimAttrSetItem
                    where dimAttrSetItem.DimensionAttribute == dimAttr.RecId &&
                          dimAttrSetItem.DimensionAttributeSet == dimensionSetId
            {
                counter++;
                //only insert into container if it has a value
                if (conPeek(line, counter))
                {
                    combinedContainer += [dimAttr.Name, conPeek(line, counter)];
                    //info(strFmt("%1 %2",dimAttr.Name, conPeek(line, counter)));
                    dimAttributeValue = AxdDimensionUtil::validateFinancialDimensionValue(dimAttr, conPeek(line, counter));
                }
            }
            //insert the count in the first value of the container - number of dimensions divided by 2 - since we have name and value
            combinedContainer = conIns(combinedContainer, 1, int2str(conLen(combinedContainer)/2));
            ttsBegin;
            custTable = CustTable::find(custAccount, true);
            custTable.DefaultDimension = AxdDimensionUtil::getDimensionAttributeValueSetId(combinedContainer);
            custTable.update();
            ttsCommit;
        }
    }
}

Delete transactional data | AX 2012



void handleTable(SysDictTable sysDictTable)

{
    TableGroup      tableGroup;

    if (tableSet.in(sysDictTable.id()))
        return;
    tableSet.add(sysDictTable.id());

    if (sysDictTable && !sysDictTable.isTmp() && !sysDictTable.isMap())
    {
        tableGroup = sysDictTable.tableGroup();

        // Handle company specific tables to be deleted
        if (sysDictTable.dataPrCompany())
        {
            switch(tableGroup)
            {
                case TableGroup::Transaction:
                case TableGroup::WorksheetHeader:
                case TableGroup::WorksheetLine:
                //FIX - Support new AX2012 transaction table types
                case TableGroup::TransactionHeader:
                case TableGroup::TransactionLine:
                    this.handleTransTable(sysDictTable);
                    break;
                default:
                    this.handleNonTransTable(sysDictTable);
                    break;
            }
        }
        else
        {
            // Handle global tables to be deleted
            switch(tableGroup)
            {
                case TableGroup::Transaction:
                case TableGroup::WorksheetHeader:
                case TableGroup::WorksheetLine:
                //FIX - Support new AX2012 transaction table types
                case TableGroup::TransactionHeader:
                case TableGroup::TransactionLine:
                    this.handleGlobalTransTable(sysDictTable);
                    break;
                default:
                    break;
            }
        }
    }
}

Dynamics Ax - Update using AIF | Get Document Hash

Generate <_DocumentHash> while updating data thru AIF


In Dynamics Ax, version 2009 onwards Document hash is mandatory to update the records using AIF.

When you read data, AIF returns a document hash field. This field contains a hash of all the RecId and RecVersion values for each record that is returned. When you send the data back into AIF to update a record, it recalculates the document hash from the database records in the update and compares it to the document hash in the inbound message. If the data has changed, for example, if a record was updated or added, the calculated document hash will differ from the document hash in the inbound document and AIF will return an error.

When you use the document hash, you only have to read and submit one field for comparison instead of reading and submitting the RecId and RecVersion values for each record. However, if a concurrency error occurs when you use the document hash, AIF can only report that a record was changed and not which record changed.

While implementing some of the scenarios we may even need to perform update in 1 step this could be only possible when are able to generate <_DocumentHash> using X++. Below code describes same.
I have created a test class which extends to AxdBaseRecordInfo and have created one method. In the method I am passing a recId for LedgerJournalTrans and it should return documenthash.

class MyHashCode  extends AxdBaseRecordInfo
{

}

public static str getHashCode(RecId     _recId)
{
    AxdBaseUpdate           axdBaseUpdate = AxdbaseUpdate::construct();
    Map                          dataSourceMap;
    Query                       query = new Query(QueryStr(AxdLedgerGeneralJournal));
    AxdBaseRecordInfo      topAxdBaseRecordInfo;
    QueryRun                  _queryRun;
    str                           documentHash;
    QueryBuildRange         qr;
    LedgerJournalTrans     ledgerJournalTrans;
    RecId                        recId;

    ;
    recId                       = _recId;
    
    select firstOnly ledgerJournalTrans
        where ledgerJournalTrans.RecId == recId;

    dataSourceMap               = new Map(Types::Integer,Types::Integer);
    
    axdbaseUpdate.buildDataSourceParentMap(dataSourceMap, query.dataSourceNo(1)) ;
    query.dataSourceNo(1).addRange(fieldnum(LedgerJournalTrans, RecId)).value(queryValue(recId));

    topAxdBaseRecordInfo        = new AxdBaseRecordInfo(ledgerJournalTrans,1,dataSourceMap);
    documentHash                = topAxdBaseRecordInfo.getRecordHash();

    return documentHash;

}

Job
static void generateDocHash(Args _args)
{
    ;

    info(MyHashCode::getHashCode(5637158049));
}


Above code has been designed to support AX 2012 changes, if you are looking how to perform same in AX 2009 then follow :
http://community.dynamics.com/product/ax/axtechnical/b/axsantoshkumar/archive/2008/07/14/dynamics-ax-update-using-aif-to-get-the-document-hash.aspx

Happy DAXing :)




Thursday, September 13, 2012

“How Do I” Videos — Dynamics AX


Read full post at Dynamics AX Developer Center
http://msdn.microsoft.com/en-us/dynamics/ax/cc507280 


“How Do I” Videos — Dynamics AX

On this page you will find videos designed for all Microsoft Dynamics AX developers, from the novice to the professional. New videos are added regularly, so check back often.

Forms Series

This how-to video series is focused on forms and their features in Microsoft Dynamics AX.

Enterprise Portal Series

This how-to video series is focused on Enterprise Portal and its features in MicrosoftDynamics AX.
Enterprise Portal Deployment Webinar
(48 minutes, 04 seconds)
Enterprise Portal Development Webinar
(73 minutes, 49 seconds)

User Interface Series

This how-to video series is focused on user interface features in Microsoft Dynamics AX.

Integration Series

This how-to video series is focused on development features that enable integration with Microsoft Dynamics AX including Application Integration Framework (AIF) and Business Connector.

Database Series

This how-to video series is focused on the database features in Microsoft Dynamics AX.

Reporting Series

This how-to video series is focused on reporting features in Microsoft Dynamics AX.

Miscellaneous Series

This how-to series contains videos about various features in Microsoft Dynamics AX and related content.


*Shared from Dynamics AX Developer Center.

Friday, September 7, 2012

How add financial dimension on forms inside Ax2012


1.      Perform
a)      Open AOT>>Data Dictionary>>Extended Data Types type/select DimensionDefault and drag it in table which will be used further as a datasource in form where you have to show the Dimensions. Do Remember  that you have to drag it in table not at DataSource.
b)     Open Table in the Data, Dictionary which will be used as a Datasource, and create a realtion with table DimensionAttributeValueSet .
c)      Right Click the Relations. Select ‘New Realation’.  Select properties. Set name as DimensionAttributeValueSet, Table as DimensionAttributeValueSet.
d)     Right Click the this newly created Relation DimensionAttributeValueSet, select New>>Normal.
e)      Set the properties of Normal Realtion as:  Field=TheFieldwhichwillsaveDimensionNumberInYourTable
Source EDT= DimensionDefault
Related Field=RecId

2.      Verify that the table that will hold the foreign key to the DimensionAttributeValueSet table is a
data source on the form(the one on which you have to show dimensions).
3.      Create a tab that will contain the financial dimensions control. This control is often the only
data shown on the tab because the number of financial dimensions can be large.
4.   set properties of Tab as under
a)      Set the Name metadata of the tab to TabFinancialDimensions.
b)     Set the AutoDeclaration metadata of the tab to Yes.
c)      Set the Caption metadata of the tab to @SYS101181 (Financial dimensions).
d)     Set the NeedPermission metadata of the tab to Manual.
e)      Set the HideIfEmpty metadata of the tab to No.
       5.  Override the pageActivated method on the new tab
public void pageActivated()
{
    dimDefaultingController.pageActivated();

    super();
}
      6.   Override the following methods on the form.
class declaration
public class FormRun extends ObjectRun
{
    DimensionDefaultingController dimDefaultingController;
}
init (for the form):
public void init()
{
    super();
    dimDefaultingController=DimensionDefaultingController::constructInTabWithValues(
      true, 
      true, 
      true, 
      0, 
      this, 
      tabFinancialDimensions, 
      "@SYS138487");

    dimDefaultingController.parmAttributeValueSetDataSource(myTable_ds,
    fieldstr(myTable, DefaultingDimension));
}
    7.      Override the following methods on the form data source
            public int active()
{
    int ret;
    ret = super();
    dimDefaultingController.activated();
    return ret;
}
public void write()
{
    dimDefaultingController.writing();
    super();
}
public void delete()
{
    
    super();
  dimDefaultingController.deleted();
}




Sunday, September 2, 2012

Encrypt/Decrypt in AX 2012

Encrypt/Decrypt in AX 2012


Create a class, make it has property set to RunOn = Server
                                           OR
Create server static method

and use the below code.

static void Job2(Args _args)
{
    CryptoApi cryptoApi;
    Container cont,cont1;
    ContainerClass cc;
    ;
    
   /* Salt is like a password, While encrypting and descrypting the phrase, the CryptoAPI class has to instantiated with same salt(99999999999). The phrases/words are encrypted & decrypted based on the salt. */
    cryptoApi = new CryptoApi(99999999999);
    cc = new ContainerClass(["test123"]);
    cont = CryptoApi.encrypt(cc.toBlob()); // The encrypt method requires BLOB as a parameter
    cont1 = ContainerClass::blob2Container(CryptoApi.decrypt(cont));
    info(Strfmt("Encrypted:%1",BinData::dataToString(cont)));
    info(con2str(cont1));
}

Recent Posts