Дата публикации проблема из-за часовых поясов и использования SystemDateGet () - PullRequest
1 голос
/ 08 декабря 2011

Резюме

У нас возникла проблема, когда функция systemDateGet () возвращает AOS, когда местная дата требуется при определении даты для целей публикации.

Детали

  • У нас есть филиалы по всему миру, обе стороны международной линии датирования, с пользователи, подключающиеся к локальным терминальным серверам с соответствующими настройками часового пояса для ветки пользователя.

  • Каждый филиал связан с другой компанией, которая была настроена с правильный часовой пояс.

  • Мы запускаем одну AOS с настройкой часового пояса, установленной для головного офиса. Есть нет возможности ввести дополнительные AOS.

  • Функция SystemDateGet () возвращает дату AOS, поскольку пользователь не изменяется их сессия Axapta.

  • Количество системных полей в базе данных, связанных с датами проводки, основано на DATE и не основанный на UTCDATETIME.

  • Мы работаем с AX2009 SP1 RU7.

    • Версия ядра 5.0.1500.4570
    • Версия приложения 5.0.1500.4570
    • Локализация версия: Бразилия, Китай, Япония, Таиланд, Индия
  • Мне известно, что функция SystemDateGet () была разработана для возврата даты AOS, если только пользователь изменяет дату своего сеанса, и в этом случае эта дата возвращается.

  • Каждый пользователь имеет соответствующую настройку часового пояса в своем профиле пользователя.

Задача

Один из примеров проблемы - когда пользователь пытается опубликовать журнал, связанный с финансовыми транзакции, где проверяется период бухгалтерской книги, чтобы увидеть, открыт ли он. Например, Пользователь в Англии пытается опубликовать журнал в 15:00 30 ноября по местному времени. время стандартный код Axapta использует функцию systemDateGet () для определения даты использования в проверке (определение, если период открыт). В нашем случае AOS основан на Брисбен Австралия и функция systemDateGet () возвращаются 1 декабря (по местному времени 1:00 утра 1 декабря).

Другим примером проблемы является то, что в пятницу в Соединенных Штатах выставляется счет-фактура. а день недели, в котором находится AOS, - суббота. Нам нужна система, чтобы запишите местную дату.

Вопрос

Помимо переписывания всего системного кода, включающего systemDateGet (), имеется более 2000 сущностей. любые другие варианты, которые могут быть использованы, чтобы обойти проблему получения правильного местного дата

Ограничения решения.

  • В приведенном выше примере закрытия периода бухгалтерской книги это невозможно из точка зрения бизнес-практики, чтобы открыть следующий период до конца месяца обработки было завершено.

  • В настоящее время нет возможности приобрести дополнительные AOS.

Ответы [ 2 ]

1 голос
/ 08 декабря 2011

Создайте функцию в классе Global:

static date systemDateGetLocal()
{
    return DateTimeUtil::date(DateTimeUtil::applyTimeZoneOffset(DateTimeUtil::utcNow(), DateTimeUtil::getUserPreferredTimeZone()));
}

Затем в Info.watchDog() выполните:

systemDateSet(systemDateGetLocal());

Это может быть только частичное решение, watchDog выполняется только на стороне клиента.

0 голосов
/ 22 февраля 2012

Вот быстрое обновление.Сообщите мне, если есть какие-либо проблемы или ситуации, которые необходимо устранить.

ИСПОЛЬЗОВАНИЕ МЕСТНОГО ВРЕМЕНИ

Введение:
Ниже приведено обновление в процессе разработки, поскольку решение еще предстоит полностью протестировать во всех ситуациях.

Проблема:
Если у пользователя другой часовой пояс, чем у AOS, timeNow () и systemDateGet () функции возвращают детали AOS, когда требуется местное время.

Уточнители:
Когда местное время даты изменяется в Axapta, функция systemDateGet () возвращает локальную дату, однако функция timeNow () по-прежнему возвращает время AOS.

Изменения кодирования:
Был внесен ряд изменений кодирования для обработки ряда различных ситуаций.Комментарии могут быть добавлены в тех случаях, когда может потребоваться объяснение.

Скобки были изменены на {и}, чтобы это можно было опубликовать.

КЛАСС: ГЛОБАЛЬНЫЙ

Одно требование Iбыло дано, чтобы позволить системе обрабатывать несколько сайтов внутри компании, которые могут иметь разные часовые пояса.В настоящее время эта функциональность не требуется.

static server void setSessionDateTime(
    inventSiteId    inventSiteId = '', 
    utcDateTime     reference = dateTimeUtil::utcNow())
{
    str                             sql;
    sqlStatementExecutePermission   perm;
    connection                      conn        = new UserConnection();
    timeZone                        timeZone;
    int                             ret;
    ;

    if (inventSiteId)
    {
        timeZone = inventSite::find(inventSiteId).Timezone;
    }
    else
    {
        timeZone = dateTimeUtil::getCompanyTimeZone();
    }

    //This is to get around the kernel validation of changing timezones
    //when the user has more than one session open.

    sql     = strfmt("Update userInfo set preferredTimeZone = %1 where userInfo.id = '%2'", enum2int(timeZone), curUserId());
    perm    = new SQLStatementExecutePermission(sql);
    perm.assert();

    ret = conn.createStatement().executeUpdate(sql);

    dateTimeUtil::setUserPreferredTimeZone(timeZone);
    dateTimeUtil::setSystemDateTime(reference);

    CodeAccessPermission::revertAssert();
}

static int localTime()
{
    utcDateTime tmp;
    ;
    setSessionDateTime();

    tmp = dateTimeUtil::applyTimeZoneOffset( dateTimeUtil::utcNow(), dateTimeUtil::getCompanyTimeZone());
    return dateTimeUtil::time(tmp);
}

Следующий метод был реализован как перекрестная проверка, чтобы гарантировать, что systemDateGet() возвращает ожидаемое значение.

static date localDate()
{
    utcDateTime tmp;
    ;
    setSessionDateTime();

    tmp = dateTimeUtil::applyTimeZoneOffset( dateTimeUtil::utcNow(), dateTimeUtil::getCompanyTimeZone());
    return dateTimeUtil::date(tmp);
}

CLASS: APPLICATION

Изменить метод setDefaultCompany.Добавьте строку setSessionDateTime(); сразу после супер звонка.Это позволяет изменить время, когда пользователь меняет компанию (другое требование, которое мне было дано).

CLASS: INFO

, чтобы система использовала правильную дату / время с началасеанс.

void startupPost()
{
    ;
    setSessionDateTime();
}

Измените метод canViewAlertInbox(), добавив строку setSessionDateTime(); в качестве первой строки.Это необходимо, если у пользователя есть несколько форм, открытых для разных компаний.

Изменения, зависящие от локализации:

В зависимости от вашего пакета обновления и локализаций, вам нужно будет изменитьфункция объектов, чтобы использовать функцию localTime (), заменяя timeNow ().ВАЖНОЕ ПРИМЕЧАНИЕ. Не изменяйте класс BatchRun для использования новой функции localTime, так как это приведет к неправильной работе.

В нашей системе насчитывалось около 260 экземпляров, которые можно было изменить.Если вы не используете все модули и локализации, фактическое количество строк, которое вам нужно изменить, будет меньше.

Итоговое примечание:

На сегодняшний день существует ряд () звонки в коде.Я еще не прошел каждую строку, чтобы убедиться, что она закодирована правильно, то есть с использованием today () вместо systemDateGet ().

Известные проблемы:

Я столкнулся с ситуацией, когда функция изменения часового пояса не работала полностью, как ожидалось.Это было, когда один сеанс выполнял синхронизацию базы данных, а другой был открыт в другой компании.Поскольку обычные пользователи никогда не смогут сделать это, я не потратил много времени на его решение на данном этапе.Это то, что я собираюсь решить.

...