Доброго времени суток!

Есть Бп в кором я выбираю коллекцию записей из Продукт в счете, для того чтоб потом их передать в 1с в формате json. Мне нужно выбрать поле "Code" из Продуктов чтоб потом записать  его отдельно. Выбрать я его смогла, проблема в том что я не понимаю в каком формате его нужно передать (коллекция записей?).  Буду благодарна за помощь.

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

Нравится

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

Добрый день, Анастасия.



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



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



Подготовил несколько полезных ссылок с академии, в которых происходит работа с коллекциями внутри скрипттаски. Вы можете получать две такие коллекции, а потом с помощью C# создать свою коллекцию кастомных объектов(предварительно создав этот объект в конфигурации), где и объединять их. После записать данную коллекцию кастомных объектов в параметр процесса и с него брать значения для сервиса. Таким образом у Вас будет только один источник данных.

Либо же прямо в скрипттаске использовать запросы к БД, например, через EntitySchemaQuery и внутри вызывать веб-сервис с параметрами.



https://community.terrasoft.ru/questions/rabota-s-kollekciyami-v-bp

https://academy.terrasoft.ru/docs/7-16/developer/back-end_development/operatsii_s_dannymi_back_end/dostup_k_dannym_cherez_orm#reference-2158

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

Каким инструментом можно визуализировать коллекцию?

 

В БП я получаю коллекцию записей, которые надо показать пользователю. Эти данные не хранятся в системе. Я придумал следующую схему: создал объект в конфигураторе с такими же колонками как и у коллекции, заполняю этот объект при обходе коллекции, потом вывожу на страницу деталь с объектом. После закрытия страницы очищаю объект. Также тут возможна проблема при одновременной работе нескольких пользователей с данным объектом, надо фильтровать записи по ID запущенного процеса.



Вопрос: есть ли способ реализовать это все проще?

Нравится

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

В 7.18.1 обещали сделать что-то подобное, но интересно как оно будет работать на деле. https://academy.terrasoft.ru/docs/release/opisanie-relizov/opisanie-rel…

 

Появилась возможность работать с коллекциями записей в элементах [ Преднастроенная страница ] и [ Выполнить действие процесса ]. Это позволит передавать в параметрах списки записей, например, чтобы заполнить деталь на преднастроенной странице. Чтобы использовать функциональность в дизайнере процессов, необходимо в разделе [ Конфигурация ] добавить и настроить параметр “Коллекция записей” для нужного элемента.

В 7.18.1 обещали сделать что-то подобное, но интересно как оно будет работать на деле. https://academy.terrasoft.ru/docs/release/opisanie-relizov/opisanie-rel…

 

Появилась возможность работать с коллекциями записей в элементах [ Преднастроенная страница ] и [ Выполнить действие процесса ]. Это позволит передавать в параметрах списки записей, например, чтобы заполнить деталь на преднастроенной странице. Чтобы использовать функциональность в дизайнере процессов, необходимо в разделе [ Конфигурация ] добавить и настроить параметр “Коллекция записей” для нужного элемента.

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

Здравствуйте. Подскажите пожалуйста, как можно преобразовать коллекцию записей в строку в бизнес-процессе и эту строку записать в одно текстовое поле?

Нравится

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

Добрый день.

 

Можно обработать коллекцию программно в элементе 'Задание-сценарий', а можно через подпроцесс обработки коллекции, в который Вы из главного процесса в дочерний будете передавать параметр строка и в него каждый раз будете дописывать нужное значение через элемент формула.

Подробнее об обработке коллекции в процессе можно почитать на Академии в этой статье.

У меня сделано так. Нужны только email, вот они в строку и записываются.

 

Guid commTypeId = new Guid("EE1C85C3-CFCB-DF11-9B2A-001D60E938C6");
var respGroupId = Get<Guid>("ObjectOwnerGroup");
string emails ="";
Select selectQuery = new Select(UserConnection)
                    .Column("Number")
                    .From("ContactCommunication")
                    .Join(JoinType.LeftOuter, "SysAdminUnit")
                    .On("SysAdminUnit","ContactId").IsEqual("ContactCommunication", "ContactId")
                    	.And("ContactCommunication", "NonActual").IsEqual(Terrasoft.Core.DB.Column.Parameter(0))
                    	.And("ContactCommunication", "CommunicationTypeId").IsEqual(Terrasoft.Core.DB.Column.Parameter(commTypeId))
                    .Join(JoinType.LeftOuter, "SysUserInRole")
                    .On("SysAdminUnit", "Id").IsEqual("SysUserInRole", "SysUserId")
                    	.And("SysAdminUnit","Active").IsEqual(Terrasoft.Core.DB.Column.Parameter(1))
                    .Where("SysUserInRole", "SysRoleId").IsEqual(Terrasoft.Core.DB.Column.Parameter(respGroupId))
                    .And("ContactCommunication", "Number").Not().IsNull() as Select;
// Выполнение запроса к базе данных и получение результирующего набора данных.
using (DBExecutor dbExecutor = UserConnection.EnsureDBConnection())
{
    using (IDataReader reader = selectQuery.ExecuteReader(dbExecutor))
    {
        while (reader.Read())
        {
        	emails = emails + ", " + reader.GetColumnValue<string>("Number");
            // Обработка результатов запроса.
        }
    }
} 
Set("ObjectOwnerGroupMail", emails);
return true;

 

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

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

Подскажите пожалуйста, где ошибка. В БД данные есть

Нравится

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

1) Название объекта не "AccountOwnerShip" а "AccountOwnership"

2) В объекте "AccountOwnership" нет колонки "AccountAccountOwnershipType"

Здравствуйте! Какую ошибку возвращает, что в errorInfo?

1) Название объекта не "AccountOwnerShip" а "AccountOwnership"

2) В объекте "AccountOwnership" нет колонки "AccountAccountOwnershipType"

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

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

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

 

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

 

Для этого необходимо создать процесс с двумя элементами: 

1. Элемент [Читать коллекцию] контактов у которых сегодня день рождения

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

2. Элемент [Подпроцесс] в который передать коллекцию контактов которых нужно поздравить.

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

 

В самом же подпроцессе необходимо создать параметр процесса который соответствует отдельному элементу коллекции, в нашем случае это контакт: 

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

 

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

Нравится

Поделиться

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

Всем привет.

Используется BPMonline Bank Sales Версия 7.5.0.1275
Возникает проблема с параметром процесса типа Коллекция. Диаграмма процесса приложена.

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

System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: Значение индекса находится вне допустимого диапазона значений
   at Terrasoft.Core.Entities.EntityCollection.FindNodeByIndex(Int32 index)
   at Terrasoft.Core.Process.BirthdayQuery.ScriptTask2Execute(ProcessExecutingContext context)
   at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Индекс при этом равен 1. То есть, от коллекции, похоже, осталась только одна запись.

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

Код сценария Выборка данных у кого ДР

        var esqBirthdays = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Contact");
        contactIdFieldName = esqBirthdays.AddColumn("Id").Name;
        esqBirthdays.AddColumn("GivenName");
        esqBirthdays.AddColumn("MiddleName");
               
        esqBirthdays.IsDistinct = true;
                       
        //Получение сегодняшней даты
         today = DateTime.Today;
       
        var esqMacrosTypeMonth = EntitySchemaQueryMacrosType.Month;
        var esqFilterByMonth = esqBirthdays.CreateFilter(FilterComparisonType.Equal, "BirthDate", esqMacrosTypeMonth, today.Month);
        esqBirthdays.Filters.Add(esqFilterByMonth);
               
        var esqMacrosTypeDay = EntitySchemaQueryMacrosType.DayOfMonth;
        var esqFilterByDayToday = esqBirthdays.CreateFilter(FilterComparisonType.Equal, "BirthDate", esqMacrosTypeDay, today.Day);
        esqBirthdays.Filters.Add(esqFilterByDayToday);
       
        //Есть моб тел?
        var esqFilterWithMobilePhone = esqBirthdays.CreateFilterWithParameters(FilterComparisonType.Equal, "[ContactCommunication:Contact].CommunicationType", new Guid("F039972E-470E-457F-9B77-65054B3534B0"));
        esqBirthdays.Filters.Add(esqFilterWithMobilePhone);
       
        //Выполнение запроса и получение результирующей коллекции
        entitiesBD = esqBirthdays.GetEntityCollection(UserConnection);
    numberOfentitiesBDInCollection = entitiesBD.Count;
        currentIndexBD = 0;
        esqSqlText = esqBirthdays.GetSelectQuery(UserConnection).GetSqlText();
               
        return true;

Код сценария Формирования текста СМС и номера

        Entity element = entitiesBD[currentIndexBD];
        Guid contactID = element.GetTypedColumnValueGuid>(contactIdFieldName);
    string contactName = element.GetTypedColumnValuestring>("GivenName");
        string contactMiddleName = element.GetTypedColumnValuestring>("MiddleName");
        string BirthDateText = DateTime.Today.ToString("dd MMMM");
        string messageText = "Дорогой(ая) "+contactName+"! Росинбанк поздравляет Вас с Днем Рождения "+BirthDateText+"  и желает Вам всех благ! Росинбанк";
        if(contactMiddleName!=null) messageText = "Дорогой(ая) "+contactName+" "+contactMiddleName+"! Росинбанк поздравляет Вас с Днем Рождения "+BirthDateText+"  и желает Вам всех благ! Росинбанк";
        SMSTextBD = messageText;
       
        var contactComm = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "ContactCommunication");
        var contacctNumberFieldName = contactComm.AddColumn("Number").Name;
       
        var esqFilter1 = contactComm.CreateFilterWithParameters(FilterComparisonType.Equal, "Contact", contactID);
        contactComm.Filters.Add(esqFilter1);
       
        var esqFilter2 = contactComm.CreateFilterWithParameters(FilterComparisonType.Equal, "CommunicationType", new Guid("F039972E-470E-457F-9B77-65054B3534B0"));
        contactComm.Filters.Add(esqFilter2);
       
        var mobilePhoneCollection = contactComm.GetEntityCollection(UserConnection);
        if(mobilePhoneCollection.Count>0)
        {
        phoneNumberBD = mobilePhoneCollection[0].GetTypedColumnValuestring>(contacctNumberFieldName);
        } else
        {
        phoneNumberBD = "No number";
        }
       
        //var SMSObject = new SendSMSClass(SMSServiceAddress);
        //SMSObject.SendSMS(phoneNumber, messageText);

return true;   
csharp>

Нравится

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

Добрый день!
Попробуйте выполнять проверку и автоинкремент индекса в элементе “Задание сценарий”. Например,

if(IndexBD < entitiesBD.Count){
...
IndexBD++;
} else {
...
}
return true;

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

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

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

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, хоть и приводится к строке.

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