Dynamics AIF : Working Times service

Today I created an AIF web service to expose the Working times functionality in Ax 2009. The service itself is quite simple but there was the issue with the workTimeId. The application on the other side doesn’t care about the Id of the working times and wants Dynamics to use a number sequence for the workTimeId field. This post will not deal with the creation of a number sequence reference but shows how you can fill in the WorkTimeId automatically and especially how you can link the WorkTimeLine to the WorkTimeTable via the WorkTimeId.

First things first, we create a query which contain the two tables.

AxdWorkTime Query Object

Since we are planning on updating / deleting through the service, we must not forget to set the properties on the datasources. Properties Delete and Update must be set to Yes.

Then we create the AIF service by using the Wizard available in AX 2009. Afterwards we have the following objects available :

  • AIF Service object
  • AIF Service class
  • AxWorkTimeTable entity class
  • AxWorkTimeLine entity class
  • AxdWorkTime document classWorkTimeDocument / WorkTimeDocument_WorkTimeTable / WorkTimeDocument_WorkTimeLine Classes
  • Some datacontainertype macros stuff

Created project

Now we are going to make sure the WorkTimeId is fetched from a number sequence and inserted automatically. For this we need to do 2 things :

  • Set the WorkTimeId as not mandatory (Both on the axWorkTimeTable and axWorkTimeLine entities)
  • Modify the setWorkTimeId method on the axWorkTimeTable entity to use the number sequence
protected void initMandatoryFieldsExemptionList()
{
    super();
    this.setParmMethodAsNotMandatory(methodstr(AxWorkTimeTable,parmWorkTimeId));
}
protected void setWorkTimeId()
{
    NumberSequenceReference numberSequenceReference;
    ;

    if (this.isMethodExecuted(funcName(), fieldNum(WorkTimeTable, WorkTimeId)))
    {
        return;
    }

    if (this.isSetMethodsCalledFromSave())
    {
        if (this.isFieldSetExternally(fieldnum(WorkTimeTable, WorkTimeId)))
        {
            if (!this.workTimeTable())
            {
                numberSequenceReference = NumberSeqReference::findReference(typeId2ExtendedTypeId(typeid(WorkTimeId)));
                this.checkNumber(numberSequenceReference.numberSequenceTable(),fieldNum(WorkTimeTable, WorkTimeId),this.parmWorkTimeId());
                if (numberSequenceReference.NumberSequence && numberSequenceReference.numberSequenceTable().Continuous)
                {
                    NumberSeq::newReserveNum(numberSequenceReference).reserve(this.parmWorkTimeId());
                }
            }
        }
        else
        {
            if (this.isFieldSet(fieldnum(WorkTimeTable, WorkTimeId)))
            {
                return;
            }

            if (!this.parmWorkTimeId())
            {
                this.parmWorkTimeId(NumberSeq::newGetNum(NumberSeqReference::findReference(typeId2ExtendedTypeId(typeid(WorkTimeId)))).num());
            }
        }
    }
}

And last but not least we need to link the AxWorkTimeLine to the AxWorkTimeTable via the WorkTimeId. The wizard already did some action to achieve this by putting the prepareForSave method on the AxdWorkTime document class.

public boolean prepareForSave(AxdStack _axdStack,  str _dataSourceName)
{
    AxWorkTimeTable   AxWorkTimeTable;
    AxWorkTimeLine    AxWorkTimeLine;
    ;
    switch (classidget(_axdStack.top()))
    {
        case classnum(AxWorkTimeTable) :
            AxWorkTimeTable = _axdStack.top();
            return true;

        case classnum(AxWorkTimeLine) :
            AxWorkTimeLine  = _axdStack.top();
            AxWorkTimeTable = AxWorkTimeLine.parentAxBC();
            AxWorkTimeLine.parmWorkTimeId(AxWorkTimeTable.parmWorkTimeId());
            return true;

        default :
            error(strfmt("@SYS88979",classId2Name(classidget(_axdStack.top()))));
            return false;
    }
    return false;
}

Since the parm method will call the setWorkTimeId method once, we still need to place some code there :
The code will call the parent entity’s parmWorkTimeId method.

protected void setWorkTimeId()
{
    if (this.isMethodExecuted(funcName(), fieldNum(WorkTimeLine, WorkTimeId)))
    {
        return;
    }

    if (!this.parmWorkTimeId())
    {
        this.parmWorkTimeId(this.axWorkTimeTable().parmWorkTimeId());
    }
}

The only thing still needed now is pointing out who is the parent entity. Therefore I’ve created a method that creates an axWorkTimeTable entity.

public AxWorkTimeTable axWorkTimeTable(AxWorkTimeTable _axWorkTimeTable = null)
{
    AxWorkTimeTable axWorkTimeTable;

    if (!prmisdefault(_axWorkTimeTable))
    {
        axWorkTimeTable = _axWorkTimeTable;
    }
    else
    {
        this.setWorkTimeId();
        axWorkTimeTable = WorkTimeTable::find(this.parmWorkTimeId()).axWorkTimeTable();
    }

    return axWorkTimeTable;
}
public AxWorkTimeTable axWorkTimeTable()
{
    AxWorkTimeTable axWorkTimeTable = AxWorkTimeTable::newWorkTimeTable(this);
    return AxWorkTimeTable;
}

If someone wants to add something, be my guest… comments are welcome !