AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 13.11.2014, 21:05   #1  
Ruff is offline
Ruff
Дмитрий Ерин
Аватар для Ruff
1C
 
475 / 396 (14) ++++++
Регистрация: 18.09.2003
Адрес: Тула
! Баг: Циклическое делегирование в WorkFlow
AX2009

Стандартный функционал в некоторых случаях некорректно обрабатывает длинные цепочки делегирования. Например, если у пользователя Boss в параметрах настроено активное делегирование по всем конфигурациям (Результат = Все) на пользователя Zam, а у пользователя Zam - делегирование по конкретной конфигурации "Конф0001" на пользователя Buh, то при запуске документооборота по какой-либо другой конфигурации будет выдана ошибка "Обнаружено циклическое делегирование: Zam->Boss->Zam". Хотя на самом деле должно было сработать делегирование Boss->Zam. Если документооборот выполняется по конфигурации "Конф0001", цепочка будет определена верно (Boss->Zam->Buh).

Проблема кроется в методе \Classes\SysWorkflowHelper\getDelegate:
X++:
public server static WorkflowUser getDelegate(
    WorkflowUser _user,
    WorkflowConfigurationTable _configTable)
{
    WorkflowTrackingMessage trackingMessage;
    userId delegateUser;
    Set delegatedUsers = new Set(Types::String);
    utcdatetime delegateDate = DateTimeUtil::utcNow();
    SetEnumerator userEnumerator;
    str users;

    //inline method
    void findDelegate(WorkflowUser _userId)
    {
        WorkflowWorkItemDelegationParameters delegationParameters;

        while select delegationParameters where
                delegationParameters.User == _userId && delegationParameters.Enabled == NoYes::Yes &&
                delegationParameters.FromDate < delegateDate && delegationParameters.ToDate > delegateDate
        {            
            switch (delegationParameters.Type)
            {
                case WorkflowWorkItemDelegationType::All:
                    delegateUser = delegationParameters.Delegate;
                    break;
                case WorkflowWorkItemDelegationType::Category:
                    if (delegationParameters.CategoryName == _configTable.CategoryName)
                    {
                        delegateUser = delegationParameters.Delegate;
                    }
                    break;
                case WorkflowWorkItemDelegationType::Configuration:
                    if (delegationParameters.ConfigurationSequenceNumber == _configTable.SequenceNumber)
                    {
                        delegateUser = delegationParameters.Delegate;
                    }
                    break;
                default:
                    throw error(strfmt("@SYS122124", enum2str(delegationParameters.Type)));
            }

            if (delegateUser)       //////// <== Вот это проверка срабатывает некорректно!
            {
                if (delegatedUsers.in(delegateUser))
                {
                    userEnumerator = delegatedUsers.getEnumerator();
                    while(userEnumerator.moveNext())
                    {
                        if (!users)
                        {
                            users = userEnumerator.current();
                        }
                        else
                        {
                            users = users + '->' +  userEnumerator.current();
                        }
                    }
                    users = users + '->' +  delegateUser;
                    trackingMessage = strfmt("@SYS122125", users);
                    throw error(trackingMessage);
                }
                else
                {
                    delegatedUsers.add(delegateUser);
                    findDelegate(delegateUser);
                }
                break;
            }
        }        
    }
    ;

    delegatedUsers.add(_user);
    findDelegate(_user);

    return strlen(delegateUser) > 0 ? delegateUser : _user;
}
Суть бага в том, что в рекурсивной локальной функции findDelegate() используется внешняя переменная delegateUser, которая (по задумке автора) при некоторых условиях (см. switch) может оказаться пустой, что должно означать переход к следующей итерации цикла. И это прекрасно работает при первом вызове findDelegate(), но при следующем (по глубине рекурсии) вызове она хранит значение, оставшееся от прошлого вызова, что и приводит к описанной ошибке.

Лечить можно по-разному:
  1. завести локальный флаг, устанавливая его внутри switch и проверяя вместо if (delegateUser)
  2. очищать эту переменную в начале каждой итерации цикла и восстанавливать перед выходом из функции:
    X++:
    while select ...
    {
       delegateUser = '';
       ...
    } // while
    if (!delegateUser) delegateUser = _userId;
    } // findDelegate()
  3. вообще убрать этот чудной switch и дописать нужные проверки непосредственно к запросу:
    X++:
    ...
                    && (delegationParameters.Type                           == WorkflowWorkItemDelegationType::All
                    ||  (   delegationParameters.Type                       == WorkflowWorkItemDelegationType::Category
                        &&  delegationParameters.CategoryName               == _configTable.CategoryName  )
                    ||  (   delegationParameters.Type                       == WorkflowWorkItemDelegationType::Configuration
                        &&  delegationParameters.ConfigurationSequenceNumber== _configTable.SequenceNumber  )
                       )
          {
              delegateUser = delegationParameters.Delegate;
              ...
  4. Свой вариант)
__________________
За это сообщение автора поблагодарили: Logger (3), S.Kuskov (2).
Теги
ax2009, workflow, баг, делегирование, ошибка

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
atinkerersnotebook: Developing a Product Approval Workflow in Dynamics AX 2012 Blog bot DAX Blogs 0 09.11.2013 17:12
atinkerersnotebook: Using Vendor Requests to Manage On-boarding New Vendors Blog bot DAX Blogs 1 22.10.2013 02:24
workflowax: What is a workflow owner used for? Blog bot DAX Blogs 0 01.06.2010 15:05
Solutions Monkey: Using Microsoft Dynamics Ax 2009 Workflow controls in EP Blog bot DAX Blogs 0 30.07.2008 10:05
Arijit Basu: AX 2009 Workflows: A Quick overview Blog bot DAX Blogs 0 19.06.2008 02:07

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 05:56.