Всем добрый день. Версия 7.12.

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

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

 

Нравится

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

Добрый день!



Имеется view. Хочу вывести показатель "сумма" строк с учетом фильтра. Выбираю объект, устанавливаю фильтр и получаю ошибку:



{errorCode: "ArgumentNullOrEmptyException", message: "Значение аргумента "queryExpressions" не может быть пустым", stackTrace: undefined, errors: Array(0)}



Может быть надо как-то "правильно" указывать значения view или еще чего-то надо?

Нравится

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

Быстров Сергей,

Такая ошибка возникает для пустых и null объектов типа System.String, то есть, вероятнее всего, причина в данных используемого представления.

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

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

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

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

Запрос даже до профайлера не дошел (по крайне мере не видел его там). Вьюха просто состоит из колонок текстовых и ID. Я могу работать с ней (есть справочник + используется в БП), но ни график ни показатель сделать не могу. Показатель простой - количество без фильтра (в таблице 5 строк). Запрос у вьюхи тоже элементарный (прямая копия таблицы с другой базы).

Быстров Сергей,

Такая ошибка возникает для пустых и null объектов типа System.String, то есть, вероятнее всего, причина в данных используемого представления.

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

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

Реализовал разделение календаря по сотрудникам в фильтре через кучу diff. Встал вопрос - как наполнить каждый разными данными?

По умолчанию activityCollection планировщика указан как ScheduleGridData. Соответственно, на каждый календарь на странице создаю ScheduleGridData0, ScheduleGridData1, ScheduleGridData2 и так далее и подставляю эти значения в каждый activityCollection, но календари становятся вообще пустыми. Я так понимаю, вопрос в методах отрисовки, но тогда придется переписывать половину CRM.

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

Вот пример одного из календарей

{
            "operation": "insert",
            "name": "Schedule0",
            "parentName": "DataViewsContainer",
            "propertyName": "items",
            "values": {
                 "id": "ActivitySectionV2Scheduler0",
                 "selectors": {"wrapEl": "#ActivitySectionV2Scheduler0"},
                 "itemType": Terrasoft.ViewItemType.SCHEDULE_EDIT,
                 "visible": {"bindTo": "isSchedulerVisible0"},
                 "startHour": Terrasoft.SysSettings.cachedSettings.SchedulerTimingStart,
                 "displayStartHour": Terrasoft.SysSettings.cachedSettings.SchedulerDisplayTimingStart + "-00",
                 "dueHour": Terrasoft.SysSettings.cachedSettings.SchedulerTimingEnd,
                 "timeScale": {"bindTo": "getTimeScale"},
                 "period": {"bindTo": "getSchedulerPeriod"},
                 "timezone": [{}],
                 "startDate": null,
                 "dueDate": null,
	         "activityCollection": {"bindTo": "ScheduleGridData0"},
                 "selectedItems": {"bindTo": "SelectedRows"},
                 "changeSelectedItems": {"bindTo": "onChangeSelectedItems"},
                 "scheduleItemDoubleClick": {"bindTo": "onScheduleItemDoubleClick"},
                 "scheduleItemTitleMouseOver": {"bindTo": "scheduleItemTitleMouseOver"},
                 "scheduleItemTitleClick": {"bindTo": "scheduleItemTitleClick"},
                 "change": {"bindTo": "changeScheduleItem"},
                 "selection": {"bindTo": "SchedulerSelection"},
                 "floatingItemsCollection": {"bindTo": "SchedulerFloatItemsCollection"},
                 "selectionKeyPress": {bindTo: "onSelectionKeyPress"},
                 "floatingItemReady": {"bindTo": "onFloatingItemReady"},
                 "selectionKeyPressSymbols": {"bindTo": "SchedulerSelectionPressedKeys"},
                 "itemBindingConfig": {
                     "itemId": {"bindTo": "Id"},
                     "title": {"bindTo": "getScheduleItemTitle"},
                     "changeTitle": {"bindTo": "onTitleChanged"},
                     "startDate": {"bindTo": "StartDate"},
                     "changeStartDate": {"bindTo": "onStartDateChanged"},
                     "dueDate": {"bindTo": "DueDate"},
                     "changeDueDate": {"bindTo": "onDueDateChanged"},
                     "status": {"bindTo": "getScheduleItemStatus"},
                     "changeStatus": {"bindTo": "onStatusChanged"},
                     "background": {"bindTo": "Background"},
                     "fontColor": {"bindTo": "FontColor"},
                     "isBold": {"bindTo": "IsBold"},
                     "isItalic": {"bindTo": "IsItalic"},
                     "isUnderline": {"bindTo": "IsUnderline"},
                     "markerValue": {"bindTo": "getScheduleItemHint"}
                   },
                   "floatingItemBindingConfig": {
                        "caption": {"bindTo": "getSimpleModuleCaption"},
                        "width": {"bindTo": "getSimpleModuleWidth"}
                   }
}

 

Нравится

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

Смотрите, как реализовано расписание для нескольких пользователей в дополнении «Advanced schedule for bpm'online». 

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

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

Подскажите, пожалуйста, хотя бы в 2-3 строчках, общую идею куда копать чтобы это реализовать, заранее огромное спасибо!

Нравится

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

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

 

 

Возможно вам будут полезны эти приложения 1 2 3 доступные на меркетплэйсе

 

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

 

 

Возможно вам будут полезны эти приложения 1 2 3 доступные на меркетплэйсе

 

В первом, Advanced schedule for bpm'online, как раз есть то, что Вы хотите:

Дополнение платное, но есть «тест-драйв», можно установить и посмотреть, как оно сделано.

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

Добрый день. Версия 7.12.

Возникла проблема с отправкой сообщения из БП на клиентскую часть. Используем стандартный механизм:

Terrasoft.Configuration.MsgChannelUtilities.PostMessage(userConnection, MessageName ,MessageText );

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

Я вообще правильно ли понимаю, что сообщения по MsgChannelUtilities должны получать все, кто сейчас находится в системе? И как тогда отправить сообщение непосредственному пользователю, запустившему БП?

Нравится

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

Добрый день

Работа 2-х пользователей в системе под одним аккаунтом - не совсем корректная работа с системой.

Скорее всего будет приходить сообщение только одному пользователю.



Чтобы отослать сообщение всем, используйте метод MsgChannelUtilities.PostMessageToAll с передачей Id пользователя, запустившего БП, а на клиенте уже разбирайте ответ

Добрый день

Работа 2-х пользователей в системе под одним аккаунтом - не совсем корректная работа с системой.

Скорее всего будет приходить сообщение только одному пользователю.



Чтобы отослать сообщение всем, используйте метод MsgChannelUtilities.PostMessageToAll с передачей Id пользователя, запустившего БП, а на клиенте уже разбирайте ответ

ясно, спасибо, попробую с PostMessageToAll 

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

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

Всем доброго времени суток. Версия 7.12.

В модуле HtmlEditModule многие обработчики кнопок wysiwyg-редактора завершаются примерно следующим образом:

var container = this.ownerCt;
var editor = container.editor;
if (editor) {
	editor.execCommand("bold");
}

Вопрос такой - а где обрабатывается отправляемая команда? Необходимо расширить редактор для определённых задач.

Нравится

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

Обработка происходит в 2х редакторах AceEdit.js (SourceCodeEdit) и ckeditor.js (HtmlEditModule) расположеных соответственно в \Terrasoft.WebApp\conf\content  и \Terrasoft.WebApp\Resources\ui\CKEditor

 

Скорее всего вам нужен CKEditor, так как первый используется для редактирования исходного кода (js и cs)

Обработка происходит в 2х редакторах AceEdit.js (SourceCodeEdit) и ckeditor.js (HtmlEditModule) расположеных соответственно в \Terrasoft.WebApp\conf\content  и \Terrasoft.WebApp\Resources\ui\CKEditor

 

Скорее всего вам нужен CKEditor, так как первый используется для редактирования исходного кода (js и cs)

Григорий Чех,

в ckeditor нашёл только вот это

define("ckeditor", ["ckeditor-base"], function() {
	var warningMessage = Ext.String.format(Terrasoft.Resources.ObsoleteMessages.ObsoleteModule,
		"ckeditor", "ckeditor-base");
	window.console.log(warningMessage);
});

 

Как я выше уже написал смотрите в папке Resources\ui\CKEditor\ вашего сервера

Это всё, что нашлось.

Я выше уже 2 раза написал где смотреть а вы почему то ищете в конфигурации

Так же обратите внимание на статью 

У CKEditor есть свой сайт, где могут быть плагины, которые реализуют то, что хотите доработать. Вопросы возможности установки плагинов обсуждались здесь.

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

Добрый день!

Пробую при работе с SVN сделать отдельную ветвь разработки и далее откатиться на старый вариант кода.

Есть пакет p1 версии 1.0.1

Создаю новую ветвь 1.0.2 и делаю ее основной.

Но далее я не понимаю как необходимо переключать пакет в BPM Online на новую версию.

Нужно ли создавать новый пакет версии 1.0.2 в самой BPM Online руками, который полностью будет дублировать пакет версии 1.0.1 и располагаться рядом с ним.

Или можно все это сделать в самом SVN несколькими командами.

И после выполнения перехода на новую ветку как проводить откат на старую со старым кодом.

Новая версия пакета должна находиться в другом хранилище или нет?

 

Нравится

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

Смотрите документацию и обсуждения по работе с svn, например тут

Смотрите документацию и обсуждения по работе с svn, например тут

Григорий Чех,

 

Я верно понимаю, что все действия идут только на стороне SVN и на стороне BPM Online не потребуется дополнительно перенастраивать пакет?

Александр Кулиш,

Все верно, все действия идут на стороне svn. Вы можете использовать различную стратегию svn, более детально можете ознакомится тут: https://habr.com/ru/post/170589/

Дополнительных действий на стороне bpmonline делать не нужно, Вы просто настраиваете хранилище, и работаете с ним, более детально описано тут: https://academy.terrasoft.ru/documents/technic-sdk/7-13/rabota-s-paketami 

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

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

Место событий Entity, событие Saved, для которого был организован событийный подпроцесс. Последний со скриптом и сообщением которое запускает этот скрипт по событию. 

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

Нравится

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

Добавьте еще подписку на событие, перед сохранением.

Так же делаете подписку, скрипт.

В параметрах создайте нужные переменные нужных типов.

После чего в самом скрипте "перед сохранением", делайте так:

ContactOld = Entity.GetTypedOldColumnValue<Guid>("Contact");

Затем, в вашем скрипте "После сохранения" делайте сверку

if (ContactOld != Entity.GetTypedColumnValue<Guid>("Contact") { // }

Добавьте еще подписку на событие, перед сохранением.

Так же делаете подписку, скрипт.

В параметрах создайте нужные переменные нужных типов.

После чего в самом скрипте "перед сохранением", делайте так:

ContactOld = Entity.GetTypedOldColumnValue<Guid>("Contact");

Затем, в вашем скрипте "После сохранения" делайте сверку

if (ContactOld != Entity.GetTypedColumnValue<Guid>("Contact") { // }

Это можно сделать только в событийном процессе объекте перед сохранением записи

Entity.GetColumnOldValue("Name")

или

Entity.GetTypedOldColumnValue<String>("Name");

 

Добрый день!

На вход элемента скрипта обработки сохранения подается переменная ProcessExecutingContext context (https://monosnap.com/file/TP10NeOGRBkG4zXPFKxrVZM8Tvj4I6).

В ней есть public object ThrowEventArgs { get; set; }, которая приводится к объекту EntityAfterEventArgs. А в этом объекте уже есть массив измененных колонок: public EntityColumnValueCollection ModifiedColumnValues { get; set; }

Еще проще проверить что столбец изменен

var flag = Entity.GetChangedColumnValues().Any(col => col.Name == "Date");

Всем спасибо!

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

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

В продолжаю изучение бизнес-процессов. Кейс следующий:

В элементе "Читать данные" в разделе "Значение каких колонок вычитать?" вывожу колонку Название (string). Затем в бизнес-сценарии хочу ее передать и проанализировать. Каким образом передаются эти значения?

Спасибо!

Нравится

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

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

string myString = Get&lt;string&gt;("myParameter");

 

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

string myString = Get&lt;string&gt;("myParameter");

 

Alex Zaslavsky,

Спасибо, попробую!

Получить и обработать коллекцию в интрпритируемом БП можно примерно так:  

var entities = Get&lt;ICompositeObjectList&lt;ICompositeObject&gt;&gt; ("ReadDataUserTask1.ResultCompositeObjectList");
var result = "";
foreach(var entity in entities) 
{
   var cityName = entity.GetTypedColumnValue&lt;string&gt;("Name");
}
Если нужна только одна прочитаная запись то получить ее можно так:
var entity = entities.FirstOrDefault();
 
Показать все комментарии

Добрый день!



Вопрос следующего характера:

Необходимо изменить номера обращений - переделать поле текстовое в числовое. Есть пример https://community.terrasoft.ru/articles/sortirovka-po-nomeru-dogovora-d… но там выводится новая колонка, но моя задача - изменить текущую.



1) Что стоит предусмотреть и что может повлиять на работу? (сейчас создаются новые обращения формата "только цифры")

2) Если в это поле будет писаться текст (случайно попадет) - что изменится?

3) Что станет с БП, которые берут значение этого поля как текст?

Нравится

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

Быстров Сергей,

Как то так попробуй (код набросал на глазок, те сырой нужно  отлаживать)

initQuerySorting: function(esq) {
	var columnName = "Number";
	if (esq.columns.contains(columnName)) {
		//var numColumn = esq.addColumn(columnName);
		var numColumn = esq.columns[columnName];
		if (numColumn.orderPosition &amp;&amp; numColumn.orderPosition &gt; 0) {
			var numNewColumn = esq.addColumn("NewNumberIntegere");
			numNewColumn.orderDirection = numColumn.orderDirection;
			numNewColumn.orderPosition = numColumn.orderPosition;
			delete numColumn.orderDirection;
			delete numColumn.orderPosition;
		} else {
			this.callParent(arguments);
		}
}
},

 

А почему нельзя добавить новую колонку, спрятав при необходимости старую, при этом все базовая функциональность и ваши наработки работающие с номерами останется работоспособной

1) трудно сказать  нужно тестировать полностью весь блок работы с обращениями выискивая блох

2) в число текст не впихнуть будет ошибка при сохранении

3) зависит от того как именно обрабатывается строка в БП

Григорий Чех,

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

Быстров Сергей,

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

Григорий Чех,

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

Быстров Сергей,

Есть еще костыльный вариант установить шаблон маски в SP{0:00000000} тогда номера будут формироватся в виде SP000000001,  SP000000002 и тд что позволит сортировать по текстовому полю номер, возможно вам это подойдет если пользователи не будут ругаться на лидирующие нули.

Григорий Чех,

А вот на это ругается первая линия, потому что "лишние цифры - это плохо". Поэтому сразу откинули такой вариант. Может можно как-то переопределить фильтр: когда мы пытаемся фильтровать по номеру, на самом деле фильтр делается по другому полю "UsrNumber"?

Быстров Сергей,

Фильтр не трогать, а можно попытатся переопределить сортировку, те при попытке сортировать по номеру отсортировать по новому числовому полю номер

Григорий Чех,

А провернуть такое можно, если в реестре не выведена эта колонка? Просто еще ни разу не делал подобного. Если есть какие-то примеры - буду рад.

Быстров Сергей,

Как то так попробуй (код набросал на глазок, те сырой нужно  отлаживать)

initQuerySorting: function(esq) {
	var columnName = "Number";
	if (esq.columns.contains(columnName)) {
		//var numColumn = esq.addColumn(columnName);
		var numColumn = esq.columns[columnName];
		if (numColumn.orderPosition &amp;&amp; numColumn.orderPosition &gt; 0) {
			var numNewColumn = esq.addColumn("NewNumberIntegere");
			numNewColumn.orderDirection = numColumn.orderDirection;
			numNewColumn.orderPosition = numColumn.orderPosition;
			delete numColumn.orderDirection;
			delete numColumn.orderPosition;
		} else {
			this.callParent(arguments);
		}
}
},

 

Григорий Чех,

Спасибо за помощь, получилось вот так:

initQuerySorting: function(esq) {
	this.callParent(arguments);
	var columnName = "Number";
	if (esq.columns.contains(columnName)) {
	var numColumn = esq.columns.collection.get(columnName);
		if (numColumn.orderPosition &amp;&amp; numColumn.orderPosition === 1) {
			var numNewColumn = esq.columns.collection.get("UsrNumber");
			numNewColumn.orderDirection = numColumn.orderDirection;
			numNewColumn.orderPosition = 0;
			delete numColumn.orderPosition;
		}
	}
},
getGridDataColumns: function() {
	return {
		"UsrVIPobr": {path: "UsrVIPobr"},
		"UsrNumber": {path: "UsrNumber"}
	};
},

 

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