Добрый день.

Есть используемые разделы Лиды, Тендеры, Продажи. Для того чтобы посмотреть количество завершенных или не завершенных проектов по ответственному, необходимо заходить в каждый раздел и смотреть там. А необходима вся картина целиком: Ответственный и все продажи, тендеры и лиды по нему с определённым фильтром - как это можно сделать?

Был другой вариант, вести все записи в одном разделе (например Продажи) с присвоением типа продажа/лид/тендер - но тогда другая проблема: отображение колонок в разделе строго определенное. Есть возможность сохранять разные варианты отображения колонок?

Нравится

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

Попробуйте построить диаграмму "Список" в разделе "Контакты". Сделайте фильтр по текущему контакту. Добавьте в диаграмму колонку, нажмите "+", выберите интересующий объект, в котором контакт является ответственным, и постройте по нему показатель. Например, "+" -> "Продажа (по колонке Ответственный)" -> "Количество". Настройте фильтры для объекта.

В диаграмме отобразятся показатели по отфильтрованным в разделе "Контакт" контактам.

Попробуйте построить диаграмму "Список" в разделе "Контакты". Сделайте фильтр по текущему контакту. Добавьте в диаграмму колонку, нажмите "+", выберите интересующий объект, в котором контакт является ответственным, и постройте по нему показатель. Например, "+" -> "Продажа (по колонке Ответственный)" -> "Количество". Настройте фильтры для объекта.

В диаграмме отобразятся показатели по отфильтрованным в разделе "Контакт" контактам.

Мне логичнее кажется 2-й вариант, так как тендер - это всего лишь Продажа с определённым типом (и возможно, со своими стадиями).



А настраивать колонки для разных фильтров можно с помощью дополнения https://marketplace.creatio.com/app/list-setup-folder-creatio

Или сделать схему по view, выбирающему при помощи union из интересующих таблиц нужные колонки в единообразном виде, создать раздел или справочник по ней. А потом смотреть в реестре или строить аналитику по ней.

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

Не могу понять в чем ошибка... помогите разобраться...

https://[url_app]/0/ServiceModel/EntityDataService.svc/ActivityCollection?$filter=CreatedOn ge datetime'2018-12-01T00:00' возвращает ошибку - см. аттач.

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

Нравится

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

<message xml:lang="">Unrecognized 'Edm.DateTime' literal 'datetime'2018-12-12T00:00'' in '13'.</message>

Очень интересно...

https://[url_app]/0/ServiceModel/EntityDataService.svc/ActivityCollection?$filter=CreatedOn ge datetime'2018-12-12' - а вот так заработало...

Как оказалось, если нужно с часовым поясом, то надо «/0/ServiceModel/EntityDataService.svc/ActivityCollection?$filter=CreatedOn ge datetime'2018-12-01T00:00:00' », так работает.

А еще в статье  путаница: 

где-то в примере указывают ?select=Id, а где-то $select...

по факту работает так:

$filter=CreatedOn ge datetime'2018-12-01'&$select=Id...

В спецификации тоже везде с долларом.

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

Добрый день.

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

Есть объект Акции и Партнеры. У акции есть справочное поле с типом акции. Есть бизнес-процесс, который по определённому алгоритму изменяет акции. Изменение акций выполняется  через элемент "Изменить данные".

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

Нравится

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

Можно делать не массовое изменение, а читать еще неизмененные, их изменять, индивидуально делать доп.действия, читать следующие неизмененные и т.п.



Второй вариант - сделать БП, который реагирует на изменение акции



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

Можно делать не массовое изменение, а читать еще неизмененные, их изменять, индивидуально делать доп.действия, читать следующие неизмененные и т.п.



Второй вариант - сделать БП, который реагирует на изменение акции



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

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

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

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

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

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

Здравствуйте, подскажите пожалуйста как можно добавить условия в выборку записей в секции, например:

...
where isActive = 0
...

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

 

Спасибо!

Нравится

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

Сериков Асхат Кайратович,

Если требуется, чтобы записи загружались изначально и фильтр нельзя было отрубить, то в схеме секции:

//можно ещё использовать функцию getFilters
initQueryFilters: function(esq) {
	var filters = this.callParent(arguments);
	//добавляем свои фильтры
	return filters;
}

 

Фильтр?

 

Алексей-Карягин пишет:

Фильтр?

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

Хотелось бы сразу выгружать отфильтрованные данные, а не применять фильтрацию на все данные  

Сериков Асхат Кайратович,

Если требуется, чтобы записи загружались изначально и фильтр нельзя было отрубить, то в схеме секции:

//можно ещё использовать функцию getFilters
initQueryFilters: function(esq) {
	var filters = this.callParent(arguments);
	//добавляем свои фильтры
	return filters;
}

 

Сериков Асхат Кайратович пишет:

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

Нет, фильтры работают не так. По условиям фильтрации класс EntitySchemaQuery формирует SQL-запрос, который и идёт от сайта в базу. А уже по нему из базы возвращается коллекция записей-результатов.

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

 

Сериков Асхат Кайратович,

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

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

Доброго дня!
Подскажите пожалуйста, необходимо сделать выборку по групповым задачам.
Начал делать по аналогии с выборкой по "Ответственному"
Добавил Lookup Control, сделал линк на датасет "Группа контактов". Вот только теперь при выборе группы контактов никакие задачи не отображаются. Что я сделал не так? Или может я что то не доделал?
Заранее спасибо

Нравится

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

Добрый день Дмитрий!!!

вы внимательно проанализируйте как происходит Инициализация и фильтрация раздела По контакту и вам все станет ясно. Одним добавлением DatasetLink-om там не обойдешься. Плюс прошу описать какая у вас платформа и конфигурация. Чтобы вам подсказать. Если уже будет сложно разобраться как происходит стандартная фильтрация. Я готов вам по полочкам разложить рассказать как это все работает.

Буду Вам очень благодарен если расскажете

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

Александр, вот я пытался сделать по аналогии, однако при выборе в поле "Группу ответственных" ничего не происходило.
Буду дальше пытаться :)

Lookup поле работает. Я могу выбрать группу контактов.
Видимо дело в чек боксе. Поскольку после нажатия задачи не фильтруются.

Вот обработчик чек-бокса для фильтрации по "Ответственному"

function chbShowForContactOnClick(Control) {
	if ((!IsEmptyValue(edtTaskOwner.Value) || !Control.IsChecked) && 
		BaseWorkspace.WasShowed && (!TasksWorkspace.NoRefresh)) {
		TasksWorkspace.TaskOwnerIsChanged = true;
		RefreshTasks();
	}
}

Подскажите пожалуйста как мне адаптировать этот код для моего чекбокса (

function chbShowForContactGroupOnClick(Control) {
 
}

Судя по строке:

TasksWorkspace.TaskOwnerIsChanged = true;

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

Как я понял все происходит именно здесь

function ApplyContactFilter() {
	var Dataset = BaseWorkspace.GridDataset;
	var Grid = BaseWorkspace.Grid;
	var IsGridPageActive = pcData.ActivePage.Name == pgGridData.Name;
	var MyTasksIsActive = IsGridPageActive &&
		(Grid.ActiveView.Name == TasksWorkspace.MyTaskView.Name);	
    var ForControlIsActive = IsGridPageActive &&
		(Grid.ActiveView.Name == TasksWorkspace.ForControlView.Name);
	chbShowForContact.IsEnabled = (!MyTasksIsActive);
	edtTaskOwner.IsEnabled = chbShowForContact.IsEnabled;
	fgShowTasksBody.IsEnabled = chbShowForContact.IsEnabled;
	var TaskOwnerID = edtTaskOwner.Value;
	var EmptyContact = IsEmptyGUID(TaskOwnerID) || (!chbShowForContact.IsChecked);
	var IDs = GetContactsFilterArray();
	if ((!IsGridPageActive) && (IDs.length == 0)) {
		if (ShowConfirmationDialog(
			"Действие может занять некоторое время. Продолжить?") != mrYes) {
			TasksWorkspace.NoRefresh = true;
			chbShowForContact.IsChecked = true;
			TasksWorkspace.NoRefresh = false;
			IDs.push(edtTaskOwner.Value);
		}
	}
	var ShowForContact = ((IDs.length > 0) || (!EmptyContact));
	if (EmptyContact) {
		TaskOwnerID = Connector.CurrentUser.ContactID;
	}
	if (IsGridPageActive) {
		SetAttribute(BaseWorkspace.GridWindow, 'OwnerID', TaskOwnerID);
		if (MyTasksIsActive) {
			EnableDatasetFilters(Dataset, true, 'MyTasks');
			return;
		}
		if (ForControlIsActive) {
			EnableDatasetFilters(Dataset, true, 'ForControl');
			if (IDs.length > 1) {
				EnableDatasetFilters(Dataset, false, 'CreatedByID');
				ApplyDatasetIncludeFilter(Dataset, 'CreatedByIDs', IDs, true);
			} else {
				EnableDatasetFilters(Dataset, false, 'CreatedByIDs');
				ApplyDatasetFilter(Dataset, 'CreatedByID', TaskOwnerID,
					ShowForContact);
			}
			SetAttribute(Self, 'ContactsFilterArray', IDs);
			return;
		}
	} else {
		var ScheduleControl = 
			wndSchedulerArea.Window.ComponentsByName('ScheduleControl');
		SetAttribute(TasksWorkspace.SchedulerWindow, 'OwnerID', TaskOwnerID);
		ApplyDatasetFilter(Dataset, 'ShowInScheduler', true, true);   			
	}
	if (ShowForContact) {
		if (IDs.length == 1) {
			SetContactWhite(IDs[0]);
		}
		SetAttribute(Self, 'ContactsFilterArray', IDs);
		BaseFilters = Dataset.SelectQuery.Items(0).Filters.Items(0);
		var Filter = BaseFilters.ItemsByCode('ContactIDs');
		if (!Assigned(Filter)) {
			Filter = BaseFilters.Items(0).ItemsByCode('ContactIDs');
		}
		var Parameters = Dataset.SelectQuery.Parameters;
		var TeamFilter = Filter.ItemsByCode('tcTeam');
		var SubSelectFilter = TeamFilter.TestExpression
			.ExpressionSelectQuery.Items(0).Filters;
		var OwnerIDsFilter = Filter.ItemsByCode('tcOwnerIDs');
		var ContactIDsFilter = Filter.ItemsByCode('tcContactIDs');
		var SubContactIDsFilter = SubSelectFilter.ItemsByCode('tcContactIDs');
		ApplyIncludeFilter(OwnerIDsFilter, IDs, true, null, Parameters);
        ApplyIncludeFilter(ContactIDsFilter, IDs, true, null, Parameters);
        ApplyIncludeFilter(SubContactIDsFilter, IDs, true, null, Parameters);
		TeamFilter.IsEnabled = true;
		Filter.IsEnabled = true;
	}            	
	var IsSchedulerPageActive = (pcData.ActivePage.Name == pgScheduler.Name);
	if (IsSchedulerPageActive) {
		if (TasksWorkspace.TaskOwnerIsChanged) {
			if (ShowForContact) {
				if (TaskOwnerID == Connector.CurrentUser.ContactID) {
					SetTimeZone(ScheduleControl, TaskOwnerID, true);
					ScheduleControl.ShowAdditionalTimeZone = false;
				} else {
					SetTimeZone(ScheduleControl, TaskOwnerID, false);
				}
			} else { 
				ScheduleControl.ShowAdditionalTimeZone = false;
			}
			TasksWorkspace.TaskOwnerIsChanged = false;
		}
	}
}

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

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

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

А не подскажете как это сделать? А то я что то не понимать :exclaim:

Создаете свою функцию, в которой будет включаться/отключаться фильтр. Затем вызываете созданную Вами функцию, из функции ApplyTasksWorkspaceFilter.
Пример:

function MyTaskFilter() {
	var Dataset = BaseWorkspace.GridDataset;
	var MyFilterName = 'MyFilter';
	var Value = edtMyLookup.Value;
	if (!IsEmptyValue(Value)) {
		ApplyDatasetFilter(Dataset, MyFilterName, Value, true);
	} else {
		EnableDatasetFilters(Dataset, false, MyFilterName);
	}
}
 
function ApplyTasksWorkspaceFilter() {
	var Dataset = BaseWorkspace.GridDataset;
	ApplyStandardWorkspaceFilter(); 
	var Grid = BaseWorkspace.Grid;
	var IsCycleView = (Grid.ActiveView.Name == 'dgvCycleTasks') && 
			!(pcData.ActivePage.Name == pgScheduler.Name)
	EnableDatasetFilters(Dataset, IsCycleView, 'IsCycle');
	if ((chbShowForPeriod.IsChecked) ||
		(pcData.ActivePage.Name == pgScheduler.Name)) {
		var FromDate = 
			TasksWorkspace.DatePeriodMemoryDataset.ValAsDateTime('From');
		var ToDate = TasksWorkspace.DatePeriodMemoryDataset.ValAsDateTime('To');
		ApplyTaskDateFilter(Dataset, FromDate, ToDate);
		if (TasksWorkspace.SchedulerWindow == null) {
			TasksWorkspace.SchedulerWindow = wndSchedulerArea.Window;
		}
		SetScheduleAreaTimePeriod(FromDate, ToDate);
	}
	ApplyDatasetGroupIDFilter(BaseWorkspace.GroupsDataset,	Dataset);
	ApplyContactFilter();
 
	MyTaskFilter();
} 
 
......
 
 
function edtMyLookupOnChange(LookupControl) {
	RefreshTasks();
}

Cпасибо огромное!

Сделал фильтр по примеру, теперь при выборе группы ответственных в поле выдает ошибку "Исключение брошено и не поймано"
В чем может быть причина? подскажите пожалуйста

Вам необходимо выполнить пошаговую отладку кода, с помощью Microsoft Script Debugger или Microsoft Visual Studio.

Пример отладки кода приведен в статье.

Если честно, я так и не понял в чем причина ;(
после отладки перенаправляет на эту функцию:

У Вас исключение происходит скорее всего в функции ApplyContactGroupFilter.
Необходимо установить debugger в ApplyContactGroupFilter.

Пример кода:

function MyTaskFilter() {
        debugger;
        var Dataset = BaseWorkspace.GridDataset;
        var MyFilterName = 'MyFilter';
        var Value = edtMyLookup.Value;
        if (!IsEmptyValue(Value)) {
                ApplyDatasetFilter(Dataset, MyFilterName, Value, true);
        } else {
                EnableDatasetFilters(Dataset, false, MyFilterName);
        }
}

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

Одна задача выполнена, но появилась новая проблема...
После фильтрации, при нажатии на "Группу ответственных" в колонке, выдает ошибку: "Не удается найти карточку редактирования для выбранного элемента". А поскольку помимо фильтрации по групповым задачам необходима фильтрация по каждому ответственному, который входит в эту группу, хочу спросить как можно ли реализовать открытие карточки "Группа ответственных"?
(По такому принципу: отфильтровал по группе, посмотрел кто входит в группу, отфильтровал по ответственному №1, №2...)

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

А не подскажете какие изменения нужно добавить в фильтре, если мне необходимо отобразить задачи не только пользователя, но также задачи всех групп, в которые входит этот пользователь?
Или это вообще не в фильтре нужно делать?

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

Доброго времени суток! Возникла следующая проблема:
В бизнес-процессе есть запрос:

EntitySchemaQuery CountOfOrderesq = new EntitySchemaQuery(UserConnection.EntitySchemaManager,"UsrOrderProvidersProduct");
CountOfOrderesq.IsDistinct = true;
CountOfOrderesq.AddAllSchemaColumns();
CountOfOrderesq.Filters.Add(CountOfOrderesq.CreateFilterWithParameters(FilterComparisonType.Equal, "UsrOrderId", OrderId));
CountOfOrderesq.Filters.Add(CountOfOrderesq.CreateFilterWithParameters(FilterComparisonType.Greater, "UsrShipped", 0));
var CountOfOrders = CountOfOrderesq.GetEntityCollection(UserConnection);

Далее его результат вызывается в цикле

foreach (var Order in CountOfOrders){
        EntitySchema Activityschema = UserConnection.EntitySchemaManager.GetInstanceByName("Activity");
        var OrderNumber = Order.GetTypedColumnValuestring>("UsrClientsOrderId.Number");//вот здесь
        var ClientsOrder = Order.GetTypedColumnValueGuid>("UsrClientsOrderId");
        var ActivityEntity = Activityschema.CreateEntity(UserConnection);
        ActivityEntity.SetDefColumnValues();
        ActivityEntity.SetColumnValue("Title", "Повторная комплектация по заказу клиента " + OrderNumber);
        ActivityEntity.SetColumnValue("UsrComplicateAftProvidersOrder", true);
        ActivityEntity.SetColumnValue("TypeId", "ad9476d6-cec0-4c69-b361-c80db1670fb5");//тип комплектация
        ActivityEntity.SetColumnValue("OrderId", ClientsOrder);
        ActivityEntity.Save();
        ActivityEntities.Add(ActivityEntity);
}

При выполнении появляется ошибка:

Terrasoft.Common.ItemNotFoundException: Значение с именем "UsrClientsOrderId.Number" не найдено
в Terrasoft.Core.Entities.EntityColumnValueCollection.GetByName(String name)
в Terrasoft.Core.Entities.Entity.InternalGetColumnValue(String valueName)
в Terrasoft.Core.Entities.Entity.GetTypedColumnValue[TResult](String valueName)
в Terrasoft.Core.Process.UsrProcess1.ScriptTask1Execute(ProcessExecutingContext context)
в Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Sql-текст запроса:

SELECT DISTINCT
 [UsrOrderProvidersProduct].[Id] [Id],
 [UsrOrderProvidersProduct].[CreatedOn] [CreatedOn],
 [UsrOrderProvidersProduct].[CreatedById] [CreatedById],
 [CreatedBy].[Name] [CreatedBy.Name],
 [CreatedBy].[PhotoId] [CreatedBy.PhotoId],
 [UsrOrderProvidersProduct].[ModifiedOn] [ModifiedOn],
 [UsrOrderProvidersProduct].[ModifiedById] [ModifiedById],
 [ModifiedBy].[Name] [ModifiedBy.Name],
 [ModifiedBy].[PhotoId] [ModifiedBy.PhotoId],
 [UsrOrderProvidersProduct].[ProcessListeners] [ProcessListeners],
 [UsrOrderProvidersProduct].[UsrProductId] [UsrProductId],
 [UsrProduct].[Name] [UsrProduct.Name],
 [UsrProduct].[PictureId] [UsrProduct.PictureId],
 [UsrOrderProvidersProduct].[UsrQuantity] [UsrQuantity],
 [UsrOrderProvidersProduct].[UsrUnitId] [UsrUnitId],
 [UsrUnit].[Name] [UsrUnit.Name],
 [UsrOrderProvidersProduct].[UsrOrderIdId] [UsrOrderIdId],
 [UsrOrderId].[Number] [UsrOrderId.Number],
 [UsrOrderProvidersProduct].[UsrCompleted] [UsrCompleted],
 [UsrOrderProvidersProduct].[UsrShipped] [UsrShipped],
 [UsrOrderProvidersProduct].[UsrClientsOrderIdId] [UsrClientsOrderIdId],
 [UsrClientsOrderId].[Number] [UsrClientsOrderId.Number],
 [UsrOrderProvidersProduct].[UsrMust] [UsrMust],
 [UsrOrderProvidersProduct].[UsrProcessed] [UsrProcessed],
 [UsrOrderProvidersProduct].[UsrTotalAmountWithoutVAT] [UsrTotalAmountWithoutVAT]
 
 FROM [dbo].[UsrOrderProvidersProduct] [UsrOrderProvidersProduct]

 WITH(NOLOCK) LEFT OUTER JOIN [dbo].[Contact] [CreatedBy]
 WITH(NOLOCK) ON ([CreatedBy].[Id] = [UsrOrderProvidersProduct].[CreatedById]) LEFT OUTER JOIN [dbo].[Contact] [ModifiedBy]
 WITH(NOLOCK) ON ([ModifiedBy].[Id] = [UsrOrderProvidersProduct].[ModifiedById]) LEFT OUTER JOIN [dbo].[Product] [UsrProduct]
 WITH(NOLOCK) ON ([UsrProduct].[Id] = [UsrOrderProvidersProduct].[UsrProductId]) LEFT OUTER JOIN [dbo].[Unit] [UsrUnit]
 WITH(NOLOCK) ON ([UsrUnit].[Id] = [UsrOrderProvidersProduct].[UsrUnitId]) LEFT OUTER JOIN [dbo].[ORDER] [UsrOrderId]
 WITH(NOLOCK) ON ([UsrOrderId].[Id] = [UsrOrderProvidersProduct].[UsrOrderIdId]) LEFT OUTER JOIN [dbo].[ORDER] [UsrClientsOrderId]
 WITH(NOLOCK) ON ([UsrClientsOrderId].[Id] = [UsrOrderProvidersProduct].[UsrClientsOrderIdId])

 WHERE [UsrOrderProvidersProduct].[UsrOrderIdId] = @P1 AND [UsrOrderProvidersProduct].[UsrShipped] > @P2

Подскажите пожалуйста решение проблемы. Заранее спасибо!

Нравится

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

Здравствуйте, Олег!

Попробуйте убрать Id в Вашем запросе:

var OrderNumber = Order.GetTypedColumnValue("UsrClientsOrder[s]Id[/s].Number");//вот здесь
var ClientsOrder = Order.GetTypedColumnValue("UsrClientsOrder[s]Id[/s]");

Приставка Id добавляется автоматически к колонкам типа Guid.

Здравствуйте, Андрей!

Так называются поля в объекте, если убрать Id то система вообще их не найдет.

Олег,

попробуйте переименовать колонку в объекте (убрать id) и применить рекомендацию выше.

Сообщите, пожалуйста, результат.

Андрей,

Заменили данное поле на "UsrClientOrder", ошибка повторяется снова.

var ClientsOrder = Order.GetTypedColumnValue("UsrClientsOrderId");
Так же уточню, что эта строка работает, ошибка появляется именно в обращении к "UsrClientsOrderId.Number".

Олег,
давайте попробуем следующим образом:

var countColumnName = Order.AddColumn("UsrClientsOrderId.Number").Name;
var OrderNumber = Order.GetTypedColumnValue<string>(countColumnName);

Андрей, решили проблему другим способом, тот что выше выдает ту же самую ошибку.

var OrderNumber = Order.GetTypedColumnValue<string>("UsrClientsOrderIdNumber");

Выяснилось, что колонки в коллекции называются так же как в запросе, но БЕЗ точки.

Добрый день Олег!!!

я бы еще рекомендовал при создание EntitySchemaQuery запросов, заранее "составному полю" присваивать свои Алиасы. Тогда при обработки значений запроса вам легче будет обрабатывать результаты запроса.

так же бы не рекомендовал при составление EntitySchemaQuery запросов включать все столбцы из EntitySchema, когда в результате к примеру вам нужны только 2 или 3 столбца. Это очень сильно влияет на производительность ваших страниц.

Здравствуйте, Михаил!

Спасибо за советы! Один вопрос, а каким образом присваивается Алиас к к колонке в запросе?

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

Добрый день Олег!!!

в вашем примере вы получаете все колонки из EntitySchema  CountOfOrderesq.AddAllSchemaColumns(); а я бы рекомендовал получать именно те колонки которые потом будут использоваться в обработке запроса. По вопросу Алиаса для колонки в EntitySchemaQuery:  ESQ.AddColumn("ReverseRelationType.Id", "ReverseRelationTypeId")  , где  ReverseRelationTypeId это и есть наш Алиас.

Спасибо!

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

Коллеги, приветствую.

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

F6F4725A-C7C6-4AA2-BE50-E4878ACB7D4B

Я выполняю простой запрос из MS SQL Server Management Studio -

SELECT
        UsrInDebtId
FROM
        UsrDebt
WHERE
        Id='F6F4725A-C7C6-4AA2-BE50-E4878ACB7D4B';

Получаю какой- то результат.

Аналогично из кода C#

...
myConnection.Open();
SqlCommand myCommand = new SqlCommand("...", myConnection);
SqlDataReader myReader = myCommand.ExecuteReader();
while (myReader.Read()) {
   ...
}
...    

Уникальный идентификатор я сохраняю в параметре addedRecordId -

Guid addedRecordId = Get("addedRecordId");

Далее я хочу использовать класс Select из пространства имен Terrasoft.Core.DB -

var userConnection = Get("UserConnection");
Select select = (Select)new Select(userConnection)
            .Column("UserInDebtId")
            .From("UsrDebt").As("UD")
            .Where("UD", "Id")
            .IsEqual(addedRecordId); // строка 42

Получаю ошибки компиляции -

Как я могу использовать Guid в условии IsEqual?

Был бы весьма признателен за информацию.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

Может быть, существует возможность получить строковое представление уникального идентификатора из события- сигнала и далее уже программно создать Guid, который и передать в предикат?..

Например:

string str = "F6F4725A-C7C6-4AA2-BE50-E4878ACB7D4B";
Guid guid = new Guid(str);

А затем уже:

...
.IsEqual(guid);

Хотя и не совсем ясно, что бы это могло дать...

Алексей,

В этом случае можно решить задачу двумя способами:

Вариант 1.
.IsEqual(addedRecordId.ToString());
Вариант 2.
.IsEqual(Column.Parameter(addedRecordId));

Второй вариант более корректный.

Здравствуйте, Олег! Большое спасибо за ответ, попробую сегодня.

В обоих случаях получаю такую ошибку компиляции:

Cannot implicity convert type 'Terrasoft.Core.DB.Query' to 'Terrasoft.Core.DB.Select'. An explicit
conversion exists (are you missing a cast?)

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

Олег, спасибо.

Помогло использование переменной с неявным типом:

var selectQuery = 
	new Select(userConnection) ...
Показать все комментарии

Вот этот код перебирает все выделенные записи в реестре.

for (var i = 0; i Page.TreeGrid.SelectedNodes.Count; i++) {

...

 }

Дорогие знатоки, как сделать так, чтобы перебирались все записи выборки?

Нравится

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

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

Page.TreeGrid.DataSource.LoadRows();
foreach (var row in Page.TreeGrid.DataSource.Rows)
{
     //TODO
var name = row.GetTypedColumnValue<string>("Name"); //обращение к колонке
}

"Андрей Каспаревич" написал:

Здравствуйте, Илья!

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

Page.TreeGrid.DataSource.LoadRows();

foreach (var row in Page.TreeGrid.DataSource.Rows)

{

     //TODO

var name = row.GetTypedColumnValue<string>("Name"); //обращение к колонке

}

С уважением,

Каспаревич Андрей

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

Спасибо работает

foreach (var row in Page.TreeGrid.DataSource.Rows)

Данный код проходит только 41 запись, а например, не все 3700 записей. Как сделать чтобы по всей выборке проходил?

Здравствуйте, Илья!
Перед загрузкой данных в DataSource попробуйте установить неограниченное количество записей на странице источника данных:

Page.TreeGrid.DataSource.PageRowsCount = -1;
Page.TreeGrid.DataSource.PageRowsCount = -1;
Page.TreeGrid.DataSource.LoadRows();
foreach (var row in Page.TreeGrid.DataSource.Rows)

с таким кодом уже работает, спасибо

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

Всем здравствуйте!

Есть карточка редактирования. В ней среди прочих полей есть поля "Плательщик" и "Платежные реквизиты".
Необходимо, чтобы при выборе плательщика в первом поле осуществлялось ограничение выборки для выбора значения во втором. То есть, чтобы отображались реквизиты только выбранного контрагента (плательщика). Как реализовать подобную логику? Я так понимаю: нужно добавить в соответствующий SelectQuery атрибут типа "ПлательщикID" и условие отбора по нему. Но как это условие активировать (по какому событию? и какой функцией?)? Как заполнить атрибут значениями перед выборкой?
Есть-ли какая-то подробная инструкция? Очень хотелось бы её получить.

Нравится

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

Это называется фильтрация.

"Алейник Алексей Вадимович" написал:Я так понимаю: нужно добавить в соответствующий SelectQuery атрибут типа "ПлательщикID" и условие отбора по нему.

Да. А потом у контрола, который нужно отфильтровать создаём обработчик события OnPrepareSelectWindow. Обработчик создаётся в левом нижнем блоке окна TSAdmin, на вкладке "События".

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

function edtOpportunityOnPrepareSelectWindow(LookupDataControl) {
	var TaskDataset = dlData.Dataset;
	var AccountID = GetFieldValueFromDisabledField(TaskDataset, 'AccountID');
	var OpportunityDataset = LookupDataControl.DataField.LookupDataset;
	var IsEnabled = (!IsEmptyValue(AccountID));
	ApplyDatasetFilter(OpportunityDataset, 'CustomerID', AccountID, IsEnabled);
}

Пример взят из scr_TaskEdit.

Сделал всё по аналогии. В результате: при вызове функции ApplyDatasetFilter() ошибка небработанного исключения (см. приложенный скриншот).

Возможно, не всё правильно в SelectQuery. Там должны быть и фильтр, и параметр с одинаковыми названиями.

Взгляните пожалуйста на скриншоты SelectQuery, может быть это внесёт ясность и поможет найти у меня ошибку

Вроде бы правильно. А скрипт?

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

function edtPaymentsDetailIDOnPrepareSelectWindow(LookupDataControl, SelectWindow) {
	//TODO
	var OrderDataset = dlData.Dataset;
    var ConsigneeID = GetFieldValueFromDisabledField(OrderDataset, 'ConsigneeID');
    var PaymentsDetailDataset = LookupDataControl.DataField.LookupDataset;
    var IsEnabled = (!IsEmptyValue(ConsigneeID));
    ApplyDatasetFilter(PaymentsDetailDataset, 'CustomerID', ConsigneeID, IsEnabled);
}

А почему фильтр 'CustomerID', а не 'ConsigneeID'?

О, не заметил, спасибо!

Исправил, но к сожалению, ошибка та же: необработанное исключение

Значит, что-то ещё не заметили. Можете в отладчике дойти до момента свала, последовательно заходя в функции и заметить, где "что-то пошло не так". Или в момент свала посмотреть стек вызова функций.

В тех. поддержке подсказали, в чём проблема. Я передавал в функцию ApplyDatasetFilter() вторым параметром название несуществующего параметра SQL-запроса. Первый параметр этой функции - это исходный датасет (в моём случае - AccounBilllingInfo), из которого выбирается параметр SQL-запроса (в моём случае - AccountID). А это значит, что текст моего скрипта должен был выглядеть вот так:

function edtPaymentsDetailIDOnPrepareSelectWindow(LookupDataControl) {
    var OrderDataset = dlData.Dataset;
    var ConsigneeID = GetFieldValueFromDisabledField(OrderDataset, 'ConsigneeID');
    var PaymentsDetailDataset = LookupDataControl.DataField.LookupDataset;
    var IsEnabled = (!IsEmptyValue(ConsigneeID));
    ApplyDatasetFilter(PaymentsDetailDataset, 'AccountID', ConsigneeID, IsEnabled);
}

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

Да, все равно, спасибо Вам большое, Вы мне очень помогли:twisted:

Стал переносить логику из тестовой конфигурации на рабочую. В результате заимел ошибки при добавлении новой заявки через действие "Резервирование/Заявка" в разделе счета и через добавление кнопкой "Добавить" из раздела "Заявки" (см. скриншот add.png). Скрипты тестовой и рабочей конфигураций полностью совпадают. Остальные сервисы также тщательно сверил, но ошибку найти никак не могу. Проблема ещё в том, что не до конца понятно, как пользоваться MS Editor для отладки. Документации по нему почти никакой нету.
Может кто поможет мне локализовать ошибку, где её искать? Заранее благодарен.

Судя по скриншоту, в SelectQuery не добавлена колонка DocumentName или в Dataset-е для этого поля не прописано значение колонки для отображения.

Действительно! Почему-то очистилось несколько полей отображения в датасете. Спасибо!

Аналогичную логику по созданию фильтрации данных необходимо выполнить для других полей:
При заполненном поле "Счет" отфильтровать поля "Договор" и "Документ".
Попытался сделать аналогично рекомендованным ранее вариантам.
К сожалению, реализованный вариант почему-то отсеивает абсолютно все записи.

function edtContractIDOnPrepareSelectWindow(LookupDataControl) {//обработчик поля "Договор"
	//TODO
	var OrderDataset = dlData.Dataset;
    var InvoiceID = GetFieldValueFromDisabledField(OrderDataset, 'InvoiceID');
	var InvoiceID = OrderDataset.Values('InvoiceID');
    var ContractDataset = LookupDataControl.DataField.LookupDataset;
    var IsEnabled = (!IsEmptyValue(InvoiceID));
    ApplyDatasetFilter(ContractDataset, 'ID', InvoiceID, IsEnabled);   
//    debugger;
}
 
function edtDocumentIDOnPrepareSelectWindow(LookupDataControl) {//обработчик поля "Документ"
	//TODO
	var OrderDataset = dlData.Dataset;
    var InvoiceID = GetFieldValueFromDisabledField(OrderDataset, 'InvoiceID');
    var DocumentDataset = LookupDataControl.DataField.LookupDataset;
    var IsEnabled = (!IsEmptyValue(InvoiceID));
    ApplyDatasetFilter(DocumentDataset, 'ID', InvoiceID, IsEnabled);
//    debugger;
}

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

ApplyDatasetFilter(ContractDataset, 'ID', InvoiceID, IsEnabled); 


Вам нужен фильтр не 'ID', а какой-то другой. Возможно, 'InvoiceID'.

"Зверев Александр" написал:
Алейник Алексей Вадимович пишет:

ApplyDatasetFilter(ContractDataset, 'ID', InvoiceID, IsEnabled);

Вам нужен фильтр не 'ID', а какой-то другой. Возможно, 'InvoiceID'.


Взгляните сами - все эти поля есть в стандартной конфигурации. Я попробовал заменить 'ID' на 'InvoiceID' и, как я и предполагал, террасофт выдал ошибку о том в SelectQuery запрашиваемого датасета (в моём случае, как видно из скриншота invoice2.png этим датасетом является ds_Invoice, а SelectQuery - sq_Invoice) нет такого параметра.

Фильтр 'ID' - это фильтр по ID, как это ни странно. Сейчас вы хотите найти те документы, у которых ID совпадает с ID выбранного счёта. Естественно, таких нет.

Нужно добавить фильтр 'InvoiceID' в sq_Contract и sq_Document, если там такого ещё нет.

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