Вопрос

Добрый день!
 

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

работа идет через DataService, пользователь Supervisor.

иногда в процессе работы выходит ошибка 401.

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

может есть какое-то время жизни токена? или может нужно как-то настроить сайт в иис чтобы не было ошибок?

У меня такой же вопрос

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

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

Без кода трудно понять 

но конечно у каждой сесии (сеанса подключения) есть таймаут

При каждом вызове внешнего сервиса нужно подключать авторизационные кукие как это описанно в статье https://academy.terrasoft.ua/documents/technic-sdk/7-13/rabota-s-obekta… Или для доступа к данным сделать свой анонимный вэб сервис

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

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

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

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

Кроме обычной куки, нужно ещё BPMCSRF.

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

передаем. без этого бы вообще не сработало

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

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

просто в чем странность - иногда через 30 минут выходит ошибка, а иногда и через 4ч нормально работает. вот что непонятно

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

Zaitova Liubov,

Здравствуйте. не забывайте, что куки авторизации действительны определенное время. Например Вы аторизировались под Supervisor "покидали" некие запросы в срм и потом на протяжении 1 часа действий со стороны Вашего приложения не происходило то тогда Ваши куки устаревают, если мене не изменяет память, по умолчанию таймаут сеанса пользователя составляет 20-30 мин. Данную настройку можно редактировать в профиле пользователя системы. 

http://prntscr.com/l7fu09

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

Здравствуйте! Интересует вопрос по интеграции с телефонией Asterisk. в статье https://academy.terrasoft.ru/documents/sales-team/7-10/sravnenie-vozmoz… обнаружил, что у Asterisk нет возможности принимать входящие звонки.

Можно будет ли доработать функционал для принятия звонков?

Поскольку для интеграции необходимо установить Terrasoft Messaging Service ,какое дополнительное оборудование придется приобретать?

И какой коннектор лучше использовать? (Asterisk, или коннектор к любой ip телефонии)

 

Спасибо!

У меня такой же вопрос

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

Чесноков Егор, 

да, там только пакет с коннектором устанавливается. Но нужно понимать, что в системе будут сохранятся только те звонки, которые прошли когда у пользователя была открыта bpm'online. Если этого недостаточно, то смотрите в сторону webitel call manager. Но это АТС, которую все равно необходимо настраивать. 

Используйте Webitel AnyVoip как транспорт. Вместо коннектора Asterisk. 

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

Я правильно понимаю, что при использовании этого коннектора мы можем обойтись без TMS?

Чесноков Егор, 

да, там только пакет с коннектором устанавливается. Но нужно понимать, что в системе будут сохранятся только те звонки, которые прошли когда у пользователя была открыта bpm'online. Если этого недостаточно, то смотрите в сторону webitel call manager. Но это АТС, которую все равно необходимо настраивать. 

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

Спасибо!

По настройке Asterisk есть отдельная статья. Terrasoft Messaging Service ставится на сервер под Windows.

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

Добрый день! 
Появилась необходимость изменить базовое поле поиска, при выборе в окне справочного поля, и подставить туда своё значение.
Как это выглядит на примере:

 

При открытии данного модального окна, должно быть своё предустановленное значение
Вопрос в том, как это реализовать. 

Поиски не увенчались успехом, застопорился на схеме LookupPage.js

var primaryDisplayColumn = entitySchema.primaryDisplayColumn;
if (primaryDisplayColumn) {
	this.lookupInfo.searchColumn = {
		value: primaryDisplayColumn.name,
		displayValue: primaryDisplayColumn.caption
	};
}

Значение для данной колонки берётся отсюда, но как его подменять для определённого поля - не сообразил

У меня такой же вопрос

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

В lookupListConfig просто укажи searchValue, пример:

columns: ["Id", "Name"],
searchValue: "Вериф",
columnName: "Name",
orders: [{
   columnPath: "Name",
   direction: Terrasoft.OrderDirection.ASC
}],

 

В lookupListConfig просто укажи searchValue, пример:

columns: ["Id", "Name"],
searchValue: "Вериф",
columnName: "Name",
orders: [{
   columnPath: "Name",
   direction: Terrasoft.OrderDirection.ASC
}],

 

Григорий Чех, columnName упорно изменяться не хочет. А именно значение в списке слева на первом скрине

Покажите свой код

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

"Gun": {
   "dataValueType": Terrasoft.DataValueType.LOOKUP,
   "lookupListConfig": {
      columns: ["LkpGauges", "UsrConfigProduct"],
      searchValue: "Вериф", // Вот это работает, в инпуте value заполняется
      columnName: "UsrConfigProduct",
      orders: [{
          columnPath: "UsrConfigProduct"
          direction: Terrasoft.OrderDirection.ASC
      }],
      "filters": [ //Фильтры ]
   }
}

 

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

Это справочное поле, не уверен, что сыграет роль. Но на всякий случай скажу. 

И еще, поле над которым производится действие, является полем в детали с редактируемым реестром

Это интересно. Т.е. теоретически можно прокинуть searchColumn в lookupInfo, но если у объекта есть колонка для отображения - всё перетрется.

варианта 2:

- Доделывать Lookup-модуль

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

 

Попробуйте так

"Gun": {
   "lookupListConfig": {
      searchValue: "Вериф",
      searchColumn: "UsrConfigProduct"
   }
}

 

Варфоломеев Данила,

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

Самое интересное в том, что у меня получалось прокинуть значения. Но при обращении к lookupinfo он забирает все равно свои значения, которые получил из схемы ConfItem.js (куда ссылается справочное поле). И там прописано поле для отображения
(PrimaryDisplayColumnName)

 

Варфоломеев Данила,

пробовал и так - не работает... 

Попробуй переопределить loadVocabulary как то так\:

loadVocabulary: function(args, tag) {
    var column = this.getColumnByName(tag);
    args.schemaName = column.referenceSchemaName; //подставь свой
     this.callParent(arguments);
 }

Если не получится отпишись, вечером смогу проєксперементировать.

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

не совсем понял, что менять. Однако там все равно схема (ConfItem) по которой открытие справочника производится, я думаю, что её подменить можно, но это не то, что мы ищем

Прокинуть как-то туда primaryDisplayColumnName, у меня не увенчалось успехом

VadimCh пишет:
Однако там все равно схема (ConfItem) по которой открытие справочника производится

 Я немного неправильно описал.
Схема ConfItem генерится на основании объекта в конфигурации. На ConfItem ссылается справочное поле, которое вы пытаетесь открыть. Соответственно и берется PrimaryDisplayColumnName из ConfItem. Те 2 варианта так и остаются: либо менять PrimaryDisplayColumnName в null в каждом объекте на которое ссылается нужное вам справочное поле, либо переделать логику LookupPage.

Варфоломеев Данила,

В рамках реализации задачи, заместил LookupPage, и переработал тот кусок кода, который скидывал в посте, и присоединил новую схему

"lookupListConfig": {
  lookupPageName: "KmFiltrationBaseLookup",
}

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

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

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

Как можно вызвать ре-калькуляцию полей "Итого", "Скидка, %". В коробке данная функция выполняется при смене фокуса поля после редактирования

У меня такой же вопрос

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

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

Например такой вариант

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

2)Получив в детали событие скидка поменялась делите суммарную скидку на количество продуктов (строк) -это если я правильно понял ваш алгоритм. Пересчитываете зависимые поля в детали ("Итого", "Скидка, %").

Если не понятно как какой то пункт сделать пишите вопросы.

 

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

Например такой вариант

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

2)Получив в детали событие скидка поменялась делите суммарную скидку на количество продуктов (строк) -это если я правильно понял ваш алгоритм. Пересчитываете зависимые поля в детали ("Итого", "Скидка, %").

Если не понятно как какой то пункт сделать пишите вопросы.

 

Григорий Чех пишет:
Если не понятно как какой то пункт сделать

Спасибо за ваш ответ. Действительно не совсем понятно...

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

я правильно понял?

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

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

Добрый день! 

Возникла проблема с обработкой ответа в массиве, при вызове веб-сервиса через стандартный элемент в бизнес-процессе.

В настройках раздела "Веб-сервисы" есть деталь "Методы сервиса", при настройке обработки ответа, есть поле "Является массивом", при его активации, в бизнес-процессе возможность записать данный ответ в параметр БП для дальнейшей обработки представляет возможным только с типом данных "Коллекция значений с атрибутами", и соответственно разобрать это можно только с помощью "Задания-сценарий"

Пример настройки ответа:
 

Вопрос, как разобрать обработанный ответ?

Как я понял, нужно обращаться к ICompositeObjectList, но совсем не понятно, как это работает...

Пример ответа (Для каждого контакта поля в выборке id, name, phone):

 

 

У меня такой же вопрос

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

Вам нужен пример, как эти данные в коде обработать?

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

Литвинко Павел,
Да. А если ещё конкретнее, то пример, как разобрать массив уже "обработанный" стандартными возможностями обработки ответа (первый скрин).

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

По скольку в академии этот вопрос "опущен", но такая необходимость возникает. Сейчас в стандартном поле "Ответ сервиса" непонятный html документ вываливается, даже без данного массива, но HTTP ответ 200

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

если бы одну, то проблем бы конечно было меньше, но интересует выборка большого кол-ва данных

да, тоже такого варианта придерживаюсь "Можно ещё попробовать считать всё внутри квадратных скобок в одну большую текстовую переменную, а потом разбирать программно в скрипте"

Но, сейчас в ответе сервиса html документ без данного ответа но с кодом 200, и также интересно, что же все таки возвращает эта настройка обработки ответа, та, что на первом скрине

Посмотреть, что вообще пришло в ответ, можно в Fiddler (если сайт поднят локально). Может, что-то изменилось и во входящих параметрах и возвращаемый массив стал пустым?

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

Действительно, пересобрал сейчас - заработало, видимо что-то пропустил)
То есть Fiddler должен вернуть обработанный ответ? 

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

https://academy.terrasoft.ru/api/netcoreapi/7.12.0/Terrasoft.Common~Ter…

 

Fiddler позволяет посмотреть, какие запросы и ответы ходили по HTTP.

В 7.13 эту коллекцию можно будет обработать в интерфейсе, там доработали возможность для ответов-массивов. Документация должна появиться после релиза. В 7.12, где эта галочка впервые появилась, — только кодом, но готовых примеров тоже нет. Также, сомневаюсь, что любая автоматизация сумеет разобрать строку на 4 поля по разделителям вроде «Phone: » (разве что делать элементами-формулами), так что перебирать в скрипте всё равно потребуется.

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

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

У меня такой же вопрос

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

В мобильном приложении это делается кодом на странице. См. тут, свойство «readOnly».

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

О деталях ещё есть такая статья.

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

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

Есть инструкция по созданию пользовательского виджета итогов: https://academy.terrasoft.ru/documents/technic-sdk/7-10/dobavlenie-polz…

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

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

Возможно, есть какие-то примеры решения подобных задач?

У меня такой же вопрос

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

Добрый день, можете посмотреть данное дополнение https://marketplace.terrasoft.ru/app/calculated-metrics-bpmonline либо оно закроет вашу нужду, либо на его основе можете сделать свое решение

Добрый день, можете посмотреть данное дополнение https://marketplace.terrasoft.ru/app/calculated-metrics-bpmonline либо оно закроет вашу нужду, либо на его основе можете сделать свое решение

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

Добрый день!
Появилась следующая задача: фильтровать список ответственных, когда выбирается группа ответственных. Также подставлять группу, при выборе ответственного. Вроде как такая логика заложена в базовую конфигурацию onPrepareOwner, но не получается разобраться в ней. 

У меня такой же вопрос

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

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

Было в сервисе в CasePage (Case)

Сергей,

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

 

 

 

Сергей,

Есть 2 вопроса:

1. Что такое группа ответственных - это группа пользователей? Объясните на примере.

2. В какой схеме реализована эта логика (onPrepareOwner) и какие именно вопросы есть по её реализации? 

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

Было в сервисе в CasePage (Case)

Сергей,

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

 

 

 

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

Группа ответственных - это группа пользователей (подразделение в оргструктуре). В ней находятся пользователи и они становятся ответственными.

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

Да, метод смотрел, но я так понимаю там не он один нужен. Ну и сама суть - метод же именно то что мне нужно, но при копировании его просто так - чуда не происходит

Фильтрация может настраиваться как пользовательскими средствами, через бизнес-правила, так и кодом. Подробнее описано тут.

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

Есть ли в консоли какие-то ошибки при попытке проверить эту функциональность?

И приведите, пожалуйста, пример своего кода.

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

Пытаюсь действовать по примеру:

"attributes": {
// Колонка модели представления.
   "Owner": {
// Тип данных атрибута.
      "dataValueType": Terrasoft.DataValueType.LOOKUP,
// Конфигурационный объект атрибута типа LOOKUP.
      "lookupListConfig": {
// Массив фильтров, применяемых к запросу для формирования данных поля-справочника.
         "filters": [
            function() {
               var group = this.get("Group");
               var filterGroup = Ext.create("Terrasoft.FilterGroup");
// Добавление фильтра "IsUser" в результирующую коллекцию фильтров.
// Выбирает все записи из корневой схемы Contact, к которой присоединена
// колонка Id из схемы SysAdminUnit, для которых Id не равен null.
               filterGroup.add("IsUser",
               Terrasoft.createColumnIsNotNullFilter("[SysAdminUnit:Contact].Id"));
// Добавление фильтра "InGroup" в результирующую коллекцию фильтров.
// Выбирает все записи из корневой схемы Contact, к которой присоединена
// колонка из схемы SysAdminUnitRole.
               filterGroup.add("InGroup",
               Terrasoft.createColumnFilterWithParameter(
               Terrasoft.ComparisonType.EQUAL,
               "[SysAdminUnitInRole:SysAdminUnit:Contact].SysAdminUnitRoleID",
               group));
               return filterGroup;
           }
        ]
   }
}

Я уверен на 99% что так делать нельзя, но уже не представляю как связать SysAdminUnit между собой, чтобы происходила фильтрация. Неужели никто с такой задачей не сталкивался?

Для начала можно написать обычный SQL-запрос, который получает интересующие значения. А потом думать, как его перевести на язык ESQ с фильтрами или бизнес-правил.

"Owner": {
	"dataValueType": Terrasoft.DataValueType.LOOKUP,
	// Конфигурационный объект атрибута типа LOOKUP.
	"lookupListConfig": {
		// Данный фильтр отображает ответственных из группы
		"filters": [
			function() {
				var filterGroup = Ext.create("Terrasoft.FilterGroup");
				if (this.get("Group") != null) {
					filterGroup.add("IsActive", Terrasoft.createColumnFilterWithParameter(3, "[SysAdminUnit:Contact].[SysUserInRole:SysUser].SysRole.Id", this.get("Group").value));				
					return filterGroup;
				}
			}
		]
	}
}

Вышло такое. Оно работает. Может кому понадобится. Спасибо https://community.terrasoft.ru/questions/filtr-pola-kontakt-po-funkcion… 

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

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

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

Тест ошибки в журнале:

System.ArgumentException: user does not have mail account
   в Terrasoft.Core.Process.SyncImapMail.ScriptTask1Execute(ProcessExecutingContext context)
   в Terrasoft.Core.Process.ProcessScriptTask.InternalExecute(ProcessExecutingContext context)
   в Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

У меня такой же вопрос

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

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

Для решения необходимо выполнить следующий скрипт:

delete from QRTZ_TRIGGERS 
where (TRIGGER_GROUP = 'imap' or TRIGGER_GROUP = 'exchange')
and (TRIGGER_NAME like '%UId%')

Где UId - пользователя (не контакта) у которого возникает ошибка.

Спасибо, проблема решена!

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

Здравствуйте!
Помогите, пожалуйста, разобраться с проблемой, как объединить фильтрацию и сортировку в oData?

фильтрация - работает

http://url/0/ServiceModel/EntityDataService.svc/ContactCollection?$sele…

сортировка- работает

http://1url/0/ServiceModel/EntityDataService.svc/ContactCollection?$select=Name&$orderby=Name

сортировка и фильтрация- НЕ работает
http://url/0/ServiceModel/EntityDataService.svc/ContactCollection?$sele…

выходит ошибка

 

<error xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">

<code>4</code>

<message xml:lang="">

The query parameter '$orderBy' begins with a system-reserved '$' character but is not recognized.

</message>

<innererror>

<message>

The query parameter '$orderBy' begins with a system-reserved '$' character but is not recognized.

</message>

<type>System.Data.Services.DataServiceException</type>

<stacktrace>

at System.Data.Services.HttpContextServiceHost.VerifyQueryParameters() at System.Data.Services.DataServiceHostWrapper.VerifyQueryParameters() at System.Data.Services.DataService`1.ProcessIncomingRequestUri() at System.Data.Services.DataService`1.HandleRequest()

</stacktrace>

</innererror>

</error>

 

не могу понять что не так.

У меня такой же вопрос

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

Проверьте такой вариант у меня ошибки нет

http://127.0.0.1:520/0/ServiceModel/EntityDataService.svc/ContactCollection?$select=Name&$orderby=Name&$filter=Phone ne '12'

 

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

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

http://url/0/ServiceModel/EntityDataService.svc/ContactCollection?($sel…)  - вот так не работает, а с запятыми - просто не фильтрует

 

Проверьте такой вариант у меня ошибки нет

http://127.0.0.1:520/0/ServiceModel/EntityDataService.svc/ContactCollection?$select=Name&$orderby=Name&$filter=Phone ne '12'

 

Григорий Чех, да, спасибо, заработало

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