Добрый день! Подскажите пожалуйста как зарегистрировать dll-ку в bpmonline и как использовать его в бизнес процессах, напримере у меня смс агрегатор, спасибо!

Нравится

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

Добрый день, 

Вы можете добавить библиотеку на вкладке [Внешние сборки]. Детальнее тут: https://academy.terrasoft.ru/documents/technic-sdk/7-11/razdel-konfigur…

Для использования функционала внешней библиотеки в бизнес-процессе необходимо добавить ее в using. На вкладке [Методы] дизайнера процессов. https://academy.terrasoft.ru/documents/technic-bpms/7-12/rabochee-prost…

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

Добрый день!

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

Нравится

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

Иван, здравствуйте!

На данный момент, логика расчета среднего показателя реализована только для колонок, которые фактически присутствуют в БД. Пока агрегирующие значения не хранятся в БД, а их можно только сформировать динамически (например, вывести колонку в реестр), то рассчитать по ним итоги (среднее/минимум/максимум) возможности нет.

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

Юлия, спасибо за ответ! уже нашёл похожий пост по хэштегу #среднее время, там как раз про представление в БД.

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

При попытке использовать параметр в запросе $top (см пример запроса)

ProductStockBalanceCollection?$top=100$filter=Warehouse/Id eq guid'ba765c02-b0aa-11e6-bea8-00155d020d02'

получаю ответ о некорректности использования этого параметра

Incorrect format for $top argument '100$filter=Warehouse/Id eq guid'ba765c02-b0aa-11e6-bea8-00155d020d02''.

 

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

Без использования этого параметра - отрабатывает корректно 

Нравится

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

Добрый день!

Есть такой метод

            calcCountRec: function() {

                    var esq = Ext.create("Terrasoft.EntitySchemaQuery", {

                        rootSchemaName: "UsrProductInActivity"

                    });

                    esq.addAggregationSchemaColumn("Id",

                        Terrasoft.AggregationType.COUNT, "UsrProductInActivityCount");

                    esq.filters.addItem(this.Terrasoft.createColumnFilterWithParameter(

                        this.Terrasoft.ComparisonType.EQUAL, "UsrActivity",  this.get("UsrActivity").value));

                    esq.getEntityCollection(function(response) {

                        if (response.success) {

                            var collection = response.collection;

                           if (collection) {

                                this.set("CountRec", collection.getByIndex(0).get("UsrProductInActivityCount"));

                            }

                        }

                    }, this);

                    

                },

 

где CountRec - это виртуальный атрибут

            "CountRec": {

                "type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,

                "dataValueType": this.Terrasoft.DataValueType.FLOAT

            }

 

 

Необходимо при сохранении записи в методе save написать некие проверки, в которых было бы задействовано значение рассчитанного атрибута CountRec

Подскажите, где и как можно вызвать метод calcCountRec, чтобы значение CountRec не было undefined ? (может быть надо как-то сам метод изменить?)

если в save вызвать, и потом в save проверки - то значение undefined

если в onEntityInitialized вызвать, а потом в save проверки - то значение undefined

 

 

Нравится

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

Можно вообще всё вычислять без арибута прямо в методе сохранения. Или сделать обычное поле и заполнять значением суммы при сохранении записи на детали продуктов при помощи БП или триггера.

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

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

А как можно вычислить без атрибута прямо в методе сохранения?

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

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

Это одно из вычислений(просто пример вычисления)

Есть второе вычисление - в другом методе

                

                calcCurrencyIdFromActivity: function() {

                var activityId = this.get("UsrActivity");

                if (activityId) {

                    var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {

                        rootSchemaName: "Activity"

                    });

                    esq.addColumn("Id");

                    esq.addColumn("UsrCurrency.Id", "CurrencyActivity");

                    esq.filters.add("ActivityId", this.Terrasoft.createColumnFilterWithParameter(

                        this.Terrasoft.ComparisonType.EQUAL, "Id", activityId.value));

                    esq.getEntityCollection(function(response) {

                        if (response && response.success) {

                            if (!response.collection.isEmpty()) {

                                var result = response.collection.getItems()[0];

                                this.set("CurrencyIdActivity", result.get("CurrencyActivity"));

                            }

                        }

                    }, this);

                }

            }

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

типа if this.get("CurrencyIdActivity").value==.. &&  this.get("CountRec").value

Но если вызывать эти функции, а потом посмотреть значения этих атрибутов, то они undefined, соответственно проверку выполнить невозможно.

 

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

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

то есть те же самые 2 метода,вызвать их в методе save, но  внутри методов вместо записи  в виртуальные атрибуты запись в локальную переменную?

то есть вместо, например,

this.set("CountRec", сollection.getByIndex(0).get("UsrProductInActivityCount"));

будет

var cc= сollection.getByIndex(0).get("UsrProductInActivityCount"))

И в каждом методе будет своя локальная переменная,но они же локальные будут (поэтому атрибуты-то и делались, чтобы можно было с ними работать на выходе..),  нужен для условия результат как первого метода и второго метода, и если условие будет не соблюдено,то выводится сообщение при сохранении.

Или вы имеете ввиду объединить 2 метода в один как-то?

 

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

 

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

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

 

Можно записать просто в локальную переменную внутри обработчика сохранения. Для удобства вызова написать функцию, которая получает на вход нужные Id и возвращает по ним значение из таблиц базы.

Да, спасибо большое. Мой вопрос как раз состоял в том, как должна выглядеть подобная функция, чтобы она возвращала рассчитанное значение? Не могли бы вы привести пример? Заранее спасибо.

Функция нижеприведенная, к сожалению, не может вернуть ни значения currencyActivity, ни значения sumQuantity, ни значения сс, потому что все эти переменные существуют только  в рамках esq.getEntityCollection(function(response) {...}

calcCheckCurrency: function() {

                var activityId = this.get("UsrActivity");

                if (activityId) {

                    var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {

                        rootSchemaName: "Activity"

                    });

                    esq.addColumn("Id");

                    esq.addColumn("UsrCurrency.Id", "CurrencyActivity");

                    esq.addColumn("UsrSumQuantity","SumQuantity");

                    esq.filters.add("ActivityId", this.Terrasoft.createColumnFilterWithParameter(

                        this.Terrasoft.ComparisonType.EQUAL, "Id", activityId.value));

                    esq.getEntityCollection(function(response) {

                        if (response && response.success) {

                            if (!response.collection.isEmpty()) {

                                var result = response.collection.getItems()[0];

                                var currencyActivity=result.get("CurrencyActivity");

                                var sumQuantity=result.get("SumQuantity");

                                

                                

                                if ((currencyActivity !==this.get("UsrCurrency").value) &&

                                    (

                                    ((this.isAddMode() || this.isCopyMode()) && (sumQuantity>=1))

                                    ||

                                    ((this.isEditMode()) && (sumQuantity>1))

                                    )

                                   )

                                    {

                                        var cc=1;

                                        //this.showInformationDialog("Валюта не совпадает //с ранее выбранной");

                                    }

    

                            }

                        }

                    }, this);

                }

        },

 

                

В таком случае можно всю логику реализовать тоже внутри функции, которая вызывается по завершению getEntityCollection.

Добрый день! Внутри это где? Не поняла вас.

Проблема-то как раз в том, что асинхронно работает, и после завершения getEntityCollection  не доступны данные там вычисленные, они undefined.

Нужно, если условие не выполняется (условие проверяется внутри getEntityCollection), то выводить предупреждение и не сохранять карточку. Если выполняется, то сохранять карточку.

О методе save написан текст вышеприведенный, условие проверяется внутри getEntityCollection, предупреждение выводится - все прекрасно. Но не понятно, как вызвать здесь родительское стандартное сохранение

Если написать так:

                                if ((currencyActivity !==this.get("UsrCurrency").value) &&

                                    (

                                    ((this.isAddMode() || this.isCopyMode()) && (sumQuantity>=1))

                                    ||

                                    ((this.isEditMode()) && (sumQuantity>1))

                                    )

                                   )

                                    {

                                        var cc=1;

                                        this.showInformationDialog("Валюта не совпадает с ранее выбранной");

                                    }

                                   else this.callParent(arguments);

то возникает ошибка (Cannot read property 'superclass' of undefined)

                            

Если this.callParent(arguments) поставить в методе save в конце всей вышеприведенной функции, то тогда предупреждение выводится, но и сохранение также происходит ( а надо, чтобы не происходило)

 

 

 

 

 

Похожий вопрос решают тут.

 

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

Спасибо, помогла связанная тема 

https://community.terrasoft.ru/questions/pereopredelenie-metoda-save-pr…

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

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

Очень хочется, чтобы вызывался callback при завершении задачи в инструментальной панели. Есть ли такая возможность?

Нравится

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

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

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

 

Если же есть пожелания по более удобной реализации, можете завести идею и там подробнее описать желаемое поведение системы.

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

Добрый день. 

Переопределил UserCasesListModule для главной страницы портал.

Добавил в него дополнительные поля.

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

Для этого модифицирую "filterData" в moduleConfig 

{\"className\":\"Terrasoft.FilterGroup\",\"items\":{"
+ this.getCreatedOnFilter()
+ "},\"logicalOperation\":0," 
+ "\"isEnabled\":true,\"filterType\":6,\"rootSchemaName\":\"Case\",\"key\":\"\"}"

Сам метод getCreatedOnFilter (возвращает сериализованный фильтр):

getCreatedOnFilter: function(){
   var filterGroup = Terrasoft.createFilterGroup();
   filterGroup.add("CreatedOnFilter", 
        Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "CreatedBy", 
        Terrasoft.SysValue.CURRENT_USER_CONTACT.value)
   );
   var fgSerializeInfo = filterGroup.getDefSerializationInfo();
   fgSerializeInfo.serializeFilterManagerInfo = true;
   var serializeFilter = filterGroup.serialize(fgSerializeInfo); 
   return Ext.encode(serializeFilter);
}

В итоге получаю ошибку {message: "Ошибка декодирования значения из JSON-строки"}

Нравится

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

Добрый день

Я вижу, что в вашей строке ошибка

....key\":\"\"}"

если десериализировать эту строку, то объект получиться таким:

{
   ...
   key:
}

что некорректно. Нужно либо убрать поле key, либо дать ему значение

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

Есть файл *.dbf около 25 столбцов и 300000 строк. Нужно импортировать в бд bpm. На данный момент импорт реализован в БП через "Задание-сценарий" и данные успешно импортируются, но это занимает ооочень много времени и блокирует приложение полностью. Как можно ускорить процесс или хотя-бы сделать так, чтобы приложение не висло?

Нравится

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

Добрый день! Добавьте после стартового сигнала - сигнал ожидания 1сек. В результате, данный скрипт будет выполняться в параллельном потоке

Если система используется on site и вариант выше всё равно работает слишком долго,  то можно подключиться к базе dbf и залить данные в основную базу bpm'online при помощи SQL Server Management Studio. Учтите, при таком сохранении не отработает логика на уровне объектов и БП, её нужно будет реализовать самостоятельно.

Чубко Илья,

Спасибо!

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

Всем привет, есть необходимость подключить стороннюю JS библиотеку.

Создаю свою папку с библиотекой, в этой директории: Terrasoft.WebApp\Resources\ui

папка "ExternalLib", файл ExternalLib.js

В LeadPage:

 define("LeadPageV2", ["LeadPageV2Resources", ......, "jQuery","ExternalLib"

В консоле получаю ошибку("Файл не найден") :

https://xxx.ru/0/ExternalLib.js?hash=0ccc17c0d48d40469d1f114c719c305a

Подскажите пожалуйста, в чем проблема?

 

Нравится

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

Приветствую, Роман!

Таким образом вы не подключите внешнюю библиотеку, т.к. система не знает, что она существует.

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

Здравствуйте! Посмотрите в данной статье описано как использовать файловый контент в пакетах: https://academy.terrasoft.ru/documents/technic-sdk/7-12/ispolzovanie-fa…

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

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

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

Примерно как описание группы вопросов в анкете, далее вопросы, снова описание группы вопросов...

Делать для этого Текстовое поле, скрывать Имя  и заполнять из карточки в карточку одинаковыми значениями не хочется.

Нравится

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

Добрый день. А элемент Группа полей разве Вам не подойдёт? Он вроде как для таких целей и был создан.

Кисловский Михаил Андреевич,

Ок, группа полей, но есть ограничение на длину названия, перенос строк.

То есть описание-разделитель не формата "Группа Вопросов 1", а "В данном разделе представлены вопросы из группы 1. Подразумевается ответ об участниках департамента и еще пару предложение описания раздела"

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

 

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

На данный момент в приложении нет возможности реализовать Вашу задачу пользовательскими средствами.

У соответствующей команды разработки уже есть задача (6745) по реализии аналогичного функционала которая даст возможность реализации Вашего кейса.

На данный момент можно, средствами разработки, написать diff который использовать в необходимом css для отображения описания полей на странице.

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

Добрый день! В документации по разработке, в статье о ProcessEngineService говорится:

Вызов метода Execute() можно выполнять с помощью HTTP-запросов GET и POST.

В посте от 14 года среди ответов есть следующий:

Добрый день.К сожалению, передача параметров в потоке метода POST в текущих версиях bpm’online не реализована.

Скажите, пожалуйста, существует ли сейчас возможность передачи параметров в бизнес-процесс в теле post-запроса? И если существует, то очень хотелось бы посмотреть пример реализации, потому что у меня упорно не получается передать параметры (при этом, через GET всё работает)

Нравится

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

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

Такая возможность есть, 

Пример: URI /0/ServiceModel/ProcessEngineService.svc/RunProcess

Body 

{"parameterValues":[{"name":"TextParameter","value":"TestValue."}],"schemaUId":"9c7ff5ab-5808-4b1c-9c9e-e66537c00cf8","schemaName":"UsrProcess1"}

 

Tsopa,

Спасибо большое, сработало! Подскажите ещё, пожалуйста, как передать json в value? Обычный текст передается корректно, а json не ловится из бизнес-процесса.

Tsopa,

Всё заработало, и json передался. Спасибо большое!

Tsopa,

Добрый день!

А что указать в Body, чтобы в ответе получить значение параметра с именем "Result" (имя для примера указал)?



А теперь более подробно мой вовпрос.

Есть БП с текстовым параметром (TextResult), целочисленным параметром (IntResult), идентификатор (AccountId). В БП я задаю им определенные значения, явно отличные от пустой строки, нуля и пустого Guid. После выполнения БП я хочу получить результирующее значение любого параметра.

Пробовал как указано на академии Get запрос делать прямо в строке браузера http://localhost:8082/0/ServiceModel/ProcessEngineService.svc/TestProce…

ответ: <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">null</string>     ---- null, вместо текста который должен был быть результатом.

на запрос http://localhost:8082/0/ServiceModel/ProcessEngineService.svc/TestProce… получаю ответ <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">0</string>   ---- опять ноль, хотя указывал разные целые числа

ну и для Guid ответ <string xmlns="http://schemas.microsoft.com/2003/10/Serialization/">"00000000-0000-0000-0000-000000000000"</string>  --- снова ноль.

НО входящие значения параметров БП применяются и всё отлично.

Если из js делаю post запрос как вы предложили, то надеюсь получу результат, правда не знаю как указать ResultParameterName=TextResult...

 

Вот код

var bpUrl = Terrasoft.workspaceBaseUrl +'/ServiceModel/ProcessEngineService.svc/RunProcess';
var data = {
	"schemaName":"TestProcess",
	"resultParameterName":"TextResult" //пробовал и с заглавной буквы ResultParameterName
};
 
var result = Terrasoft.AjaxProvider.request({
	url: bpUrl,
	headers: {
		'Accept': 'application/json',
		'Content-Type': 'application/json'
	},
	method: "POST",
	jsonData: data,
	scope: this,
	callback: function(request, success, response) {
		var responseObject = Terrasoft.decode(response.responseText);
		debugger; //здесь останавливаюсь и получаю
		//см скриншот
	}
});

Нет TextResult !!! 

Помогите плиз, или может хоть кто знает почему GET запрос пустые параметры возвращает.

C GET разобрался. Нужно обязательно компилировать код, даже если простая формула.

Вопрос с POST запросом в силе.

Степин Константин Владимирович,

Если рассматривать метод Execute, то возможности отправлять параметры в теле POST запроса нет. Также, не рекомендуется отправлять POST запросы к методу Execute так как он устарел. Вместо этого стоит воспользоваться методом /RunProcess.

Пример POST-запроса: 

https://[site name]/0/ServiceModel/ProcessEngineService.svc/RunProcess

пример Header:

Content-Type: application/json

BPMCSRF: BgsjByc16fsEZfuAr/CxDO

Cookie: BPMLOADER=vuhtzmo2wh2mxgb1amggorf2; .ASPXAUTH=FFF4F....; BPMCSRF=BgsjByc16fsEZfuAr/CxDO;

пример Body:

{"schemaName":"Process3", "parameterValues"[{"name":"UsrParam","value":"TestValue"}]}

 

Также примет POST-запроса к Execute:

https://[site]/0/ServiceModel/ProcessEngineService.svc/[schemaName]/Execute

пример Header:

Content-Type: application/json

BPMCSRF: BgsjByc16fsEZfuAr/CxDO

Cookie: BPMLOADER=vuhtzmo2wh2mxgb1amggorf2; .ASPXAUTH=FFF4F....; BPMCSRF=BgsjByc16fsEZfuAr/CxDO;

пример Body:

{}

 

Tsopa,

Это именно то что я искал, спасибо!

Tsopa,

Я так понимаю, что в версии 5.4 нету шансов отправить параметры в теле POST-запроса ?

Ігор Андрусенко,

К сожалению, в версии 5.4 такая возможность не реализована. 

Добрый день!



Каким образом при вызове процесса через ProcessEngineService.svc / RunProcess можно получить результат выполнения этого процесса в виде переменной этого процесса.



В теле запроса что и как прописать, чтобы получить значение параметра процесса после его выполнения?



Пробовал в тело запроса прописать значения переменной: "resultParameterName": "Result". Но к сожалению не возвращается значение параметра Result?



Приходит ответ в следующем виде:



{ "ErrorInfo": null, "success": true, "processId": "7a71fb9e-536e-4d85-817b-e70b6c17c4a8", "processStatus": 1}

В статье есть пример получения результата:

Web-cервис ProcessEngineService.svc позволяет запустить определенный бизнес-процесс и получить результат выполнения этого процесса через заданный параметр. Для этого необходимо вызвать метод Execute() в следующем формате:

http[s]://<адрес_приложения_bpm'online>/0/ServiceModel/ProcessEngineService.svc/PROCESSSCHEMANAME/Execute?ResultParameterName=RESULTPARAMETERNAME[&<опциональные входящие параметры бизнес процесса>],

где

  • PROCESSSCHEMANAME — название схемы процесса, экземпляр которого необходимо запустить на выполнение;
  • RESULTPARAMETERNAME — имя параметра процесса, который хранит результат выполнения процесса. Если этот параметр не задан, то web-сервис запустит указанный бизнес-процесс без ожидания результата его выполнения.

ВАЖНО

Если в вызываемом процессе отсутствует параметр с именем RESULTPARAMETERNAME, web-сервис вернет значение null.

Например, необходимо выполнить запуск бизнес-процесса CustomProcess. Результат выполнения процесса хранится в исходящем параметре процесса CustomProcessResult и возвращается в запросе. Дополнительно в процесс CustomProcess передается параметр incomeParam со значением "IncomeParamValue". Тогда строка GET-запроса будет следующей:

.../0/ServiceModel/ProcessEngineService.svc/CustomProcess/Execute?ResultParameterName=CustomProcessResult&incomeParam=IncomeParamValue

Результат выполнения метода Execute() возвращается в виде строки, содержащей JSON-объект (допустимо получение значения null). Десериализация JSON-объекта и приведение полученного результата к определенному типу данных должны выполняться в коде, вызывающем web-сервис.

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

Интересует получение результата POST запроса с передачей данных в теле запроса в JSON формате. Результат такого запроса хотим получить в формате JSON.

Из всего этого понимаю:

1. Что метод RunProcess можно вызвать и передать в него тело запроса, но сформированый результат он не вернет?

2. Для получения сформированного результата нужно еще будет сделать запрос методом Execute, который должен вернуть сохраненьй в системе результат процесса, который был вызван методом RunProces в 1-м пункте?

Выше написано:

Вызов метода Execute() можно выполнять с помощью HTTP-запросов GET и POST.

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

все что передаем в теле запроса методом Execute бизнес-процесс не может прочитать.

Лишь через RunProcess бизнес-процесс видит тело запроса.

Как подготовить тело запроса для метода Execute, чтобы бизнес-процесс обработал данные?

Если в теле не видит, попробуйте передавать в адресе, как в GET.

 методом GET нельзя передавать большие объемы информации, потому что данные, передаваемые этим методом входят в соств URL, длина которого ограничена

Если передаются большие объёмы, то и процесс, скорее всего, будет выполняться не мгновенно. Возможно, лучше не ждать его завершения, а пересмотреть архитектуру запуска сервиса. Например, из БП запускать вызов веб-сервиса (уже в противоположную сторону) или писать результаты в какую-то таблицу, а потом забирать по OData.

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

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