Проблема при использовании базового функционала, при отправке запроса используя сгенерированую форму приходит в ответ следующее:

The server encountered an error processing the request. Please see the service help page for constructing valid requests to the service. The exception message is 'Элемент коллекции с именем BpmSessionId не найден'. See server logs for more details. The exception stack trace is:

at Terrasoft.Core.MetaItemCollection`1.GetByName(String name) at Terrasoft.Configuration.GeneratedWebFormService.GeneratedWebFormService.SaveWebFormLeadData(FormData formData) at SyncInvokeSaveWebFormLeadData(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage31(MessageRpc& rpc) at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)

в cookies запроса в свою очередь sessionid передается, в какую сторону копать?

p.s. sessonid также передается в данных post запроса

Нравится

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

Добрый день!

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

Для более детального анализа прошу обратиться в службу технической поддержки и предоставить информацию о лендинге и версии приложения, а также о том, был развернут новый сайт на 7.7 либо обновлен сайт версии 7.6.
Спасибо!

sales Версия 7.7.0.2284, какая информация нужна о лендинге? да было обновление с 7.6, как проверить и исправить системные настройки?

Олег, добрый день!

Без анализа конкретного сайта и конкретного лендинга невозможно предоставить решение по Вашему запросу.
В связи с этим прошу предоставить в службу технической поддержки следущую информацию:
1. Адрес приложения клиента(желателен доступ к сайту с помощью тестового пользователя либо обезличенная бд сайта).
2. Название лендинга в bpm'online и точный адрес расположения самой формы лендинга.
Также прошу прошу продублировать текст ошибки, возникающей при отправке запроса.

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

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

Существует вопрос с использованием полнотекстового поиска mssql 2014 и bpm 7.x

Вопрос заключается в Задаче:

Необходимо реализовать такую систему поиска, при которой пользователь bpm.online в строке поиска (какая-нибудь кастомная строка поиска) заводит интересующий его запрос.
После запуска поиска пользователем, система должна выдать результаты:
а) по всем соответствующим запросу записям в bpm'online
б) по всем приаттаченым к записям документам(word и т.д.), причем если приложен текстовый документ, поиск должен происходить не только по наименованию, но и по его содержанию.

Существуют ли какие-нибудь решения в этом направлении, подсказки, советы и т.д.
Особенно в пункте "Б".

Нравится

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

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

Просто оставлю здесь эту ссылку.

"Демьяник Алексей" написал:

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

Просто оставлю здесь эту ссылку.

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

У меня стоит задача не покупать/использовать партнерское решение, а найти советы для последующей разработки механизма полнотекстового поиска по документам для конкретного проекта-внедрения. Используя при этом компонент sql full-text search.

Разработали бы отдельный модуль полнотекстового поиска к любому продукту. Думаю, купили бы

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

Полнотекстовый поиск есть в модуле расширенной работы с файлами, тот же самый что и в PT Docs.

Вот страница на комьюнити.
Вот страница в маркетплейс.

Коллеги, обращайтесь!

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

Добрый день коллеги! Я столкнулся с проблемой при работе с бизнес процессом Bpmonline 7.7.0.2111. Ранне в 7.6 в блоке задачи сценарий была переменная UserConnection. В Bpmonline 7.7 этой переменной нет. когда я хочу передать UserConnection, выдает ошибку что являеть тип а не переменная. Как можно достать UserConnection на с# бизнес процесса Bpmonline 7.7 ? См. фото

Нравится

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

UserConnection фото

Можно использовать context.UserConnection, хотя странно, в базовых процессах используется просто UserConnection.

Добрый день!

В версии 7.7 экземпляр типа UserConnection можно получить через метод Get. Например, var userConnection = Get(“UserConnection”);
Следует отметить, что для обращения к параметрам процесса следует также использовать методы Get и Set.
Пример работы с параметрами:
var parameter1 = Get("Parameter1");
Set("Parameter2", parameter1.ToString());
var parameter2 = Get("Parameter2");

Кроме того можно в свойствах элементе "Задание-сценарий" убрать признак [Для интерпретируемого процесса]. В таком случае можно работать с экземплярами аналогично версии 7.6.

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

А как в исходном коде указать параметру тип UserConnection? Раньше можно было так:

public methodName(UserConnection userConnection, string stringParam, ...)
{
...
}

Здравствуйте!
В схемах сервисов принять так:

var userConnection = (UserConnection)HttpContext.Current.Session["UserConnection"];

Это уже есть в базовом сервисе, достаточно унаследоваться от BaseService и будет доступно свойство UserConnection:

public class TestDataService : BaseService

В хелпер класах (которые не сервисы) принято передавать в конструктор при создании:

new RightsHelper(userConnection); 

А внутри использовать тот, который передали

Спасибо, Алексей!

Подскажите пожалуйста, а как присвоить значение параметру типа Файл? Насколько я понимаю Set("Parameter2", "Parameter2"); работает только для строк..

Добрый день!
Конструкция Set("ProcessParameter", someVariable); подходит для всех типов. ProcessParameter – название параметра процесса. someVariable – переменная, созданная ранее в ScriptTask

Олег, здравствуйте!

Так не получается. Код

var webClient = new WebClient();
byte[] imageBytes = webClient.DownloadData("http://93.158.58.239:3333/someimage.jpg");
MemoryStream ms = new MemoryStream(imageBytes);
Set("scanParam", ms);

выдает ошибку

The best overloaded method match for 'Terrasoft.Core.Process.IProcessParameterStore.SetParameterValue(System.Guid, string, string)' has some invalid arguments

Параметр scanParam - типа Файл

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

Какую задачу Вы решаете? Базовые элементы процесса не умеют работать с файлами.

Здравствуйте, Алексей.
Как видно из кода выше, я получаю файл по url. Затем нужно его записать в параметр, чтобы использовать далее по процессу.

"Демьяник Алексей" написал:

Базовые элементы процесса не умеют работать с файлами.

То есть я не смогу записать значение моего файлового параметра в базу, например, с помощью элемента "Изменить данные"?

Элемент "Изменить данные" не умеет работать с типом данных "BLOB". Вы можете добавить файл в бизнес процессе, однако для этого необходимо использовать элемент "Задание сценарий". В нем необходимо реализовать логику добавления файла на деталь. Пример Вы можете найти в схеме ImapClient, метод AddAttachmentToActivity

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

Добрый день

В карточке Инцидента:
Если в поле Заявитель.Инцидент выбран Контакт, где ТИП=Сотрудник, то: поле Происхождение.Инцидент должен автоматически подтягиваться значение из справочника "Обнаружено сотрудником".

Подскажите, пожалуйста, как из Инцидента обратиться к справочнику Контактов, а из него - к справочнику Типов. Заранее спасибо

Нравится

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

Получать значение из другой таблице по Id можно при помощи функции GetEntityTypedColumnValue. Пример её использования.
По Id контакта получаете значение его поля «Тип» и сравниваете с Id записи «Сотрудник» в справочнике типов.

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

Добрый день

Подскажите, как сделать следующее:
при нажатии на ОК в карточке Инцидента поле "План.дата завершения" становилась недоступной для редактирования всеми пользователями системы.

Нравится

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

Недоступность задаётся методом Page.PlanEndDateEdit.SetEnabled(false) у контрола. Можете на при открытии карточки на событии PageLoadComplete проверять нужное условие и в зависимости от этого делать доступным или нет.

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

Добрый день

Если я создаю Активность (Задачу) из Изменения , а к этому Изменению привязано несколько Инцидентов , то:

при нажатии на ОК в Активности нужно подвязать номер Инцидента. А если их несколько, то неудобно заходить на вкладку Инциденты в Изменении и смотреть эти номера. Можно ли при нажатии на ОК в Активности сделать сообщение с выбором этих номеров ? Т.е. я выбираю этот номер Инцидента и он указывается в поле Инцидент.Активность.

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

Нравится

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

Это можно с помощью действия OpenLookupUserTask, вот пример работы с ним.

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

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

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

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

чтобы именно при нажатии на "молнию" срабатывал фильтр?

И как сделать кнопку-молнию в опред.поле?

Кнопка «молния» добавляется в дизайнере карточки как дочерний элемент-кнопка к полю ввода.
Как прописывается логика её наполнения отфильтрованными значениями, см. тут.

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

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

Нравится

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

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

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

Добрый день!

Каким образом в БП (используя элемент Edit access rights желательно) установить права на таблицу с деталями такими же, как у основной записи?
Например, на адреса контрагента такие же, как у самого контрагента (может, не лучший пример, но он далеко не единственный)

Нравится

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

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

Процессом не получится. Давайте рассмотрим на Вашем примере. Предположим объект "Контрагент" администрируется по записям. Вся информация о правах хранится в таблице SysAccountRights.

Для реализации Вашей задачи Вам необходимо включить администрирование по записям для объекта "Средство связи контрагента".

Далее, Вам необходимо на событие "после сохранения записи" (процесс на объекте) либо на событие "после добавления записи"/"после изменения записи" создать бизнес процесс, который:

1) Удалит данные из таблицы SysAccountCommunicationRights для записей из таблицы AccountCommunication, у которых в поле AccountId содержится Id добавленной/измененной записи
2) Скопирует права из таблицы SysAccountRights для измененной/созданной записи в таблицу SysAccountCommunicationRights.

Элементом "Изменить права доступа" решить данную задачу не получится.

"Демьяник Алексей" написал:1) Удалит данные из таблицы SysAccountCommunicationRights для записей из таблицы AccountCommunication, у которых в поле AccountId содержится Id добавленной/измененной записи
2) Скопирует права из таблицы SysAccountRights для измененной/созданной записи в таблицу SysAccountCommunicationRights.

Как я понимаю, эти таблицы в AddData и DeleteData недоступны, и необходимо писать скриптом это всё? Может, есть готовый пример? Не верю, что ни у кого не возникало такой задачи.

И еще вопрос - как отследить, что изменились права на запись Контрагента, если это сделано вручную через Actions / Set up access rights? Чтобы сразу же изменить на подчиненные детали

Добрый день!

Раздавать права следует скриптом. Пример можно посмотреть в схеме RightsHelper (методы GetRecordRights, SetRecordRight).
Отследить изменение прав доступа в Account можно используя триггер в базе данных, при помощи sql запроса изменить права доступа на запись в детали.

Пример триггеров, на которых реализовали данную логику:

ALTER TRIGGER [dbo].[SysAccountRight_AI]
ON [dbo].[SysAccountRight]
AFTER INSERT
AS 
BEGIN
SET NOCOUNT ON;
DECLARE @SysAdminUnitId UNIQUEIDENTIFIER
SELECT @SysAdminUnitId = SysAdminUnitId FROM inserted
INSERT INTO [dbo].[SysAccountAddressRight]
( 
[RecordId]
,[SysAdminUnitId]
,[Operation]
,[RightLevel]
,[Position]
,[SourceId])
SELECT [det].[Id], [mast].[SysAdminUnitId], [mast].[Operation], [mast].[RightLevel], [mast].[Position], [mast].[SourceId] 
FROM [SysAccountRight] as [mast]
JOIN [AccountAddress] AS [det] ON [det].[AccountId] = [mast].[RecordId]
WHERE [mast].[SysAdminUnitId] = @SysAdminUnitId
INSERT INTO [dbo].[SysAccountBillingInfoRight]
( 
[RecordId]
,[SysAdminUnitId]
,[Operation]
,[RightLevel]
,[Position]
,[SourceId])
SELECT [det].[Id], [mast].[SysAdminUnitId], [mast].[Operation], [mast].[RightLevel], [mast].[Position], [mast].[SourceId] 
FROM [SysAccountRight] as [mast]
JOIN [AccountBillingInfo] AS [det] ON [det].[AccountId] = [mast].[RecordId]	
WHERE [mast].[SysAdminUnitId] = @SysAdminUnitId
END
ALTER TRIGGER [dbo].[SysAccountRight_FD]
ON [dbo].[SysAccountRight]
FOR DELETE
AS
BEGIN
SET NOCOUNT ON;
DECLARE @AccountID UNIQUEIDENTIFIER
DECLARE @SysAdminUnitUD UNIQUEIDENTIFIER
DECLARE @Operation INT
SELECT @AccountID = [RecordId] FROM deleted
SELECT @SysAdminUnitUD UNIQUEIDENTIFIER
SELECT @Operation = [Operation] FROM deleted
SELECT @SysAdminUnitUD = [SysAdminUnitId] FROM deleted
DELETE
FROM [dbo].[SysAccountAddressRight]
WHERE [RecordId] IN (SELECT [det].[Id]
FROM [AccountAddress] AS [det]
WHERE [det].[AccountId] = @AccountID)
AND [Operation] = @Operation AND [SysAdminUnitId] = @SysAdminUnitUD
DELETE
FROM [dbo].[SysAccountBillingInfoRight]
WHERE [RecordId] IN (SELECT [det].[Id]
FROM [AccountBillingInfo] AS [det]
WHERE [det].[AccountId] = @AccountID)
AND [Operation] = @Operation AND [SysAdminUnitId] = @SysAdminUnitUD
END
ALTER TRIGGER [dbo].[AccountAddress_AI]
ON [dbo].[AccountAddress]
AFTER INSERT
AS 
BEGIN
SET NOCOUNT ON;
DECLARE @RecordId UNIQUEIDENTIFIER
SELECT @RecordId = Id FROM inserted
DECLARE @SysAdminUnitId UNIQUEIDENTIFIER
SELECT @SysAdminUnitId = Id FROM SysAdminUnit WHERE ContactId = (select CreatedById FROM inserted)
INSERT INTO [dbo].[SysAccountAddressRight]
( 
[RecordId]
,[SysAdminUnitId]
,[Operation]
,[RightLevel]
,[Position]
,[SourceId])
SELECT [mast].[Id], [det].[SysAdminUnitId], [det].[Operation], [det].[RightLevel], [det].[Position], [det].[SourceId] 
FROM [AccountAddress] AS [mast]
JOIN [SysAccountRight] AS [det] ON [det].[RecordId] = [mast].[AccountId]
WHERE [det].[SysAdminUnitId] <> @SysAdminUnitId AND [mast].[Id] = @RecordId
END
Показать все комментарии

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

AddItem()

например:

Page.usrComboBox.AddItem("test1","test1");
Page.usrComboBox.AddItem("test2","test2");
...

вопрос - где в Page.usrComboBox хранятся эти данные?
Спасибо!

Нравится

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

Влад,

Текущее значение можно получить так:

Page.usrComboBox.Value

Или Page.usrComboBox.SelectedItem, а точнее его ключ и значение:
Page.usrComboBox.SelectedItem.Text
Page.usrComboBox.SelectedItem.Value
Плюс отвечая на вопрос по поводу хранения всех данных, если вы не используете источник данных и добавляете значения в ручную, можно их кешировать в какой-то переменной для последующего использования. А выбранное пользователем значение читается как описано выше.

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

usrComboBox.value 

- в данном случае выбрасывает искючение (изза того что value - не uid а string)

Вопрос решен, спасибо!

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

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

Имеется примерно такой запрос:

var newSelect = new Select(CurrentUserConnection)
        .Column("Table1", "Column1").As("Column1")
        .From("Table1").As("Table1")
        .Where("Table1", "Column2").IsNotEqual(  ...  ) as Select;

И имеется некоторая коллекция значений, к примеру:

List myList = new List();

Вопрос в следующем: Каким образом можно в условие запроса передать список значений моей коллекции (будь то Array, ArrayList, List, Dictionary, Hashtable, SortedList или другое - значения не имеет)?

Условно говоря, мне нужно мою коллекцию представить в виде типа "Select", чтобы можно было использовать в месте отмеченном 3-мя точками, - это если следовать сигнатуре этих методов, согласно описанию из SDK (www.terrasoft.ru/bpmonlinesdk/). Но как это сделать? Прошу помощи!

Нравится

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

Виталий, для этого нужно использовать конструкцию .Not().In(массив_или_список_идентификаторов) .
Пример использования (схема EditSynchUserInSynchRole):

var ldapGroupsIds = new List<QueryParameter>();
	var ldapUserLoginAttribute = SysSettings.GetValue(UserConnection, "LDAPUserLoginAttribute").ToString();
	using (var ldapUtils = new LdapUtilities(UserConnection)) {
		var usersCollection = ldapUtils.GetUsersAttributesByFilter(ldapUserLoginAttribute + "=" + ldapEntry, new [] {"distinguishedName"});
		var userDn = string.Empty;
		foreach (SearchResultEntry user in usersCollection) {
			userDn = user.DistinguishedName;
			break;
		}
		var ldapGroupIdentityAttribute = SysSettings.GetValue(UserConnection, "LDAPGroupIdentityAttribute").ToString();
		var groupsCollection = ldapUtils.GetGroupsAttributesByFilter("member=" + userDn, new [] {ldapGroupIdentityAttribute});
		foreach(SearchResultEntry group in groupsCollection) {
			ldapGroupsIds.Add(new QueryParameter(ldapUtils.IdentityAttributeToString(group.Attributes[ldapGroupIdentityAttribute][0])));
		}
	}
 
	if (ldapGroupsIds.Count < 1) {
		return true;
	}
 
	var delete = new Delete(UserConnection).From("SysUserInRole").
	Where("SysUserId").IsEqual(Column.Parameter(userId)).
	And().Exists(new Select(UserConnection).
		Column("Id").From("SysAdminUnit").
		Where("SysUserInRole", "SysRoleId").IsEqual("SysAdminUnit", "Id").
		And("SynchronizeWithLDAP").IsEqual(Column.Parameter(true)).
		And("LDAPEntryId").Not().In(ldapGroupsIds));
	delete.Execute();

Если же передавать массив, то так (схема AdministrativeGrantedRightsGridPage):

	object[] objectParameters = new object[adminUnitCollection.Count];
	for (int i = 0; i < adminUnitCollection.Count; i++) {
		objectParameters[i] = adminUnitCollection[i];
	}
}
var entitySchemaManager = Page.UserConnection.EntitySchemaManager;
var rightsSchema = entitySchemaManager.GetInstanceByName("SysAdminUnitGrantedRight");
var select = new Select(Page.UserConnection)
		.Column(rightsSchema.Name, "Id")
		.Column(rightsSchema.Name, "GrantorSysAdminUnitId")
		.Column("Grantor", "Name").As("GrantorSysAdminUnitName")
	.From(rightsSchema.Name)
	.InnerJoin("SysAdminUnit").As("Grantor").On("Grantor", "Id").IsEqual(rightsSchema.Name, "GrantorSysAdminUnitId")
	.Where(rightsSchema.Name, "GranteeSysAdminUnitId").In(Column.Parameters(objectParameters))
	.OrderByAsc("Grantor", "Name") as Select;

Хм... Честно говоря, если судить по информации из SDK (http://i.piccy.info/i9/fa961117bdc660b65920ae24393d4c3e/1452507140/1535…), то оператор "In()" не принимает произвольную коллекцию, потому и решил переспросить. Во всяком случае, вопрос закрыт. В очередной раз спасибо Вам, Александр!

Я тоже думал, что только массивы из Object, но оказалось, что не только массивы.
В первом примере обратите внимание, что коллекция из элементов именно типа QueryParameter.

А это действительно важно, использовать именно тип "QueryParameter"? Т.е., к примеру:

List<Guid> guids = new List<Guid>();

нельзя использовать? Или тот же тип "string"? В том же SDK есть только такой пример: http://i.piccy.info/i9/7c65675471d92405256ab8d1e300693f/1452512386/1789…

Если следовать этому описанию, то коллекция ГУИДов должна выглядеть так:

List<QueryParameter> guids = new List<QueryParameter>();
guids.Add(new QueryParameter((new Guid("...")).ToString()))

Верно ли это? Тогда я не смогу указать оператор "In()" для колонки, содержащую тип "Guid", т.к. я буду проверять наличие текущей записи в коллекции guids, а у нее QueryParameter содержит тип "string". Что-то тут нечисто... Подскажете, как быть?:confused:

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

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