Рассказать я хочу о Блоках типовых маршрутов с которыми очень важно хорошо ознакомиться:
Первое что мне удалось найти: Раздел "Управления деловыми процессами" - "Согласование с уменьшающимся составом рецензентов"
Для работы сего блока, необходимо заполнять Параметр "Рецензенты" от которого все и танцует, и список этот будет уменьшаться при согласовании задания, исключая тех, кто уже высказал свое мнение.
Как вариант - отличный способ отсекать всех, кто не согласен с согласующими)))
Небольшая тонкость: При отправке задания на доработку, Невыполненные задачи блока - прекращаются!
А недавно, я узнал, что такой функцией, причем удобнее, обладает простое "Расширенное задание":
Как оказалось, все давно лежало перед самым носом: Есть "Списки на согласование", есть "вариант исключения другого списка" и даже "самозаполнение сего списка"! Да это же оказалось элементарным! Смотрите сами:
Для работы этого чуда, надо всего-навсего создать 2 Параметра: "Согласующие" и "Согласовавшие", ну и Код результата выполнения должен соответствовать вашим требованиям. После выполнения задачи и вероятной доработки, задачу получат только те, кто не входит в список Согласовавших.
Небольшая тонкость: При отправке задания на доработку, Невыполненные задачи блока - продолжают ожидать остальных согласующих, если не настроено иное поведение!
Работа с крайним сроком - отличный инструмент:
Вот пример отличной конструкции учитывающей просрочку и последствия:
Выдача нового срока, устанавливается запросом параметра у Руководителя, который в принципе может сделать задачу и сам, но в этом случае идет уведомление Исполнителя об этом факте.
Переназначение - штука которую я освоил давно, но она регулярно требуется, так как очень многие Инициаторы, в принципе не до конца понимают, кто должен выполнять их задачу по некоторым маршрутам. Для этого строится простейшая конструкция:
Запрос параметра на старте:
Далее, Запрос параметра при варианте выполнения "Переназначить":
Вот так вот - век живи, век учись!
Может для кого-то я немного и приоткрыл глаза) Удачного дня!
Можно еще добавить к работе со сроками:
Зависимость сроков относительных и Конечных, от кол-ва листов в документе и с учетом выходных дней.
Params = Sender.WorkFlowParams Day = 1 // Индекс дней Листы = Params.ValueByName("Листы").Value // Считываем кол-во листов if Листы < 15 // Менее 15 листов Params.ValueByName("Срок").Value = 5 // Срок 5 дней else if Листы < 50 // Менее 50 листов Params.ValueByName("Срок").Value = 7 // Срок 7 дней else // Более 49 листов Params.ValueByName("Срок").Value = 10 // Срок 10 дней endif endif СрокИндекс = Params.ValueByName("Срок").Value // Снимаем полученный срок в отдельную переменную while Day <= СрокИндекс // Движемся по кол-ву дней в сроке, начиная от сегоднящнего дня if (ДеньНедели(ИзмДат("Д";Сегодня();Day))) == 6 or (ДеньНедели(ИзмДат("Д";Сегодня();Day)) == 7) СрокИндекс = СрокИндекс + 1 // День выпал на выходной - увеличиваем срок на день endif Day = Day + 1 // Индекс дней endwhile Params.ValueByName("КрайнийСрок").Value = ИзмДат("Д";Сегодня();СрокИндекс) // Определяем Конечный срок смещением даты
В итоге у нас переменная "Срок" будет использоваться для относительно срока, а "КрайнийСрок", соответственного для конечного.
Было дело, собирал такие полезности в каталог ссылок. Было очень полезно. До сих помню у меня наверное с месяц настольной книгой была статейка про форматирование в Excel и в целом про работу с ним. Правда то еще было во времена форума, сейчас они все, скорее всего, уже не работают Впрочем и компьютер тот был несколько работ назад...
>> 4. Переназначение
Такая конструкция работоспособна только в том случае, когда в блоке Задание только один исполнитель. Как перенаправить (делегировать) своё задание, если исполнителей в блоке несколько - та еще задачка! Может есть кто-то, кому удалось такое реализовать? Буду признателен, если поделитесь опытом.
Святослав, в этом случае напрашиваются подзадачи.
С подзадачами делал довольно гибкую реализацию с делегированием, подключением доп. исполнителей и независимой доработкой.
Да от чего же - делегируйте на список пользователей, но тогда в случае делегирования, у всех остальных задача должна прекращаться. В идеале, это может быть "расширенное задание" на список пользователей. Кто согласовал - заносится в список Согласовавших, оставшиеся либо отправляют на доработку, либо выполняют задачу с делегированием задачи. После завершения ожидания участников или по конечному сроку - задача передает параметры в новую, где список согласовавших исключается из списка, составленного другими участниками. Алес.
С крайним сроком тоже нужно быть аккуратным, когда у тебя например 3 согласующих, 1 согласовал, 2ой на доработку, а 3й прекратился по крайнему сроку. В таком случае после блока с крайним сроком, нужно вешать блок сценарий и отслеживать отправлял ли кто-то на доработку.
У нас настройка простая:
1. Согласующие, попадают в список Согласовавшие;
2. Все кто отправляет на доработку, ждут оставшихся. Если же задача вышла в просрочку, то она попадает Инициатору, в ней он увидит требования на доработки и может увеличить срок согласования для очередного согласования без тех, кто уже согласовал.
3. Запрос на увеличение срока может быть исполнен лишь раз.
>> 4. Переназначение
Такая конструкция работоспособна только в том случае, когда в блоке Задание только один исполнитель. Как перенаправить (делегировать) своё задание, если исполнителей в блоке несколько - та еще задачка! Может есть кто-то, кому удалось такое реализовать? Буду признателен, если поделитесь опытом.
Я делал недавно, но там одним блоком не обойтись. Нужен как минимум второй блок сценарий/условие, который проверяет была ли смена исполнителя и сложный параметр маршрута (я из использовал строку внутри которой хранил XML с результатами выполнения заданий каждым пользователем). И все это с тем ограничением, что задание новому исполнителю придет только после того, как остальные исполнители по этому блоку выполнят свои задания.
Любопытные варианты
По поводу переназначения - у нас реализован близкий по смыслу механизм, когда надо поменять исполнителя по конкретному сформированному заданию.
Суть проблемы, как правило, в том, что либо пользователь, на котором висит задание не работает в системе совсем и на него направили ошибочно, либо это уволившийся руководитель вместо которого работает совсем другой человек и надо чтобы везде уже отображался новый человек (без замещения). Чтобы не гонять документы по процессам кругами, реализовали отдельный сценарий, который меняет исполнителя в сформированном задании и переносит в нужную папку "Входящие". Изменение идет через СУБД и схему задачи.
Коллеги, спасибо за то, что поделились своим опытом реализации перенаправления (делегирования) задания.
Я реализовывал данную задачу при помощи 2-х ТМ-ов: основной и вспомогательный. Стартуется задача по основному ТМ-у на список согласующих, в блоке сценарий каждому согласующему создается подзадача по вспомогательному ТМ-у, результаты согласования передаются из вспомогательного в основной. Во вспомогательном ТМ-е получается всегда один согласующий и описанная в данной статье схема перенаправления работает.
Дан Олейников, довольно интересное решение! Можете поделиться данным сценарием, буду очень признателен!
Дан Олейников, Поделитесь пожалуйста сценарием.
Святослав Романов, Алексей Исаев
LinkJobs = ''
//Создадим и зполним диалог
Dialog = Dialogs.AVID_ChangePerformer.CreateNew
ShowDialog(Dialog)
if Dialog.Result == '1'
CreateDialog = True
else
exit()
endif
Передающий = ServiceFactory.GetUserByCode(Dialog.User)
Принимающий = ServiceFactory.GetUserByCode(Dialog.User2)
IDJobs = Dialog.LongString
foreach IDJob in CSubString(IDJobs; '|')
TaskID = sql('select TaskID from SBTaskJob with(nolock) where XRecID = ' & IDJob)
Task = Tasks.GetObjectByID(TaskID)
//Выдадим прав на вложения Принмающему какие были у Передающего
Attachments = Task.GetAttachments(FALSE)
foreach Attachment in Attachments
ObjInfo = Attachment.ObjectInfo
//Передача прав на документ
if ObjInfo.ComponentType = ctEDocument
ПередатьПраваНаДокумент(ObjInfo.ID; Передающий; Принимающий)
endif
//Передача прав на папку
if ObjInfo.ComponentType = ctFolder
ПередатьПраваНаПапку(ObjInfo.ID; Передающий; Принимающий; ObjInfo.ID)
endif
endforeach
Task.Save
Path = GetTempFolder() & 'TASK_' & TaskID & '.xml'
Task.Requisites('WorkflowDescription').SaveToFile(Path)
XMLDoc = CreateObject("MSXML.DomDocument")
XMLDoc.Load(IncludeTrailingPathDelimiter(GetTempFolder()) & 'TASK_' & TaskID & '.xml')
CurrentBlocks = XMLDoc.selectSingleNode("/Settings/CurrentBlocks").ChildNodes ///RouteBlock/Block/AdditionalInfo")
need_block = sql('select WorkflowBlockID from SBTaskJob with(nolock) where XRecID = ' & IDJob)
i = 0
while i < CurrentBlocks.length
Block_ID = CurrentBlocks.Item(i).Attributes.GetNamedItem('ID').Value
if Block_ID == need_block
user = CurrentBlocks.Item(i).selectSingleNode('Block/AdditionalInfo/Value')
user.Attributes.GetNamedItem('StartedJobPerformer').Value = Принимающий.Name
endif
i = i + 1
endwhile
XMLDoc.Save(IncludeTrailingPathDelimiter(GetTempFolder()) & 'TASK_' & TaskID & '.xml')
res = ReadFile(IncludeTrailingPathDelimiter(GetTempFolder()) & 'TASK_' & TaskID & '.xml')
res = replace(res; "'"; "''")
Task.Requisites('WorkflowDescription').LoadFromFile(Path)
Task.Save
Query = SQL(Format("
update dbo.SBTaskJob
set Executor = %s, Readed = 'N'
where TaskID = %s and Executor = %s and State = 'W'"; ArrayOf(Принимающий.ID; Task.ID; Передающий.ID)))
//Положим Задание в папку Входящие принимающего
InFolderSearch = Searches.Load('FOLDER_SEARCH')
InFolderSearchCriteria = InFolderSearch.SearchCriteria
AuthorCriterion = InFolderSearchCriteria.Add('Author')
AuthorCriterion.SetCompleteValue(Принимающий.Code)
TypeCriterion = InFolderSearchCriteria.Add('FolderType')
TypeCriterion.SetSimpleValue('I') // Исходящие
Res = Searches.Execute(InFolderSearch)
// Если папку нашли - добавить в нее ссылку на задачу
if Res.Count > 0
while not Res.EOF // папок Входящие теоретически может быть несколько
InputFolderInfo = Res.Value
Folders.PasteToFolder(InputFolderInfo; Jobs.GetObjectByID(IDJob).Info)
Res.Next
endwhile
endif
//Удалим Задание из папки Входящие передающего
InFolderSearch = Searches.Load('FOLDER_SEARCH')
InFolderSearchCriteria = InFolderSearch.SearchCriteria
AuthorCriterion = InFolderSearchCriteria.Add('Author')
AuthorCriterion.SetCompleteValue(Передающий.Code)
TypeCriterion = InFolderSearchCriteria.Add('FolderType')
TypeCriterion.SetSimpleValue('I') // Исходящие
Res = Searches.Execute(InFolderSearch)
// Если папку нашли - добавить нее ссылку на задачу
if Res.Count > 0
while not Res.EOF // папок Входящие теоретически может быть несколько
InputFolderInfo = Res.Value
Folders.CutFromFolder(InputFolderInfo; Jobs.GetObjectByID(IDJob).Info)
Res.Next
endwhile
endif
LinkJobs = LinkJobs & CreateHyperlink(IDJob; 'Задание') & CR
endforeach
if LinkJobs <<>> ''
//Создадим уведомление Передающему
MSG = 'Ваши задания переданы в ответственность ' & Принимающий.FullName & ':' & CR & LinkJobs
Task = Tasks.CreateNew
Task.Requisites('Subject').AsString = 'Ваши задания переданы в ответственность ' & Принимающий.FullName
Task.ActiveText = MSG
RouteStep = Tasks.CreateRouteStep(1; Передающий; jkNotice; ''; ""; "")
Task.Route.Add(RouteStep)
Task.WorkflowProperties.ValueByName("TaskControl").Value = false
Task.SetupStandardRoute(TRUE)
Task.Start
//Создадим уведомление принимающему
MSG = 'В Вашу ответственность переданы задания от ' & Передающий.FullName & ':' & CR & LinkJobs
Task = Tasks.CreateNew
Task.Requisites('Subject').AsString = 'В Вашу ответственность переданы задания от ' & Передающий.FullName
Task.ActiveText = MSG
RouteStep = Tasks.CreateRouteStep(1; Принимающий; jkNotice; ''; ""; "")
Task.Route.Add(RouteStep)
Task.WorkflowProperties.ValueByName("TaskControl").Value = false
Task.SetupStandardRoute(TRUE)
Task.Start
ShowMessage('Задания успешно переданы!')
endif
Авторизуйтесь, чтобы написать комментарий