отчет
фильтр
Технические вопросы
Разработка

Требуется передать значения фильтров в отчет. Хотелось не перебирать операторы сравнения с помощью отладчика. В SDK нашел перечисление, вроде подходящее - Перечисление _DateTimeOperatorTypeEnum. Дай думаю проверю на нескольких данных. Поставил оператор сравнения в фильтре «Прошлый год». Получил в отладчике fbcMain.DataFieldsList.Items(0).CompareOperator = 17. И что имеем в SDK dotLastYear = 17, и dotLastYear = «В течение года до текущей даты». В связи с этим вопрос – а можно ли доверять так рекламируемому SDK. Кстати точный перевод Last Year это Прошлый год. Остальные значения можно определить только тупым перебором? (типы поля сравнения и к нему операторы сравнения).
Дальше оказалось еще интереснее. При исследовании (тупым перебором) установки для поля типа Справочник выяснилось, что при установке «Пусто», «Не пусто» и «Текущий контакт» окно выбора фильтров само сбрасывает установку на «Пусто» после формирования отчета и выяснить CompareOperator не представляется возможным! Уже боюсь копать дальше.

Пытаемся Строить отчет:

После нажатия ОК имеем:

Это нормально?

Нравится

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

Владимир, как устанавливаете значения для условий фильтрации окна?

Щелкаю левой кнопкой мышки по знаку и в низпадающем списке по "Не пусто". Поле этого по кнопке ОК. Есть другие варианты?

Другие варианты есть - на уровне скриптовой логики.
Проверяла на версиях 3.3.2 - 3.4.1, работает корректно.
На какой версии и сборке у Вас воспроизводится такое поведение (и уточните, пожалуйста, доп. информацию для воспроизведения)?

Версия 3.2.0.81

Уважаемая, Наталия, поделитесь как можно "на уровне скриптовой логики" узнать какой оператор установлен пользователем в фильтре. Буду очень признателен. (и конечно очень хочется узнать как можно этот самый оператор установить)

Попробовал на версии 3.4.0.50
fbcMain.DataFieldsList.Items(i).CompareOperator кроме "<>" все остальные ноль. Но хоть не сбрасывает. Хотя это мне не поможет, так как работаем на старой версии.

"Прищепа Владимир" написал:Уважаемая, Наталия, поделитесь как можно "на уровне скриптовой логики" узнать какой оператор установлен пользователем в фильтре. Буду очень признателен. (и конечно очень хочется узнать как можно этот самый оператор установить)

Владимир, смотрите в сторону скрипта wnd_ReportFiltersScript, функция LoadFilters (может быть полезной статья http://www.community.terrasoft.ru/forum/topic/7477)

Воспроизвела на версии 3.2.0 сбрасывание оператора сравнения - вопрос передан в департамент разработки.

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

Владимир, а Наталья дала вам ссылку с примером
А я добавлю ссылку на SDK
http://terrasoft.ru/sdk/index.html?frmname=topic&frmfile=MEMBEROVERVIEW…

"Бондарь Наталия" написал:Воспроизвела на версии 3.2.0 сбрасывание оператора сравнения - вопрос передан в департамент разработки.

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

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

Ошибка возникает внезапно.

Код стандартный

EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqResult = new EntitySchemaQuery(esqManager, "Document");
esqResult.AddColumn ("StatusId");

Entity currentDoc = esqResult.GetEntity(UserConnection, currentDocId);

Работало пять минут назад.
Сейчас перестало.
С какого рожна?
Вылетает на esqResult.AddColumn.

Какой столбец значения не имеет.

Уже не в первый раз приходится все переписывать через Select.
Но это неудобно, когда надо просто запись достать по Id.

Нравится

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

Александр, как вариант - быть может дело в том, что Вы не добавили колонку с первичным ключом (Id), а в момент, когда выполняется GetEntity(UserConnection, currentDocId); система не может по нему отфильтровать и не заполняется коллекция с колонкой StatusId, т.к. результат был null.

точно. спасибо, проверю.

нет. не помогает.

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

Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
esqDocResult.AddColumn("Id");
 
Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>("CurrentApprovalNodeId");

даёт
Exception Message: Значение с именем "CurrentApprovalNodeId" не найдено

а в таком

Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
esqDocResult.AddColumn("Id");
esqDocResult.AddColumn("CurrentApprovalNodeId");
 
Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>("CurrentApprovalNodeId");

вот так ругается
Exception Message: Элемент коллекции с именем CurrentApprovalNodeId не найден

В чем засада?!!

причем все это скопировано из документации один в один и не работает.

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

Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
var IdColumn = esqDocResult.AddColumn("Id");
var CurAppNodeIdColumn = esqDocResult.AddColumn("CurrentApprovalNodeId");
 
Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>(CurAppNodeIdColumn);

Так то же самое
Exception Message: Элемент коллекции с именем CurrentApprovalNodeId не найден

то есть оно валится на вызове

esqDocResult.AddColumn("CurrentApprovalNodeId");

В общем ничего я не понял, опять через select переписал

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

Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
var IdColumn = esqDocResult.AddColumn("Id");
var CurAppNodeIdColumn = esqDocResult.AddColumn("CurrentApprovalNodeId");
 
Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>(CurAppNodeIdColumn.Name);

попробую, но уже не сегодня. :wink:

"Шамуилов Александр" написал:esqDocResult.AddColumn("CurrentApprovalNodeId");

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

esqDocResult.AddColumn("CurrentApprovalNode.Id");

Помогло и то и другое :smile:
Данные достаются корректно, все работает, проверял.

if ( IsNew ) {
 
	Guid parentDocId = new Guid(Page.DataSource.ActiveRow.GetColumnValue("DocumentId").ToString());
 
	EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
	var esqDocResult = new EntitySchemaQuery(esqManager, "Document");
	var IdColumn = esqDocResult.AddColumn("Id");
	var CurAppNodeIdColumn = esqDocResult.AddColumn("CurrentApprovalNode.Id");
 
	Entity parentDoc = esqDocResult.GetEntity(UserConnection, parentDocId);
	Guid currentNodeId = parentDoc.GetTypedColumnValue<Guid>(CurAppNodeIdColumn.Name);
 
	var esqAppTypeResult = new EntitySchemaQuery(esqManager, "ApprovalNode");
	var appNodeIdColumn = esqAppTypeResult.AddColumn("Id");
	var appNodeTypeIdColumn = esqAppTypeResult.AddColumn("ApprovalType.Id");
	var appNodeNameColumn = esqAppTypeResult.AddColumn("Name");
 
	Entity appNode = esqAppTypeResult.GetEntity (UserConnection, currentNodeId);
	Guid appNodeTypeId = appNode.GetTypedColumnValue<Guid>(appNodeTypeIdColumn.Name);
	string appNodeTypeName = appNode.GetTypedColumnValue<string>(appNodeNameColumn.Name);
 
	Page.ApprovalTypeLookupEdit.Value = appNodeTypeId;
 
}
 
return true;

Но возникла другая проблема: как мне в скрипте выше (висит на PageLoadComplete карточки редактирования ПОСЛЕ генерации сообщения PageLoadComplete для родительского процесса) установить значение поля ApprovalTypeLookupEdit?

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

Если заменить

Page.ApprovalTypeLookupEdit.Value = appNodeTypeId;

на

Page.ApprovalTypeLookupEdit.SuspendAjaxEvents();
Page.ApprovalTypeLookupEdit.SetValueAndText(appNodeTypeId, appNodeTypeName);
Page.ApprovalTypeLookupEdit.ResumeAjaxEvents();

то просто открывается нормально карточка, но поле ApprovalTypeLookupEdit не заполняется.....

Идей, я так понимаю, нет?

Александр, так нельзя:

Page.ApprovalTypeLookupEdit.Value = appNodeTypeId;

Либо так:

Page.ApprovalTypeLookupEdit.SetValue(appNodeTypeId);

Но рекомендую все же так:

Page.DataSource.ActiveRow.SetColumnValue("ApprovalTypeId", appNodeTypeId);

А вот по фигу, извините, конечно :smile:
В смысле что все три варианта не работают :exclaim:

Япппонский городовой!!!:lol:

Надо проставлять значение и в датасорс и поле лукапа!!

Вот так работает:

Page.DataSource.ActiveRow.SetColumnValue ("ApprovalTypeId", appNodeTypeId);
Page.ApprovalTypeLookupEdit.SetValueAndText (appNodeTypeId, appNodeTypeName);	

BPMOnline Reality (Версия 5.4.1.256)

Аналогичный код у меня не работает:

    //select Tenants
    var esqTenant = new EntitySchemaQuery(UserConnection.EntitySchemaManager, "Tenant");
    esqTenant.AddColumn("Id");
    esqTenant.AddColumn("Account");
    esqTenant.AddColumn("Project");
    esqTenant.AddColumn("Facility");
    var ownerCol = esqTenant.AddColumn("Account.Owner");
    esqTenant.AddColumn("DueDate");
    //filters
    esqTenant.Filters.LogicalOperation = LogicalOperationStrict.Or;
    esqTenant.Filters.Add(esqTenant.CreateFilterWithParameters(
	    FilterComparisonType.Equal, "DueDate", dd1));
    esqTenant.Filters.Add(esqTenant.CreateFilterWithParameters(
	    FilterComparisonType.Equal, "DueDate", dd30));
    //result
    Guid accountId;
    string accountName;
 
    var tenantCollection = esqTenant.GetEntityCollection(UserConnection);
    foreach (var record in tenantCollection) {
	    Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name); //1
	    accountId = record.GetTypedColumnValue<Guid>("AccountId"); //2
	    accountName = record.GetTypedColumnValue<String>(record.Schema.Columns.GetByName("Account").DisplayColumnValueName); //3
    }

говорит "Значение с именем "Account_Owner" не найдено" (строка "1")

а также объясните почему в строке "2" нужно писать название поля как в базе (с Id), а в строке "3" - как в объекте ?

Хороший вопрос.....ТП, вы гиде? :smile:

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

В запросе типа EntitySchemaQuery необходимо название колонок писать так как в таблице объекта:

esqTenant.AddColumn("Id");
    esqTenant.AddColumn("AccountId");
    esqTenant.AddColumn("ProjectId");
    esqTenant.AddColumn("FacilityId");
    var ownerCol = esqTenant.AddColumn("Account.OwnerId");
    //или var ownerCol = esqTenant.AddColumn("Account.Owner.Id");

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

var AccountId = esqTenant.AddColumn("Account");
accountId = record.GetTypedColumnValue<Guid>(AccountId.Name);

Ошибку вызывает строка "1"

Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name);

если ее убрать все работает

если писать

esqTenant.AddColumn("AccountId");

то "Элемент коллекции с именем AccountId не найден"

Лариса, что-то я запутался :)

Если убрать

Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name);

то все работает даже с

esqTenant.AddColumn("AccountId");

или нет?

И колонка AccountId точно есть в таблице? Может она называется как-то CustomerId?
Только что у себя попробовал сделать запрос с контактов с полями OwnerId и AccountId - без ошибок.

Если убрать

Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name);

то остальной код работает.

Если писать как Вы предлагали в #18, т.е.

esqTenant.AddColumn("AccountId");

то возникает ошибка "Элемент коллекции с именем AccountId не найден".

Поле в схеме объекта называется Account, в базе AccountId

А если написать:
var ownerCol = esqTenant.AddColumn("Account.Owner.Id");

То со строкой

Guid ownerId = record.GetTypedColumnValue<Guid>(ownerCol.Name);

работает?

Да, так работает.
Спасибо!

Показать все комментарии
Lookup
lookup field value
отображаемое значение
Технические вопросы
5.x

Здравствуйте, у меня возник вопрос. Каким образом можна сменить отображаемое поле в поле-справочник. Тоесть если в обьекте указано отображаемое поле Название и везде в полях-справочник при выборе определенной записи, поле содержит Id и Name..вопрос стоит в следующем, как сделать так (к примеру) чтобы при выборе продукта, выводилось не его Имя а допустим Артикул (или еще какое-нибудь поле).

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

Нравится

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

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

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

У объекта есть возможность выбрать из списка другое первичное поле для отображения.

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


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

Игорь, можно попробовать воспользоваться методом

SomeEdit.setValueAndText(Guid,displayValue)

У метода есть аналог на C# и на JavaScript, то есть Вы можете вызвать его как с помощью AddScript, так и напрямую.
В случае использования AddScript обратиться к нужному контролу можно по его Id, который можно узнать, воспользовавшись методом, описанным здесь.

Показать все комментарии
Технические вопросы
5.x

Никак не соображу.

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

Что типа такого в PageLoadComplete мне видится

if (ParentDoc.Condition = true ){
   //продолжаем штатно

}else{
  MessageToUser ("НИЗЗЯ ТЕБЕ!!!");
  Page.Close();

}

Нравится

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

Или не из PageLoadComplete это делать?

А зачем вообще доходить до открытия ...EditPage? Можно написать свой обработчик для кнопки "Добавить" в ...GridPage. Обычно обработчики кнопок в гриде сделаны на JS из соображений оптимизации, но вполне можно написать обычный кусочек БП, который открывает или не открывает окно, в зависимости от условия.

Александр, зависит от того, какие условия Вы проверяете, и когда эти условия инициализируются.
В Вашем случае, видимо, они передаются из родительского окна. В таком случае можно делать проверку на Init.

Ну до этого я допер, что на Init. А как мне что то сказать пользователю и остановить процесс открытия страницы редактирования, вот чего я никак не допру.

И кстати, если через Init, то как мне достучатся до родительской записи для этой детали?

Поддерживаю Александра. Задачу нужно решать иначе.

Иначе то оно да, но как?

Делать проверку до начала открытия окна.

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

Разобрался, на событии нажатия на кнопку параметр
SelectedNodePrimaryColumnValue содержит Id выбранной в основном реестре записи

Возникла другая проблема.
Повесил на событие AddButtonClick свой скрипт таск:

AddButtonClick

Теперь в скрипте проверяю все что мне надо, но!, как мне прервать процесс?!!

return false;

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

Решил проблему:
1. Скрываем стандартную кнопку Добавить
2. Добавляем свою кнопку Добавить
3. На событие клика своей кнопки Добавить вешаем скрипт с проверкой нужного нам условия и в соответствии с этим заполняем параметр процесса.
4. Добавляем условные потоки управления в зависимости от значения параметра.
5. Не забываем сгенерировать сообщение "AddButtonClick" в родительский процесс по нужному нам условию.
6. Наслаждаемся :-)

addbuttonclicknew

Да, всё правильно. При желании можно ещё показать сообщение при отрицательном значении условия. И из двух условных потоков всё же лучше один сделать по умолчанию (не с ромбиком, а с чертою).

Это уже частности и очевидности, но спасибо.

:wink:

"Шамуилов Александр" написал:1. Скрываем стандартную кнопку Добавить

Можно было просто убрать логику из метода GetRegisterAddPageScript, тогда
"Шамуилов Александр" написал: все равно открывается страница редактирования записи

не должно происходить.

Показать все комментарии
замер производительности
производительность
профилирование
Технические вопросы
Разработка

Добрый день, коллеги.
Столкнулся с жалобами пользователей на производительность ПО Terrasoft CRM (да и сам стал замечать). Чаще всего жалуются на долгое открытие карточек объектов. Так вот, вопрос в чем: пробовал ли кто-нибудь копать в сторону профилирования JScript-кода Terrasoft и подсчета времени какая функция сколько работает?

Нравится

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

Есть scr_DebugUtils для тестирования отдельных функций. Также можно пройти процесс открытия в отладке, поставив debugger на OnPrepare и посмотреть, какой шаг долго срабатывает.

Здравствуйте.
Специально для таких целей инструментарий не создавали, но можно воспользоваться, например, той же Visual Studio: http://msdn.microsoft.com/ru-RU/library/dd264908.aspx. Так же желательно определить на каком этапе возникает задержка. Кроме Jscript это может быть и сеть и сервер. Для версии 5.4 на нашем ресурсе есть скрипт, который показывает разбивку по времени (клиент, сеть, сервер) выполнения того или иного действия: http://www.community.terrasoft.ua/blogs/8480. Ещё можно использовать такой инструмент как fiddler.

"Котенко Александр" написал:Для версии 5.4

Автора интересует 3.Х.

"Котенко Александр" написал:Так же желательно определить на каком этапе возникает задержка

Вот мне и нужно понять, где задержка: сервер БД или код.
Можете поподробнее рассказать как можно применять Visual Studio для профилирования JScript кода конфигурации Terrasoft CRM? Или то что вы написали относится исключительно к BPM Online?
У меня используется платформа Terrasoft 3.3.2.

Тут и тут и тут описано. Важно оттуда:

"Лучкив Александр" написал:Часто при разработке конфигурации необходимо ставить точки останова (Breakpoint) в скриптах для пошаговой отладки.

Для этого достаточно написать в скрипте команду:
debugger;

"Пунько Наталия" написал:Активируйте отладчик скриптов, установив ключ реестра JITDebug
Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Microsoft\Windows Script\Settings]
"JITDebug"=dword:00000001
Прикрепленный файл
enabledebugger.rar

"Зверев Александр" написал:Тут и тут и тут описано.

Спасибо конечно, но как отлаживать конфигурацию Terrasoft я знаю. Я не знаю как профилировать код конфигурации и возможно ли это для Terrasoft CRM. Вот это относится только к BPM Online:
"Котенко Александр" написал:Специально для таких целей инструментарий не создавали, но можно воспользоваться, например, той же Visual Studio:
???

См. scr_DebugUtils. Инструменты BPMonline никак не связаны с 3.Х.

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

Тогда я пошел довольно не простым путем - смотрел где узкое место с помощью SQL Profiler, описал вот здесь:
Анализ быстродействия CRM с помощью SQL Profiler
С помощью этого метода я четко смог увидеть где проблема: на стороне скриптов и компьютера пользователя или на стороне сервера.

Только что добавил запись в блог с описанием разработанного мной функционала для поиска узких мест в выполнении функций:
Анализ времени выполнения скриптов и поиск "узкого" места в функционале

Показать все комментарии
RecordAllChangesGridPage
Технические вопросы
5.x

Добрый день, а за что отвечает данный объект? RecordAllChangesGridPage
И как он вызывается?

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

public virtual bool InitScriptTask3Execute(ProcessExecutingContext context)

а именно
        var parameters = (Dictionarystring,object>)UserConnection.UserContext[defValuesId.ToString()];
        if (parameters["schemaId"] != null) {
                SysEntitySchemaId = (Guid) parameters["schemaId"];
        }

параметр schemaId отсутствует

Нравится

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

Разобрался что за объект - Журнал изменений.
Но вопрос остался, какой (Guid) parameters["schemaId"] должен быть?

Илья, уточните, при каких действиях возникает ошибка.
Также приведите, пожалуйста, полный текст ошибки.
Ведь если parameters["schemaId"] пуст, то он и не используется, ошибки быть не должно.

Ошибка возникает при выполнение действия процесса "открыть страницу", страница задается так:

CreateAgreementTask.PageUId = new Guid("98B6B04A-CF5E-44EE-966A-E4A566F2B773"); //AgreementEditPage

и возникает лишь при условии, что до запуска процесса окно AgreementEditPage открывалось, и в нем устнавливалась активной деталь "Журнал изменений"

ошибка такая:

Date: 30.10.2013 12:17:37 Date (UTC): 30.10.2013 8:17:37 Exception Message: The given key was not present in the dictionary. Exception Type: System.Collections.Generic.KeyNotFoundException Exception Source: mscorlib Exception Stack Trace: at System.Collections.Generic.Dictionary`2.get_Item(TKey key) at Terrasoft.WebApp.RecordAllChangesGridPageEventsProcess`1.InitScriptTask3Execute(ProcessExecutingContext context) at Terrasoft.Core.Process.ProcessScriptTask.InternalExecute(ProcessExecutingContext context) at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context) at Terrasoft.Core.Process.ProcessScriptTask.Execute(ProcessExecutingContext context, Func`2 internalExecute) at Terrasoft.WebApp.RecordAllChangesGridPageEventsProcess`1.ProcessQueue(ProcessExecutingContext context) at Terrasoft.WebApp.RecordAllChangesGridPageEventsProcess`1.OnExecuted(Object sender, ProcessActivityAfterEventArgs e) at Terrasoft.Core.Process.ProcessFlowElement.OnExecuted(ProcessActivityAfterEventArgs e) at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context) at Terrasoft.WebApp.RecordAllChangesGridPageEventsProcess`1.ProcessQueue(ProcessExecutingContext context) at Terrasoft.WebApp.RecordAllChangesGridPageEventsProcess`1.ThrowEvent(ProcessExecutingContext context, String message) at Terrasoft.UI.Core.PageSchemaUserControl.ThrowEvent(String message) at Terrasoft.UI.WebControls.Controls.PageContainer.ThrowInitToContainers(JArray arrayList) at Terrasoft.UI.WebControls.Controls.PageContainer.LoadFromAssembly() at Terrasoft.UI.WebControls.Controls.PageContainer.LoadUserControl() at Terrasoft.UI.WebControls.Controls.PageContainer.OnInit(EventArgs e) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Control.InitRecursive(Control namingContainer) at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) SessionID: m3wyerjrugyfaert5j52ughm Request URL: /ViewPage.aspx?Id=98b6b04a-cf5e-44ee-966a-e4a566f2b773&defValuesId=c32f1304-af1a-42df-a6cd-b77432d00cc8&createWithUId=a1652dea-856a-4cce-939d-c4acb2637d58 Request Path: /ViewPage.aspx Request UrlReferrer: http://crm.factor.ru/ViewPage.aspx?Id=5e5f9a9e-aa7d-407d-9e1e-1c24c3f9b… Request Type: GET User Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.116 Safari/537.36 User Host Address: 10.131.12.236 User: Sau_EV Is Authenticated: True Authentication Type: Forms Is Secure Connection: False Application Version: 5.2.0.653 Application Path: C:\inetpub\BPMonline\ Application Virtual Path: / Application Trust Level: Full Machine Name: MSK01NFCS064 Is Local: False Process ID: 1272 Process Name: w3wp.exe Process Account Name: IIS APPPOOL\BPMonline Thread Account Name: IIS APPPOOL\BPMonline OS Version: Microsoft Windows NT 6.1.7601 Service Pack 1 Net Framework Version: 4.0.30319.239 DBExecutor Type: MSSqlExecutor

Илья, видимо, система пытается вычитать данные об этом объекте из Журнала изменений, но там ничего нет.
Было бы лучше удаленно подключиться и посмотреть, в чем проблема.
Не могли бы Вы написать на support.team@bpmonline.com для скорейшего разрешения проблемы?

Показать все комментарии
Деталь
реестр
Технические вопросы
5.x

BPM 5.4.0
Может кто сталкивался с такой проблемой. Есть две детали, но смотреть их по отдельности, переключаясь от одной к другой, неудобно.
Необходимо их объединить. Так чтобы в одном окне были два этих реестра (один под другим или слева и справа неважно). Как сделать, есть ли примеры?

Нравится

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

Здравствуйте, Александр!
Такая деталь реализована в BPMonline Service Desk (раздел "Инциденты" (или "Обращения"), деталь "Комментарии").
Принцип следующий:
на страницу детали добавляется два layout'а. В один помещается собственно реестр детали, а в другой - страница реестра дополнительной детали:

Обратите внимание на положение компонента DataSource. В текущей реализации это важно!

Нет возможности развернуть Service Desc (у клиента CRM) может там есть примеры, если нет, то не могли бы скинуть файлик окна?

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

commentary.rar

Показать все комментарии
Технические вопросы
Разработка

Добрый день сообщество. Подскажите был ли у кого опыт переноса доработок из 3.3.1 в 3.4? Какими средствами решали данную задачу?

Нравится

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

Я делал.
В любом случае вам надо понадобится TSMerge.exe, что-то типа Araxis Merge, скрипты SQL чтобы перенести данные в новую базу (это имхо проще, чем дорабатывать базу - там очень много изменений)

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

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

В таком случае алгоритм такой:

1. Составляете перечень доработок - для этого сравниваете вашу конфигурацию с базовой вашей версии (3.3.1)

2. Берете новую чистую базу версии 3.4.1. Назовем ее ТЕСТ

3. Дублируете все ваши доработки (или не все, а только за исключением ненужных, как было у нас) в ТЕСТ. Т.е. в основном делаете их заново - копипастом с (если нужно) коррекцией и адаптацией. Это первая весомая часть работы.

4. Тестируете ТЕСТ. Мой совет: желательно делать это как можно более тщательно. И когда вам покажется, что все ок, проверить все еще раза три - уже чужими руками и глазами.

На данном этапе вы должны иметь новую тестовую базу версии 3.4 (ТЕСТ) со всеми доработками - в том числе со всеми вашими справочниками и, пожалуй, их значениеями. Значения не заводите заново а копируйте со старой базы:

insert into [TEST].[dbo].[tbl_SomeDictionary]
select * from [OldBase].[dbo].[tbl_OldNameOfSomeDictionary]

5. Переносите данные из старой базы в новую с помощью SQL-скрипта. Это вторая весомая часть работы.
Т.к. между таблицами есть связи то... есть два варианта:
-- правильный. Вы копируете данные в нужном порядке. Например, перед тем как скопировать таблицу контрагентов, вы копируете все справочники. А перед тем как копировать детали вы копируете все разделы, на которые они ссылаются. И т.д. и т.п.
Дело в том, что вам все равно где-то придется сбросить связи между таблицами. Поэтому я не стал ломать голову и пошел по второму пути:
-- неправильному. Я сбросил сразу все связи:

-- дропаем все ключи
 
-- tbl_Account
ALTER TABLE [dbo].[tbl_Account] DROP CONSTRAINT [FAccountAccountTypeID]
ALTER TABLE [dbo].[tbl_Account] DROP CONSTRAINT [FAccountActivityID]
ALTER TABLE [dbo].[tbl_Account] DROP CONSTRAINT [FAccountAddressTypeID]
ALTER TABLE [dbo].[tbl_Account] DROP CONSTRAINT [FAccountCampaignID]
...
etc

всего 523 строчки скрипта ))

После этого я скопировал данные. Всего 2644 строчки скрипта))

А после этого восстановил сразу все связи:

-- tbl_Account
ALTER TABLE [dbo].[tbl_Account]  WITH CHECK ADD  CONSTRAINT [FAccountAccountTypeID] FOREIGN KEY([AccountTypeID]) REFERENCES [dbo].[tbl_AccountType] ([ID])
ALTER TABLE [dbo].[tbl_Account] CHECK CONSTRAINT [FAccountAccountTypeID]
 
ALTER TABLE [dbo].[tbl_Account]  WITH CHECK ADD  CONSTRAINT [FAccountActivityID] FOREIGN KEY([ActivityID]) REFERENCES [dbo].[tbl_Activity] ([ID])
ALTER TABLE [dbo].[tbl_Account] CHECK CONSTRAINT [FAccountActivityID]
 
ALTER TABLE [dbo].[tbl_Account]  WITH CHECK ADD  CONSTRAINT [FAccountAddressTypeID] FOREIGN KEY([AddressTypeID]) REFERENCES [dbo].[tbl_AddressType] ([ID])
ALTER TABLE [dbo].[tbl_Account] CHECK CONSTRAINT [FAccountAddressTypeID]
...
etc

всего 1093 строчек скрипта))

6. Тестируем то, что получилось после переноса и долго ловим баги :exclaim:

7. Когда все проверили пятьсот раз - копируем данные заново (т.к. пока вы все это делали работа-то не стояла)

Естественно не забываем постоянно бекапить все базы, с которыми работаем.
Прикладываю мои скрипты и скрипт от техподдержки Террасофт, на основе которого я все и делал

Поддерживаю Дмитрия, причем придерживаюсь мнения, что надежнее переносить свои доработки на 3.4 (второй вариант).

Почитайте также, как мы переводили клиента с 3.0.4 на 3.3.1 - в общем то принципы переноса те же самые.
http://www.community.terrasoft.ua/blogs/4354
http://www.community.terrasoft.ua/blogs/4504

Валерий, а вы адаптировали эту утилиту под другие версии?

[quote="Валерий Андрусик"]Почитайте также, как мы переводили клиента с 3.0.4 на 3.3.1 - в общем то принципы переноса те же самые.
http://www.community.terrasoft.ua/blogs/4354
http://www.community.terrasoft.ua/blogs/4504[/quote]
Пишет недостаточно прав(( Почему?

Иван, здравствуйте.

А можно поподробней, на каком шаге, при каких действия у Вас возникает ошибка "Недостаточно прав"? Если можно также прикрепите скриншот.
Заранее спасибо!

Дмитрий, на этапе перехода по ссылке :lol:

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

"Андросов Дмитрий" написал:Валерий, а вы адаптировали эту утилиту под другие версии?

Да она не особо требует адаптации... Просто загружаем в нужную версию набор сервисов, которые были созданы еще для 3.0.4 :smile:

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

Да спасибо открылось. Валерий утилита миграции приобретаеться у Вас?

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

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

Отличная утилита. Перенес все новые сервисы в 3.4. Единственное что заметил почему то не обновились таблицы в БД. Это нужно каждую таблицу отдельно обновлять или это где то у меня косяк случился?

Должно сохранять - в коде есть вызов функции MigrateSaveTables
По крайней мере должно было выдать ошибку.

Походу из за _Right таблиц не перенеслись основные таблицы

Кстати, Right таблицы переносить не надо - они автоматически создадутся при переносе основных таблиц

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

Показать все комментарии
контроль версий
Технические вопросы
5.x

Добрый день,

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

У меня идея в том, чтобы делать полный экспорт исходного кода по конфигурации. Хорошо ли это?
Понятно, что есть конфигурации, но как сравнить исходный код.

Нравится

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

"Антон Сидоров" написал:У меня идея в том, чтобы делать полный экспорт исходного кода по конфигурации. Хорошо ли это?
Понятно, что есть конфигурации, но как сравнить исходный код.

Такое есть.

Показать все комментарии
ответственный
скрипт
фильтрация
Технические вопросы
5.x

BPM 5.4.0
Необходимо ставить в поле "Ответственный" в карточке Задачи не только контактов с типом "Сотрудник своей организации", но и с другим типом (допустим его id записан в переменную OtherTypeId)
В карточке задачи в скрипте ChildInitAfterParentScriptExecute есть такой код (наверняка он фильтрует)

Page.OwnerEdit.PrepareLookupFilter += delegate (object sender, LookupEditEventArgs e) {
        var employersContactTypeUId = "60733efc-f36b-1410-a883-16d83cab0980";          
        CollectionDictionarystring, object>> filters = e.Filters;
        filters.Add(new Dictionarystring, object> {
           {"comparisonType", FilterComparisonType.Equal},
           {"leftExpressionColumnPath", "Type"},
           {"useDisplayValue", false},
           {"rightExpressionParameterValues", new object[] {employersContactTypeUId}}});       
};

Как добавить еще один фильтр с условием ИЛИ?

Нравится

3 комментария
filters.Add(new Dictionary<string, object> {
           {"comparisonType", FilterComparisonType.Equal},
           {"leftExpressionColumnPath", "Type"},
           {"useDisplayValue", false},
           {"rightExpressionParameterValues", new object[] {employersContactTypeUId}},
           {"logicalOperation", FilterComparisonType.Or}
}); 
filters.Add(new Dictionary<string, object> {
           {"comparisonType", FilterComparisonType.Equal},
           {"leftExpressionColumnPath", "Type"},
           {"useDisplayValue", false},
           {"rightExpressionParameterValues", new object[] {otherTypeUId}},
           {"logicalOperation", FilterComparisonType.Or}
}); 

Александр, думаю, вы немного ошиблись вместо FilterComparisonType.Or надо LogicalOperationStrict.Or.
Но все равно в результате этого у меня выводит пустой список.

Как часто: сам задал вопрос, сам ответил.
А все тупо:

filters.Add(new Dictionary<string, object> {
           {"comparisonType", FilterComparisonType.Equal},
           {"leftExpressionColumnPath", "Type"},
           {"useDisplayValue", false},
           {"rightExpressionParameterValues", new object[] {employersContactTypeUId,otherTypeUId}},
});
Показать все комментарии