Показать сообщение отдельно
Старый 06.07.2009, 15:57   #1  
petergunn is offline
petergunn
Участник
 
118 / 274 (10) ++++++
Регистрация: 30.08.2005
Адрес: Tyumen
! form SysDateLookup - баг?
Axapta 3.0 SP5, Dynamics Ax 4.0 SP2 (application version: 4.0.2501.347)

Доброго времени суток.
При выборе дат вблизи 'пограничных' значений лет (1901, 2153-2154) обнаружились некоторые 'накладки' в реализации функционала формы SysDateLookup.

Сценарий тестирования: вводим в поле с типом EDT TransDate дату 31.12.2153, жмем кнопу вызовы lookup формы - кнопка перехода на следующий месяц недоступна (по сути календарь должен быть доступен до 31.12.2154), жмем PageDown (ArrowRight, ArrowDown) и преодолеваем это ограничение, наблюдаем корректные данные 2154 года, потом идут только названия месяцев 2155 года, далее пустые ячейки, и после этого по второму кругу календарь с начала времен (1901 года)

При просмотре кода некоторые фрагменты вызвали вопросы - в штатной lookup форме выбора дат SysDateLookup объявлены 2 текстовые константы допустимого диапазона дат:
Forms\SysDateLookup\ClassDeclaration:
X++:
	...
    #define.maxDate('31-12-2153')
    #define.minDate('01-01-1901')
    ...
и далее по тексту методов идет конвертация в даты через str2date() :
Forms\SysDateLookup\enableNextButton():
X++:
void enableNextButton()
{
    if (year(monthShown)    == year(str2date(#maxDate,123)) &&
        mthofyr(monthShown) == mthofyr(str2date(#maxDate,123)))
	...
}
Forms\SysDateLookup\enableNextButton():
X++:
void enablePrevButton()
{
    if (year(monthShown)    == year(str2date(#minDate,123)) &&
        mthofyr(monthShown) == mthofyr(str2date(#minDate,123)))
	...
}
Forms\SysDateLookup\drawMonth():
X++:
void drawMonth()
{
    ...
    for (w = 1; w <= 6; w++)
    {
        ...
        if (drawingDate >= str2date(#maxDate, 123))
        {
            daysTable.setRowLabel(w,num2str(1,2,0,0,0));
        }
        ...
    }
    ...
}

первое что напрашивается - явное объявление макро-констант с типом date и отказ от избыточных вызовов преобразований str2date().
второй момент - верхняя граница диапазона дат #maxDate задана не верно (31.12.2153): значение функции maxdate() = 31.12.2154
Forms\SysDateLookup\ClassDeclaration:
X++:
	...
    #define.maxDate(31\12\2154)
    #define.minDate(01\01\1901)
    ...
для предотвращения выхода за границы допустимого интервала дат при навигации по календарю можно добавить дополнительную проверку в метод nextMonth().
Forms\SysDateLookup\nextMonth():
X++:
void nextMonth(int keyPressed)
{
    boolean doUnlock    ;
    //  -->  fix SysDateLookup code
    boolean allowChange = ( keyPressed == #taskPageDown && buttonNextMonth.enabled() )  ||
                          ( keyPressed == #taskPageUp && buttonPrevMonth.enabled() ) ;
    ;

    if( !allowChange )
        return ;
    //  <--  fix SysDateLookup code
    doUnlock = element.lockWindowUpdate(true);
    ...
}
P.S. Сценарий тестировался на Axapta 3.0 SP5, Dynamics AX 4.0 SP2, но похоже что актуален и для Dynamics AX 2009 (объявление #define.maxDate('31-12-2153') присутствует).
Изображения