Приветствую! 

Недавно занялся изучением и работой с платформой Creatio. По тому по коду прошу не ругать ;) 
 

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

Код реализации с getEntity:

var message;
				
var recordId = this.get("Id");
				
if(recordId) {
		var esq1 = this.Ext.create("Terrasoft.EntitySchemaQuery", {
						rootSchemaName: "UsrSwimmProgramm"
		});
				
		var filterA = esq1.createColumnFilterWithParameter(
					Terrasoft.ComparisonType.EQUAL, "UsrSPBooleanActive" , 1);
		var filterP = esq1.createColumnFilterWithParameter(
					Terrasoft.ComparisonType.EQUAL, "UsrSPLookupPeriod.Name" , "Ежедневно");
		esq1.filters.logicalOperation = Terrasoft.LogicalOperatorType.AND;
		esq1.filters.add("filterA",filterA);
		esq1.filters.add("filterP",filterP);
				
		esq1.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, 
						"NumberDayLesson", Terrasoft.AggregationEvalType.ALL);
				

				esq1.getEntity(recordId, function(result) {
					if (!result.success) {
						this.showInformationDialog("Ошибка запроса");
						return;
					}
					message = result.entity.get("NumberDayLesson") + "\n";
				this.showInformationDialog(message);
				}, this);
			
				}

Код реализации с getEntityCollection:

var message;
var recordId = this.get("Id");
				
if(recordId) {
			var esq1 = this.Ext.create("Terrasoft.EntitySchemaQuery", {
						rootSchemaName: "UsrSwimmProgramm"
				});
				
				var filterA = esq1.createColumnFilterWithParameter(
					Terrasoft.ComparisonType.EQUAL, "UsrSPBooleanActive" , 1);
				var filterP = esq1.createColumnFilterWithParameter(
					Terrasoft.ComparisonType.EQUAL, "UsrSPLookupPeriod.Name" , "Ежедневно");
				esq1.filters.logicalOperation = Terrasoft.LogicalOperatorType.AND;
				esq1.filters.add("filterA",filterA);
				esq1.filters.add("filterP",filterP);
				
				esq1.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, 
						"NumberDayLesson", Terrasoft.AggregationEvalType.ALL);
				
				esq1.getEntityCollection( function(result){
					message = result.collection.getByIndex(0).get("NumberDayLesson");
					this.showInformationDialog(message);
				},this);
				
	}

 

Так вот, почему при всех равных метод getEntity выдает не определенной значение, а вот с getEntityCollection все работает норм ? 

 

 

Нравится

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

Добрый вечер.

 

Метод getEntity используется для получения одной строки набора данных по заданному первичному ключу.

И в Вашем случае этот метод не срабатывает, потому что в заданном наборе данных не находит запись по этому recordId. Фактически, при использовании этого метода Вы добавляете ещё один фильтр по полю Id записи.

 

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

Спасибо большое, Алла. Уже смотрю.

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

Доброго времени суток!
Допустим, у меня есть раздел "Автомобили" с возможностью добавления новых автомобилей. В клиентской части мне необходимо отловить событие после добавления новой записи в этот раздел и добавить дополнительную логику на фронте. Думаю, должно быть что-то вроде "onItemInserted". Подскажите, пожалуйста,  как это лучше реализовать или какое название метода, который отрабатывает после вставки. Заранее благодарен.

Нравится

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

Добрый день!

 

На клиентской части в карточке редактирования Вы можете переопределить метод BasePageV2#onSaved

onSaved: function() {
	this.callParent(arguments);
},

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

Добрый день!

 

На клиентской части в карточке редактирования Вы можете переопределить метод BasePageV2#onSaved

onSaved: function() {
	this.callParent(arguments);
},

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

Если учитывать изменения на объекте процессами, интеграциями (или одновременно разными пользователями), лучше реализовать логику на событии вставки на уровне БП, а затем на сторону браузера передавать по ClientMessageBridge.

Лопатин Константин, Благодарю за совет! 

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

Доброго времени суток.

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

В случае, если на карточке редактирования присутствует вкладка с определенным ключом - необходимо "привязать" к ней деталь из diff (код ниже)
В случае, если вкладка найдена не была - добавить вкладку с привязкой детали (то есть выполнить процедуру вставки на основе diff)

Есть ли возможность динамически изменить свойство "parentName" у детали? (или как получить объектное представление детали для изменения свойства)

define("SomeModuleName", [], function() {
    return {
    details: {
        "DetailName": {
            "schemaName": "schemaName",
            "entitySchemaName": "entitySchemaName",
            "filter": {
                "detailColumn": "detailColumn",
                "masterColumn": "Id"
            }
        }
    },
    diff: /**SCHEMA_DIFF*/[ 
        {
            "operation": "insert",
            "name": "AddedTabName",
            "values": {
                "items": [],
                "caption": {
                    "bindTo": "Resources.Strings.AddedTabNameCaption"
                },
            },
            "parentName": "Tabs",
            "propertyName": "tabs",
            "index": 1
        },
    {
        "operation": "insert",
        "name": "CardDetail",
        "values": {
            "itemType": this.Terrasoft.ViewItemType.DETAIL,
            "visible": { "bindTo": "CardDetailVisible" }
        },
        "parentName": "AddedTabName",
        "propertyName": "items",
        "index": 0
        },
    ]/**SCHEMA_DIFF*/,
    methods: {
        onEntityInitialized: function() {
            this.callParent(arguments);
            // myMethodToUpdateVisibility();
        },
        }
    };
});

Вкладка (tab) на которую надо перенести деталь также динамически (также из кода клиентского модуля) добавляется сторонним пакетом.

Спасибо

Нравится

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

Добрый день! Возможно, проще добавить 2 детали на разные вкладки, и в зависимости от условий ненужное скрывать, чем динамически вставлять\перемещать

Добрый день! Возможно, проще добавить 2 детали на разные вкладки, и в зависимости от условий ненужное скрывать, чем динамически вставлять\перемещать

Лопатин Константин,

Спасибо за ваш вариант, попробую такой подход.

или как предложил Лопатин Константин или технически есть возможность закидывать и изымать элемент через ext, если вам вдруг не хватает геморроя в вашем проекте)

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

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

Нравится

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

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

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

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

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

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

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

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

Нравится

7 комментариев
Лучший ответ
PostMessage отправляет конкретному юзеру. Поэтому надо быть уверенным, что бп запущен от нужного пользователя и он на нужной странице(где есть код для обработки обратного сигнала). 
Если не подходит, можно воспользоваться PostMessageToAll(string sender, string message). Рассылает сообщение по всей конфигурации всем пользователям.

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

В конце БП в элементе Задание-сценарий вставляете следующую строку:
 

MsgChannelUtilities.PostMessage(UserConnection, "MyMessage", "UpdateDetail");

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

init: function () {
				this.callParent(arguments);
				this.subscriptionFunction();
			},
subscriptionFunction: function() {
				Terrasoft.ServerChannel.on(Terrasoft.EventName.ON_MESSAGE,
				this.bpListenerMessage, this);
			},
bpListenerMessage: function(scope, message) {
				if (!message || message.Header.Sender !== "MyMessage") {
					return;
				}
				var message2 = message.Body;
				if (!this.Ext.isEmpty(message2) && message2 === "UpdateDetail") {
					this.updateDetail();
				}
			}

Примерно так.

Нигрескул Алексей,

 

Не обновляет, уже и не знаю в чем дело может быть

В БП

var userConnection = Get<UserConnection>("UserConnection");
Terrasoft.Configuration.MsgChannelUtilities.PostMessage(userConnection, "ReloadDetailConcert", "UpdateDetail");
return true;

На клиенте

init: function () {
	this.callParent(arguments);
	this.subscriptionFunction();
},
subscriptionFunction: function() {
	Terrasoft.ServerChannel.on(Terrasoft.EventName.ON_MESSAGE,
	this.bpListenerMessage, this);
},
bpListenerMessage: function(scope, message) {
	if (!message || message.Header.Sender !== "ReloadDetailConcert") {
		return;
	}
	var message2 = message.Body;
	if (!this.Ext.isEmpty(message2) && message2 === "UpdateDetail") {
		this.updateDetail();
	}
},

 

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

Варфоломеев Данила,

Изменил на 

Terrasoft.Configuration.MsgChannelUtilities.PostMessageToAll("ReloadDetailConcert", "UpdateDetail");
return true;

не помогло

Нужно ли еще прописать?

messages: {
	"ReloadDetailConcert": {
		mode: Terrasoft.MessageMode.BROADCAST,
		"direction": Terrasoft.MessageDirectionType.SUBSCRIBE
	}
},

 

Prime Source,

Да нет. Должно и так работать. Даже subscriptionFunction не вызывается?

Варфоломеев Данила,

По дебагу срабатывает, и сообщение правильно ловит, и выполняет this.updateDetail(); ,но почему нет данных в детали не пойму. Может что в процессе не так? Вот его скрин, там идет цикл который делает 8 проходов, и когда в таблице 8 записей становится он выполняет скрипт сообщения и завершает

 

Prime Source,

//Relationships - название детали из details.
//пример:
this.updateDetail({detail: "Relationships"});

Проверьте код(указывается ли имя детали). Плюс должны быть настроены колонки

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

Подскажите, где можно хранить значение на странице. Например, как глобальная переменная в C#. Если есть такой способ, то как его реализовать? Спасибо

Нравится

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

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

 

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

https://academy.terrasoft.ru/search?search_api_fulltext=VIRTUAL_COLUMN&f%5B0%5D=ss_site_name%3AAcademy&page=0
https://academy.terrasoft.ru/documents/technic-sdk/7-13/dobavlenie-multivalyutnogo-polya
https://academy.terrasoft.ru/documents/technic-sdk/7-13/kak-dobavlyat-polzovatelskuyu-logiku-v-sushchestvuyushchie-elementy-upravleniya

Как добавить виртуальную колонку описано на Community - https://community.terrasoft.ru/articles/virtualnoe-virtualcolumn-lukap-lookup-pole.
https://community.terrasoft.ru/questions/uslovnoe-zapolnenie-virtualnyh-polei-v-prednastroennoi-stranice

Как вариант Вам нужно реализовать виртуальную колонку в аттрибутах:

                "Test": {
                    dataValueType: this.Terrasoft.DataValueType.LOOKUP,
                    type: this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
                    isRequired: true,
                    initMethod: "initTest"

И затем реализовать свой метод.

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

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

Нравится

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

Надо было искать не в QuickFilterModuleV2, а в CustomFilterViewModelV2.

Список колонок получает функция:

function getSimpleFilterColumnList(filters, list) {
	list.clear();
	var columnList = {};
	var columnNames = [];
	var columns = this.entitySchema.columns;
	Terrasoft.each(columns, function(column) {
if (column.dataValueType !== Terrasoft.DataValueType.GUID &&
	column.dataValueType !== Terrasoft.DataValueType.TIME &&
	column.dataValueType !== Terrasoft.DataValueType.BLOB &&
	column.dataValueType !== Terrasoft.DataValueType.IMAGELOOKUP &&
	column.usageType !== ConfigurationEnums.EntitySchemaColumnUsageType.None) {
	if (this.isColumnDeprecated(column)) {
return;
	}
	columnNames.push({
name: column.name,
caption: column.caption
	});
}
	}, this);
	var sortedColumnNames = columnNames.sort(function(a, b) {
if (a.caption === b.caption) {
	return 0;
} else {
	return a.caption > b.caption ? 1 : -1;
}
	});
	Terrasoft.each(sortedColumnNames, function(item) {
var column = columns[item.name];
columnList[column.name] = {
	value: column.name,
	displayValue: column.caption,
	dataValueType: column.dataValueType,
	referenceSchemaName: column.referenceSchemaName
};
	});
	list.loadAll(columnList);
}

 

Я попробовал переопределить этот модуль, просто сделать пустым выпадающий список. Этот модуль в версии 7.13 нельзя заместить обычным способом, я использовал материал . Раскройте пожалуйста подробнее как удалось переопределить эту функцию?

Так это тема 2018 года, тогда в 7.11 ещё было можно.

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

Привет всем !
Кто нибудь знает как убрать обязательное заполнение поля Ответственный в разделе Аналитика при выборе фильтров для построения отчета ?

Нравится

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

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

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

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

 

 

Нравится

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

Такие отчёты привязываются к разделу записями в SysModuleAnalyticsReport, где в полях указаны Id схемы отчёта и схемы его параметров. Для этого отчёта окно параметров задаётся в ContactAnniversariesReportFilter.

Зверев Александр,

Спасибо, я разобрался и сделал такую же страницу в разделе котором мне нужно.

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

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

Нравится

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

Чем onchange плох?

this.on("change:UsrAuto", function() {
	this.UpdateFinanceTab();
}, this);

 

Чем onchange плох?

this.on("change:UsrAuto", function() {
	this.UpdateFinanceTab();
}, this);

 

Алексей-Карягин,

Да в принципе ни чем, просто я не знал о нём ..
спасибо огромное, это отлично работает

Подскажите, пожалуйста, куда вставить этот код. Если в methods, то как его связать с полем справочника? Если непосредственно в код объявления справочника, то в какое свойство? Спасибо.

Руслан Хасанов, 
этот код нужно вставлять тогда когда нужно прослушивание события, например после загрузки карточки в метод onEntityInitialized
 

methods: {
    onEntityInitialized: function(){
        this.callParent();
        this.on("change:Amount", function(){
            window.alert("lalala");
        }, this);
    }
}

 

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