Thursday, March 1, 2018

AX 2012 R3 CU13 Bug: DMF default value mapping for String type

There is bug in AX 2012 R3 CU13.

If you check Default type for your data entity staging mapping field of String type, then the system tries to find any first record matching to "Default" value as XML name to get the linked field and compare against its string length.






To fix it, we need to make the following changes in three methods of the form DMFStagingDefaultTable


public class FormRun extends ObjectRun
{
    SysDictField             dictField;
    DMFFieldType             dmfFieldType;
    DMFSourceXMLToEntityMap  dmfSourceXMLToEntityMap;
    Types                    valueType;
    // Begin: Alexey Voytsekhovskiy
    int                     myMaxStrSize;
    // End: Alexey Voytsekhovskiy
}


public void init()
{
    Args                                args;
    DMFEntity                           entity;
    DMFDefinitionGroupEntityXMLFields   dmfDefinitionGroupEntityXMLFields;
    SysDictType                         dictType;

    #define.Integer('Integer')
    #define.String('String')
    #define.RealMacro('Real')
    #define.DateMacro('Date')
    #define.DateTimeMacro('UtcDateTime')
    #define.Time('Time')

    super();

    if (!element.args() || element.args().dataset() != tableNum(DMFSourceXMLToEntityMap))
    {
        throw error(strfmt("@SYS25516", element.name()));
    }

    args = element.args();

    dmfSourceXMLToEntityMap = args.record();
    // Begin: Alexey Voytsekhovskiy
    select firstOnly FieldType, FieldSize from dmfDefinitionGroupEntityXMLFields
        where dmfDefinitionGroupEntityXMLFields.FieldName == dmfSourceXMLToEntityMap.EntityField
        && dmfDefinitionGroupEntityXMLFields.Entity == dmfSourceXMLToEntityMap.Entity
        && dmfDefinitionGroupEntityXMLFields.DefinitionGroup == dmfSourceXMLToEntityMap.DefinitionGroup
        ;
    myMaxStrSize = dmfDefinitionGroupEntityXMLFields.FieldSize ? dmfDefinitionGroupEntityXMLFields.FieldSize : 256;
    // End: Alexey Voytsekhovskiy
    if (dmfDefinitionGroupEntityXMLFields.FieldType && !dmfSourceXMLToEntityMap.IsAutoDefault)
    {
        dmfFieldType = dmfDefinitionGroupEntityXMLFields.FieldType;
        if (dmfsourceXMLToEntityMap.EntityField)
        {
            entity = DMFEntity::find(dmfsourceXMLToEntityMap.Entity);
            dictField = new SysDictField(tableName2id(entity.EntityTable), fieldName2id(tableName2Id(entity.EntityTable),dmfsourceXMLToEntityMap.EntityField));
        }
        switch(dmfDefinitionGroupEntityXMLFields.FieldType)
        {
            case #Integer:
                DMFStagingConversionTable_StagingIntValue.visible(true);
                break;
            case #String:
                DMFStagingConversionTable_StagingStrValue.visible(true);
                break;
            case #RealMacro:
                DMFStagingConversionTable_StagingRealValue.visible(true);
                break;
            case #DateMacro:
                DMFStagingConversionTable_StagingDateValue.visible(true);
                break;
            case #DateTimeMacro:
                DMFStagingConversionTable_StagingUtcDataTime.visible(true);
                break;
            case #Time:
                DMFStagingConversionTable_StagingTimeValue.visible(true);
                break;
            default:
                warning("@DMF694");
                element.close();
        }
    }
    else if(dmfSourceXMLToEntityMap.IsAutoDefault)
    {
        entity = DMFEntity::find(dmfsourceXMLToEntityMap.Entity);
        dictField = new SysDictField(tableName2id(entity.EntityTable),fieldName2id(tableName2Id(entity.EntityTable),dmfsourceXMLToEntityMap.EntityField));
        dictType = new SysDictType(dictField.typeId());
        if (dictType && dictType.isTime())
        {
            valueType = Types::Time;
        }
        else
        {
            valueType = dictField.baseType();
        }
        dmfFieldType = enum2str(dictField.baseType());
        switch(valueType)
        {
            case Types::Integer:
                DMFStagingConversionTable_StagingIntValue.visible(true);
                break;
            case Types::String:
                DMFStagingConversionTable_StagingStrValue.visible(true);
                break;
            case Types::Real:
                DMFStagingConversionTable_StagingRealValue.visible(true);
                break;
            case Types::Date:
                DMFStagingConversionTable_StagingDateValue.visible(true);
                break;
            case Types::UtcDateTime:
                DMFStagingConversionTable_StagingUtcDataTime.visible(true);
                break;
            case Types::Time:
                DMFStagingConversionTable_StagingTimeValue.visible(true);
                break;
            case Types::Guid:
                DMFStagingConversionTable_StagingGuidValue.visible(true);
                break;
            default:
                warning("@DMF694");
                element.close();
        }
    }

    else
    {
        element.close();
    }
}

and on the  sole form data source field StagingStrValue

public boolean validate()
{
    boolean                             ret;
    DMFDefinitionGroupEntityXMLFields   dmfDefinitionGroupEntityXMLFields;

    ret = super();

    if(ret)
    {
        // Begin: Alexey Voytsekhovskiy
        if(strLen(DMFStagingConversionTable.StagingStrValue) > myMaxStrSize)
        {
            throw error("@DMF788");
        }

//        select firstOnly FieldSize from dmfDefinitionGroupEntityXMLFields
//            where dmfDefinitionGroupEntityXMLFields.FieldName == dmfSourceXMLToEntityMap.XMLField;
//
//        if(dmfDefinitionGroupEntityXMLFields.FieldSize)
//        {
//            if(strLen(DMFStagingConversionTable.StagingStrValue) > dmfDefinitionGroupEntityXMLFields.FieldSize)
//            {
//                throw error("@DMF788");
//            }
//        }
        // End: Alexey Voytsekhovskiy
    }

    return ret;
}

No comments: