То что было под носом, но чего я не замечал...

18 12

Рассказать я хочу о Блоках типовых маршрутов с которыми очень важно хорошо ознакомиться:

1. Согласование с уменьшающимся составом рецензентов

Первое что мне удалось найти: Раздел "Управления деловыми процессами" - "Согласование с уменьшающимся составом рецензентов"

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

Как вариант - отличный способ отсекать всех, кто не согласен с согласующими)))

Небольшая тонкость: При отправке задания на доработку, Невыполненные задачи блока - прекращаются!

 

2. Расширенное задание

А недавно, я узнал, что такой функцией, причем удобнее, обладает простое "Расширенное задание":

Как оказалось, все давно лежало перед самым носом: Есть "Списки на согласование", есть "вариант исключения другого списка" и даже "самозаполнение сего списка"! Да это же оказалось элементарным! Смотрите сами:

Для работы этого чуда, надо всего-навсего создать 2 Параметра: "Согласующие" и "Согласовавшие", ну и Код результата выполнения должен соответствовать вашим требованиям. После выполнения задачи и вероятной доработки, задачу получат только те, кто не входит в список Согласовавших. 

Небольшая тонкость: При отправке задания на доработку, Невыполненные задачи блока - продолжают ожидать остальных согласующих, если не настроено иное поведение

 

3. Работа с крайним сроком

Работа с крайним сроком - отличный инструмент:

Вот пример отличной конструкции учитывающей просрочку и последствия:

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

 

4. Переназначение

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

Запрос параметра на старте:

Далее, Запрос параметра при варианте выполнения "Переназначить":

Вот так вот - век живи, век учись!

Может для кого-то я немного и приоткрыл глаза) Удачного дня!

Тарас Асачёв

Можно еще добавить к работе со сроками:

Зависимость сроков относительных и Конечных, от кол-ва листов в документе и с учетом выходных дней.

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 = ИзмДат("Д";Сегодня();СрокИндекс) // Определяем Конечный срок смещением даты

В итоге у нас переменная "Срок" будет использоваться для относительно срока, а "КрайнийСрок", соответственного для конечного.

Тарас Асачев: обновлено 17.05.2019 в 12:59
Антон Максунов

Было дело, собирал такие полезности в каталог ссылок. Было очень полезно. До сих помню у меня наверное с месяц настольной книгой была статейка про форматирование в 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 

Дан Олейников: обновлено 27.06.2019 в 14:38

Авторизуйтесь, чтобы написать комментарий