Добрый день. Просьба помочь в ответе на следующий вопрос по очередям:

1) С чем может быть связана проблема, что после нажатия кнопки [Вернуть в очередь], в одном случае объект очереди остается в очереди, но увеличивается счетчик [Количество переносов], а в другом объект очереди исключается из очереди и через 5 минут снова входит в ней, но счетчик не сработал (т.к. создался новый объект очередь).

Какое поведение корректно при нажатии на кнопку [Вернуть в очередь]? Остаться в очереди с увеличенным счетчиком или исключение из очереди, и создание нового объекта очереди?

В документации описано такое поведение:

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

//из описания следует, что из очереди выпадать обращение не должно, верно?

Нравится

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

Логика этой кнопки сделана в схеме BasePageV2 в одном из пакетов OperatorSingleWindow:

    onPostponeQueueItemButtonClick: function() {
     var queueItemId = this.get("QueueItemId");
     if (!queueItemId) {
      this.error(this.get("Resources.Strings.QueueItemIsEmptyError"));
      //Страница не связана с элементом очереди единого окна. Действие отменено.
      return;
     }
     this.postponeQueueItem(queueItemId, function(success) {
      var messageString = (success)
       ? "QueueItemPostponeSucceedMessage"//Элемент успешно возвращен в очередь
       : "QueueItemPostponeFailedMessage";//Ошибка при возвращении элемента в очередь
      var message = this.get("Resources.Strings." + messageString);
      this.showInformationDialog(message, function() {
       if (success) {
        this.onQueueItemPostponed();
       }
      }.bind(this));
     }.bind(this));
    }
   },
    postponeQueueItem: function(queueItemId, callback) {
     var serviceCallBack = function(response, success) {
      if (!success) {
       var errorMessage =
        this.Ext.String.format(this.get("Resources.Strings.PostponeQueueItemError"),
         response.responseText);
         //Ошибка возвращения элемента в очередь. Сообщение об ошибке: {0}
       this.error(errorMessage);
       if (callback) {
        callback(false);
       }
       return;
      }
      if (callback) {
       callback(response === 1);
      }
 
     };
     ServiceHelper.callService({
      serviceName: "QueuesService",
      methodName: "PostponeQueueItem",
      data: {
       queueItemId: queueItemId
      },
      callback: serviceCallBack,
      scope: this
     });
    },

Там клиентская логика вызывает серверную функцию из QueuesService:

  [OperationContract]
  [WebInvoke(Method = "POST", UriTemplate = "PostponeQueueItem", BodyStyle = WebMessageBodyStyle.WrappedRequest,
   RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
  public int PostponeQueueItem(Guid queueItemId) {
   var userConnection = HttpContext.Current.Session["UserConnection"] as UserConnection;
   int updateCount = 0;
   string message = string.Empty;
   try {
    if (userConnection == null) {
     throw new ArgumentNullException("UserConnection");
    }
    var update =
     new Update(userConnection, "QueueItem")
      .Set("PostponesCount", new QueryColumnExpression(ArithmeticOperation.Addition,
       new QueryColumnExpression("PostponesCount"), new QueryColumnExpression(Column.Const(1))))
      .Set("OperatorId", Column.Parameter(null, "Guid"))
      .Set("NextProcessingDate", Column.Const(null))
     .Where("Id").IsEqual(new QueryParameter("QueueItemId", queueItemId));
    updateCount = update.Execute();
    message = string.Format(GetResourceValue(userConnection, "QueueItemPostponeUpdatedMessage"),
     queueItemId);
    QueuesUtilities.LogDebug(message);
   } catch (Exception e) {
    message = string.Format(GetResourceValue(userConnection, "InvokeMethodErrorMessage"),
     "PostponeQueueItem", e.Message);
    QueuesUtilities.LogError(message, e);
    throw;
   }
   return updateCount;
  }

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

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

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

Спасибо большое за ваш комментарий, взял на вооружение!

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

Добрый день. Подскажите, есть ли документация, где есть описание блоков "Следующие шаги (0)" в карточке "Обращение/Клиент".

В частности интересует:

  1. Можно ли скрывать с карточки этот блок? 
  2. Можно ли скрывать с карточки этот блок при определенных условиях, например, в зависимости от значений на индикаторе стадий)? 
  3. Можно ли дизейблить работу этого блока при определенных условиях (нельзя звонить/отправлять письмо при определенных условиях, например, в зависимости от значений на индикаторе стадий? 
  4. Можно ли убрать часть функционала в блоке "Следующие шаги (0)" (например, с данной карточки нельзя отправлять электронное письмо)?

Нравится

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

Этот механизм сделан в схеме CaseSectionActionsDashboard. В статье есть пример его доработки, добавления нового элемента для сообщений портала, в другой статье — ещё одной кнопки для звонков. Для изменения, скрытия кнопок используйте diff с merge и remove, как тут и тут. Для добавления логики видимости и доступности попробуйте использовать биндинги, как к обычным полям. Также см. обсуждение.

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

Этот механизм сделан в схеме CaseSectionActionsDashboard. В статье есть пример его доработки, добавления нового элемента для сообщений портала, в другой статье — ещё одной кнопки для звонков. Для изменения, скрытия кнопок используйте diff с merge и remove, как тут и тут. Для добавления логики видимости и доступности попробуйте использовать биндинги, как к обычным полям. Также см. обсуждение.

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

Спасибо за комментарий, очень много полезной информации!

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

Добрый день. Просьба помочь в ответе на следующий вопрос по очередям:

1) У каждого объекта очереди есть поле "Дата следующей обработки", каким образом оно заполняется? По кнопке [Запланировать на дату] или с помощью другого механизма?

2) С чем может быть связана проблема, что после заполнения по кнопке [Запланировать на дату] времени и даты, объект очереди всё равно при наполнении очереди попадает в очередь.

//вместо того, чтобы сработал алгоритм: "Объект очереди не будет отображаться в едином окне до того момента, когда наступит указанное время обработки. При наступлении запланированного времени обработки объект очереди отобразится вверху списка в очереди у того оператора, который взял в работу данный объект очереди"

3) Корректно ли поведение системы: если с домашней страницы по кнопке [Открыть] открыть объекта очереди, то объект очереди исключается из очереди, но через 1-5 минут (в зависимости от [Частота обновления]) снова отображается в очереди

Нравится

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

По инструкции:

Дата следующей обработки

Если оператор отложил обработку элемента, данная колонка отобразит дату, в которую элемент снова будет предложен оператору.

Это поле NextProcessingDate в объекте OperatorSingleWindow. Оно меняется в серверной логике схемы QueuesService, в методах ChangeQueueItemDate (заполнение) и PostponeQueueItem (очистка). А также в клиентской схеме QueueItemEditPage в методе updateQueueItemData и BasePageV2 пакета OperatorSingleWindow, которая взаимодействует с вышеупомянутым сервисом.

Логика фильтрации по этому полю реализована в схеме QueueGridUtilities:

addNextProcessingDateFilters: function(filters) {
	var nextProcessingDateFilters = new this.Terrasoft.createFilterGroup();
	nextProcessingDateFilters.logicalOperation = this.Terrasoft.LogicalOperatorType.OR;
	var nextProcessingColumnName = "NextProcessingDate";
	nextProcessingDateFilters.add("NextProcessingDateFilter", this.Terrasoft.createColumnFilterWithParameter(
		this.Terrasoft.ComparisonType.LESS_OR_EQUAL, nextProcessingColumnName, new Date()));
	nextProcessingDateFilters.add("IsNullNextProcessingDateFilter",
		this.Terrasoft.createColumnIsNullFilter(nextProcessingColumnName));
	filters.add("NextProcessingDateFilters", nextProcessingDateFilters);
},

И её применение там же ниже:

  addQueueFilters: function(filters, config) {
   filters.addItem(this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL,
    "[Queue:Id:QueueId].QueueEntitySchema", this.get("EntitySchemaUId")));
   var queueId = this.get("QueueId");
   if (!Ext.isEmpty(queueId)) {
    filters.addItem(this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL,
     "Queue", queueId));
   }
   var isSupervisorMode = this.get("IsSupervisorMode");
   if (!isSupervisorMode) {
    filters.addItem(this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL,
     "Status.IsFinal", false));
    filters.addItem(this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL,
     "[Queue:Id:QueueId].Status.IsInitial", false));
    filters.addItem(this.Terrasoft.createColumnFilterWithParameter(this.Terrasoft.ComparisonType.EQUAL,
     "[Queue:Id:QueueId].Status.IsFinal", false));
    this.addNextProcessingDateFilters(filters);
    this.addOperatorFilters(filters);
    if (!config || !config.skipOperatorFilter) {
     this.addCloseQueueFilters(filters);
    }
   }
  },

Там же есть и другой фильтр, реализованный в функции addOperatorFilters.

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

Спасибо за информацию. Основная проблема была в том, что некорректно был настроен процесс: Обработка обращений/заявок из очереди в Едином окне (в частности правило "когда считать элемент выполненным)

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

Все довольно просто: есть чтение данных с режимом чтения = "Читать коллекцию записей". Имя элемента ReadDataUserTask1. Версия bpm 7.12.4, процесс не компилируемый, соответственно напрямую, как раньше к элементу не обратиться.

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

 Нужно использовать метод T Get<T>(string propertyPath), но возникает 2 проблемки:

1) Чему равен propertyPath? Точно не ResultCompositeObjectList - поскольку он выдаёт результат для режима чтения = "Читать коллекцию записей"

2) какой тип T использовать, Entity? Или какой-то другой? В аналогичной задаче удалось определить как получить массив элементов с колонками. Но там читали коллекцию записей.

var entities = Get<ICompositeObjectList<ICompositeObject>("ReadDataUserTask1.ResultCompositeObjectList");

 

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

var x01 = Get<object>("ReadDataUserTask1.DataSourceFilters");
var x02 = Get<object>("ReadDataUserTask1.ResultType");
var x03 = Get<object>("ReadDataUserTask1.ReadSomeTopRecords");
var x04 = Get<object>("ReadDataUserTask1.NumberOfRecords");
var x05 = Get<object>("ReadDataUserTask1.FunctionType");
var x06 = Get<object>("ReadDataUserTask1.AggregationColumnName");
var x07 = Get<object>("ReadDataUserTask1.OrderInfo");
var x08 = Get<object>("ReadDataUserTask1.ResultEntity");
var x09 = Get<object>("ReadDataUserTask1.ResultCount");
var x10 = Get<object>("ReadDataUserTask1.ResultIntegerFunction");
var x11 = Get<object>("ReadDataUserTask1.ResultFloatFunction");
var x12 = Get<object>("ReadDataUserTask1.ResultDateTimeFunction");
var x13 = Get<object>("ReadDataUserTask1.ResultRowsCount");
var x14 = Get<object>("ReadDataUserTask1.CanReadUncommitedData");
var x15 = Get<object>("ReadDataUserTask1.ResultEntityCollection");
var x16 = Get<object>("ReadDataUserTask1.EntityColumnMetaPathes");
var x17 = Get<object>("ReadDataUserTask1.IgnoreDisplayValues");
var x18 = Get<object>("ReadDataUserTask1.ResultCompositeObjectList");
var x19 = Get<object>("ReadDataUserTask1.ConsiderTimeInFilter");

Но ни один из них не наполнен полями объекта и их значениями.

 

 

Нравится

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

Добрый день! Не подскажу про элемент процесса "читать коллекцию", но для работы с коллекцией проще всего использовать такой код:

var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "UsrCustom123");
esq.AddColumn("Id");
esq.AddColumn("Name");
 
var Filter1 = esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Name", "zzz");
esq.Filters.Add(Filter1);
 
var EsqCollection = esq.GetEntityCollection(UserConnection);
	if (EsqCollection.Count>0) {
		foreach (var name in EsqCollection) {
          var param1 = name.GetTypedColumnValue<string>("Name");
          var param2 = name.GetTypedColumnValue<Guid>("Id");
         ///ваш код..
        }
    }

 

Добрый день! Не подскажу про элемент процесса "читать коллекцию", но для работы с коллекцией проще всего использовать такой код:

var esq = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "UsrCustom123");
esq.AddColumn("Id");
esq.AddColumn("Name");
 
var Filter1 = esq.CreateFilterWithParameters(FilterComparisonType.Equal, "Name", "zzz");
esq.Filters.Add(Filter1);
 
var EsqCollection = esq.GetEntityCollection(UserConnection);
	if (EsqCollection.Count>0) {
		foreach (var name in EsqCollection) {
          var param1 = name.GetTypedColumnValue<string>("Name");
          var param2 = name.GetTypedColumnValue<Guid>("Id");
         ///ваш код..
        }
    }

 

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

var entities = Get<ICompositeObjectList<ICompositeObject>>("ReadDataUserTask.ResultCompositeObjectList");
var result = "";
foreach(var entity in entities) 
{
      var cityName = entity.GetTypedColumnValue<string>("Name");
}

 

Константин, я так понял вам нужно считать 1 запись, а не коллекцию?
Тогда можно просто поставить режим чтения "Читать коллекцию записей", "Читать первые 1 записей". Ну и дальше использовать коллекцию ResultCompositeObjectList

var entities = Get<ICompositeObjectList<ICompositeObject>>("ReadDataUserTask1.ResultCompositeObjectList");
var entity = entities.FirstOrDefault();

Так как, к сожалению, ReadDataUserTask1.ResultEntity всегда возвращает null для интерпретируемых процессов

Сидоров Александр В.,

Интересно как вы это поняли?  в начале первая строчка:

"Все довольно просто: есть чтение данных с режимом чтения = "Читать коллекцию записей". "

Добавить комментарий

Григорий Чех, далее в тексте автор говорит про одну запись

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

Добрый день!

Имеется унаследованная от "базовой схемы детали средств связи" деталь. Внутрь детали рядом с самим средством связи вставлены создаваемые вручную контейнеры (Terrasoft.Container) с чекбоксами (Terrasoft.CheckBoxEdit).
Задача: при полной отрисовки детали блокировать все чекбоксы кроме одного выбранного, если он есть, иначе не блокировать ничего. Решаю с помощью jquery на странице раздела. Т.к. не знаю, как поймать событие полной отрисовки детали (чтобы получить доступ к DOM), использую костыль в виде setTimeout. Как это событие можно отловить? 
И еще один вопрос: есть ли какое-то единое событие для перерисовки детали (детали перерисовывается при нажатии на кнопку "отмена" на странице, переходе между вкладками, сворачивании/разворачивании детали и т.д.). 

Возможно есть какой-то способ решения этой задачи кроме jQuery?

Нравится

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

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

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

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

Добрый день. 

выполнил вес шаги инструкции https://academy.terrasoft.ru/documents/common/7-10/kak-nastroit-integra… . Не могу понять почему не появляется трубка в BPM'Online  для осуществления звонков. как это происходит при интеграции между BPM'Online и webitel. Кто может подсказать что я упускаю. Или нужно что то настроить еще в BPMonline Messaging Service Install?

Нравится

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

Да, для интеграции с телефонией Infinity нужно ещё установить и настроить на своём сервере bpm'online Messaging Service. А если уже установили, обратите внимание на ремарку о https.

да я уже из https настройку делал и без. не появляется трубка для звонка. может что то еще нужно выполнить? нужно настройку самого  BPMonline Messaging Service делать? или дефолтных настроек достаточно? 

Если версия Infinity X, то её поддержку добавили совсем недавно и нужно вносить изменения в конфигах. Опубликованной инструкции ещё нет, обратитесь в службу поддержки.

да Infinity X

См. предыдущий ответ.

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

Задача: 

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

Нравится

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

В БП есть возможность указать запуск по сигналу при добавлении объекта или изминении определенного поля/полей объекта. Id этого объекта получает процесс как параметр стартового сигнала. Думаю это соответствует вашей задаче. Подробности смотри в документации по БП

 

 

 

В БП есть возможность указать запуск по сигналу при добавлении объекта или изминении определенного поля/полей объекта. Id этого объекта получает процесс как параметр стартового сигнала. Думаю это соответствует вашей задаче. Подробности смотри в документации по БП

 

 

 

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

спасибо большое, то что нужно!

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

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

Нравится

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

Как работать с утилитой WorkspaceConsole, см. справку.

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

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

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

Нравится

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

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

 

Большое спасибо!

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

Добрый день! Столкнулся со следующей проблемой:

1) Захожу в Tools -> Configuration -> Schemas:All

2) Кликаю по кнопке "Add"

3) Выбираю "Source code"

4) Появляется сообщение:

> An error occurred in bpm'online. We apologize for the inconvenience.

> Back to Previous Page.

> Please notify the bpm'online support about this error.

> We guarantee your confidentiality and anonymity.

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

Какова может быть причина данной ошибки?

Нравится

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

Добрый день!

Пришлите, пожалуйста, скриншоты из консоли. (Нажмите F12 - Перейдите на вкладку Консоль - Воспроизведите ошибку)

Анна, скрин консоли прикрепил

engineer7,

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

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

Если ошибка будет продолжать воспроизводится, советую Вам отправить подробное описание кейса со скриншотами поведения на почтовый ящик support@bpmonline.com

В логах нашел более подробное описание: 
Exception Message: Value for argument "uid" must be specified.
Exception Type: Terrasoft.Common.ArgumentNullOrEmptyException
Exception Source: Terrasoft.Common

Exception Stack Trace:
   at Terrasoft.Common.ValidateUtilities.CheckArgumentEmpty(Guid source, String argumentName)
   at Terrasoft.Core.Packages.PackageIdentifierMapper.GetIdByUId(Guid uid, Guid workspaceId)
   at Terrasoft.Core.SchemaManager`1.CreateSchemaItem(Guid packageUId, String name, TSchemaManagerSchema parentSchema, Boolean extendParent, UserConnection userConnection)
   at Terrasoft.Core.SchemaManager`1.CreateDesignSchema(UserConnection userConnection, Guid parentSchemaUId, Guid packageUId, Boolean extendParent)
   at Terrasoft.Core.SchemaManager`1.Terrasoft.Core.ISchemaManager.CreateDesignSchema(UserConnection userConnection, Guid parentSchemaUId, Guid packageUId, Boolean extendParent)
   at Terrasoft.WebApp.WorkspaceExplorerModule.CreateSchema(String managerName, Guid packageUId, IDictionary`2 extraParameters)
   at Terrasoft.WebApp.WorkspaceExplorerModule.OnTreeAddMenuItemClick(Object sender, AjaxEventArgs e)
   at Terrasoft.UI.WebControls.Controls.ComponentAjaxEvent.OnEvent(Object sender, AjaxEventArgs e)
   at Terrasoft.UI.WebControls.Controls.Observable.FireAsyncEvent(String eventName, ParameterCollection extraParams)
   at Terrasoft.UI.WebControls.Controls.ScriptManager.RaisePostBackEvent(String eventArgument)
   at Terrasoft.UI.WebControls.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Form:
    submitAjaxEventConfig: {&quot;config&quot;:{&quot;viewStateMode&quot;:&quot;include&quot;,&quot;extraParams&quot;:{&quot;tag&quot;:&quot;&quot;,&quot;ManagerName&quot;:&quot;SourceCodeSchemaManager&quot;}}}
    __EVENTTARGET: ScriptManager
    __EVENTARGUMENT: AddSourceCodeSchemaMenuItem|event|Click
    __VIEWSTATEFIELDCOUNT: 37
    __VIEWSTATE0:

engineer7,

для детального анализа Вашего кейса необходим доступ к сайту с ошибкой. Направьте нам его, пожалуйста, на почтовый ящик support@bpmonline.com (параметры для входа/удаленного подключения или обезличенный бекап БД)

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