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



Тогда из БП приходится посылать message, прописывать методы его обработки на странице и т.п.



Можно это сделать универсально, создав User task, указав в нём элемент для обновления (деталь или поле), а также новое значение для поля? А дальше уже базовые механизмы выполнят всё, что нужно на странице

2 комментария

Это было бы супер!)

Владимир, уже давно заведена идея, чтобы это происходило автоматически: «Данные, которые изменяются при выполнении бизнес-процесса, не актуализируются/обновляются на странице редактирования, если пользователь в текущий момент находится на ней». Она принята, но пока не реализовывалась. Зафиксировал и в том виде, как предлагаете Вы, чтобы обновлять принудительным запуском действия. Спасибо за идею!

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

С версии 7.16 появилась возможность множественного запуска бизнес-процессов через элемент подпроцесс. 

 

К примеру необходимо создать бизнес-процесс который будет отправлять письмо-поздравление всем контактам у которых сегодня день рождения. 

 

Для этого необходимо создать процесс с двумя элементами: 

1. Элемент [Читать коллекцию] контактов у которых сегодня день рождения

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

2. Элемент [Подпроцесс] в который передать коллекцию контактов которых нужно поздравить.

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

 

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

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

 

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

Нравится

Поделиться

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

Как пенести на другую среду признак деактивации процесса в пакете?

 

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

В элементе sql-скрипт необходимо добавить следующий запрос. Запрос должен соответствовать СУБД, с которой работает система, ниже пример запроса подходящего для MSSQL и PostgreSQL : 

INSERT INTO "SysProcessDisabled" ("Name", "SysSchemaId")
SELECT "Name","Id"
FROM "SysSchema"
WHERE "Name" IN ('Название процесса (важно! не заголовок)')

Пример скрипта деактивации процесса "Квалификация продажи v7.8.0"

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

 

Название процесса можно найти в дизайнере процесса.

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

 

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

Нравится

Поделиться

3 комментария

А у меня всё равно такие процессы исполняются... 

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

Зверев Александр пишет:

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

 И, к сожалению, стартуют по сигналу. А надо совсем отключить

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

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

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

из-за чего есть необходимость обновить страницу справочника с Бизнес процесса.

Подскажите как это можно реализовать.

Спасибо.

Нравится

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

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

 

Для передачи сообщений из серверной логики на клиент используется механизм ClientMessageBridge.

 

Также посмотрите обсуждение в этом посте.

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

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

спасибо за вариант, но уже все реализовано по другому, осталось проблему с рефрешем страницы решить.

попытался реализовать через ClientMessageBridge, хочу повторить пример со статьи, но опять есть вопрос, с Процесса сообщение уходит, в ClientMessageBridge попадает, но потом хочу получить сообщение в нужной мне схеме, 

я беру (BaseLookupConfigurationSection) так как этот функционал мне нужен при добавлении строки, но туда сообщение NewUserSet не доходит, как понять в чем ошибка?

Так же появляется ошибка:

Приведите Ваш код, который Вы разработали для этой функциональности.

1. В процессе добавил в Задание-сценарий:

string messageText = "{\"name\": \"" + "TestName" + "\"}";

string sender = "NewUserSet";

MsgChannelUtilities.PostMessageToAll(sender, messageText);

return true;

 

2. вот код замещающей схемы ClientMessageBridge :

 /**

 * @class ClientMessageBridge.ELBase

 * @extends ClientMessageBridge.NUI

 */

define(

    "ClientMessageBridge",

    ["ConfigurationConstants"],

    function(ConfigurationConstants) {

        return {

            messages: {

                "NewUserSet": {

                    "mode": Terrasoft.MessageMode.BROADCAST,

                    "direction": Terrasoft.MessageDirectionType.PUBLISH

                }

            },

            methods: {

                /**

                 * @inheritDoc ClientMessageBridge.UIv2#init

                 * @override

                 */

                init: function() {

                    this.callParent(arguments);

                    this.addCustomMessages();

                },

                

                addCustomMessages: function() {

                    this.addMessageConfig({

                        sender: "NewUserSet",

                        messageName: "NewUserSet"

                    });

                },

                afterPublishMessage: function(

                    sandboxMessageName,

                    webSocketBody,

                    result,

                    publishConfig) {

                    if (sandboxMessageName === "NewUserSet") {

                        var name = webSocketBody.name;

                        window.console.info("Опубликовано сообщение: " + sandboxMessageName +". Данные: name: " + name);

                    }

                }

            }

        };

    }

);

 

3. и код замещающей схемы BaseLookupConfigurationSection:

/**

 * @class BaseLookupConfigurationSection.ELBase

 * @extends BaseLookupConfigurationSection.UIv2

 */

define(

    "BaseLookupConfigurationSection",

    [],

    function(BusinessRuleModule, ConfigurationConstants) {

        return {

             messages: {

                "NewUserSet": {

                    "mode": Terrasoft.MessageMode.BROADCAST,

                    "direction": Terrasoft.MessageDirectionType.PUBLISH

                }

            },

            methods: {

                /**

                 * @inheritDoc GridUtilitiesV2.NUI#checkCanDelete

                 * @override

                 */

                checkCanDelete: function(items, callback, scope) {

                    this.callGetLookupDisabledActionsService(this.getParentMethod(this, arguments));

                },

                

                callGetLookupDisabledActionsService: function(callback) {

                    this.showBodyMask();

                    this.callService(

                        this.getGetLookupDisabledActionsServiceConfig(),

                        this.handleGetLookupDisabledActionsServiceResponse.bind(this, callback),

                        this

                    );

                },

                

                getGetLookupDisabledActionsServiceConfig: function() {

                    return {

                        serviceName: "GetUserRolesService",

                        methodName: "GetLookupDisabledActions",

                        data: {

                            lookupEntitySchemaUId: (this.getGridEntitySchema() || {}).uId

                        }

                    };

                },

                

                handleGetLookupDisabledActionsServiceResponse: function(callback, response) {

                    this.hideBodyMask();

                    if (response &&

                        response.success &&

                        !(response.data || []).includes(EL.const.db.EL_RECORD_ACTION.DELETE)) {

                        callback();

                    } else {

                        this.showInformationDialog(this.get("Resources.Strings.ForbiddenToEditLookupMessage"));

                    }

                },

// Инициализация схемы.

                init: function() {

                    this.callParent(arguments);

                    this.sandbox.subscribe("NewUserSet", this.onNewUserSet, this);

                },

// Обработчик события получения сообщения NewUserSet.

                onNewUserSet: function(args) {

                    var name = args.name;

                    window.console.info("Получено сообщение: NewUserSet. Данные: name: " + name);

                }

            }

        };

    }

);

 

А почему у Вас на странице, где будет ловиться сообщение, указано «"direction": Terrasoft.MessageDirectionType.PUBLISH», а не «"direction": Terrasoft.MessageDirectionType.SUBSCRIBE», как в примере? Не в этом ли дело?

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

вы правы, получилось, с этим спасибо, сообщение я получил.

но изначально я же хотел обновить страницу, и для этого я заменил вывод на this.reloadEntity();

получилось так:

// Инициализация схемы.

                init: function() {

                    this.callParent(arguments);

                    this.sandbox.subscribe("NewUserSet", this.onNewUserSet, this);

                },



                onNewUserSet: function(args) {

/*                   var name = args.name;

                   window.console.info("Получено сообщение: NewUserSet. Данные: name: " + name);*/

                    

                    this.reloadEntity();

                }

 

Но теперь я вижу что reloadEntity - undefined,

и получаю такую ошибку:

Функция reloadEntity задана в BasePageV2. Видимо, BaseLookupConfigurationSection, куда Вы добавляете обработчик, не наследуется от неё.

спасибо за ответ!

а возможно есть еще какие то варианты как обновить страницу?

Видимо, разобраться в логике этой функции и реализовать аналогичное для этой страницы? Она такая:

reloadEntity: function(callback, scope) {
	Terrasoft.chain(
		this.initEntity,
		function(next) {
			this.onEntityInitialized();
			this.actualizeDcmActionsDashboard(next, this);
		},
		function() {
			this.updateDetails();
			this.sandbox.publish("CardRendered", null, [this.sandbox.id]);
			this.hideBodyMask();
			Ext.callback(callback, scope);
		},
		this
	);
},

 

ок, спасибо, буду что то думать.

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

Возможно кто-то сталкивался с таким кейсом - в бизнеспроцессе открывается страница редактирования, в ней кнопка "Сохранить" при нажатии сразу закрывает страну. Про не закрывание страницы при добавлении на делать даных есть описание кейса на странице академии https://academy.terrasoft.ru/documents/technic-sdk/7-16/kak-sohranyat-ne-zakryvaya-otkrytuyu-biznes-processom-stranicu-redaktirovaniya , но ножно ли сделать что бы поля на странице можно быть сохранить не закрывая страницу? Другими словами при нажатии "Сохранить" страница не закрывалась а кнопка заменялась на "Закрыть"?

Нравится

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

Александр, в статье по той ссылке в начале предлагается, как такое сделать:

Если необходимо сохранить запись несколько раз, не закрывая страницу редактирования, то необходимо методу this.save() в качестве аргумента передавать конфигурационный объект со свойством isSilent равным true. Например:

this.save({isSilent : true});

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

Александр, в статье по той ссылке в начале предлагается, как такое сделать:

Если необходимо сохранить запись несколько раз, не закрывая страницу редактирования, то необходимо методу this.save() в качестве аргумента передавать конфигурационный объект со свойством isSilent равным true. Например:

this.save({isSilent : true});

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

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

Доброго времени суток, коллеги!

 

Хотел попробовать добавить уведомление ответственному по возвращению из стадии "OnHold" в "В работе", создал шаблон уведомления, выстроил цепочку чтения данных и отправки, но не знаю как считать id обращения для чтения ответственного именно в том обращении, которое возварщается "В работу" когда стартовым действием является не "сигнал" а "стартовый таймер".

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

Как это можно реализовать?

Нравится

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

Руслан, если по таймеру, то надо каким-то образом определять, какой Id имеется в виду. Если выйдет настроить фильтр, в который попадут только такие записи, можно использовать его.

 

Либо добавить служебное логическое поле «обработан» и программно его значение-галку снимать при смене стадии и ставить после отправки.  И фильтровать в БП по таймеру записи, где снято.

 

Хотя, если делаем обработчик события смены стадии, можно всё сделать в нём и нет смысла в отдельном БП по таймеру.

 

Вам нужно по таймеру обработать все обращения со статусом "В работе" или только последнее?

Ксензов Егор,

Мне нужно обработать индивидуально обращение, которое было возварщено из стадии OnHold и отправить уведомление именно тому ответственному, обращение которого было возвращено. Знаю как "цеплять к id" если 1 шаг это стартовый сигнал, а вот с таймером не разобрался как сделать

Шарифуллин Руслан,

здравствуйте! Тогда Вам необходимо добавить в данный процесс подпроцесс который будет обрабатывать обновленную коллекцию. В данной статье описана работа с коллекциями в БП. Это так на вскидку.

Руслан, если по таймеру, то надо каким-то образом определять, какой Id имеется в виду. Если выйдет настроить фильтр, в который попадут только такие записи, можно использовать его.

 

Либо добавить служебное логическое поле «обработан» и программно его значение-галку снимать при смене стадии и ставить после отправки.  И фильтровать в БП по таймеру записи, где снято.

 

Хотя, если делаем обработчик события смены стадии, можно всё сделать в нём и нет смысла в отдельном БП по таймеру.

 

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

Коллеги, всем здоровья. Не могу разобраться в синтаксисе методов Get и Set для элемента процесса "задание-сценарий". Прошу помощи.

 

Кейс следующий.

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

 

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

 

Судя по странице документации для получения/передачи параметров нужно использовать методы Set и Get вот с таким синтаксисом:



Get(string path)

Set(string path, T value)

 

При этом: 

T — тип значения параметра;

path — строка, определяющая путь к параметру или свойству. Путь формируется согласно правилам:

имя параметра”,

“имя свойства”,

“имя элемента.имя параметра”,

“имя элемента.имя свойства”.

 

В Creatio Community я нагуглил вот такой пример Get метода для получения коллекции:



Get>("ReadDataUserTask1.ResultCompositeObjectList");



А path сформировал исходя из того, что элемент (шаг) чтения данных называется ReadDataUserTask6, а параметр, который мне нужен - ResultCompositeObjectList.



В результате в сценарии получился вот такой код:



string[] products = Get>("ReadDataUserTask6.ResultCompositeObjectList");



string productstring = "";

String seperator = ", ";

productstring += String.Join(seperator, products);



Set("ProcessSchemaParameter2", string productstring);



return true;

 

При компиляции шага получаю вот это:



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

 

Открываю исходный код бизнес-процесса, смотрю на 40 строчку и не понимаю, что не так:

 

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

 

(а) синтаксис в точности такой же, как указано в документации:

Set(string path, T value)



(б) Похоже я неверно указываю тип значения параметра. В параметре процесса, куда я хочу записать результат, указан следующий тип данных "строка (500 символов)":



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



Если это не "String", то что? И вообще, как определить эти значения, которые нужно подставлять вместо буковки Т? Ведь автор примера в community их откуда-то взял :) Поделитесь знаниями? :)



Заранее спасибо.

 

Нравится

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

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

 

Вот таким образом можно получить значение параметра:

DateTime collectionDate = Get<DateTime>("CollectionDate");

 

А вот так присвоить:

Set<DateTime>("StorageDate", storageDate);

 

Вам в Set в скобочках нужно для данных, которые Вы устанавливаете, указать тип.

 

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

 

Вот таким образом можно получить значение параметра:

DateTime collectionDate = Get&lt;DateTime&gt;("CollectionDate");

 

А вот так присвоить:

Set<DateTime>("StorageDate", storageDate);

 

Вам в Set в скобочках нужно для данных, которые Вы устанавливаете, указать тип.

 

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

 на сколько я помню то Set ставится без указания типа

Set(" StorageDate ", storageDate);

В вашем случае Вы указали все верно, только не нужно было указывать тип для передаваемого параметра - Set("ProcessSchemaParameter2", productstring);

Александр Тыра пишет:

на сколько я помню то Set ставится без указания типа Set(" StorageDate ", storageDate);

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

 

Странно то, что установка параметра процесса работает и в синтаксисе, который приведен мной с указанием типа данных в скобочках.

 

На досуге попробую разобраться с этим, если будет что-то интересное, то поделюсь здесь.

Коллеги, всем спасибо за ответы. Действительно, указание типа данных в синтаксисе для метода "Set" работает. Это оказалось очень полезным для отладки. Чтобы убедиться в работоспособности метода я попробовал передать статичную строку "Hello" и вывести её на автогенерируемую страницу. Сработало только с указанием типа данных.



При этом синтаксис для метода Set, указанный Аллой отличается от синтаксиса, указанного в официальной документации. 

У Аллы (то, что сработало): 

Set<DateTime>("StorageDate", storageDate);

 

То есть, в терминологии документации это

Set<Т>(string path, value)

 

Сравните с тем, что написано в статье документации:

Set(string path, T value)

 

Это меня и смутило.

 

И ещё - всё-таки, как "простому смертному" понять, что при работе с коллекцией нужно декларировать тип данных как <ICompositeObjectList<ICompositeObject>> ? Я не нашёл этого в описании, а это ведь важное знание, без него функционалом метода пользоваться не получится. 



Коллеги из Террасофт - если вы нас читаете, поправьте, пожалуйста сигнатуру метода Set в указанной статье документации и добавьте сопоставление значения параметра T в методе для *каждого* типа данных в бизнес-процессе. Вот скриншот дропдауна с вариантами типа данных в параметре процесса. Смотрите, сколько их там:

 

Не знаю как другим, а мне как разработчику это просто категорически важно. ОК, для коллекции значений я нагуглил <ICompositeObjectList<ICompositeObject>> . А вот как понять, какой тип данных у коллекции значений с атрибутами? А у коллекции объектов (EntityCollection)?

 

А ещё ведь возникают вопросы вроде "у вас 5 вариантов дробных чисел, для всех вариантов прописывать <float>?"

 

Кому-то это очевидно, кому-то нет. А на мой взгляд должно быть очевидно каждому. Без это клиенты вынуждены "рыскать" по форумам, а это на мой взгляд неправильно.

Евгений, поискал по содержимому cs-файлов конфигурации, вариант Set без типа в угловых скобках не раз встречается в «коробке». Например, в FileImportProcess для логического:

Set("IsUsePersistentFileImportEnabled", UserConnection.GetIsFeatureEnabled("UsePersistentFileImport"));

А со скобками встречается только в доработанном коде. Вероятно, по аналогии с Get.

 

В чём преимущество с типом, что хотите его внести в документацию? Как именно не работает на автогенерируемой странице со строкой? А если строку-константу явно привести к string, то нормально? 

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

Да, именно если для строки-константы явно указать string, то работает. Согласен, что по всей видимости код доработан по аналогии с Get. Речь о внесении в документацию идет не из-за преимуществ с типом/без типа, а из-за того, что если указывать тип так, как это написано в документации, компилятор выдаёт ошибки. Т.е. то, что сейчас написано в документации, не соответствует тому, как фактически нужно делать. 



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

По последнему, я искал не в файлах, а через базу в SysSchemaSource. В облаке тоже можно, если ставить дополнение для SQL-запросов.

 

По отсутствию примера Set, недокументированному параметризируемому Set<> и списку типов, согласен, написал им. Обратите внимание, в академии внизу есть форма для обратной связи.

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

Большое спасибо за комментарии, за пояснения и за доставку обратной связи "по адресу". Это очень ценно. Также буду иметь ввиду форму обратной связи на страницах академии. 

Спасибо за полезную информацию

Друзья, нид хелп) 

Задача ровно такая же, как у Евгения.

Скрипт вот такой:

string[] placeId = Get<ICompositeObjectList<ICompositeObject>>("WebService1.AxCandidatesPlaceid");

string placeidstring = "";

string seperator = ", ";

placeidstring += String.Join(seperator, placeId);

Set("ParsedPlaceId", placeidstring);

return true;

где AxCandidatesPlaceid - текстовый параметр из коллекции входящих параметров 

 

При компиляции получаю ошибку: 

Cannot implicitly convert type 'Terrasoft.Common.ICompositeObjectList<Terrasoft.Common.ICompositeObject>' to 'string[]'

 

Подскажите, как можно исправить? Куда смотреть? 

Сергей, Вы считали объект типа ICompositeObjectList<Terrasoft.Common.ICompositeObject> и пытались автоматически преобразовать в массив строк. Если такое не предусмотрено, нужно самостоятельнообрабатывать, например, перебирая элементы коллекции и считывая значения поля, где хранится интересующий текст.

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

Добрый день, коллеги!

 

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

 

1) Остановить процесс, внести изменения, запустить процесс - но в таком случае при остановке процесса будут сбиты процессы эскалации по текущим обращениям.

 

2) Не останавливая процесс, внести изменения, сохранить и опубликовать запрашиваемые системой параметры - но при таком способе тестовая система наглухо зависала во время "публикации" минуты на 3.

 

Как будет правильнее вносить изменения в БП на продуктивной среде?

Нравится

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

Руслан, это два разных вопроса:

 

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

 

2. Вносить изменения в систему с публикацией в любом случае стоит в то время, когда там никто не работает. Например, ночью.

 

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

Руслан, это два разных вопроса:

 

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

 

2. Вносить изменения в систему с публикацией в любом случае стоит в то время, когда там никто не работает. Например, ночью.

 

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

Зверев Александр,  в данный момент в продуктивной системе 1485 обращений по которым эскалация либо уже идёт, либо теоретически может начаться. Поэтому сложно предугадать момент когда БП точно не будут отрабатывать. По 1-му пункту не знал, спасибо. Буду делать в нерабочее время с сохранением новой версии процессов.

В любом случае сервер когда-то останавливается на некоторое время: для обновления версии системы, каких-то работ на серверах IIS и БД и др. Если есть доступ к базе, увидеть, что происходит в системе на сервере, можно при помощи запросов на свежие записи в таблицах SysUserSession, SysProcessLog и SysProcessElementLog.

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

Использую для запуска БП ProcessModuleUtilities.executeProcess

Нужно подавить уведомление об успешном запуске.

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

Каким штатным образом это можно сделать? Параметр передать?

Нравится

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

Эта функция выглядит так:

/**
 * Launches business process by identifier or name.
 * @param {Object} config Configuration object.
 * @param {String} [config.sysProcessName] Name of the process schema.
 * @param {String} [config.sysProcessId] Unique identifier of the process schema.
 * @param {Object} [config.parameters] Process parameters.
 * @param {Function} [config.callback] Callback function.
 * @param {Object} [config.scope] Callback scope.
 */
executeProcess: function(config) {
	const callback = config.callback || this._executeProcessCallback.bind(this, config);
	const scope = config.scope || this;
	if (config.sysProcessName) {
		this._executeProcessByName(config, callback, scope);
	} else {
		this._executeProcessById(config, callback, scope);
	}
},

Она вызывает вторую, которая и показывает сообщение:

/**
 * @private
 */
_executeProcessCallback: function(config, request, success, response) {
	if (!this.responseCallback(request, success, response)) {
		this.loadSchemaCaptionByName(config.sysProcessName, function(caption) {
	this._showSuccessfullyRunProcessPopup(caption);
		}, this);
	}
},

Насколько понимаю, в первой вызов второй со стандартным обработчиком включается только если не передан свой.

То есть можно попробовать передать в параметре callback пустую функцию или с какими-то своими действиями. 

Пример вызова процесса с добавлением обработчика есть в схеме SystemDesigner, где он выглядит: 

/**
 * Starts OpportunityManagement actualization process.
 * @private
 */
runActualizeOpportunityManagementProcess: function(callback) {
	var processUtils = this.getProcessModuleUtilities();
	this.showBodyMask();
	processUtils.executeProcess({
		sysProcessName: "ActualizeOpportunityManagement",
		callback: function() {
			this.hideBodyMask();
			callback.call(this);
		},
		scope: this
	});
},

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

Эта функция выглядит так:

/**
 * Launches business process by identifier or name.
 * @param {Object} config Configuration object.
 * @param {String} [config.sysProcessName] Name of the process schema.
 * @param {String} [config.sysProcessId] Unique identifier of the process schema.
 * @param {Object} [config.parameters] Process parameters.
 * @param {Function} [config.callback] Callback function.
 * @param {Object} [config.scope] Callback scope.
 */
executeProcess: function(config) {
	const callback = config.callback || this._executeProcessCallback.bind(this, config);
	const scope = config.scope || this;
	if (config.sysProcessName) {
		this._executeProcessByName(config, callback, scope);
	} else {
		this._executeProcessById(config, callback, scope);
	}
},

Она вызывает вторую, которая и показывает сообщение:

/**
 * @private
 */
_executeProcessCallback: function(config, request, success, response) {
	if (!this.responseCallback(request, success, response)) {
		this.loadSchemaCaptionByName(config.sysProcessName, function(caption) {
	this._showSuccessfullyRunProcessPopup(caption);
		}, this);
	}
},

Насколько понимаю, в первой вызов второй со стандартным обработчиком включается только если не передан свой.

То есть можно попробовать передать в параметре callback пустую функцию или с какими-то своими действиями. 

Пример вызова процесса с добавлением обработчика есть в схеме SystemDesigner, где он выглядит: 

/**
 * Starts OpportunityManagement actualization process.
 * @private
 */
runActualizeOpportunityManagementProcess: function(callback) {
	var processUtils = this.getProcessModuleUtilities();
	this.showBodyMask();
	processUtils.executeProcess({
		sysProcessName: "ActualizeOpportunityManagement",
		callback: function() {
			this.hideBodyMask();
			callback.call(this);
		},
		scope: this
	});
},

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

Зверев Александр,не уверен , что так сработает, я делал , что в калл бэеке показывал маску, а сообщением по заверешению бп ее скрывал

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

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

Добрый день. В результате изучения моб. приложения. Столкнулись с рядом проблем. 

1) Можно, ли расставить сигналы таким образом?

https://i.imgur.com/nKBk78M.png.

2) Дело в том, что данный бизнес процесс связан с кейсом. А если запускается по сигналу, то можно увидеть что связь с кейсом пропадает. Как быть быть в данной ситуации???

https://i.imgur.com/oeQA186.png

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

https://i.imgur.com/HMQYg7N.png

Первый процесс это продолжение через моб. версию. (Диаграмма выполнения: https://i.imgur.com/9ZxIBnH.png)

А второй с ошибкой это запуск через сайт. (Диаграмма выполнения: https://i.imgur.com/V2Ck5iR.png)

Нравится

2 комментария

Не совсем понимаю, что Вы хотите сделать в БП и причём тут мобильное приложение.

Само по себе мобильное не выполняет процессы, они запускаются на сайте, если происходят изменения в записи объекта, для которых в БП настроен сигнал. Если мобильное приложение работает оффлайн, то данные в основной системе добавятся или изменятся в момент синхронизации. 

Узнать больше о том, как выполнялись элементы БП и какие в этот момент были значения параметров, можно, включив трассировку.

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

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