Guid contactId = UserConnection.CurrentUser.ContactId; //id контакта текущего пользователя
string contactName = UserConnection.CurrentUser.ContactName; //имя контакта текущего пользователя
string contactmail = Terrasoft.Configuration.CommonUtilities.GetEntityTypedColumnValue(UserConnection, "Contact", "Email", contactId);
string contactdol = Terrasoft.Configuration.CommonUtilities.GetEntityTypedColumnValue(UserConnection, "Contact", "JobTitle", contactId);

мне нужно в карточке е-мейл узнать должность и е-мейл текущего пользователя.
при опубликовании, появляется ошибка:

Нравится

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

Опубликовала без ошибок:
Guid contactId = UserConnection.CurrentUser.ContactId; //id контакта текущего пользователя
string contactName = UserConnection.CurrentUser.ContactName; //имя контакта текущего пользователя
string contactmail = Terrasoft.Configuration.CommonUtilities.GetEntityTypedColumnValue(UserConnection, "Contact", "Email", contactId);
string contactdol = Terrasoft.Configuration.CommonUtilities.GetEntityTypedColumnValue(UserConnection, "Contact", "JobTitle", contactId);

Все получилось!

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

Добрый день

Если мне нужно скопировать данные заголовка из одной е-мейл-активности в другую, то:
defValues.Add("Title",Page.TitleEdit.Value.ToString());
А как скопировать данные из html body ?

Нравится

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

Так же само. Если из контрола не берётся, то можно из поля в DataSource.

на странице карточки е-мейл есть BodyEdit, но нет HTMLBodyEdit. В DataSource колонки HTMLBody и Body имеются. Поэтому, не могу также скопировать данные , как в примере defValues.Add("Title",Page.TitleEdit.Value.ToString()); .

Значит, из DataSource.

написала так:

defValues.Add("HtmlBody", Page.DataSource.ActiveRow.GetTypedColumnValue("HtmlBody"));

получилось!

У меня вопрос: а каким образом можно добавить некоторый текст перед скопированным HtmlBody ? Ну хотя бы логику подскажите... заранее спасибо

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

спасибо, получилось склеить.

еще вопрос: между строками, к-ые склеила, нужно, чтобы был переход на другую строку (т.е. не все было на одной строке).

не работает:
string s = "From: /n Sent: ";

в итоге выводит на одной строке, без перехода на другую: From: /n Sent: .

/n - это надо объявить где-то?

Это же HTML. Тут переход тегами делается.

<br /> 

подскажите, а выделение жирным с помощью какого тега делается?

<b></b>

Смотрите учебник по HTML, там ещё много других интересных тегов.

А про копирование Файлов из одной е-мейл активности в другую где можно посмотреть?

Я Вам уже писал, поищите внимательно по этому же сайту и по исходникам конфигурации.

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

Добрый день
Я создала кнопку "Переслать", при ее нажатии - создается новая е-мейл с копированием некоторых данных из "старой" е-мейл. Пожалуйста, подскажите, как написать: если мне в поле Title в новой е-мейл нужно:
1) если поле Активность.Инцидент не заполнено, то defValues.Add("Title", Page.TitleEdit.Value.ToString());
2) если поле Активность.Инцидент заполнено, то Title надо указывать следующий текст: Обращение № __ (здесь указывать номер этого Инцидента)

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

Нравится

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

Вы можете заказать такие доработки у компании Terrasoft или кого-то из партнёров.
Также можете изучить C# и запрограммировать самостоятельно.

поле Активность.Инцидент, это старая активность или только что созданная?

"Kurvan Muminov" написал:

поле Активность.Инцидент, это старая активность или только что созданная?

это старая

в принципе, я разобралась.

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

Добрый день!

Есть желание увеличить быстродействие системы. Выполняю запрос по поиску полей таблиц к которым существует много запросов, но на них нет индексов. И одна из таблиц выпадает AccountCommunication [Средства связи Юр. лиц]. Сам объект унаследовал структуру от объекта [Базовое средство связи]. Так вот получается, что в базовом объекте нет индексов на основные поля для поиска, такие как Id,[Position]. Есть какая-то причина отсутствия индексов на этих полях или их можно создать?

Нравится

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

И как все-таки будет правильно, добавить индекс на базовый объект или в тот который унаследовал? Или при добавление в унаследованный объект в базовый он добавится автоматически?

Анастасия, с точки зрения БД родительский и дочерний объекты — это 2 разных таблицы. Следовательно, средствами Management Studio можно добавлять в дочернюю таблицу индексы, если в ходе анализа выяснилось, что это может увеличить производительность.
Сомневаюсь, что на Id стоит добавлять индекс, ведь это и так первичный ключ. А на второе — можно попробовать.

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

Анастасия, с точки зрения БД родительский и дочерний объекты — это 2 разных таблицы. Следовательно, средствами Management Studio можно добавлять в дочернюю таблицу индексы, если в ходе анализа выяснилось, что это может увеличить производительность.

Сомневаюсь, что на Id стоит добавлять индекс, ведь это и так первичный ключ. А на второе — можно попробовать.


Вот и мне не понятно... Индекс уникальный некластеризованый в БД на Id стоит, а приложение показывает, чтот у этого объкта на этом поле нет индекса.

Смотрите на уровне БД, там вернее. Колонка Id в любой таблице bpm'online — первичный ключ. Возможно, поэтому её явно и не показывает как индекс.

"Астапеева Анастасия" написал:Есть желание увеличить быстродействие системы.

Желание или необходимость? :smile:

"Астапеева Анастасия" написал:Так вот получается, что в базовом объекте нет индексов на основные поля для поиска, такие как Id,[Position].

не думаю что поле Position - подходящая кандидатура для построения индекса (если я правильно понимаю, это порядковый номер в рамках 1 контрагента?)... кардинальность большая. Индексы хорошо строить по колонкам с практически уникальными значениями (опять же, если СУБД потом будет их использовать).

По-идее индекса по Id и AccountID должно быть вполне достаточно.

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

В общем, есть впечатление что не тут копаете, Анастасия... Могу посоветовать книгу, правда на английском... но может и русские версии уже есть: SQL Server 2008 Query Performance Tuning Distilled (2009)
версия СУБД может и немного старовата, но для CRM систем более чем сгодится.

"komgbu" написал:

Желание или необходимость? :smile:

В общем, есть впечатление что не тут копаете, Анастасия... Могу посоветовать книгу, правда на английском... но может и русские версии уже есть: SQL Server 2008 Query Performance Tuning Distilled (2009)

версия СУБД может и немного старовата, но для CRM систем более чем сгодится.

Именно желание. Спасибо большое за книгу и совет.

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

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

Нравится

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

Можно на PageLoadComplete карточки проверять, если IsNew или IsCopy, то заполнять поле.
Или же настроить в свойствах детали в «Рабочих местах» ещё одну связь типа «Значение по умолчанию» с нужным полем.

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

Добрый день

Подскажите, как на С# написать условие:
если текстовое поле не заполнено, то...

Нравится

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

Работает:

if (Page.ChangeRequestEdit.Value != null) //&&(Page.IncidentEdit.Value == null))
{
Page.BaseMessagePanel.AddMessage(Warning, "Выберите номер Обращения, связанного с указанным ЗИ", MessageType.Warning);
return false;

}
else
{
return true;
}

А вот так не работает (опубликовывает без ошибок, но карточка без проблем закрывается):

if ((Page.ChangeRequestEdit.Value != null)&&(Page.IncidentEdit.Value == null))
{
Page.BaseMessagePanel.AddMessage(Warning, "Выберите номер Обращения, связанного с указанным ЗИ", MessageType.Warning);
return false;

}
else
{
return true;
}

Подскажите, в чем ошибка? Мне нужно проверить условие если поле Запрос на изменение заполнен, а поле Инцидент не заполнен, то выводится сообщение об ошибке...

Нет, не правильное условие. У меня поле - это поле справочника, а не текстовое. Подскажите, как на С# написать условие: если поле справочника не заполнено?

Там может быть не только null, но и Guid.Empty.
То есть, для каждого поля проверять так:

if (Page.AccountEdit.Value == null || new Guid(Page.AccountEdit.Value.ToString()) == Guid.Empty) {

Или так:

if (Page.CityEdit.Value == null || Page.CityEdit.Value.Equals(Guid.Empty)) {

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

спасибо, разобралась.

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

Добрый день

Подскажите, как сделать следующее:

Если поле ЗИ.Активность заполнено, то можно было бы выбрать номер того Обращения , который подвязан к этому Запросу на Изменение (ЗИ).

Нравится

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

Откомпилировалось без ошибок, но по-прежнему при определенном номере ЗИ выдает полный список номеров Обращений.

Page.IncidentEdit.PrepareLookupFilter += delegate (object sender, LookupEditEventArgs e) {
if (!Page.ChangeRequestEdit.Value.Equals(Guid.Empty)) {
var filters = e.Filters;
filters.Add(new Dictionary {
{"comparisonType", FilterComparisonType.Equal},
{"leftExpressionColumnPath", "ChangeRequest.Id"},
{"useDisplayValue", false},
{"rightExpressionParameterValues", new object[] {(Guid)Page.ChangeRequestEdit.Value}}});

}
};

- это нужно в ChildInitAfterParentScript, правильно?

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

на лукап я захожу, но не фильтрует...

так тоже опубликовывает, но не фильтрует:
Page.IncidentEdit.PrepareLookupFilter += delegate (object sender, LookupEditEventArgs e) {
if (!Page.ChangeRequestEdit.Value.Equals(Guid.Empty)) {
var filters = e.Filters;
filters.Add(new Dictionary {
{"comparisonType", FilterComparisonType.Equal},
{"leftExpressionColumnPath", "[ServiceRequestInChangeRequest:Incident].ChangeRequest.Id"},
{"useDisplayValue", false},
{"rightExpressionParameterValues", new object[] {(Guid)Page.ChangeRequestEdit.Value}}});

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

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

Есть связь м/д объектами Запрос на изменение и Инцидент и запрос на обслуживание: ChangeRequestInServiceRequest.

Пишу в ChildInitAfterParentScript на странице карточки задачи:
Page.IncidentEdit.PrepareLookupFilter += delegate (object sender, LookupEditEventArgs e) {
var changerequestId = (Guid)Page.ChangeRequestEdit.Value;
if (changerequestId !=Guid.Empty) {
Collection> filters = e.Filters;
filters.Add(new Dictionary {
{"comparisonType", FilterComparisonType.Equal},
{"leftExpressionColumnPath", "[ChangeRequestInServiceRequest:ServiceRequest].ChangeRequest.Id"},
{"useDisplayValue", false},
{"rightExpressionParameterValues", new object[] {(Guid)Page.ChangeRequestEdit.Value}}});

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

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

не соображу, какое именно наложение фильтра сделать нужно.

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

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

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

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

Добрый день.

Подскажите, как сделать следующее:
При сохранении Активности с типом Задача, если ЗИ.Активность заполнено, то карточка ЗИ не сохранялась, а выдавала сообщение о необходимости заполнения поля Обращение.Активность.

Нравится

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

Добрый день
Подскажите, пожалуйста, как создать кнопку "Переслать" в реестре активностей, которая стояла бы на одному ряду с кнопками Добавить, Копировать,Изменить,Удалить ?

Нравится

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

И чтобы при нажатии на эту кнопку появлялась новая е-мейл-активность

И чтобы при нажатии на эту кнопку появлялась новая е-мейл-активность

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

Добрый день.
Создала кнопку "Переслать" непосредственно на странице карточки e-mail, обработчик:

все опубликовалось без ошибок. Но при нажатии на кнопку "Переслать" новое окно е-мейл активности не создается. Подскажите, почему?

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

var defValuesId = Guid.NewGuid();
var defValues = new Dictionary ();
defValues.Add("Contact", Page.ContactEdit.Value.ToString());
defValues.Add("Account", Page.AccountEdit.Value.ToString());
defValues.Add("CopyRecepient", Page.CopyRecepientEdit.Value.ToString());
defValues.Add("Recepient", Page.SenderEdit.Value.ToString());
defValues.Add("Body", Page.BodyEdit.Value.ToString());

var ActivityId = Guid.NewGuid();

UserConnection.SessionData[defValuesId.ToString()] = defValues;
var parameters =
new Dictionary {
{"createWithUId", ActivityId.ToString()},
{"entitySchemaUId", "C449D832-A4CC-4B01-B9D5-8A12C42A9F89"},
{"defValuesId", defValuesId.ToString()}
};
OpenTaskEditPage.OpenerInstanceId = InstanceUId;
OpenTaskEditPage.UseCurrentActivePage = true;

OpenTaskEditPage.PageUId = new Guid("dcdda065-321b-4560-aacb-05f6cc72cd80");
OpenTaskEditPage.PageParameters = parameters ;
return true;

Возможно, дело в формате объекта defValues.
Обычно он такого типа:

var defValues = new Dictionary <string, object>();
defValues["SysAdminUnitType"] = SysAdminUnitTypeId;

Записывается не строка, а значение типа Guid.

Если же дело не в этом, попробуйте провести отладку и посмотреть, как отрабатывает OpenPageUserTask.

я за основу брала : http://www.community.terrasoft.ru/forum/topic/9208
мне же не нужно создавать инцидент, генерировать номер для активности не нужно. Достаточно ли будет сигнала нажатия на кнопку "Переслать" и скрипта по открытию окна е-мейл активности?

пишу в этом скрипте:
var defValuesId = Guid.NewGuid();
var defValues = new Dictionary ();

defValues.Add("Contact", Page.ContactEdit.Value.ToString());
defValues.Add("Account", Page.AccountEdit.Value.ToString());
defValues.Add("CopyRecepient", Page.CopyRecepientEdit.Value.ToString());
defValues.Add("Recepient", Page.SenderEdit.Value.ToString());
defValues.Add("Body", Page.BodyEdit.Value.ToString());

var ActivityId = Guid.NewGuid();

UserConnection.SessionData[defValuesId.ToString()] = defValues;
var parameters =
new Dictionary {
{"createWithUId", ActivityId.ToString()},
{"entitySchemaUId", "c449d832-a4cc-4b01-b9d5-8a12c42a9f89"},
{"defValuesId", defValuesId.ToString()}
};
OpenTaskEditPage.OpenerInstanceId = InstanceUId;
OpenTaskEditPage.UseCurrentActivePage = true;

OpenTaskEditPage.PageUId = new Guid("dcdda065-321b-4560-aacb-05f6cc72cd80");
OpenTaskEditPage.PageParameters = parameters ;

return true;

Опубликовывает без ошибок, но рез-та нет: при нажатии на кнопку "переслать" ничего не происходит.

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

"TatianaM" написал:

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

var defValuesId = Guid.NewGuid();

var defValues = new Dictionary ();

defValues.Add("Contact", Page.ContactEdit.Value.ToString());

defValues.Add("Account", Page.AccountEdit.Value.ToString());

defValues.Add("CopyRecepient", Page.CopyRecepientEdit.Value.ToString());

defValues.Add("Recepient", Page.SenderEdit.Value.ToString());

defValues.Add("Body", Page.BodyEdit.Value.ToString());

var ActivityId = Guid.NewGuid();

UserConnection.SessionData[defValuesId.ToString()] = defValues;

var parameters =

new Dictionary {

{"createWithUId", ActivityId.ToString()},

{"entitySchemaUId", "C449D832-A4CC-4B01-B9D5-8A12C42A9F89"},

{"defValuesId", defValuesId.ToString()}

};

OpenTaskEditPage.OpenerInstanceId = InstanceUId;

OpenTaskEditPage.UseCurrentActivePage = true;

OpenTaskEditPage.PageUId = new Guid("dcdda065-321b-4560-aacb-05f6cc72cd80");

OpenTaskEditPage.PageParameters = parameters ;

return true;

Ваш объект называется OpenTaskEditPage1 а в скрипте OpenTaskEditPage

невнимательность... огромное спасибо.

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

Да, можно.

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

а в каком месте? и какого поля значение?

Это зависит от того, что Вы хотите запрограммировать.

"TatianaM" написал:

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

Попробуйте после скрипта открытия 2й страницы добавить вторую ветку процесса(с помощью элемента "И")
и послать завершающий сигнал( с передачей в родительский процесс) нажатие кнопки Cancel (точно не помню как называется, вроде, CancelButtonClick) или OK

А, так требуется карточку активности закрыть? Думал, что речь о состоянии «Закрыта». Если карточку, то действительно нужно в старой активности после открытия карточки новой вызвать код, как на кнопке закрытия:

(Page.AspPage as Terrasoft.UI.WebControls.Page).Close();

Или же смотрите рекомендации автора предыдущего сообщения.

А если Вам надо после сохранения второй закрывать первую, то тогда сложнее.

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

"Зверев Александр" написал:Или же смотрите рекомендации автора предыдущего сообщения.

Сделала по рекомендации, но при нажатии на ОК в новой активности появляется ошибка, и окно активности не закрывается:

Предупреждение
The INSERT statement conflicted with the FOREIGN KEY constraint "FKInijGB83hrW19KtJno3hZK8". The conflict occurred in database "bptest", table "dbo.ChangeRequest", column 'Id'.
The statement has been terminated.

Такое сообщение говорит о том, что Вы неправильно заполнили в сохраняемой записи поле «Запрос на изменение». Смотрите рекомендации другого автора предыдущего сообщения:

"Мария Ватулина" написал:

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

"Зверев Александр" написал:Такое сообщение говорит о том, что Вы неправильно заполнили в сохраняемой записи поле «Запрос на изменение»

сама разобралась...

пишу:
defValues.Add("Incident",Page.IncidentEdit.Value.ToString());

но если поле Incident в "старой" е-мейл активности не заполнено, то при нажатии на ОК система выдает ошибку о том, что неправильно заполнили в сохраняемой записи поле "Инцидент".

Тогда делаю проверку на заполнение:
if (Page.IncidentEdit.Value != null)
{defValues.Add("Incident",Page.IncidentEdit.Value.ToString());}
else
{ defValues.Add("Incident","");} - то опубликовывает без ошибок, но не срабатывает при проверке, опять выдает ошибку о неправильно заполненном в сохраняемой записи поле "Инцидент".

Это потому, что Вы непонятно зачем работаете с полем «Инцидент» как с текстовым. А оно справочное. Если в копируемой записи поле не заполнено, то вообще нет смысла из него копировать.

нет, мне нужно его копировать, потому что поле "инцидент" может быть как заполнено, так и не заполнено.
пишу проверку так:

if (new Guid (Page.IncidentEdit.Value.ToString()) != Guid.Empty)
{defValues.Add("Incident",Page.IncidentEdit.Value.ToString());}
else {defValues.Add("Incident","");}

опубликовывает без ошибок, но при открытии новой е-мейл активности система выдает:
Exception Message: Нераспознанный формат идентификатора GUID.

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

понятно, получилось так:

if (new Guid (Page.IncidentEdit.Value.ToString()) != Guid.Empty)
{defValues.Add("Incident",Page.IncidentEdit.Value.ToString());}

"Зверев Александр" написал:Если карточку, то действительно нужно в старой активности после открытия карточки новой вызвать код, как на кнопке закрытия:
(Page.AspPage as Terrasoft.UI.WebControls.Page).Close();

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

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

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

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

версия 5 сервис деск

Был применен скрипт:
delete from "SysProfileData"
where "ObjectId" =(select distinct "SysSchemaId" from "SysSchemaInSolution"
where "Name" = 'Название схемы');
commit;

где значение Name - название схем, а именно:
BaseApprovalGridPage
ApprovalInServiceRequestGridPage.

Например, для очистки, профилей пользователей страницы
BaseApprovalGridPage. Скрипт будет иметь вид:

delete from "SysProfileData"
where "ObjectId" =(select distinct "SysSchemaId" from "SysSchemaInSolution"
where "Name" = 'BaseApprovalGridPage');
commit;
"
Данный скрипт не удаляет настроек колонок

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

Нравится

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

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

SELECT TOP 1000 [Id]
      ,(select max([Name]) from [SysSchemaInSolution] where [SysSchemaId]  = [ObjectId])
      ,[ModifiedOn]
      ,[CreatedOn]
      ,[CreatedById]
      ,[ModifiedById]
      ,[SysUserId]
      ,[ObjectId]
      ,[Key]
      ,[ObjectData]
      ,[ObjectDifference]
  FROM [SysProfileData]
  order by [ModifiedOn] desc

Если меняем настройки колонок в нескольких разделах, появляются изменённые записи, все связанные со схемой MainPage, но с разным значением поля Key.
Попробуйте поменять настройки средствами пользователя и посмотреть, какие записи при этом обновятся.

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