Доброго утра, коллеги.

 

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

 

Подробнее: Я создал свой раздел, где добавил два элемента. В нём есть деталь, где есть счётчик входов и они должны присваиваться к определенному элементу, который я выбрал и отображаться в аналитике "Показатель". У меня есть поле id, которое связано с id-элемента раздела, но как отфильтровать по нему, у меня не выходит, так как в фильтрах не отображается возможность сортировать по полю раздел.id. Можете что-то посоветовать? Буду благодарен.

 

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

Нравится

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

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

Или Вы имеете в виду как-то иначе?

 

Где у Вас должен отображаться этот показатель, в разделе или в карточке?

 

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

 

scr_release_notes_dashboard_on_page.png

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

Согласно статье https://academy.terrasoft.ru/documents/technic-sdk/7-16/klass-entityschemaquery-rabota-s-filtrami можно подключать и отключать фильтры и далее считывать уже разные отфильтрованные данные

var esqFirstFilter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Country.Name", "Испания");
var esqSecondFilter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Country.Name", "Франция");
esq.filters.logicalOperation = Terrasoft.LogicalOperatorType.OR;
esq.filters.add("esqFirstFilter", esqFirstFilter);
esq.filters.add("esqSecondFilter", esqSecondFilter);
esq.getEntityCollection(function (result) {
    if (result.success) {
        result.collection.each(function (item) {
            // Обработка элементов коллекции.
        });
    }
}, this);
 
// Для второго фильтра указывается, что он не будет участвовать в построении результирующего запроса.
// При этом данный фильтр не удаляется из коллекции фильтров запроса.
esqSecondFilter.isEnabled = false;
 
esq.getEntityCollection(function (result) {
    if (result.success) {
        result.collection.each(function (item) {
            // Обработка элементов коллекции.
        });
    }
}, this);

Решил сделать так же

var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
	rootSchemaName: "KtJasperFullNumberPool"
});
var requestFilter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, 
	"KtRequest", this.get("KtRequest").value);
var productFilter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, 
	"KtOpportunityProductInterest", this.get("Id"));
esq.filters.add("requestFilter", requestFilter);
esq.filters.add("productFilter", productFilter);
esq.getEntityCollection(function (result) {
	if (result.success) {
		this.set("IsVisibleKtJasperNumbersInKtRequestDetail", result.collection.getItems().length > 0 ? true : false);
	}
}, this);
productFilter.isEnabled = false;
esq.getEntityCollection(function (result) {
	if (result.success) {
		this.set("NumberCounts", result.collection.getItems().length);
	}
}, this);

Но при запуске, когда доходим до второго "esq.getEntityCollection" получаю ошибку "message: Uncaught Terrasoft.ItemAlreadyExistsException: Элемент с ключом "24f2c79e-4a52-457f-9e8e-e24009bb135b" Уже существует"

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

Как бы не старался, не могу сделать что бы как в примере с ак=ккадемии работало.

Подскажите, что я делаю не так, и что это за элемент что при чтении создается новый?

Нравится

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

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

Литвинко Павел,

 в какую колонку? Может у меня что-то не так?

А что это за GUID «24f2c79e-4a52-457f-9e8e-e24009bb135b»?

Это запись в таблице KtJasperFullNumberPool, Id поля, фильтра или ещё что-то?

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

Добрый день. Столкнулись со следующей проблемой, что есть много писем и после обработки одного письма из списка - обновляется весь список писем и надо перейти к обратно к последнему. Понял как реализовать прокрутку, но никак не получается запустить ее после полной загрузки (писем более 30).

 

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

Нравится

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

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

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

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

Был создан БП, который отправляет сообщение после создания обращения и его привязки к письму. Он же обрабатывает письмо, чтобы оно ушло в обработанное. В схеме CommunicationPanelEmailSchema ловится это сообщение и запускается  this.reloadEmails(); 

 

Хотим сделать так, чтобы this.reloadEmails(); загружал все письма, а не просто первые 15 а после уже прокручивал их до самого низа. 

 

По загрузке самое простое что нашли - это увеличить RowCount  до обновления и вернуть значение обратно после (в целом работает даже)

 

По прокрутке:

var element = document.getElementById("EmailContainerListGrid");
element.scrollTo(0,element.scrollHeight);

Не получается пока соединить это дело, чтобы прокрутка запускалась строго после загрузки писем

 

А если просто на уровне JS при помощи setInterval сделать таймер с запуском функции по его срабатыванию? Или длительность загрузки бывает слишком разной?

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

Можно найти в CommunicationPanelEmailSchema эту функцию reloadEmails и вызываемую ею loadEmails и внести в переопределённой схеме туда свои команды для прокрутки (и заодно можно убрать проверку на RowCount в _loadEmdPage)?

Сейчас эти функции выглядят так:

/**
 * Calls emails list reload.
 */
reloadEmails: function() {
	this.$EmdCollection.clear();
	this._saveTabSettings();
	this._setLoadingState(true);
	this.$DisplayState = EmailConstants.emailPanelDisplayState.Folders;
	if (this.get("EmailType") === EmailConstants.emailType.INCOMING && this.get("IsProcessed")) {
		this.sandbox.publish("UpdateNewNotProcessedIncomingEmailsCounter", 0);
	}
	this.loadEmails(true);
},
 
 
/**
 * Load emails list.
 * @protected
 * @param {Boolean} clearCollection Clear existing emails list flag.
 */
loadEmails: function(clearCollection) {
	if (!this._anyMailboxSelected() && this.$EmailType !== EmailConstants.emailType.DRAFT) {
		this._setLoadingState(false);
		return;
	}
	this.Terrasoft.chain(
		function(next) {
			this._loadEmdPage(clearCollection, next, this);
		},
		function(next, ids) {
			this._loadActivitiesByIds(clearCollection, ids);
		},
		this
	);
},

То есть в цепочке после _loadEmdPage и _loadActivitiesByIds вызвать свою функцию для прокрутки.

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

define("CommunicationPanelEmailSchema", ["CommunicationPanelEmailSchemaResources", "ContainerListGenerator",
	"ConfigurationConstants", "ConfigurationEnums", "ModalBox", "NetworkUtilities",
	"EmailConstants", "ProcessModuleUtilities", "ExchangeNUIConstants", "BusinessRulesApplierV2",
	"EntityConnectionLinksUtilities", "css!EntityConnectionLinksUtilities", "CheckModuleDestroyMixin",
	"ProcessEntryPointUtilities", "EmptyEmailPanelSchema"],
function(resources, ContainerListGenerator, ConfigurationConstants, ConfigurationEnums, ModalBox, NetworkUtilities,
		EmailConstants, ProcessModuleUtilities, ExchangeNUIConstants, BusinessRulesApplier) {
	return {
		entitySchemaName: EmailConstants.entitySchemaName,
		methods: {
			init: function () {
				this.callParent(arguments);
				Terrasoft.ServerChannel.on(Terrasoft.EventName.ON_MESSAGE, this.onMyBpFinish, this);
			},
			onMyBpFinish: function(scope, message) {
				if (!message || message.Header.Sender !== "UpdateEmailHistory") {
					return;
				}
				var ID = message.Body; 
				var EmailID = "emailContainer-"+ ID + "-ViewModule_RightSideBarModule_EmailModule";
				var element = document.getElementById(EmailID);
				element.remove();
			}
		}
	};
});

 

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

var ID = message.Body;
var collection = this.get("EmailCollection");
var foundItem = collection.collection.items.find(item => item.id === ID);
foundItem.set("IsNeedReload", false);
this.reloadEmailsData([ID]); //возможно лишнее, но пусть будет
collection.remove(foundItem);

 

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

Всем добрый день!

Столкнулся с следующей проблемой перестали выгружаться пакеты в ФС, пишет. что изменений не обнаружено. Редис чистил, пересоздавал приложение в IIS, удалял пакеты из папки Pkg в конфигурации - не помогает.

Кто нибудь сталкивался с такой проблемой?

Нравится

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

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

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

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

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

Нравится

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

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

 

  • Сделать в БП функцию на C#, вычисляющую значение при помощи классов EntitySchemaQuery или Select. В нескольких блоках-скриптах её вызывать, получая и передавая кодом значения в параметры.
  • Сделать отдельную схему — пользовательское действие, в которой и реализовать на C# логику вычисления. У действия есть входящие и исходящие параметры. В БП самодельное действие добавляется блоком «Выполнить действие процесса», как и стандартные.
  • Если хочется без кода, можно создать подпроцесс, где и добавить элементы чтения данных. Вставлять в основной процесс блоком «Подпроцесс (Действие вызов)». Данные аналогично передавать в параметрах.

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

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

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

Добрый день!

Существует проблема следующего характера:

В целях безопасности пароль от учетной записи Exchange меняется раз в неделю. Пользователи не знают свой пароль, заходят через Active Directory.

 

Есть ли способ проходить авторизацию через AD? Возможно, кто-то решал эту проблему?

Нравится

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

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

 

На данный момент решение в коробке не реализовано.

Рекомендуем переход на O365 и использование там либо пароля для приложения (не зависит от пароля в домене), либо OAuth2.0.

 

Также обратите внимание на аналогичное обсуждение в прошлом году.

 

Мотков Илья,

Добрый день, подскажите, планируется ли это реализовать? Есть такая задача на какой-то конкретный релиз?

Если нет, можете ли что-то подсказать по реализации?

Артём, нет, не планируется. Используйте обходные варианты.

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

Исходные данные JS-кода.

Атрибут.

"ArticleName": {
  "dataValueType": this.Terrasoft.DataValueType.TEXT,
  "type": this.Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
  "value": ""
},

Метод получения значения атрибута

getArticleName: function() {
  var articleName = this.get("ArticleName");
  return articleName ? articleName : "";
},

Метод кнопки

onGetArticleNameClick: function () {
// Первый запуск - <пусто>
// Последующие запуски - <наименование>
this.showInformationDialog(this.getArticleName());
this.set("ArticleName", "");
// Данные реестра.
var gridData = this.getGridData();
if (gridData) {
  var activeRow = this.getActiveRow();
  if (activeRow) {
    // Поле Id.
    var activeRowId = activeRow.get("Id");
    if (activeRowId)
    {
      var serviceData = { id: activeRowId };
      ServiceHelper.callService("VSKBSourceCodeServices", "GetArticleName", 
        function (response) {
          var result = response.GetArticleNameResult;
          this.set("ArticleName", result);
        }, serviceData, this);
    }
  }
}
// Всегда <пусто>
this.showInformationDialog(this.getArticleName());
},

Не могу понять, почему ServiceHelper.callService не заполняет значение атрибута ArticleName сразу? Ощущение, как будто вызов клиентского веб-сервиса GetArticleName выполняется асинхронно.

Нравится

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

Здравствуйте! Данная проблема связана из-за асинхронности js ф-ция обратного вызова запускается в другом потоке и контекст this - уже не виден. Вам нужно до вызова ServiceHelper объявить переменную, например scope и записать в нее this:

 var scope = this; 

а в ф-ции обратного вызова уже писать:

scope .set("ArticleName", result);

Как то так, должно стработать.

Здравствуйте! Данная проблема связана из-за асинхронности js ф-ция обратного вызова запускается в другом потоке и контекст this - уже не виден. Вам нужно до вызова ServiceHelper объявить переменную, например scope и записать в нее this:

 var scope = this; 

а в ф-ции обратного вызова уже писать:

scope .set("ArticleName", result);

Как то так, должно стработать.

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

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

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

ServiceHelper.callService, и затем выполнить обращение к этому атрибуту.

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

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

Коллеги, подскажите в чем причина.

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

На в разделе Контакты все отлично работает,

но в разделах Сервис и Контрагенты работает только если ремарить фильтр

//filter: BaseFiltersGenerateModule.OwnerFilter, Но работает без этого фильтра.

В чем может быть причина? Спасибо.

/**
 * @class AccountSectionV2.ELBase
 * @extends AccountSectionV2.NUI
 */
define(
	"AccountSectionV2",
	[
		"ProcessModuleUtilities",
		"ELJSConst",
		"ELAccountActionMenuMixin", 
		"BaseFiltersGenerateModule"
	],
	function(
		ProcessModuleUtilities,
		ELJSConst, 
		BaseFiltersGenerateModule
	) {
		return {
			entitySchemaName: "Account",
 
			mixins: {
				ELAccountActionMenuMixin: "Terrasoft.ELAccountActionMenuMixin"
			},
 
        methods: {
 
				initFixedFiltersConfig: function() {
				var fixedFilterConfig = {
					entitySchema: this.entitySchema,
					filters: [
						{name: "Owner",
							caption: this.get("Resources.Strings.OwnerFilterCaption"),
							dataValueType: Terrasoft.DataValueType.LOOKUP,
							filter: BaseFiltersGenerateModule.OwnerFilter,
							columnName: "Owner",
							defValue: this.Terrasoft.SysValue.CURRENT_USER_CONTACT
						}
					]
				};
				this.set("FixedFilterConfig", fixedFilterConfig);
			},
define("BaseFiltersGenerateModule", ["BaseFiltersGenerateModuleResources", "ConfigurationConstants"], 
	function(resources, ConfigurationConstants) {
		function getIsNotNullFilterGroup(refSchema) {
			const userFilter = Terrasoft.createColumnIsNotNullFilter(refSchema + ".Id");
			const filters = Ext.create("Terrasoft.FilterGroup");
			filters.addItem(userFilter);
			return filters;
		}
 
		function employeesFilter() {
			const sysAdminUnitRef = "[SysAdminUnit:Contact]";
			const employeesFilter = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL,
					sysAdminUnitRef + ".ConnectionType",
					ConfigurationConstants.SysAdminUnit.ConnectionType.AllEmployees);
			const filters = getIsNotNullFilterGroup(sysAdminUnitRef);
			filters.addItem(employeesFilter);
			return filters;
		}
 
		function allUsersFilter() {
			return getIsNotNullFilterGroup("[VwSystemUsers:Contact]");
		}
 
		function selfFilter() {
			let primaryColumnName = "Id";
			if (this.entitySchema && this.entitySchema.primaryColumnName) {
				primaryColumnName = this.entitySchema.primaryColumnName;
			}
			const primaryColumnValue = this.get(primaryColumnName);
			return Terrasoft.createColumnFilterWithParameter(
				Terrasoft.ComparisonType.NOT_EQUAL, primaryColumnName, primaryColumnValue);
		}
 
		return {
			OwnerFilter: employeesFilter,
			SelfFilter: selfFilter,
			AllUsersFilter: allUsersFilter
		};
	});

 

Нравится

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

Уточните, когда и где работает или нет? И как не работает, как будто фильтра не существует или пустая выборка?

 

Все наложенные фильтры можно увидеть в запросе, уходящем к /0/DataService/json/SyncReply/SelectQuery, а если система развёрнута  локально, итоговый запрос в базу видно в SQL-профайлере. Возможно, условия стандартного и добавленного фильтров противоречат?

 

Также проверьте, всё ли правильно сделано в соответствии со статьёй о создании быстрого фильтра.

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

Есть необходимость передавать параметр из рассылки в шаблон письма. @Invoke макросы в рассылках почему-то не работают, возможно из-за того, что нет связи с разделом, там шаблоны хранятся в таблице BulkEmail и наверное работают иначе.

Есть ли инструкция или пример как сделать кастомный макрос в шаблоне письма для рассылок?

 

Находил старую тему, но там решение проблемы не описано.

https://community.terrasoft.ru/questions/dobavlenie-obrabotcika-makrosa-v-sablone-email-soobsenia

Нравится

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

@Invoke макросы в рассылках почему-то не работают,

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

 

Для рассылок используются макросы со значениями  поля из таблиц.

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

 

 

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

Из поля в рассылке (объект «Email») можно тоже по связям от участника рассылки:

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

Доброго дня, коллеги!

 

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

 

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

 

Заранее благодарю!

Нравится

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

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

 

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

Команда разработки ответственная за этот функционал в курсе существования этой проблемы и будет работать над внедрением ее решения в будущих релизах Creatio.

 

Вы можете вывести данный справочник как раздел. Тогда задача будет решена.

 

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

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

 

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

Команда разработки ответственная за этот функционал в курсе существования этой проблемы и будет работать над внедрением ее решения в будущих релизах Creatio.

 

Вы можете вывести данный справочник как раздел. Тогда задача будет решена.

 

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

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