Trabalhando com datas no Microsoft Dynamics Ax

Muitas vezes precisamos trabalhar com datas no Ax.

Existem algumas funções que faciliam muito este trabalho.

Dica: O comando “Shift+F4” abre a lista de funções do Ax

Fiz um job exemplificando a utilização destas:

 

static void dateJob(Args _args)
{
Date birthday = 311\2013;
;
//Ano a partir da data
info(strfmt(“Ano: %1”, year(birthday)));

//Mês a partir da data
info(strfmt(“Mês (numeral): %1”, mthofyr(birthday)));

//Nome do mês
info(strfmt(“Mês (extenso): %1”, mthname(mthOfyr(birthday))));

//Próximo mês
info(strfmt(“Próximo mês: %1”, mthName(mthofyr(nextmth(birthday)))));

//Semana a partir da data
info(strfmt(“Semana: %1”, wkofyr(birthday)));

//Dia a partir da data
info(strFmt(“Dia: %1”, dayofmth(birthday)));

//Dia da semana (numeral)
info(strfmt(“Dia da semana (numeral): %1”, dayofwk(birthday)));

//Dia da semana (extenso)
info(strfmt(“Dia da semana (extenso): %1”, dayname(dayofwk(birthday))));

//Dias passados desde o início do ano
info(strfmt(“Dia do ano (conta quantos dias passaram): %1”, dayofyr(birthday)));
}

 

A saída deste job será a seguinte:

Imagem

Como pegar o valor anterior do campo durante uma modificação

As vezes, durante o desenvolvimento, é necessário verificar o valor anterior de um registro na tabela.

A primeira opção que muitos de nós pensamos seria declarar uma variável para guardar o valor, modifica-lo e depois fazer a comparação, porém as tabelas do Ax possuem um método que verifica o valor “commitado” do Table Buffer.

Este método é o orig().

Segue exemplo:

static void origMethod(Args _args)

{
CustTable ct;
;

select ct where ct.AccountNum == “000003”;

ct.AccountNum = “Modificado”;

info(strfmt(“Valor atual: %1, valor anterior: %2”,
ct.AccountNum,
ct.orig().AccountNum));
}

O info irá exibir a seguinte mensagem:

infolog

 

Erro nos índices das tabelas – Recriar SqlDictionary

Depois de bem mais de um ano sem fazer uma única postagem, venho postar algo de interesse para quem está passando por um problema chatíssimo: índices de campos.

Este script recria os registros dos Ids da tabela desejada que não se encontram na SqlDictionary.

Quem já teve a experiência de participar de uma migração, por exemplo, deve ter se deparado com este problema.

#macrolib.DictField
// This type is used instead of Types::Int64 for fields of type
// RecId/RefRecId/createdTransactionId/modifiedTransactionId
#define.RecIdBaseType   (49)
// For nonsystem fields of type UtcDateTime an additional field is created
// that holds the actual time zone in which the value has been set
#define.TZIDsuffix      ('_TZID')          

SqlDictionary   sqlDict;
SysdictType     dictType;
DictTable       dictTable;
DictField       dictField;
ArrayIdx        arrIdx;
Counter         numOfSqlFields; // number of records created in SqlDictionary
fieldName       fieldName;
fieldId         fieldId;
tableId         tableId = tablenum(TheTable2Fix);  // TARGET

boolean processTableField(
    DictField   _dictField,
    ArrayIdx    _arrIdx,
    boolean     _isTzIdField = false
    )
{
    ArrayIdx    dictArrIdx;
    str         infoName;       // this field name is for messages only
    FieldName   sqlName;
    boolean     ret;
    ;
    if (_isTzIdField)
    {
        if (    _dictField.baseType()   != Types::UtcDateTime
            ||  _dictField.id()         == fieldnum(Common, createdDateTime)
            ||  _dictField.id()         == fieldnum(Common, modifiedDateTime)
           )
        {
            throw error(Error::wrongUseOfFunction(funcname()));
        }
        dictArrIdx  = _dictField.arraySize() + _arrIdx;
        sqlName     = _dictField.dateTimeTimeZoneRuleFieldName(_arrIdx - 1);
        infoName    = _dictField.name() + #TZIDsuffix;
    }
    else
    {
        dictArrIdx  = _arrIdx;
        sqlName     = _dictField.name(DbBackend::Sql, _arrIdx);
        infoName    = _dictField.name();
    }
    select firstonly sqlDict
        where   sqlDict.tabId   == _dictField.tableid()
            &&  sqlDict.fieldId == _dictField.id()
            &&  sqlDict.array   == dictArrIdx
                ;
    if (!sqlDict)
    {
        sqlDict.clear();
        sqlDict.initValue();
        sqlDict.tabId           = _dictField.tableid();
        sqlDict.fieldId         = _dictField.id();
        sqlDict.array           = dictArrIdx;
        sqlDict.name            = strupr(_dictField.name(DbBackend::Native, _arrIdx));
        sqlDict.sqlName         = sqlName;
        dictType                = new SysDictType(_dictField.typeId());
        if (_isTzIdField)
        {
            sqlDict.fieldType   = Types::Integer;
        }
        else
        if (        _dictField.id()     == fieldnum(Common, RecId)
            ||      _dictField.id()     == fieldnum(Common, createdTransactionId)
            ||      _dictField.id()     == fieldnum(Common, modifiedTransactionId)
            ||      _dictField.typeId() == extendedtypenum(RecId)
            ||      _dictField.typeId() == extendedtypenum(RefRecId)
            ||  (   dictType
                &&  dictType.isExtending(extendedtypenum(RecId))
                )
           )
        {
            // This type is used instead of Types::Int64 for fields of type
            // RecId/RefRecId/createdTransactionId/modifiedTransactionId
            sqlDict.fieldType   = #RecIdBaseType;
        }
        else
        {
            sqlDict.fieldType   = _dictField.baseType();
        }
        sqlDict.strSize         = _dictField.stringLen();
        sqlDict.shadow          = bitTest(_dictField.flags(), #DBF_SHADOW);
        sqlDict.rightJustify    = bitTest(_dictField.flags(), #DBF_RIGHT);
        sqlDict.flags           = sqlDict.shadow;   // not _dictField.flags() at all!
        sqlDict.nullable        =   _dictField.baseType() == Types::Container
                                ||  _dictField.baseType() == Types::VarString
                                    ;
        if (sqlDict.validateWrite())
        {
            sqlDict.insert();
            ret = true;
            info(strfmt(@"Created record for field %1.%2%3",
                        dictTable.name(), infoName,
                        _dictField.arraySize() > 1 ? strfmt(@"[%1]", _arrIdx) : ''));
            // for all nonsystem UtcDateTime fields we also create a related TZID-field
            if (   !_isTzIdField
                &&  _dictField.baseType()   == Types::UtcDateTime
                &&  _dictField.id()         != fieldnum(Common, createdDateTime)
                &&  _dictField.id()         != fieldnum(Common, modifiedDateTime)
               )
            {
                processTableField(_dictField, _arrIdx, true);
            }
        }
        else
        {
            ret = checkFailed(strfmt(@"%1 record for %2.%3 was not created",
                                     tablestr(SqlDictionary), dictTable.name(), infoName));
        }
    }
    return ret;
}
;
dictTable = new DictTable(tableId);
if (!dictTable)
{
    throw error(strfmt(@"Failed to create %1 for '%2' (%3)",
                classstr(DictTable), tableid2name(tableId), tableId));
}
if (dictTable.isSystemTable())
{
    throw error(strfmt(@"'%1' is a system table, no way...", dictTable.name()));
}
if (!dictTable.isSql())
{
    throw error(strfmt(@"Table '%1' should not be in DB", dictTable.name()));
}
for (fieldId = dictTable.fieldNext(0); fieldId; fieldId = dictTable.fieldNext(fieldId))
{
    dictField = dictTable.fieldObject(fieldId);
    if (dictField && dictField.isSql())
    {
        fieldName = dictField.name();
        for (arrIdx = 1; arrIdx <= dictField.arraySize(); arrIdx++)
        {
            numOfSqlFields++;
            processTableField(dictField, arrIdx);
        }
    }
}
select firstonly sqlDict
    where   sqlDict.tabId   == tableId
        &&  sqlDict.fieldId == 0
            ;
if (!sqlDict)
{
    sqlDict.clear();
    sqlDict.initValue();
    sqlDict.tabId       = tableId;
    sqlDict.name        = strupr(dictTable.name());
    sqlDict.sqlName     = dictTable.name(DbBackend::Sql);
    sqlDict.strSize     = numOfSqlFields;       // for the table "header" - num of fields 
    sqlDict.flags       = dictTable.isView();   // that's the way it is
    sqlDict.insert();
    info(strfmt(@"Created record for table %1", dictTable.name()));
}

Créditos: http://gl00mie.blogspot.com.br/