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

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

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

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

Добрый день!

Подскажите, как в 5-ке вывести всплывающее окно (уведомление) пользователю? Аналог в 7-ке - это:

showOrderInfo: function() {
    var activeRowId = this.get("ActiveRow");
    var gridData = this.get("GridData");
    var dueDate = gridData.get(activeRowId).get("Date");
    this.showInformationDialog(dueDate);
}

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

Нравится

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

Вам подойдет следующий способ отсюда:

http://www.community.terrasoft.ru/forum/topic/11784

"Вильшанский Дмитрий" написал:

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

Создаем скрипт подготовки и Действие процесса "Открыть окно сообщения"

Пишем в скрипте:

InfoMessageUserTask.Page = Page;

InfoMessageUserTask.Icon = "INFORMATION";

InfoMessageUserTask.Buttons = "OK";

InfoMessageUserTask.MessageText = "Тариф успешно заведен в Bill-Master";

*не забываем использовать Localizible strings

Также можно сделать следующим образом:

InfoMessageUserTask.ResponseMessages = new Dictionary<string, string> {{"ok", "SomeMessage"}}  Генерация сообщения SomeMessage по нажатию кнопки ok

Увы, это способ я находил... Я потому и создал новый пост, чтобы узнать, есть ли другой способ, к примеру, не создавая "Действие процесса". И, насколько я понял, одними средствами C# это сделать не получится. Но спасибо всё равно, что уделили время моему вопросу!

Средствами C# сделать можно всё. То же действие «Открыть окно сообщения» можно создать и выполнить программно.

Пример из ApprovalInServiceRequestEditPage:

var openMessageWindow = new QuestionUserTask(UserConnection); 
openMessageWindow.Page = Page;
openMessageWindow.ProcessInstanceId = InstanceUId;
openMessageWindow.MessageText = ServiceApprovalNotFindedMessage;
openMessageWindow.Buttons = "OK";
openMessageWindow.Icon = "INFO";
openMessageWindow.ResponseMessages = new Dictionary<string, string> {
      	{"ok", "ClosePageMessage"},
};
openMessageWindow.Execute(context);

Александр - очень признателен за ответ: как раз то, что надо! Спасибо, что всегда выручаете!!! С наступающим Вас праздником!)

Виталий, Вам тоже хороших праздников!

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

На сторінці реєстру звернень добавив кнопку, прописав назву, встановив відступ і опублікував схему.
Після чого не зміг відкрити схему в дизайнері.
Дає
Exception Message: Ссылка на объект не указывает на экземпляр объекта.
Exception Type: System.NullReferenceException
Exception Source: Terrasoft.UI.WebControls

Виявилось, що я не можу взагалі жодної сторінки відкрити в дизайнері, - всюди те саме.

І що то воно таке ?

error.txt

Нравится

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

Деякі сторінки все ж відкриваються:
Cостояния запросов на обслуживание
Cостояния инцидентов

Потім пачка базових сторінок відкривається, але починаючи з "Базовая страница редактирования" - помилка.

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

Схема сторінки виявилась битою, не вистачало цілої купи методів (це з того, що вдалося помітити)
Це спотворило весь згенерований C#-текст схеми.

Відновлювався з нічної бази, тож видно було, що схема бита задовго до створення кнопки.
Кнопку я добавляв на робочій, просто, щоб перевірити, що все ок, перед заливкою оновлень.
Тож опісля всі оновлення залив. Те, що добавив - працює.

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

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

Добрый день! Подскажите, пожалуйста, как корректно внести изменения в процесс выполнения рассылки.
Задача такая, если тип рассылки - Рассылка смс, то емайл для всех адресатов один и тот же, тема - код + мобильный номер контакта, и тема письма с дополнениями.
Вношу изменения в процесс :
var manager = UserConnection.GetSchemaManager("EntitySchemaManager") as EntitySchemaManager;
SetMassMailingStatus(MassMailingId, new Guid("ED5F422E-F46B-1410-6590-1C6F65E24BE8"), manager, this.UId);//В работе
Dictionary macrosDictionary = new Dictionary();
PrepareMailSubjectAndBody(manager);
var targetEntitySchemaQuery = new EntitySchemaQuery(manager, "MassMailingContact");
var idMailing = targetEntitySchemaQuery.AddColumn("Id").Name;
var idMassMailing = targetEntitySchemaQuery.AddColumn("MassMailing").Name;

// здесь определяю, если id рассылки для смс, то emailOfMailing или один, или берется у контакта
if (idMassMailing == "c6d6980b-20c3-4b07-8fe9-a2cd44641f7c") {
var emailOfMailing = "sms@massreach.com";
} else {
var emailOfMailing = targetEntitySchemaQuery.AddColumn("Email.Number").Name;
}

var MobilePhoneOfMailing = targetEntitySchemaQuery.AddColumn("MobilePhone.Number").Name;
//var emailOfMailing = targetEntitySchemaQuery.AddColumn("Email.Number").Name;
var accountOwnership = targetEntitySchemaQuery.AddColumn("Contact.Account.Ownership.Name").Name;
var idContactOfMailing = targetEntitySchemaQuery.AddColumn("Contact.Id").Name;
var contactNameOfMailing = targetEntitySchemaQuery.AddColumn("Contact.Name").Name;
var contactGenderNameOfMailing = targetEntitySchemaQuery.AddColumn("Contact.Gender.Name").Name;
targetEntitySchemaQuery.Filters.Add(targetEntitySchemaQuery.CreateFilterWithParameters(FilterComparisonType.Equal, "MassMailing.Id", MassMailingId));
var listFilter = new EntitySchemaQueryFilterCollection(targetEntitySchemaQuery, LogicalOperationStrict.Or);
listFilter.Add(targetEntitySchemaQuery.CreateIsNullFilter("SendStatus"));
listFilter.Add(targetEntitySchemaQuery.CreateFilterWithParameters(FilterComparisonType.NotEqual, "SendStatus", new Guid("8074FFC0-6107-E011-A646-16D83CAB0980")));
targetEntitySchemaQuery.Filters.Add(listFilter);
var mailingCollection = targetEntitySchemaQuery.GetEntityCollection(UserConnection);
var credentials = new MailCredentials() {
Host = GetSysSettingsValue("SmtpHost"),
Port = Convert.ToInt32(GetSysSettingsValue("SmtpPort")),
UserName = GetSysSettingsValue("SmtpUserName"),
UserPassword = GetSysSettingsValue("SmtpUserPassword"),
};
int smtpTimeout = int.Parse(Terrasoft.Core.Configuration.SysSettings.GetValue(UserConnection, "SmtpTimeout").ToString());
if (smtpTimeout 35) {
smtpTimeout = 35000;
} else {
smtpTimeout *= 1000;
}
credentials.Timeout = smtpTimeout;
object enableSsl = Terrasoft.Core.Configuration.SysSettings.GetValue(UserConnection, "SmtpEnableSsl");
if (enableSsl != null) {
credentials.UseSsl = (bool)enableSsl;
}
var mailClient = new Terrasoft.Mail.SmtpClient(UserConnection, credentials);
foreach (var mailingMacros in mailingCollection) {
Guid targetId = mailingMacros.GetTypedColumnValue(idMailing);
string recepient = mailingMacros.GetTypedColumnValue(emailOfMailing);
if(string.IsNullOrEmpty(recepient)) {
continue;
}
Guid contactId = mailingMacros.GetTypedColumnValue(idContactOfMailing);
ErrorCode = "None";
MacrosHelper.UserConnection = UserConnection;

//аналогично для body
if (idMassMailing == "c6d6980b-20c3-4b07-8fe9-a2cd44641f7c") {
Body = "[Sender]itcol[/Sender][SMS]" + body +"[/SMS]";
} else {
string body = MacrosHelper.ProcessText(
MailBody,
UserConnection.CurrentUser.ContactId,
contactId);
}

string body = MacrosHelper.ProcessText(
MailBody,
UserConnection.CurrentUser.ContactId,
contactId);

//аналогично для title
if (idMassMailing == "c6d6980b-20c3-4b07-8fe9-a2cd44641f7c") {
string title = "794dcc7c3a404454 "+ MobilePhoneOfMailing;
} else {
string title = MailSubject;
}

// string title = MailSubject;
string from = GetSysSettingsValue("MassMailingFromAddress");
MailMessage message = null;
try {
message = new MailMessage {

Subject = title,
Charset = "utf-8",

BodyHtmlText = body,
From = new EmailAddress {
AsString = from
}
};
message.To.Add(new EmailAddress {
AsString = recepient.Trim()
});
FillAttachments(MassMailingId, message.Attachments);
} catch (FormatException e) {
throw new SmtpException("ErrorOnSend", e.Message, e);
}
string mailCodeId = String.Empty;
if (ErrorCode.Equals("None")) {
try {
mailClient.SendMessage(message);
} catch (Exception e) {
ErrorCode = e.Message;
}
}
SetMassMailingContactSendStatus(ErrorCode, targetId, manager);
}
SetMassMailingStatus(MassMailingId, new Guid("FF7F4232-F46B-1410-6690-1C6F65E24BE8"), manager, Guid.Empty);//Завершена
return true;

При компиляции получаю, что имя emailOfMailing отсутствует в текущем контексте, стока ошибки вот эта:
string recepient = mailingMacros.GetTypedColumnValue(emailOfMailing);

аналогично для других переменных - title и body.
Подскажите, пожалуйста, что я делаю неверно. Спасибо!!

Нравится

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

Добрый день! Подскажите, пожалуйста, в версии 5.х организована рассылка сообщений. Если у контакта, участвующего в рассылке сообщений, стоит статус "оправлено", разве нельзя еще раз отправить ему сообщение?

Нравится

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

При нажатии на кнопку «Запустить рассылку» оно специально отфильтровывает те записи с детали, у которых состояние равно «Отправлено», чтобы можно было запустить рассылку второй раз только оставшимся и тем, у кого в первый раз отправилось с ошибкой.

Теоретически, логику можно доработать. Например, вытянуть поле «Состояние отправки» в карточку детали и при необходимости менять вручную.

Спасибо, Александр!

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

Добрый день!

Столкнулся с проблемой, когда представление в BPM наследует таблицу, выводит в интерфейсе мою добавленную колонку, но в SQL таблицу эта колонка не добавляется. Вот как это выглядит:

Добавил колонку "Специальная цена" в таблицу, которую наследует представление:
1

В представлении эта колонка отображается как унаследованная. Все верно:
2

Но в БД ее нет:
3

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

Вот и вопрос: как добавить эту же колонку в представление?

Нравится

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

Виталий,

Во View базы данных колонка добавляется ручками путем правки этого самого View.

Через конфигурацию по сути только настраивается соответствие сущности в системе и представления в БД.

Допустим так... Тогда как этими ручками добавить во View колонку? В контекстном меню ничего нет. В схеме тоже никаких команд. В дизайнере тем более. На MSDN тоже нет ни слова о добавлении во View колонки.

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

Подскажите, если не трудно. Заранее спасибо!

"Виталий Марушко" написал:Допустим так... Тогда как этими ручками добавить во View колонку? В контекстном меню ничего нет. В схеме тоже никаких команд. В дизайнере тем более. На MSDN тоже нет ни слова о добавлении во View колонки.

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

Но вопрос о том, как мне это сделать, если у меня нет доступа к БД остается открытым...

Да. Все верно. Можно сделать через ALTER например.

При работе с представлением вам в любом случае придется создавать его самостоятельно в БД.
Если у вас нет прямого доступа к БД, значит нужно искать варианты выполнения SQL-скрипта по модификации/созданию представления из приложения.

Виталий

Если у вас версия 7.x сделать это можно с помощью sql-сценария в пакете
Если у вас версия 5.x то думаю стоит посмотреть в сторону класса CustomQuery.

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

Ессть готовая страница для выполнения произвольных SQL-запросов, её нужно загрузить в конфигурацию.

Во View действительно добавлять колонки только руками.

"Толмачев Дмитрий Юрьевич" написал:Через конфигурацию по сути только настраивается соответствие сущности в системе и представления в БД.

это тоже потом только ручками?

1. Добавляете во View колонку через БД
2. В конфигурации в объект добавляете колонку с тем же именем и типом, публикуете

Объект в конфигурации и View в БД связываются благодаря одинковому названию и наличию галки «Представление».

"Зверев Александр" написал:В конфигурации в объект добавляете колонку с тем же именем и типом, публикуете

bpm мог бы научиться сам считывать колонки View, конечно...

Иногда View вместо таблицы используют в особых случаях, со сложными union и join, триггерами. Там нельзя просто так взять и добавить колонку, нужно думать.

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

Добрый день!

Вопрос по BPMonline Realty 5.4

Подскажите, как правильно настроить автоматическую синхронизацию BPM с почтой. Требуется получение электронных писем с почтового сервера gmail (к примеру). Если синхронизация настраивается, то можно ли задать периодичность/расписание? Возможно, есть какие-то примеры.

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

Нравится

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

Добрый день!

вопрос по bpm online realty версии 5.4.1.728

Подскажите, какие есть варианты настройки автоматического получения электронных писем с почтового сервера gmail. Если синхронизация настраивается, то можно ли задать периодичность/расписание?

Нравится

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

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

Вопрос по bpm online realty 5.4.1.728

Интересует возможность настройки синхронизации с gmail (для входящих писем). Какие существуют способы настройки синхронизации, возможно ли задавать расписание на автоматическое получение входящих писем?
Спасибо!

Нравится

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

Добрый день
При открытии Задачи авт-ки отправляется уведомление (е-мейл) ответственному по этой Задаче. Можно ли сделать так, чтобы этот е-мейл делал запись в календаре в Outlook или чтобы была пометка зафиксировать это в календаре в Outlook ?

Нравится

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