Технические вопросы
5.x

Задача раскрасить основной реестр раздела давно решенна, но возникла другая: раскрасить реестр ДЕТАЛИ РАЗДЕЛА.

Не пойму как.....

Нравится

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

Пытаюсь на PageLoadComplete страницы реестра детали сделать так:

var primaryColumnValue = Page.DataSource.ActiveRow.PrimaryColumnValue;
 
var config = new DataSourceRowConfig(primaryColumnValue);
 
config.AddConfig(new DataSourceRowColorConfigValue("Red"));

но вылетает на первой же строчке....

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

Александр, попробую уточнить возможно ли, и если да - то как у коллег из департамента разработки. Результат сообщу Вас сегодня в течении дня.

Очень бы хотелось чтобы возможно..... :biggrin:

Александр, судя по всему - возможно :)

Шаги:

1. Создать метод в нужной Вам странице реестра - GetDetailRowConfig(Entity module). Ну к примеру:

string primaryColumnName = module.Schema.PrimaryColumn.Name;
string primaryColumnValue = module.GetColumnValue(primaryColumnName).ToString();
var config = new DataSourceRowConfig(primaryColumnValue);
string PriorityColumnValue = module.GetTypedColumnValue<Guid>("Priority").ToString();
if(PriorityColumnValue == "guid приоритета критичный"){
   config.AddConfig(new DataSourceRowColorConfigValue("Red"));
}else if(PriorityColumnValue == "guid приоритета важный") {
   config.AddConfig(new DataSourceRowColorConfigValue("Yellow"));
}

2. На PageLoad (по аналогии с BaseModulePage) прописать делегаты:

Page.TreeGrid.GetRowConfigHandler = GetDetailRowConfig;
Page.DataSource.Loaded += Page.TreeGrid.DataLoaded;

Супер, опробую завтра с утра.

Все заработало, супер, спасибо.

"Олейник Дмитрий" написал:

Александр, судя по всему - возможно :)

Шаги:

1. Создать метод в нужной Вам странице реестра - GetDetailRowConfig(Entity module). Ну к примеру:

string primaryColumnName = module.Schema.PrimaryColumn.Name;

string primaryColumnValue = module.GetColumnValue(primaryColumnName).ToString();

var config = new DataSourceRowConfig(primaryColumnValue);

string PriorityColumnValue = module.GetTypedColumnValue<Guid>("Priority").ToString();

if(PriorityColumnValue == "guid приоритета критичный"){

   config.AddConfig(new DataSourceRowColorConfigValue("Red"));

}else if(PriorityColumnValue == "guid приоритета важный") {

   config.AddConfig(new DataSourceRowColorConfigValue("Yellow"));

}

2. На PageLoad (по аналогии с BaseModulePage) прописать делегаты:

Page.TreeGrid.GetRowConfigHandler = GetDetailRowConfig;

Page.DataSource.Loaded += Page.TreeGrid.DataLoaded;

С уважением,

Олейник Дмитрий

Эксперт 3-й линии поддержки


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

Page.TreeGrid.GetRowConfigHandler = delegate(Terrasoft.Core.Entities.Entity row) {                   
	string primaryColumnName = row.Schema.PrimaryColumn.Name;
	string primaryColumnValue = row.GetTypedColumnValue<string>(primaryColumnName);
	var config = new DataSourceRowConfig(primaryColumnValue);
	Guid resultId = row.GetTypedColumnValue<Guid>("DesignatedUseStatusId");
	string cellColor = String.Empty;
	//Указываем цвет фона ячеек реестра в зависимости от условия
	if (resultId.Equals(new Guid("{F79FBF11-5799-55E8-E043-323E1EACFB56}"))) { //Целевое использование не подтверждено
		cellColor = "Red";
	//	config.AddConfig(new DataSourceRowColorConfigValue(cellColor));
	}
	if (resultId.Equals(new Guid("{F79FBF11-5798-55E8-E043-323E1EACFB56}"))) { //Целевое использование подтверждено
		cellColor = "Green";
	//	config.AddConfig(new DataSourceRowColorConfigValue(cellColor));
	}
 
	var cellsBackground = new Dictionary<string, DataSourceRowColumnBackgroundColorConfigValue>();
	if (!cellColor.Equals(String.Empty)) {
		cellsBackground.Add("Result", new DataSourceRowColumnBackgroundColorConfigValue(cellColor));
		config.AddConfig(new DataSourceRowColumnsBackgroundColorConfigValue(cellsBackground));
	}
 
	return config;
};
Page.DataSource.Loaded += Page.TreeGrid.DataLoaded;
 
return true;

В делегате все ок.
Возможно, проблемы есть на диаграмме. Событийный подпроцесс для цепочки сообщений PageLoad и скрипта создали?

"Maxim Gritsenko" написал:

В делегате все ок.

Возможно, проблемы есть на диаграмме. Событийный подпроцесс для цепочки сообщений PageLoad и скрипта создали?


я все сделал как должно быть и Событийный подпроцесс тоже, высылаю скриншот.

Какая версия/сборка?

"Maxim Gritsenko" написал:

Какая версия/сборка?


Версия 5.1.1.159

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

"Maxim Gritsenko" написал:

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

Добрый день. Максим,
вы уточнили у свойх коллег?

Добрый день.
Пока что в процессе.

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

Пришел ответ от коллег из разработки.

Да, это возможно. Более того, код из вложения должен работать. Специально развернул 5.1.1 и проверил (практически один в один переписал код клиента). Раскраска реестра работает.

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

1) В реестр не вынесена (скрыта) колонка с названием Result;
2) В схеме реестра вообще отсутствует колонка с названием Result.

Я проверил и для текстовых полей, и для полей типа «Справочник» - вот результат:

На всякий случай привожу код обработки LoadPage (пример для базовой страницы реестра адресов):

Page.TreeGrid.GetRowConfigHandler = delegate (Terrasoft.Core.Entities.Entity row) {
string primaryColumnName = row.Schema.PrimaryColumn.Name;
string primaryColumnValue = row.GetColumnValue(primaryColumnName).ToString();
var config = new DataSourceRowConfig(primaryColumnValue);
Guid TypeColumnValue = row.GetTypedColumnValue<Guid>("AddressTypeId");
string cellColor = String.Empty;
if(TypeColumnValue.Equals(new Guid("{4F8B2D67-71D0-45FB-897E-CD4A308A97C0}"))){
cellColor = "Red";
}else if(TypeColumnValue.Equals(new Guid("{780BF68C-4B6E-DF11-B988-001D60E938C6}"))) {
cellColor = "Yellow";
}
var cellsBackground = new Dictionary<string, DataSourceRowColumnBackgroundColorConfigValue>();
if (!cellColor.Equals(String.Empty)) {
                cellsBackground.Add("Address", new DataSourceRowColumnBackgroundColorConfigValue(cellColor));
                cellsBackground.Add("Country", new DataSourceRowColumnBackgroundColorConfigValue(cellColor));
                config.AddConfig(new DataSourceRowColumnsBackgroundColorConfigValue(cellsBackground));
}
 
return config;
};
Page.DataSource.Loaded += Page.TreeGrid.DataLoaded;
return true;
Показать все комментарии
DataGrid
excel
Технические вопросы
Разработка

Как то можно повлиять на выгрузку в Excel из DataGrid? Не устраивает как даты выгружаются, хотелось бы дописать логику выгрузки. Еще есть необходимость проставлять типы ячеек.

Нравится

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

Здравствуйте, Михаил Евгеньевич!

Механизм экспорта записей из реестра в MS Excel реализован на уровне ядра приложения Terrasoft.

В связи с этим, возможности внести конфигурационные изменения в него нет.

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

Добрый день! Столкнулись с такой проблемой: при выборе двух записей для объединения в контрагентах, через "Действия"-"Объединить выделенные записи". После выбора данных которые должны отображаться в итоговой записи и нажатии на кнопку "Объединить", вылетает ошибка "При слиянии записей произошла ошибка - Error converting data type nvarchar to int". Смысле ошибки понятен, что какие-то поля не конвертируются к нужному типу. Но проблема в том, что не получается отследить из-за каких полей могут быть косяки.
Может кто сталкивался с такой проблемой или знает как можно решить её, буду очень признателен!

Нравится

1 комментарий
Закрыть окно
закрыть приложение
Технические вопросы
Разработка

Добрый день!

Никто не сталкивался с проблемой - как закрыть окно приложения сразу же после логина?

Т.е. при логине я проверяю некоторые условия и не хочу чтобы продолжался запуск и инициализация разделов и пр.
в OnPrepare окна wnd_Main вызов метода Close() не помогает - остается "шапка" приложения без разделов внутри.

Спасибо!

Нравится

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

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

Выключиться можно так:

Connector.Attributes('ForceClose') = true;
Connector.Logoff();

Спасибо, Максим, попробую сделать так.

Я перенес логику на событие wnd_MainOnActivate, вроде все закрывается, единственное - все равно отрисовывается "шапка". Но цель - не дать пользователю работать, выполняется :)

Хитрый пользователь может в пошаговом режиме перешагнуть проверку и выход.

К счастью, у наших хитрых пользователей не было, нет и не будет Visual Studio на машинах :)

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

Приветствую.
У меня поле LookupDataControl отображает список одного из полей датасета(Description).
Допустим, я выбрал из списка одно из значений.
Как мне получить соответствующия этому Description значения из других колонок(например его ID и т.д.)?

Нравится

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

То есть, как мне можно обратиться, каким методом к полю LookupDataControl, забрать из него значения соответствующие соседней другим колонкам в записи?
Что я только не перепробовал...

edt...LookupDataset.DataFields('ID').Value...
Миллион этих вариаций. Не могу никак угадать и попасть в метод. Выручайте...)

Как вообще зацепиться за лукап датасет какого-то поля и обращаться к его колоночкам?
В функции OnPrepareSelectWindow всё просто, там этот лукапДС передается в виде параметра, а самому как его взять...Туплю)

Поле справочного типа (Lookup) содержит идентификатор (ID) и отображаемое значение.
Код вида:

var OfferingID = dlData.Dataset.Values('OfferingID');

вернет идентификатор выбранного значения.
Такой код:

var OfferingName = dlData.Dataset.DisplayValues('OfferingID');

вернет отображаемое значение.
Где OfferingID - название поля в датасете.

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

var OffDataset = Services.GetNewItemByUSI('ds_Offering');
ApplyDatasetFilter(OffDataset, 'OfferingID', OfferingID, true);
OffDataset.Open();
var OfferingCode = OffDataset.Values('Code');
OffDataset.Close();

Наталья, у меня чуть замороченее ситуация:

Упрощу для рассказа:
Есть поле ввода Индекса(IntegerDataControl) скажем для датасета dlData.
Второе поле - LookupDataControl для датасета dlContact.

После ввода числа в поле Индекса на событии выхода из поля OnExit происходит присваивание переменной Index, равной соответственно введенному значению.

На событии OnPrepareSelectWindow для LookupDataControl'a поля у меня происходит ApplyDatasetFilter(LookupDataset, 'Index', Index, true), после чего лукапдатасет рефрешется, и в выпадающем списке остаются уже отфильтрованные по индексу строчки.

Мне требуется:
1. Выбрать одну любую строчку
2. Получить значение этой строчки(которое отображается) (Description)
3. Получить соответствующую этому Description запись из другого столбца, к примеру(ID), либо (City) и т.д.

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

Что-то как-то запутано объясняете.
У вас это все происходит в карточке редактирования?
Наталья объяснила основы, я попробую показать на примере, может яснее станет либо для вас, либо для нас, что же вы хотите.

Допустим надо узнать первое средство связи основного контакта из карточки контрагента, тогда нам надо
посмотреть, что из себя представляет lookup-поле "основной контакт"


DatasetLink = dlData
DataFieldName = PrimaryContactID

тогда

//узнаем id основного контакта
var ContactID = dlData.Dataset.Values('PrimaryContactID');
//проверка на то, что в поле указан основной контакт
if (ContactID !=null) {
     //берем запись контакта из датасета, к которому он привязан, это можно узнать в ds_Account
     var ContactDataset = GetOpenedDatasetByUSIWithFilter('ds_Contact','ID', ContactID);
     //записываем в переменные значения интересующих нас полей
     var Communication1 = ContactDataset.Values('Communication1');
     var Communication1TypeName = GetDatasetFieldValueByID('ds_CommunicationType', ContactDataset('Communication1TypeID'), 'Name') //зная id записи с помощью этой функции можно вынуть значения нужного нам поля
     //в итоге можно вывести, например "Телефон: 123456" или "e-mail: 123123.ru"
     Log.Write(1, Communication1TypeName + ': ' + Communication1);
}

Вот так можно получать нужную вам информацию.

Наталья, строчка dlData.Datset.Values('Value') возвращает то что нужно, но проблема в том, что когда я меняю значение в поле LookupDataControl - значение остается прежним(для поля, которое выбирается по умолчанию), а не переписывается на новое выбранное. Как возможно это решить?

Проще говоря, я думал что при смене значения в лукапдатаконтроле, позиционирование датасета на запись соответственно этому контролу меняется. А тут походу нет...Помогите разобраться..

Когда меняете значение поля скриптом, поле у вас выделено (находится в активном состоянии)?

"Сазанов Александр Владимирович" написал:

Когда меняете значение поля скриптом, поле у вас выделено (находится в активном состоянии)?


Оно активируется в случае наличия записей в датасете после фильтрации. Если есть записи ->dlDataset.Open();

Видимо не так меня поняли, или я не так вас понял, может быть у вас похожая проблема как эта?

В общем конкретизирую и объясню задачу:

Имеется поле для ввода данных(Index) в ручную.
Имеется поле LookupDataControl(привязан к датасету dlData).

При вводе данных вполе Index после выхода из него на событии OnExit происходит присваивание переменной Index в соответствии с введенным значением, сразу же активируется фильтр ApplyDatasetFilter(dlData.Dataset, 'Index', Index, true).
После чего, выполяется условие
if (dlData.Dataset.RecordsCount > 0){
dlData.Dataset.Open();
}

Отсюда поле становится активным.
На событии OnPrepareSelectWindow у данного LookupDataControl выполняется функция:

PrepareLookupDataControl(LookupDataControl, dlDemand.Dataset);
var Dataset = dlDemand.Dataset;
var DataFieldName = LookupDataControl.DataFieldName;
var DataField = Dataset.DataFields.ItemsByName(DataFieldName);
var Index = dlNewContactClient.Dataset.DataFields('Index').Value;
var LookupDataset = DataField.LookupDataset;
ApplyDatasetFilter(LookupDataset , 'Index', Index, true);
edtDemandAdress.UnprepareDropdownList();
RefreshDataset(LookupDataset );

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

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

Да-с, запутливый у вас код, для начала

"Нестеров Артем Валерьевич" написал:ApplyDatasetFilter(dlData.Dataset, 'Index', Index, true).
После чего, выполяется условие
if (dlData.Dataset.RecordsCount > 0){
dlData.Dataset.Open();
}

Если у вас записей больше 0, то датасет dlData.Dataset уже открыт, то зачем его открывать второй раз или это уже надо открыть с фильтром? Либо переоткрыть, либо это вообще не надо.

if (dlData.Dataset.RecordsCount > 0) {
    ApplyDatasetFilter(dlData.Dataset, 'Index', Index, true);
   RefereshDataset(dlData.Dataset);
}

Следующее, кто мешает получить LookupDataset в одну строчку?

var LookupDataset = LookupDataControl.DataField.LookupDataset;

Идем дальше, вы случаем не edtDemandAdressOnPrepareSelectWindow описали?
Только этим я могу объяснить строчки:

edtDemandAdress.UnprepareDropdownList();//тут вы сбрасываете список?
RefreshDataset(LookupDataset );//а тут вы его переоткрываете?

Если это так, то edtDemandAdress.UnprepareDropdownList(); надо вешать туда, где вы считаете индекс, а тут он не нужен. Если не так, то я ничего не понял.
Следующее, что меня смущяет: dlData, dlDemand, dlNewContactClient. Такое количество датасетов обычно только в воркспейсе, но писать это там самоубийство, в скрипте какого окна все пишется грид или эдит?
Короче, на словах ничего не понятно, не видно. Надо подключаться, через teamviewer например.

Как обращаться я писал в комментарии 5 и Наталья в комментарии 3:
LookupControl.Value - будет содержать id записи
Допустим у вас к lookupControl привязаны контакты, выбираете, отображается "Иванов Иван", но их может быть 2-3, а то и более штук, поэтому в LookupControl храниться id контакта
получить датасет этого контакта можно так

var ContactDataset = GetOpenedDatasetByUSIWithFilter('ds_Contact', //USI датасета, к которому должен быть привязан lookup-поле
'ID', //название фильтра, он должен быть в sq_Contact
LookupControl.Value //Id записи, которое мы получили
);

потом получайте, что хотите
ContactDataset('Name')
ContactDataset('Address') и т.д.

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

В случае LookupControl получить значения можно так:

var Dataset = LookupControl.LookupDatasetLink.Dataset;
Dataset.Locate('ID', LookupControl.Value);
var FieldValue = GetFieldValueFromDisabledField(Dataset, 'FieldName')

Наталья, а LookupControl это имя поля получается?

Да, LookupControl - это имя добавленного контрола.

Дальше появилась вообще непонятная проблема.

Ввожу индекс, выхожу из поля, на событии OnExit происходит фильтрация датасета и его рефреш, в поле LookupControl выбираю одно из отфильтрованных значений(всё работает как надо).
Если после этого я снова ввожу индекс, то появляется неопознанная ошибка. Пробовал уже и закрывать датасет - ничего не помогает. Проще говоря, если что-то выбрано в поле LookupControl, то при изменении индекса появляется ошибка(на моменте выполнения рефреша). Также пробовал присвоить LookupControl.Value = null - проблема также остается. Прошу помощи.

P.S. Как я понял, может помочь деинициализация этого LookupControl'a, но не знаю как этого сделать и возможно ли это...

Артем, вложите, пожалуйста, сервисы.

Наталья, может ЛукапКонтрол прописывается куда-то в атрибуты окна? Как вернуть его состояние до захода?

Наталья, так сможете посмотреть?

function edtIndexOnExit(Control) {          //Ловим значение на OnExit из вводимого поля индекса
                var Index = dlNewContactClient.Dataset.DataFields('Index').Value;      //Само значение
                var DemandDataset = dlDemand.Dataset;          //Датасет по которому производится фильтрация для просмотра лукап поля
                edtDemand.Value = null;            //Обнуляю значение лукап поля для случая изменения индекса
                if (Index != null){  
                               var IsDemand = CheckIsDemandPossible(DemandDataset, Index);      //Ну собственно, начали
                }     
}
 
 
function CheckIsDemandPossible(DemandDataset, Index){       
                DemandDataset.Close();             //Закрыл датасет для фильтрации(на случай если уже открывали при обращении к лукапу)
                ApplyDatasetFilter(DemandDataset, 'Index', Index, true);         //Включили фильтр
                DemandDataset.Open();         //---Здесь и идет сваливание,если поле лукапа было открыто пользователем---                                                 
                if (DemandDataset.RecordsCount != 0){              //Это уже возвращаемые значения для дальнейшей работы
                                               if (System.MessageDialog("Индекс запрещен к отправке.\r\nОформить до востребования - нажмите 'да', \r\nотменить заказ - нажмите 'нет'", mdtWarning,
                                                               (mdbYes + mdbNo), 0) == wmrYes) {
                                                                 return 1;
                                               }
                                               else return 0;    
                }
                return 2;              
}
 
 
/*Не понятно почему он не хочет открываться в нужном месте. Если придется убирать оттуда это открытие – это потянет за собой переработку логики модуля. Может быть есть способ деинициализировать лукапконтрол, т.е. перевести его в то состояние, каким он является до начала работы с ним? Всё комьюнити перерыл – ничего не нашел.*/

Когда в лукапконтрол не заходишь - всё отрабатывает великолепно. Но стоит туда зайти, даже не обязательно выбирая запись просто выйти - при следующем OnExit датасет уже не открывается в том месте где я указал сваливание

Артем попробуйте переделать функцию так (если фильтр применяется для чего-то еще, то не подойдет, если только узнать кол-во, то можно работать с копией):

function CheckIsDemandPossible(DemandDataset, Index) {       
                var DemandDatasetCopy = Services.GetNewItemByUSI(DemandDataset.USI);
                DemandDatasetCopy.Close();             //Закрыл датасет для фильтрации(на случай если уже открывали при обращении к лукапу)
                ApplyDatasetFilter(DemandDatasetCopy, 'Index', Index, true);         //Включили фильтр
                DemandDatasetCopy.Open();         //все еще есть сваливание?                                                 
                if (DemandDatasetCopy.RecordsCount != 0) {              //Это уже возвращаемые значения для дальнейшей работы
                                               if (System.MessageDialog("Индекс запрещен к отправке.\r\nОформить до востребования - нажмите 'да', \r\nотменить заказ - нажмите 'нет'", mdtWarning,
                                                               (mdbYes + mdbNo), 0) == wmrYes) {
                                                                 return 1;
                                               }
                                               else return 0;    
                }
                return 2;              
}

Вернул аналогичным

Артем, отладчик ставили перед Dataset.Open?
Можно увидеть текст запроса (Dataset.SelectQuery.SQLText) который будет отправлен на сервер?
Также советую перед Dataset.Open() делать EnableDatasetFilters(Dataset, false);

PS: а какая ошибка при свале на Dataset.Open() ?

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

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

Здравствуйте!
Можно ли узнать Id контакта, который является пользователем BPM, по Id, который я получаю в коде как

UserConnection.CurrentUser.Id

Решено. Id пользователя и связь с контактом находится в таблице SysAdminUnit

Нравится

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

"Эмин Юнусов" написал:UserConnection.CurrentUser.Id

Добрый день.
UserConnection.CurrentUser.ContactId

Можно проще:

UserConnection.CurrentUser.ContactId;

а ещё есть:

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

Добрый день.
Возникла следующая проблема:
Существовал бизнес процес, по которому было много документов.
Процесс изменили вместе с изменением внутренней логики, соответственно изменился порядок и количество задач в процессе.
Вопрос:
1. Как можно корректно завершить старые процессы (т.е. сохранить процесс_old) и паралельно запускать новые процессы.
2. Как изменить текущий процесс со старого на новый.

По пункту 1 сделал так:
- создал копию процесса = процесс_new и опубликовал, в таблице SysSchemaInSolution откатился до предыдущей версии процесса.
- Переименовал процесс в процесс_old и опубликовал.
- Переименовал процесс_new в процесс и опубликовал.
- в таблице [SysModuleAction] изменил ссылку действия на новый процесс.
Все заработало.

Но проблема по пункту 2 осталась. как изменить ID процессов запущенных с момента обновления сервиса до изменения его ID

Нравится

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

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

Здравствуйте, Андрей.
Мне нужно изменить ID процесса который выполняется.
т.е. был процесс, а стал процесс_new, и мне нужно чтобы дальнейшее выполнение происходило в процесс_new (внутренне они идентичны).

Илья, можете попробовать поменять [SysSchemaId] и [Name] в таблице [SysProcess], но не уверен, что изменение [SysSchemaId] не приведет к нарушению работы процесса.
Во всяком случае, при изменении [Name] Вы будете видеть, где какой процесс.

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

Использую вот такой вот скрипт, где FileID - id нашего файла

EntitySchemaManager esqManager = UserConnection.EntitySchemaManager;
var esqResult = new EntitySchemaQuery(esqManager, "File");
esqResult.AddAllSchemaColumns();
esqResult.AddColumn("Data");
Entity currentFile = esqResult.GetEntity(UserConnection, FileID);
       
//файл должен появиться
while (currentFile == null) {
        currentFile = esqResult.GetEntity(UserConnection, FileID);     
}
var currentFileName = currentFile.GetTypedColumnValuestring>("Name");
var currentFileData = currentFile.GetBytesValue("Data");

var Response = Page.Response;

Response.AddHeader("Content-Disposition", "attachment; filename=\""" + System.Web.HttpUtility.UrlPathEncode(currentFileName) + ""\"""");

Нравится

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

Здравствуйте, Александр!
Думаю, стоит воспользоваться готовым решением из процесса "Скачать шаблон для импорта контрагентов", например:

public virtual bool DownloadTemplateScriptExecute(ProcessExecutingContext context) {
			var entitySchemaManager = UserConnection.EntitySchemaManager;
var entitySchema = entitySchemaManager.GetInstanceByName("File"); 
var entitySchemaQuery = new EntitySchemaQuery(entitySchemaManager, entitySchema.Name);
 
var dataColumn = entitySchemaQuery.AddColumn("Data");
entitySchemaQuery.Filters.Add(
	entitySchemaQuery.CreateFilterWithParameters(
		FilterComparisonType.Equal, "[KnowledgeBaseFile:FileId].KnowledgeBase", new object[] {new Guid("edb71f06-f46b-1410-e980-20cf30b39373")}));
entitySchemaQuery.Filters.Add(
	entitySchemaQuery.CreateFilterWithParameters(
		FilterComparisonType.Equal, "Name", new object[] {FileName.ToString()}));
 
var entityCollection = entitySchemaQuery.GetEntityCollection(UserConnection);
if (entityCollection.Count > 0) {
	var data = entityCollection[0].GetBytesValue(dataColumn.Name)  as byte[];    
	var response = HttpContext.Current.Response; 
	TSConfiguration.PageResponse.Write(response, data, FileName, TSConfiguration.ContentType.XmlType);
}
 
return true;
		}

К сожалению у меня TSConfiguration не знает методов PageResponse и ContentType, и в процессе "Скачать шаблон ..." вместо TSConfiguration стоит скрипт

Response.AddHeader("Content-Disposition", "attachment; filename=\"" + System.Web.HttpUtility.UrlPathEncode(FileName) + ""\"""");

Александр, какая у Вас версия ядра?
Попробую воспроизвести.
По поводу загрузки данных попробуйте перед вызовом LoadRows() установить

Page.DataSource.PageRowsCount = -1; //или заведомо вольшое числ
Показать все комментарии

Добрый день.
Подскажите пожалуйста, можно ли указать страницу объекта при действии "Открыть страницу выбора из справочника"

Нравится

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

Здравствуйте, Илья!
Пример Вам в помощь.
Открытие окна выбора элемента из справочника (с фильтрами)
Создать Действие процесса (UserTask). Действие = Открыть страницу выбора из справочника

Создать скрипт подготовки перед действием и написать в нем следующее:

var SSDocumentOfferingtId = new Guid(SysSettings.GetValue(UserConnection, "SSDocumentOfferingtId").ToString());//UID Объекта
Collection<Dictionary<string, object>> filters = new Collection<Dictionary<string, object>>(); 
filters.Add(new Dictionary<string, object> { 
    {"comparisonType", FilterComparisonType.Equal},
    {"leftExpressionColumnPath", "Document"},
    {"useDisplayValue", false},
    {"rightExpressionParameterValues", new object[] {ParentDocumentSpecificationId}}
});
filters.Add(new Dictionary<string, object> { 
    {"comparisonType", FilterComparisonType.NotEqual},
    {"leftExpressionColumnPath", "IsVsat"},
    {"useDisplayValue", false},
    {"rightExpressionParameterValues", new object[] {true}}
});
filters.Add(new Dictionary<string, object> { 
    {"comparisonType", FilterComparisonType.IsNull},
    {"leftExpressionColumnPath", "[ProductsParts:DocumentOffering].Parent"},
    {"useDisplayValue", false},
    {"rightExpressionParameterValues", new object[] {}}
});
 
OpenSpecOfferingLookupUserTask.ProcessKey = InstanceUId;
OpenSpecOfferingLookupUserTask.PageParameters = new Dictionary<string, object>() {
    {"LookupFilters", filters},
    {"schemaUId", SSDocumentOfferingtId},
    {"customClosedEvent", "SpecOfferingLookupPageClosed"} //Сообщение при закрытии окна
};
OpenSpecOfferingLookupUserTask.UseCurrentActivePage = true;
return true;

Создать скрипт обработки после действия и написать в нем следующее:

var offerings = OpenSpecOfferingLookupUserTask.GetSelectedValues(UserConnection) as Dictionary <string, object>;
var offeringId = Guid.Empty;
foreach (var offering in offerings) {
    offeringId = new Guid(offering.Key.ToString());
    break;
}
if (offeringId == Guid.Empty) {
    return true;
}
return true;

Здравствуйте Андрей.
В этом примере используется стандартный справочник, а мне нужно использовать свою собственную страницу отображения справочника. Вопрос как в Действие = Открыть страницу выбора из справочника подставить свою страницу отображения?

Илья, насколько я вижу из кода действия, то за то, какая страница будет открыта отвечает параметр "lookupPageSchemaUId". Попробуйте добавить его в PageParameters с соответсвующим UId страницы.

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

  pageParameters.Add("lookupPageSchemaUId", "dff16a7e-027f-45aa-8662-1a4f01c4238c");

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

Илья, здравствуйте.

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

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

Показать все комментарии
7.x
Обновление детали
Технические вопросы

Добрый день!
Нужно при выборе продажи в счете подтягивать все оборудование из продажи в счет.
Деталь «Оборудование» создана по аналогии с деталью «Продукты».
Оборудование сохраняю вот так:

this.methods.InsertEquipment = function(Equipment, Invoice) {
var insert = Ext.create('Terrasoft.InsertQuery', {
rootSchemaName: 'InvoiceEquipment'
});
insert.setParameterValue('Equipment', Equipment, Terrasoft.DataValueType.GUID);
insert.setParameterValue('Invoice', Invoice, Terrasoft.DataValueType.GUID);
return insert;
};
Но на странице счета оборудование в детали сразу не появляются (только после обновления страницы).

Как можно решить эту проблему?

Нравится

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

Здравтсвуйте, Елена!
Для обновления детали необходимо вызвать после update'a в БД соответсвующую функцию:

this.reloadDetail('detailName');

Или можно в глобальную переменную сохранить this в методе "init", а затем через эту переменную вызывать уже reloadDetail.

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