В статье За 6 шагов мастер готов рассказано как легко можно создать мастер и запросить у пользователя все необходимые данные. Но теперь с этими данными нужно что-то делать, для этого нужны вычисления в событиях мастера.
События в мастере открываются по кнопке События. У мастера есть 3 события: До выбора, Начало, Завершение. Также у каждого этапа есть свои события: Начало, Завершение, Previous, Next, Finish, Cancel (у заключительного этапа OK). Назначения этих событий описаны в справке.
Предлагаю посмотреть примеры типовых вычислений и особенности вычислений в мастерах.
Так как мастер предназначен для упрощения работы пользователя, нужно заполнять параметры значениями по-умолчанию, если это возможно. Заполнять параметры можно в событии "Начало" мастера. Самые частые случаи:
Заполнить текущего пользователя (например, параметры Автор, Инициатор):
Params = Wizard.Params
Params.ValueByName('Автор').Value = EDocuments.CurrentUser
Заполнить работника текущего пользователя:
Params = Wizard.Params
// Найти всех работников для текущего пользователя
CurrentEmployeeIDList = GetEmployeesByUserID(EDocuments.CurrentUser.ID; ; FALSE)
if CurrentEmployeeIDList.Count > 0
// Заполнить параметр первым работником
Params.ValueByName('Работник').Value = References.РАБ.ObjectInfo(CurrentEmployeeIDList.Values(0))
endif
Заполнить текущую дату (например, параметры Дата договора, Дата документа):
// Заполнить дату заявления текущей датой
Params.ValueByName('ДатаДокумента').Value = Today()
Заполнить редко изменяющийся параметр значением, хранящимся в реестре.
Например, каждый секретарь чаще всего создает заявку на имя определенного руководителя, можно код руководителя записывать в реестр, а при повторном запуске мастера считывать оттуда, таким образом для 90% случаев мы облегчим работу секретарю:
// Считать из реестра код руководителя - в событии "Начало" мастера
Params = Wizard.Params
Register = "HKEY_CURRENT_USER\Software\Computer\DIRECTUM\Параметры мастеров действий\"
ChiefCode = РеестрЧтение(Register & Wizard.Title; "ЗначПоУмолч")
if Assigned(ChiefCode)
Params.ValueByName('Руководитель').Value = References.РАБ.GetObjectByCode(ChiefCode).Info
endif
// Если данные изменились, то записать в реестр код руководителя - в событии "Finish" последнего этапа
// (когда пользователь нажимает кнопку Готово)
Params = Wizard.Params
Register = "HKEY_CURRENT_USER\Software\Computer\DIRECTUM\Параметры мастеров действий\"
ChiefCode = РеестрЧтение(Register & Wizard.Title; "ЗначПоУмолч")
CurrentChiefCode = Params.ValueByName('Руководитель').Value.Code
if CurrentChiefCode <<>> ChiefCode
РеестрЗапись(Register & Wizard.Title; "ЗначПоУмолч"; CurrentChiefCode)
endIf
Корректность введенного значения нельзя проверить сразу после заполнения параметра пользователем на форме, а только после нажатия какой-либо кнопки. Логично проверять при нажатии кнопки Далее. Чтобы работа всего мастера не прерывалась, а прерывался только этап, и при этом работало в веб-доступе, необходимо использовать генерацию исключений.
// Проверить является ли дата начала отпуска рабочим днем
Params = Wizards.Params
DateFrom = Params.ValueByName('C').Value
// Получить первый рабочий день, включая текущий день
WorkDay = ServiceFactory.GetRelativeDate(DateFrom; 0; dotDays)
// Если указанная дата и первый рабочий день отличаются, то сгенерировать исключение
if DateDiff('D'; WorkDay; DateFrom) <> 0
Raise(CreateException('EDIRInvalidUserAction'; 'Отпуск (отгул) не должен начинаться с выходного дня.'; ecWarning))
endif
Переходы можно задавать в зависимости от определенных условий, например, если пользователь установил флажок Отправить задачу по ТМ, то нужно перейти на этап с запросом параметров для ТМ, иначе пропустить этот этап. Если в вычислениях не указан этап для перехода, то переходит на следующий этап. Переходы нужно задавать с событиях "Next" и "Previous" этапов:
Params = Wizard.Params
// Если нужно отправить задачу, то перейти на этап Параметры ТМ, иначе сразу на этап проверка данных
if Params.ValueByName('Отправить задачу по ТМ').Value
Wizard.NextStep = Wizard.Steps.ValueByName('Параметры ТМ')
else
Wizard.NextStep = Wizard.Steps.ValueByName('Проверка данных')
endif
В мастерах рекомендуется делать специальный этап для проверки введенных данных пользователем перед тем, как он нажмет кнопку Готово. Эти данные формируются ввиде текста и записывают в текстовый параметр, которые размещен на форме этапа. Я предлагаю вычисления, которые выводят все значения параметров всех типов с заданных этапов, без привязки к именам параметров. Этот способ удобно использовать, когда на этапе проверки нужно выводить именно введенные данные, а не сформированные на их основе. Преимущество способа в том, что при добавлении\удалении с этапа параметра, он появится\удалится на этапе проверки данных автоматически. Вычисления пишем в событие "Начало" этапа с проверкой данных:
STEP_NAME_INDEX = 0
TITLE_INDEX = 1
Params = Wizard.Params
// Массив в формате: Имя параметра, Заголовок для вывода информации для проверки
StepNameArray = ArrayOf(
ArrayOf('Основные параметры'; 'Основные параметры');
ArrayOf('Параметры ТМ'; 'Параметры согласования'))
foreach StepName in CArrayElement(StepNameArray)
// Проверить, что этап существует
if Wizard.Steps.IndexOfName(StepName[STEP_NAME_INDEX]) <> -1
// Добавить заголовок в данные для проверки
Result = AddSubString(StepName[TITLE_INDEX]; Result; CR & CR)
// Получить все элементы формы этапа
Elements = Wizard.Steps.ValueByName(StepName[STEP_NAME_INDEX]).Elements
ElementCount = Elements.Count
Index = 0
// Пройтись по каждому элементу
while Index < ElementCount
Element = Elements.Values(Index)
Index = Index + 1
// Если элемент формы связан с параметром
if Element.ElementType = wfetQueryParameter
// Получить параметр
Param = Element.Parameter
// Если элемент связан с параметром, то получить его значение
if in(ArrayOf(wptReferenceRecordInfo; wptUser); Param.ParamType)
ParamValue = ''
if Assigned(Param.Value)
if Param.ParamType = wptUser
ParamValue = Param.Value.FullName
else
ParamValue = Param.Value.Name
endif
endif
else
// Если параметр типа Логическое значение, то заменить TRUE\FALSE на Да\Нет
if Param.ParamType = wptBoolean
ParamValue = IfThen(Param.Value; 'Да'; 'Нет')
else
// Для параметров типа Список записей справочников сформировать список
if in(ArrayOf(wptReferenceRecordInfoList; wptUserList; wptEDocumentInfoList); Param.ParamType)
ParamValue = ''
if Assigned(Param.Value)
ParamValue = TAB & TAB
foreach Record in Param.Value
if Param.ParamType = wptUserList
ParamValue = AddSubString(Format('%s%s'; ArrayOf(TAB & TAB; Record.FullName)); ParamValue; CR)
else
ParamValue = AddSubString(Format('%s%s'; ArrayOf(TAB & TAB; Record.Name)); ParamValue; CR)
endif
endforeach
endif
else
// Иначе просто получить значение параметра
ParamValue = Param.Value
endif
endif
endif
// Добавить заголовок параметра на форме и значения параметра в данные для проверки
Result = AddSubString(Format('%s: %s'; ArrayOf(Element.Caption; ParamValue)); Result; CR & Tab)
endif
endwhile
endif
endforeach
Params.ValueByName('Данные для проверки').Value = Result
Результатом работы мастера может быть новая запись справочника. Очень часто возникает вопрос: в записях справочника бывают табличные части, которые нужно заполнять, как это организовать в мастере? Рекомендуется 3 варианта:
Вычисления пишем в событие "Finish" этапа с проверкой данных:
// Создать запись справочника Совещания
MeetingRec = References.СВЩ.CreateNew()
// Тема
MeetingRec.Содержание = Params.ValueByName('Тема').Value
// Дата и время
MeetingRec.ДатаВремя = Params.ValueByName('Дата').Value)
// Продолжительность
MeetingRec.Цена1 = Params.ValueByName('Продолжительность').Value
// Место проведения - запись справочника (значение параметра это IReferenceInfo, для заполнения реквизита нужно получить код)
MeetingRec.Room = Params.ValueByName('Место').Value.Code
// Заполнить участников в табличной части из параметра типа Список записей справочников
if Assigned(Params.ValueByName('Участники').Value)
ParticipantDataSet = MeetingRec.DetailDataSet(2)
foreach Participant in Params.ValueByName('Участники').Value
ParticipantDataSet.Insert
ParticipantDataSet.РаботникТ2 = Participant.Code
ParticipantDataSet.AdditionT2 = Participant.Name
endforeach
endif
MeetingRec.Save
Для отправки задачи можно воспользоваться специальной функцией. Вычисления пишем в событие "Finish" этапа с проверкой данных:
// Массив соответствия: параметр задачи - параметр мастера
// Параметры ТМ и мастера должны быть одинакового типа
ParamArray = ArrayOf(
ArrayOf('Participants'; 'Согласующие');
ArrayOf('MeetingApprovalDeadline'; 'СрокСогласования');
ArrayOf('NeedNotice'; 'Уведомление'))
endif
TaskMeeting = WizardCreateStandardRouteTask(
Wizard;
Params.ValueByName('ТМ').Value.Code;
ParamArray;
ArrayOf('КарточкаСовещания'; 'Вложения'); ; ; FALSE)
В мастерах рекомендуется на завершающем этапе выводить результаты работы мастера со ссылками на созданные объекты (записи справочника, документы, задачи и т.д.). Эти данные формируются ввиде текста и записываются в текстовый параметр, который размещен на форме завершающего этапа. Также при созднии этих объектов могут возникать ошибки (например, проблемы со службой WorkFlow и поэтому не удалось отправить задачу), эту ошибку можно запомнить и на завершающем этапе вывести ее.
Text = ''
// Создать запись справочника Совещания
MeetingRec = References.СВЩ.CreateNew()
// Заполнить реквизиты...
// Перед сохранением записи отключить генерацию исключений
FreeException()
ExceptionsOff()
MeetingRec.Save
ExceptionsOn()
if ExceptionExists()
Exception = GetLastException()
// Запомнить ошибку
Text = AddSubString('Не удалось создать запись справочника "Совещания": ' & Exception.Message; Text; CR & CR)
else
// Запомнить гиперссылку на запись справочника
Text = AddSubString('Оформлено совещание: ' & MeetingRec.HyperLink(hltText); Text; CR & CR)
endif
// Отправить задачу по ТМ, перед отправкой отключить генерацию исключений
FreeException()
ExceptionsOn()
TaskMeeting = WizardCreateStandardRouteTask(Wizard;
Params.ValueByName('ТМ').Value.Code; ParamArray; ArrayOf('КарточкаСовещания'; 'Вложения'); ; ; FALSE)
ExceptionsOff()
if ExceptionExists()
// Запомнить ошибку
Exception = GetLastException()
Text = AddSubString(Format('Не удалось отправить задачу по совещанию: %s'; Exception.Message); Text; CR & CR)
else
// Запомнить гиперссылку на задачу
Text = AddSubString(
Format('Отправлена задача по совещанию: %s'; CreateHyperlink(Task.ID; 'Задача')); Text; CR & CR)
endif
Params.ValueByName('Итоговые данные').Value = Text
Примечание: опускаю совсем создание документов, так как этот вопрос будет рассмотрен в следующей статье, в которой будет рассказано про совместное использование мастеров действий и конструктора доументов.
Как можно заполнить программно пустою параметр типа "Список электронных документов"? Метод ADD не работает.
Еще обратите внимание на метод Combine - он позволяет гибко собирать IContents по частям.
Как программно получить результат, выполнения задания?
Авторизуйтесь, чтобы написать комментарий