Добрый день!

 

Есть родительский процесс в рамках которого "Менеджер" добавляет в обьект "Заявка" новую стадию заявки (связанный обьект "Стадия"), согласно которой Заявка попадает в очередь обработки Оператором. Дальше по итогам взятия Оператором из очереди данной заявки и ее проработки - в заявку добавляется новая стадия - и вот в этот момент необходимо отправить емейл уведомление "Менеджеру" о том, что заявка проработана.

Первую часть с менеджером реализовал в виде родительского процесса который переходит в подпроцесс:

Изображение удалено.

Подпроцесс в свою очередь по сигналу добавления новой стадии "запускает" отправку емейл уведомления менеджеру:

Изображение удалено.

Но наткнулся на 2 проблемы:

1. При использовании стартового сигнала в подпроцессе - сам подпроцесс не считывает параметр "Менеджер" из родительского процесса, как и любые другие параметры (пробовал менять стартовый параметр "Сигнал" на "Простое" - параметры передаются успешно). 

2. Как избежать запуска "Подпроцесса" для других заявок у которых новая стадия добавляется не с родительского процесса, а другими механизмами? (во избежание загрузки системы лишними процессами)

Нравится

5 комментариев
Лучший ответ

Александр, Вы смешиваете два механизма: безусловный запуск подпроцесса из основного процесса и запуск процесса по сигналу на каком-то событии объекта.

 

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

 

По общему механизму со стадиями, который Вы создаёте, не вполне понял. Если после добавления стадии нужно проверить, создана ли она по процессу, можно создать в объекте стадии новое поле и ставить там пометку. Если Вы имеете в виду две разных стадии, по процессу создалась вторая, а уведомление отправить автору первой, то в процессе на событии создания второй стадии можно по связям с заявкой вычислить первую, её автора-менеджера и отправить уведомление ему. Если по типу стадии нельзя однозначно сказать, какая идёт за какой, можно добавить в объект справочное поле со ссылкой на предыдущую.

Добрый вечер.

 

Если рассматривать Вашу реализацию задачи, то, во-первых, подпроцесс из родительского процесса можно не вызывать, он вызовется автоматически при наступлении события, указанного в сигнале. Во-вторых, параметр "Менеджер" можно вычитывать из записи в таблице 'Стадии' (это будет тот, кто создал эту стадию) и потом ему отправлять уведомление. Избежать запуска подпроцесса при добавлении новой стадии другими способами можно, если добавить в таблицу стадий некоторое поле-признак, которое будет указывать на добавление стадии по процессу, и перед отправкой письма проверять установлено ли значение для данного параметра. А в родительском процессе устанавливать значение этого параметра при создании стадии.

 

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

 

А в данном примере можно и не использовать подпроцесс, а добавить отправку e-mail менеджеру прямо в родительском процессе, но опять таки только тогда, когда новая стадия уже создана, то есть у Вас должен быть переход на отправку письма по условию.

Алла Савельева пишет:

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

А какой элемент в таком случае подойдет для запуска? 

 

 

Алла Савельева пишет:

А в данном примере можно и не использовать подпроцесс, а добавить отправку e-mail менеджеру прямо в родительском процессе, но опять таки только тогда, когда новая стадия уже создана, то есть у Вас должен быть переход на отправку письма по условию.

Тут же опять вопрос: а как понять что новая (последующая, другая) стадия уже создалась, если текущий экземпляр процесса работает в рамках созданной им одной записи, а все последующие стадии создаются вне процесса и прямо в процессе не участвуют?

Алла Савельева пишет: Во-вторых, параметр "Менеджер" можно вычитывать из записи в таблице 'Стадии' (это будет тот, кто создал эту стадию) и потом ему отправлять уведомление.

Этот вариант не подойдет, т.к. процесс отправит ему уведомление раньше времени, до того как будет создана следующая стадия.

 

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

Признак "добавление стадии по процессу" можно добавить в запись созданную по процессу, но нам все равно нужно сначала как то дождаться создания последующей стадии и только потом отправить "Менеджеру" уведомление.

 

Александр, Вы смешиваете два механизма: безусловный запуск подпроцесса из основного процесса и запуск процесса по сигналу на каком-то событии объекта.

 

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

 

По общему механизму со стадиями, который Вы создаёте, не вполне понял. Если после добавления стадии нужно проверить, создана ли она по процессу, можно создать в объекте стадии новое поле и ставить там пометку. Если Вы имеете в виду две разных стадии, по процессу создалась вторая, а уведомление отправить автору первой, то в процессе на событии создания второй стадии можно по связям с заявкой вычислить первую, её автора-менеджера и отправить уведомление ему. Если по типу стадии нельзя однозначно сказать, какая идёт за какой, можно добавить в объект справочное поле со ссылкой на предыдущую.

Зверев Александр,

Александр, спасибо за советы, сделал подобным образом, только на стадию добавил не пометку, а статус. И дальше уже в рамках одного процесса по элементу "Обработать сигнал" отслеживаю изменение статуса в ранее созданной по процессу стадии, а после этого отправляю email создателю стадии.

А за то, что "Стартовый сигнал" не будет в под.процессе не будет принимать параметр из родительского процесса уже начал догадываться, но явно в академии ничего не нашел.

 

Алла Савельева,

Вам тоже спасибо за совет, направление по признаку учел.

Показать все комментарии

Всем привет.

Используется BPMonline Bank Sales Версия 7.5.0.1275
Возникает проблема с параметром процесса типа Коллекция. Диаграмма процесса приложена.

В первом сценарии делаем выборку данных и результирующую коллекцию присваиваем параметру процесса. Во втором сценарии достаем нужную информацию из выборки через Entity, которую, в свою очередь, вытаскиваем из коллекции по индексу. Сам индекс инкрементируем в Формуле и проверяем не превысил ли он количество элементов в выборке. Так вот, первый шаг проходит хорошо. Все данные достаются и показаны в окне Проверка результата и соответствуют действительности. Но при заходе на второй круг в элементе-сценарии Формирования текста SMS и номера возникает ошибка

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: Значение индекса находится вне допустимого диапазона значений
   at Terrasoft.Core.Entities.EntityCollection.FindNodeByIndex(Int32 index)
   at Terrasoft.Core.Process.BirthdayQuery.ScriptTask2Execute(ProcessExecutingContext context)
   at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Индекс при этом равен 1. То есть, от коллекции, похоже, осталась только одна запись.

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

Код сценария Выборка данных у кого ДР

        var esqBirthdays = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Contact");
        contactIdFieldName = esqBirthdays.AddColumn("Id").Name;
        esqBirthdays.AddColumn("GivenName");
        esqBirthdays.AddColumn("MiddleName");
               
        esqBirthdays.IsDistinct = true;
                       
        //Получение сегодняшней даты
         today = DateTime.Today;
       
        var esqMacrosTypeMonth = EntitySchemaQueryMacrosType.Month;
        var esqFilterByMonth = esqBirthdays.CreateFilter(FilterComparisonType.Equal, "BirthDate", esqMacrosTypeMonth, today.Month);
        esqBirthdays.Filters.Add(esqFilterByMonth);
               
        var esqMacrosTypeDay = EntitySchemaQueryMacrosType.DayOfMonth;
        var esqFilterByDayToday = esqBirthdays.CreateFilter(FilterComparisonType.Equal, "BirthDate", esqMacrosTypeDay, today.Day);
        esqBirthdays.Filters.Add(esqFilterByDayToday);
       
        //Есть моб тел?
        var esqFilterWithMobilePhone = esqBirthdays.CreateFilterWithParameters(FilterComparisonType.Equal, "[ContactCommunication:Contact].CommunicationType", new Guid("F039972E-470E-457F-9B77-65054B3534B0"));
        esqBirthdays.Filters.Add(esqFilterWithMobilePhone);
       
        //Выполнение запроса и получение результирующей коллекции
        entitiesBD = esqBirthdays.GetEntityCollection(UserConnection);
    numberOfentitiesBDInCollection = entitiesBD.Count;
        currentIndexBD = 0;
        esqSqlText = esqBirthdays.GetSelectQuery(UserConnection).GetSqlText();
               
        return true;

Код сценария Формирования текста СМС и номера

        Entity element = entitiesBD[currentIndexBD];
        Guid contactID = element.GetTypedColumnValueGuid>(contactIdFieldName);
    string contactName = element.GetTypedColumnValuestring>("GivenName");
        string contactMiddleName = element.GetTypedColumnValuestring>("MiddleName");
        string BirthDateText = DateTime.Today.ToString("dd MMMM");
        string messageText = "Дорогой(ая) "+contactName+"! Росинбанк поздравляет Вас с Днем Рождения "+BirthDateText+"  и желает Вам всех благ! Росинбанк";
        if(contactMiddleName!=null) messageText = "Дорогой(ая) "+contactName+" "+contactMiddleName+"! Росинбанк поздравляет Вас с Днем Рождения "+BirthDateText+"  и желает Вам всех благ! Росинбанк";
        SMSTextBD = messageText;
       
        var contactComm = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "ContactCommunication");
        var contacctNumberFieldName = contactComm.AddColumn("Number").Name;
       
        var esqFilter1 = contactComm.CreateFilterWithParameters(FilterComparisonType.Equal, "Contact", contactID);
        contactComm.Filters.Add(esqFilter1);
       
        var esqFilter2 = contactComm.CreateFilterWithParameters(FilterComparisonType.Equal, "CommunicationType", new Guid("F039972E-470E-457F-9B77-65054B3534B0"));
        contactComm.Filters.Add(esqFilter2);
       
        var mobilePhoneCollection = contactComm.GetEntityCollection(UserConnection);
        if(mobilePhoneCollection.Count>0)
        {
        phoneNumberBD = mobilePhoneCollection[0].GetTypedColumnValuestring>(contacctNumberFieldName);
        } else
        {
        phoneNumberBD = "No number";
        }
       
        //var SMSObject = new SendSMSClass(SMSServiceAddress);
        //SMSObject.SendSMS(phoneNumber, messageText);

return true;   
csharp>

Нравится

1 комментарий

Добрый день!
Попробуйте выполнять проверку и автоинкремент индекса в элементе “Задание сценарий”. Например,

if(IndexBD < entitiesBD.Count){
...
IndexBD++;
} else {
...
}
return true;

Показать все комментарии

Добрый день!

Engagement Center 7.6
стандартный процесс - создание обращение через CTI-панель по входящему звонку
В процессе есть параметры ContactID и AccountID
Звонит какой-то пользователь в системе( Supervisor, допустим) другому пользователю.
У этого Supervisor заполнен Контрагент-Наша компания.

Сам процесс на входе как-то получает значения параметров ContactID и AccountID ( звонящий пользователь и его контрагент).
Где это происходит, в каком месте, скажите, пожалуйста?

Нравится

11 комментариев

Добрый день!

Вся функциональность запуска процессов в CTI панели выполнена в отдельном пакете CTIProcessActions
Цель данного блока - дать возможность операторам колл центра, при обработке входящих обращений, запускать преднастроенные процессы обработки.
В системе можно настроить перечень процессов, которые будут отображаться в CTI панели. Так же можно указать группу пользователей, которые будут иметь возможность запускать процессы из CTI.

Настройка процессов для CTI панели
Перечень процессов, который отображается в cti панели настраивается в справочнике "Действие cti панели". В справочнике можно добавлять/удалять кнопки запуска процессов, указывать текст кнопки, сам процесс для запуска и порядок расположения.

Обязательное условие для корректного запуска процесса из cti панели - наличие параметров ContactId, AccountId, PhoneNumber. В эти параметры передаются данные контрагента или контакта по звонку. В процессе можно использовать эти данные для быстрого поиска обращений по абоненту или созданию новой записи с данными из cti панели.
ContactId – принимает идентификатор контакта в звонке, тип данных – справочник, справочник контактов
AccountId – принимает идентификатор контрагента в звонке, тип данных – справочник, справочник контрагентов
PhoneNumber – принимает номер абонента в CTI панели, строка, 250 символов

Отображение процессов для пользователей
Зачастую процессы нужны только пользователям, которые являются сотрудникаци КЦ. Что бы настроить отображение процессов только для нужной группы сотрудников в системе создана группа "Операторы КЦ". Только пользователи, которые включены в эту группу будут видеть кнопки запуска процессов в cti панели.
Если необходимо изменить группу, для которой нужно отображать процессы, это можно сделать в системных настройках. Задать другую группу для отображения процессов можно в настройке "Группа операторов КЦ".

Передача параметров реализована на CTI панеле. Когда пользователь "кликает" по нужному процессу, система передает описанные выше параметры в процесс.

"Передача параметров реализована на CTI панеле. Когда пользователь "кликает" по нужному процессу, система передает описанные выше параметры в процесс."

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

В itil transitions при добавлении действия в CTI-панель происходит почему-то только передача параметра-контакта, а его контрагент почему-то не передается в параметр.
Хотелось бы понять почему.

Дарья, добрый день!

После ответа на звонок мы идентифицируем либо контрагента либо контакта. И далее панель, при запуске процесса, передает идентифицированную запись. Т.е. либо контакт либо контрагент. Если вы хотите получить контрагента идентифицированного контакта, то лучше его вычитать из самого контакта.

В Engagement Center у вас все же идентифицируется и контакт, и его контрагент. По крайней мере, подставляется и контакт, и его контрагент. Где же в таком случае происходит идентификация контрагента?

Дарья, идентификация Контакта и Контрагента производится процессом "ContactIdentification", который находится в пакете "OperatorCustomerEngagementCenter". В рамках данного процесса сначала производится поиск Контакта, а затем из найденной карточки контакта считывается Контрагент, что видно на скриншоте.

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

Елена, спасибо.
Посмотрите, на схему его теперь, пожалуйста.

В самом начале, идет ветвление:

Если ни определен ни контакт, ни контрагент, то открывается форма поиска клиента: и там уже пользователь либо создает новый контакт, либо выбирает существующий контакт, и из определенной карточки контакта считывается контрагент ( это то, о чем пишите вы - я не про эту ветку подпроцесса спрашивала)

Если же определен либо Контакт, либо Контрагент, то происходит сразу же выход из-под процесса
( эта стрелка самая верхняя - в ней условия [#Контакт#] != Guid.Empty || [#Контрагент#] != Guid.Empty).
Как вы видите, в этом ветке не происходит никакого считывания контрагента.
После создается обращение по процессу - в котором заполнены и контакт, и контрагент.
Вопрос - где в данном случае происходит определение контрагента? Полагаю, что и контрагент, и контакт передаются как входящие параметры в процесс.
Это возвращает нас к моему первоначальному вопросу:
"Расскажите подробнее, пожалуйста, где именно в пакете CTIProcessActions реализована функциональность передачи параметров в процесс." Где именно, в каком сервисе, каком пакете это определяется?

Дарья, процесс определения Контакта и Контрагента происходит в CTI-панели при входящем звонке, далее эти параметры передаются в процессы.

Ниже привожу код функции, которая определяет параметры в CTI-панели и зашита в коде объекта.

getActionProcessParameters: function() {
var parameters = {
PhoneNumber: this.getLastAbonentNumber()
};
var subscriberKey = this.get("IdentifiedSubscriberKey");
if (!subscriberKey) {
return parameters;
}
var subscriberCollection = this.get("IdentifiedSubscriberPanelCollection");
var subscriberPanel = subscriberCollection.get(subscriberKey);
switch (subscriberPanel.get("Type")) {
case CtiConstants.SubscriberTypes.Contact:
case CtiConstants.SubscriberTypes.Employee:
parameters.ContactId = subscriberPanel.get("Id");
break;
case CtiConstants.SubscriberTypes.Account:
parameters.AccountId = subscriberPanel.get("Id");
break;
default:
break;
}
return parameters;
},

Спасибо. Можете сказать, в каком именно объекте зашита эта функция? Название сервиса?

Дарья, данная функция находится в объекте CtiPanel.

Добрый день!
Про engagement center поняла - спасибо.
по аналогии открыла конфигурацию ITIL transitions 7.5
нашла в объекте CTIPanel эту функцию.
Функция есть и она имеет вид

getActionProcessParameters: function() {
var parameters = {
PhoneNumber: this.getLastAbonentNumber()
};
var subscriberKey = this.get("IdentifiedSubscriberKey");
if (Ext.isEmpty(subscriberKey)) {
return parameters;
}
var subscribers = this.get("IdentifiedSubscribers");
var subscriber = subscribers.get(subscriberKey);
switch (subscriber.SubscriberType) {
case CtiConstants.SubscriberTypes.Contact:
case CtiConstants.SubscriberTypes.Employee:
parameters.ContactId = subscriber.Id;
break;
case CtiConstants.SubscriberTypes.Account:
parameters.AccountId = subscriber.Id;
break;
default:
break;
}
return parameters;
}

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

Но почему-то в ITIL Transitions в процессе при этом будет заполнен только параметр контакт, в результате процесс пойдет по верхней ветке (т.к. там условие заполненности контакта или контрагента), но при этом создается обращение только с заполненным контактом.

Что не так в этой стандартной функции в определении параметров для ITIL?
Может быть исправлено это было в более новых сборках? Я сейчас рассматриваю 7.5.0.1054

Дарья, здравствуйте.

CTIPanel определяет только ИЛИ контакт ИЛИ контрагент и передает их значения в бизнес-процесс.

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

Case.BaseCasePage

onEntityInitialized: function() {
if (this.isAddMode() || this.isCopyMode()) {
this.setCaseNumber();
}
this.Terrasoft.SysSettings.querySysSettingsItem(this.statusDefSysSettingsName, function(value) {
this.set("StatusDefSysSettingsValue", value);
}, this);
this.updateOriginals();
var contact = this.get("Contact");
if (contact && !this.get("Account")) {
var account = contact.Account;
if (account) {
this.set("Account", account);
}
}
this.set("PreviousStatus", this.get("Status"));
this.callParent(arguments);
},

Показать все комментарии

Здравствуйте

В конфигурации есть ряд системных настроек, в которых указывается контакт (руководитель того или иного отдела).

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

Например, есть системная настройка Director, а в процессе используется параметр toDirector с типом "Роль в процессе".

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

Самое смешное, год назад как-то это делал:smile:. Старость - не радость.

Подскажите, пожалуйста, как проделать данный фокус.

Нравится

5 комментариев

Александр, если я правильно поняла Вашу задачу, ее можно реализовать добавив в диаграмму БП еще один параметр. В определенном событии процесса, например, на OnStart, заполнять добавленный параметр значением системной настройки, посредством вызова функции function GetSystemParameterValueEx(SystemParameterCode, Force).

Да, это, конечно, вариант, но хотелось бы обойтись без скриптов.

В нашей версии (3.2.1.65) окно администратора выглядит несколько иначе (см. прикрепленный файл)

Как видите, уже существуют параметры, которые каким-то мистическим образом связаны с соответствующими системными настройками. Присвоение значений в скрипте не производится.

Собственно, мне бы хотелось сделать еще один такой параметр и связать с настройкой.

Извините, сжало картинку.

Вот здесь крупнее
http://i.piccy.info/i7/db121ed40aa52344dd5cfd73cd5e975a/1-5-3860/447220…

Здравствуйте, Александр!

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

Для того, тобы передать в диаграмму системную настройку, необходимо на том элементе, для которого нужна данная системная настройка, создать событие BeforeExecute,

01

и в обработчик события добавить к\программный код следующего вида:

	var ParamValue = GetSystemParameterValueEx(SystemParameterName, true;)
	var Diagram = GetDiagramByItem(ActionItem);
	var ParamSet = WFSetParamValueDirect(Diagram, ParamName, ParamValue);
	IsComplete.Value = true;
	ResultLinkCodes.Value = ParamSet ? 'Yes' : 'No';

SystemParameterName - заменить на название своей системной настройки;
ParamName - название параметра диаграммы.

02

Ну нет, так нет.
Реализовал на скриптах.
Спасибо!

Показать все комментарии

Добрый день.
Создан бизнес процесс по подключению клиентов, т.е. работа с контрагентами.
Затача заключается в следующем, нужно параметр диаграммы, в моем случае Контрагент, отображать в гриде, чтобы менеджеры могли отличать процессы по названиям контрагентов.
Подскажите как извлечь параметр определенного процесса.

Нравится

8 комментариев

Андрей, ниже находится ссылка на инструкцию по добавлению колонки в реестр раздела [Процессы]. Инструкция на примере добавления колонки "Контрагент", колонка отражает прямо в гриде контрагента по каждому из запущенных процессов.
Загрузить

С параметром будет сложнее. Необходимо каким-то образом записывать значение параметра в дополнительное поле и отображать его в колонке реестра.
Получить значение параметра можно попытаться через функцию WFGetParamValue:
var AccountID = WFGetParamValue.FinishItem.ParentItems.ParentDiagram, ('AccountID');
Детальное описание работы функции WFGetParamValue Вы можете найти в скрипте scr_WorkflowUtils.

Спасибо Татьяна, но я так понимаю у нас с Вами различные запросы на выборку (sq_Workflow), так как у меня в этом запросе не используются предложения UNION ALL.
Версия : 3.3.1.67
Не могли бы Вы поделиться своим сервисом sq_Workflow?
Я думаю, что в результате этого все мои беды относительно параметров процесса исчезнут :)

Андрей, запрос, который изображен на скриншотах, создавался для примера и не входит в базовую версию, а также (поскольку это всего лишь пример) реализован всего для двух элементов БП: задачи и счёта.

Могу предложить способ, как быстро сгенерировать все UNION в запросе. Выполняете первую часть инструкции (добавление AccountID и AccountName в запрос), создаёте ещё один UNION (без колонок) и сохраняете запрос в файл. На всякий случай создайте его копию. Дальше открываете его xml-редактором и получаете примерно такое:

<?xml version="1.0" encoding="UTF-8"?>
<Service UID="1F4C50F5338E4B5CBD3A4A158B4864B3" USI="Workflow\General\Main Grid\sq_Workflow" ServiceTypeCode="SelectQuery" Caption="sq_Workflow">
	<Parameters>
		<Item Name="GroupID" UID="596057A4D59B41859FAACBBAA354A1C3" DataType="7" Value_ValueType="0">
		</Item>
		<Item Name="OwnerID" UID="3FC9B353834C4110B2E7ACE785E4AB4B" DataType="7" Value_ValueType="0">
		</Item>
		<Item Name="StateID" UID="31BD168E34574B2FB5E5F5FAB22E78D1" DataType="7" Value_ValueType="0">
		</Item>
		<Item Name="DiagramItemType" UID="D5AB9C8810B04309BD99F7BC31FAACFF" DataType="1" Value_ValueType="0">
		</Item>
		<Item Name="ID" UID="BCF58198A8CB401C9C7A7A6BDAF2AED3" DataType="7" Value_ValueType="0">
		</Item>
	</Parameters>
	<Selects>
		<Item Code="SelectTask" UID="33969FC3CB9D464CA8C6866198431BBD" FromTableUSI="tbl_Workflow">
			<Joins>
				<Item LeftTableAlias="tbl_WorkflowInGroup" UID="CF75924B77B3436AA3E8717DB8A9E02D" JoinType="0" RightFieldTableUSI="tbl_Workflow" LeftFieldSQLName="WorkflowID">
				</Item>
				<Item LeftTableAlias="Owner" UID="4961151D19A14641885992D0AC916FCD" LeftFieldTableUSI="tbl_Contact" RightFieldTableUSI="tbl_Workflow" RightFieldSQLName="OwnerID">
				</Item>
				<Item LeftTableAlias="tbl_WorkflowItem" UID="B96CB44938C0481A8FFA641F491B1EB7" RightFieldTableUSI="tbl_Workflow" LeftFieldSQLName="WorkflowID">
				</Item>
				<Item LeftTableAlias="CreatedBy" UID="9A899457854849C8BBC06C8D32EE9B18" LeftFieldTableUSI="tbl_Contact" RightFieldTableUSI="tbl_Workflow" RightFieldSQLName="CreatedByID">
				</Item>
				<Item LeftTableAlias="ModifiedBy" UID="46C5FE8DF0DD4611B5AD2E4FDCFC7160" LeftFieldTableUSI="tbl_Contact" RightFieldTableUSI="tbl_Workflow" RightFieldSQLName="ModifiedByID">
				</Item>
				<Item LeftTableAlias="ParentSubProcessItem" UID="19006DB50ABC44C0883C0110AC57FCF7" LeftFieldTableUSI="tbl_WorkflowItem" RightFieldTableUSI="tbl_Workflow" RightFieldSQLName="ParentSubProcessItemID">
				</Item>
				<Item LeftTableAlias="tbl_Task" UID="4DA83EF61FE8454EB6F3CE56D0BE9251" ParentJoinLeftTableAlias="tbl_WorkflowItem" RightFieldTableUSI="tbl_WorkflowItem" LeftFieldSQLName="WorkflowItemID">
				</Item>
				<Item LeftTableAlias="tbl_Account" UID="212B5CF89E8844A4A06E5FAA119D3F84" ParentJoinLeftTableAlias="tbl_Task" RightFieldTableUSI="tbl_Task" RightFieldSQLName="AccountID">
				</Item>
			</Joins>
			<Columns>
				<Item ColumnAlias="ID" UID="AA0A5C95B2854B26B1F389AE8B6A5816" CanDisable="False" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="ParentSubProcessItemID" UID="84FC89113D0C4BF6B2765CF4985051EE" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="OwnerID" UID="3F83F6D5C7F040E89268C7E9B176817D" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="OwnerName" UID="39B8DD9ADDC640418ED23A4803C024D3" ParentJoinCode="Owner" FieldSQLName="Name">
					<DependsOn>
						<Item Value="Owner" UID="02ACF9D51DA14EF7A56D328D670BC154">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="DiagramServiceID" UID="EFCE2726E4A54F818F4710FCA6E190AB" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="Name" UID="A204E1E7BD5D4D1591E932E466279627" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="StartDate" UID="EA5496A903E643F0B36D2645F80E512C" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="CompleteDate" UID="2ECAFCA28DD24B62AE0427A7BC7F6C69" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="Parameters" UID="EB16BDDC9A6A4D16A94BAB213C9611E6" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="WorkflowItemID" UID="0FA70074AA3543DD8F4479468CC9042B" ParentJoinCode="tbl_WorkflowItem" FieldSQLName="ID">
					<DependsOn>
						<Item Value="tbl_WorkflowItem" UID="563407B16A7F4F42AFD5E8803C782E42">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="WorkflowItemName" UID="8A779F419CE34EB59987569AF281D130" ParentJoinCode="tbl_WorkflowItem" FieldSQLName="Name">
					<DependsOn>
						<Item Value="tbl_WorkflowItem" UID="9C24B2F0C9434D10805E5A2EC303A847">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="WorkflowItemExecuteDate" UID="936F3951A7934FE7864B9B51780181C6" ParentJoinCode="tbl_WorkflowItem" FieldSQLName="ExecuteDate">
					<DependsOn>
						<Item Value="tbl_WorkflowItem" UID="48FCEC51BAA74774A3C5C0733F130A0C">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="WorkflowItemStateID" UID="DCC1A030DEE345F6B80BD105EE88D6BE" ParentJoinCode="tbl_WorkflowItem" FieldSQLName="StateID">
					<DependsOn>
						<Item Value="tbl_WorkflowItem" UID="A8166D45107B4B5FB02757627C568EFC">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="CreatedOn" UID="806340875EC64CA5A6493401CB0ACC5E" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="CreatedByID" UID="32756F26BD654C11874DF3A00A36E193" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="CreatedByName" UID="9F0BEFB4AC334731BF10AD300B914D67" ParentJoinCode="CreatedBy" FieldSQLName="Name">
					<DependsOn>
						<Item Value="CreatedBy" UID="CA44EA031F8944BF899C6A4EB34D2FD7">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="ModifiedOn" UID="9A887FB046464F26985B84E6D265D52C" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="ModifiedByID" UID="0631746DBAB744CB8AB81FD9C7C11FED" FieldTableUSI="tbl_Workflow">
				</Item>
				<Item ColumnAlias="ModifiedByName" UID="9D3CB91A12D443C09CA41742715A4586" ParentJoinCode="ModifiedBy" FieldSQLName="Name">
					<DependsOn>
						<Item Value="ModifiedBy" UID="46F1B069BE9A4C00A44746BB6D5C6681">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="TaskID" UID="5B999678D315482394CCE86FACDF3D4D" ParentJoinCode="tbl_Task" FieldSQLName="ID">
					<DependsOn>
						<Item Value="tbl_Task" UID="281CF1BF0D1E48D4A69B09D0F5A1E106">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="TaskTitle" UID="9FEA168933DA4E22A4B0BBD8CB0B15CE" ParentJoinCode="tbl_Task" FieldSQLName="Title">
					<DependsOn>
						<Item Value="tbl_Task" UID="67D8E5C560D7412580DA20C64A77FD07">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="AccountID" UID="BD27B17BC1E04C1594200CF2FF14973A" ParentJoinCode="tbl_Task">
					<DependsOn>
						<Item Value="tbl_Task" UID="4AF3085BA1814D60801699238805ED9F">
						</Item>
					</DependsOn>
				</Item>
				<Item ColumnAlias="AccountName" UID="7E89E919925747BCABC3A6AD0B919112" ParentJoinCode="tbl_Account" FieldSQLName="Name">
					<DependsOn>
						<Item Value="tbl_Account" UID="AE7BD7FC65D846719B9B31C1BA395E00">
						</Item>
					</DependsOn>
				</Item>
			</Columns>
			<Filters Code="Where" Type="Filters">
				<Item Code="GroupID" UID="5F8FAC80A0E349A98BEF5B164A396FEB" Type="CompareFilter" IsEnabled="False" ExpressionTypeCode="FieldFilterExpression" ValueExpressionTypeCode="ParamFilterExpression">
					<TestExpression FieldSQLName="GroupID" FieldTableUSI="tbl_WorkflowInGroup">
					</TestExpression>
					<ValueExpression Type="ParamFilterExpression" ParameterName="GroupID">
					</ValueExpression>
				</Item>
				<Item Code="OwnerID" UID="E33AB88031034CF892337862A8D78731" Type="CompareFilter" IsEnabled="False" ExpressionTypeCode="FieldFilterExpression" ValueExpressionTypeCode="ParamFilterExpression">
					<TestExpression FieldSQLName="OwnerID" FieldTableUSI="tbl_WorkflowItem">
					</TestExpression>
					<ValueExpression Type="ParamFilterExpression" ParameterName="OwnerID">
					</ValueExpression>
				</Item>
				<Item Code="StateID" UID="46F5F148E5B949F49AB14FA59DCADF6A" Type="CompareFilter" IsEnabled="False" ExpressionTypeCode="FieldFilterExpression" CompareOperator="1" ValueExpressionTypeCode="ParamFilterExpression">
					<TestExpression FieldSQLName="StateID" FieldTableUSI="tbl_WorkflowItem">
					</TestExpression>
					<ValueExpression Type="ParamFilterExpression" ParameterName="StateID">
					</ValueExpression>
				</Item>
				<Item Code="DiagramItemType" UID="56626203745D4AFF80074FC1B75EFD4E" Type="CompareFilter" IsEnabled="False" ExpressionTypeCode="FieldFilterExpression" ValueExpressionTypeCode="ParamFilterExpression">
					<TestExpression FieldSQLName="DiagramItemType" FieldTableUSI="tbl_WorkflowItem">
					</TestExpression>
					<ValueExpression Type="ParamFilterExpression" ParameterName="DiagramItemType">
					</ValueExpression>
				</Item>
				<Item Code="ID" UID="A92B1AB80C0045BB962A094C0FA8D05E" Type="CompareFilter" IsEnabled="False" ExpressionTypeCode="FieldFilterExpression" ValueExpressionTypeCode="ParamFilterExpression">
					<TestExpression FieldSQLName="ID" FieldTableUSI="tbl_Workflow">
					</TestExpression>
					<ValueExpression Type="ParamFilterExpression" ParameterName="ID">
					</ValueExpression>
				</Item>
			</Filters>
		</Item>
		<Item Code="Select1" UID="F56A66A86F4C4811BD14072B6A716794">
			<Filters Type="Filters">
			</Filters>
		</Item>
	</Selects>
</Service>

Первое, что необходимо сделать, - удалить все участки типа UID="F56A66A86F4C4811BD14072B6A716794". При загрузке в Администратор они будут сгенерированы заново.

Между тегами "Selects" и "/Selects" пока два элемента: один с кодом SelectTask, второй - с кодом Select1. Копируете всё, что касается первого элемента и вставляете перед вторым. В блоке, который Вы только что вставили, заменяете везде, где заметите (таких мест будет немного), Task на Invoice (например). Повторяете эти действия для создания UNION по tbl_Document, tbl_Contract и т.д. Потом удаляете блок, касающийся элемента с кодом Select1.

Загружаете запрос в Администратор, открываете и проверяете, все ли поля заполнены и все ли связи между таблицами проставлены. Если в разных таблицах колонки назывались по-разному (например, в таблице задач - Title, а в инцидентах - IncidentNumber), эти колонки будут пустыми; необходимо подставить корректное название колонки.

В принципе, всё. Дальше - по инструкции: добавляем поле в датасет, колонку в реестр и т.д.

Спасибо Олег за полный ответ.
Все работает, но как Вы сказали, только на элементах - Документ, Задача и т.д.
При использовании элементов "редактирование данных" или "чтение / запись данных" данный функционал не работает.
Придется пробовать кодом доставать значение параметра как говорила Татьяна.

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

Мы "боремся" :) вот так:
http://community.terrasoft.ua/blogs/4579
http://community.terrasoft.ua/blogs/4916

Если интересно, обращайтесь. Наш модуль также зарегистрирован как расширение:
http://community.terrasoft.ua/catalog/4881

"Татьяна Адамчук" написал:Андрей, ниже находится ссылка на инструкцию по добавлению колонки в реестр раздела [Процессы]. Инструкция на примере добавления колонки "Контрагент", колонка отражает прямо в гриде контрагента по каждому из запущенных процессов.
Загрузить

Будте добры еще раз выложить данную инструкцию, вопрос актуален!

Юрий, прикрепила инструкцию к предыдущему сообщению.

Показать все комментарии

Мне необоходимо после создания задачи скопировать в нее продукты с документа. Я решил это сделать на событие OnAfterExecute задачи и чтобы не делать копирование каждый раз после вызова элемента задачи использую параметры:
ProductsWhereCopied - булевый, значение по-умолчанию false

Вот примерный код того, как я делаю:

function Action1OnAfterExecute(ActionItem, IsComplete) {
 // Получаем ID созданной задачи
 var TaskID = WFGetParamValue(ActionItem, 'TaskID');   
 if (!IsEmptyGUID(TaskID)) {
  // Проверяем были ли скопированы в этот документ продукты ранее
   var ProductsWhereCopied = WFGetParamsMapItemValue(ActionItem,'ProductsWhereCopied');
  // Сразу после создания задачи переносим в нее продукты с документа заявки
   if (ProductsWhereCopied == false) { 
    var ParentDiagram = ActionItem.ParentItems.ParentDiagram;
    // Получаем ID документа созданного ранее
    var DocumentID = WFGetParamValue(ParentDiagram, 'DocumentID');
    // Копируем продукты с документа в задачу
    CopyOfferingsFromDocumentToTask(DocumentID, TaskID);
    // Устанавливаем признак того, что на деталь "Продукты" были скопированы
    // продукты
    WFSetParamsMapItemValue(ActionItem, 'ProductsWhereCopied', true);                  
   }   
 }
}

Загвоздка в том, что когда я повторно запускаю элемент БП "Задача", почему-то значение параметра ProductsWhereCopied остается старым, то есть false, и происходит повторное копирование продуктов.

Есть подозрение, что на событие OnExecute можно менять значение параметров и оно будет запоминаться, а на событие OnAfterExecute оно не запоминается, так как, возможно, таблица tbl_WorkflowItem уже закрыта.

Подскажите как можно сделать так, чтобы этот параметр запоминался в БД?

Нравится

1 комментарий

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

Например:

function Action1OnAfterExecute(ActionItem, IsComplete) {
 var ParentDiagram = GetDiagramByItem(ActionItem);
 // Получаем ID созданной задачи
 var TaskID = WFGetParamValue(ActionItem, 'TaskID');    
 if (!IsEmptyGUID(TaskID)) {
  // Проверяем были ли скопированы в этот документ продукты ранее
   var ProductsWhereCopied = WFGetParamValue(ParentDiagram,'ProductsWhereCopied');
  // Сразу после создания задачи переносим в нее продукты с документа заявки
   if (ProductsWhereCopied == false) {  
    // Получаем ID документа созданного ранее
    var DocumentID = WFGetParamValue(ParentDiagram, 'DocumentID');
    // Копируем продукты с документа в задачу
    CopyOfferingsFromDocumentToTask(DocumentID, TaskID);
    // Устанавливаем признак того, что на деталь "Продукты" были скопированы
    // продукты
    WFSetParamValue(ParentDiagram, 'ProductsWhereCopied', true);                   
   }    
 }
 if (IsComplete) {
    WFSetParamValue(ParentDiagram, 'ProductsWhereCopied', false);
 }
}

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

Показать все комментарии

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

Тестовый пример диаграмм процесса и подпроцесса дан в приложенных файлах. Идея не моя она была дана в топике http://community.terrasoft.ua/forum/topic/3566#comment-17027. В том же топике она и была разобрана, но так как обсуждение длинное и по большей части связанное с моей неопытностью в разаработке, то здесь приведу краткий алгоритм реализации и грабли на которые наступал я.
 Для передачи результатов завершения подпроцесса была выбрана модель которую предложила Екатерина Мельникова: для передачи информации о результате завершения подпроцесса необходимо создать связанные параметры.
1.Для этого в палитре свойств диаграммы подпроцесса TestSub открываем свойство «Объект» и параметр ResultIDSubProcess с типом «Строка».(Рекомендую кроме «Имени» и типа ничего не трогать)
2. В палитре свойств диаграммы основного процесса Test открываем свойство «Объект» и параметр ResultFromProcess с типом «Строка».
3.Нажимаем кнопку связи объектов и выбрав в нижнем левом окне подпроцесс — задаем свойства его параметра ResultIDSubProcess — назаначив ему тип Исходящий(т.е. Передающий свое значение) и связав с параметром диаграммы ResultFromProcess.
 Для присваивания значения параметру подпроцесса, мы используем способ предложенный В.Андрусиком: создание в конце каждой ветки объекта типа «Скрипт», где мы присваиваем значение парметру подпроцесса ResultIDSubProcess(далее значение в процесс предается по связям назначенным нами в интерфейсе «Связи объектов»). Я использовал просто строковые значения «Yes» и «No». 
Функции обработки вызываются на событии «OnExecute» объекта типа «Скрипт» в подпроцессе. Для присваивания значений в скрипте подпроцесса я использовал два варианта(это совершенно необязательно, просто эксперементировал). При использовании функций WFGetParamValue(Diagram,NameParam) -получить значение параметра по имени или WFSetParamValue(Diagram,NameParam,Type) — присвоить значение параметра по имени, обязательно добавлять в раздел «Использовать скрипты» в скрипте диаграммы скрипт «scr_WorkflowUtils».
 В основном процессе для анализа значений параметра процесса ResultFromProcess добавляем объект «Выбор» и пишем скрипт для извлечения значения параметра и его анализа.
P.S. В скриптах процесса и подпроцесса есть еще скрипты, в которых тоже передаются значения параметров, для заполнения значений Контрагента и Контакта в карточке Задачи, по технологии предложенной в топике: http://community.terrasoft.ua/forum/topic/927. 

Нравится

Поделиться

1 комментарий

Прикрепил файлы ;-). Версия TS CRM - 3.3.0.49 под MS SQL 2005.

Показать все комментарии