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

 

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

Нравится

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

Денис, время компиляции  увеличилось из-за длительной генерации статического контента. Это происходит с версии 7.11.



При «компилировать всё» на БД MS SQL, на коробке, продукт бандл, процедура должна занимать в среднем 5 минут, что считается приемлемым.



При «компилировать всё» на БД Oracle, на коробке, продукт бандл, процедура  иногда может занимать ~ 30 минут, что планируется решить.

 

 

На продолжительность процесса компиляции может влиять очень много факторов.

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

 

Процесс компиляции приблизительно выглядит так (значимая часть): 

  1. Происходит поиск всех измененных схем (по сути поиск происходит только в пакетах, которые установлены из SVN, то есть являются «разлоченными»)
  2. Проходит анализ на построение цепочки компиляции. Анализируется каждая схема:
    1. Если схема является новой (не замещённой) - компилируется только пакет, в котором эта схема находится
    2. Если схема является замещённой - компилируется вся цепочка наследования. 

В последнем пункте обычно и кроется проблема. 

 

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

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

Спасибо, получается чем больше наследований, тем дольше компиляция?

И чем больше пакетов с изменениями.

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

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

Добрый день!

Подскажите как перейти в другой раздел по нажатию кнопки на клиентской стороне, например в раздел итоги или обращения

 

Видел вариант с переход по вкладкам

this.setActiveTab("имя_вкладки");

Нравится

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

Вешаете на кнопку обработчик. А в него что-то вроде этого: 

var tag = "SectionModuleV2/ActivitySectionV2/";
this.sandbox.publish("PushHistoryState", {hash: tag});

ActivitySectionV2 - реестр раздела Активности

Вешаете на кнопку обработчик. А в него что-то вроде этого: 

var tag = "SectionModuleV2/ActivitySectionV2/";
this.sandbox.publish("PushHistoryState", {hash: tag});

ActivitySectionV2 - реестр раздела Активности

Дмитрий А.,

Спасибо, попробую

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

Добрый день!

При выборе шаблона email сообщения, в Обращении, заполняется тема из указанного шаблона, но при отправке подставляется  номер и тема из Обращения 

После выбора шаблона тема: "SR00540466 Проверка технической возможности, Київська обл,Київ,вул"

При отправке тема: "Re: SR00540466 Новое включение Включение"



Просьба подсказать как исправить

Нравится

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

Юрий, это не ошибка, это так специально. Ещё с 7.10:

Уведомления по обращению содержат тему из исходного письма, по которому зарегистрировано обращение. Это позволит заявителю отследить историю писем по обращению. Если обращение регистрируется по другим каналам (например, по звонку), то в поле [Тема] уведомлений указывается тема из шаблона письма.

Чтобы поменять, смотрите логику в схеме EmailWithMacrosManager, там в SendEmail и её аналогах вызывают функции, заполняющие заголовок:

/// <summary>
/// Builds an e-mail activity then sends it.
/// The sender and recipients will be obtained automatically.
/// Use this method to reply to all the participants of the parent (root) e-mail activity.
/// </summary>
/// <param name="caseId">Case record identifier.</param>
/// <param name="tplId">Template record identifier.</param>
public virtual void SendEmail(Guid caseId, Guid tplId) {
	Activity activity = CreateActivity();
	PreProcess(activity, caseId, tplId);
	CaseData data = GetCaseData(caseId);
	activity.Sender = GetSender(data);
	FillActivityWithCaseData(activity, data);
	FillTitle(activity, caseId, tplId);
	activity.Save();
	SendActivity(activity.Id);
}
...
/// <summary>
/// Fills an <paramref name="activity"/> with given <paramref name="data"/>.
/// </summary>
/// <param name="activity">Activity entity.</param>
/// <param name="data">Case data.</param>
protected virtual void FillActivityWithCaseData(Activity activity, CaseData data) {
	activity.Title = data.Title;
	activity.Recepient = data.Recipient;
	activity.CopyRecepient = data.CC;
	activity.BlindCopyRecepient = data.BCC;
	if (data.ParentActivityInReplyTo.IsNotNullOrEmpty()) {
		activity.HeaderProperties = AddInReplyToHeaderProperty(data.ParentActivityInReplyTo, activity.HeaderProperties);
	}
}
...
/// <summary>
/// Sets activity title as a subject from e-mail template if it is not specified yet.
/// Otherwise, adds a replying prefix (<see cref="ReplyingPrefix" />)
/// to an <paramref name="activity"/>'s title.
/// </summary>
/// <param name="activity">Activity entity.</param>
/// <param name="caseId">Case record identifier.</param>
/// <param name="tplId">Template record identifier.</param>
protected void FillTitle(Activity activity, Guid caseId, Guid tplId) {
	var title = activity.Title;
	activity.Title = title.IsNullOrEmpty()
		? GetTemplateSubject(SchemaName, caseId, tplId)
		: ApplyPrefix(title);
}

Видимо, Вам нужно переделать, чтобы всегда брался только GetTemplateSubject, а не тема из обращения с добавлением в начале префикса «Re:».

Александр, спасибо, пошли править, отпишусь

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

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

 

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

 

Пример кода, который получился:

generateEmailButtonsContainerConfig: function() {
	var buttonItems = [];
	var processEmailButtonConfig = this.generateEmailProcessedButtonConfig();
	buttonItems.push(processEmailButtonConfig);
	/** Добавляем новую кнопку */
	var skipEmailButtonConfig = this.generateSkipEmailButtonConfig();
	buttonItems.push(skipEmailButtonConfig);
	var deleteEmailButtonConfig = this.generateDeleteEmailButtonConfig();
	buttonItems.push(deleteEmailButtonConfig);
	var emailButtonContainerConfig = {
		"className": "Terrasoft.Container",
		"classes": {"wrapClassName": ["entity-item-relation-container"]},
		"items": buttonItems
	};
	return emailButtonContainerConfig;
},
/** НОВАЯ КНОПКА */
generateSkipEmailButtonConfig: function() {
	return {
		"className": "Terrasoft.Button",
		"style": Terrasoft.controls.ButtonEnums.style.RED,
		"caption": "SKIP",
		"click": {bindTo: "onSkipEmail"},
		"markerValue": "skipingEmail"
	};
},
/** Метод обработчик кнопки*/
onSkipEmail: function (model) {
	window.console.log("It's working");
}

Но при нажатии на кнопку - появляется ошибка:

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

Возможно надо использоваться что-то похожее на fireEvent, но за все время не было необходимости в подобном функционале - поэтому плохо понимаю как и что делать. Вроде в этой статье https://community.terrasoft.ru/articles/kak-sozdat-polzovatelskii-eleme… о чем-то, что мне поможет, говорится. Но без понимая как это все устроено - это какое-то гадание на кофейной гуще.

 

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

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

 

Может кто-то реализовывал мой кейс или нечто подобное и сможет поделиться советом?

Нравится

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

Сергей, насколько понимаю, Вы пытаетесь сделать как для зелёной кнопки EmailProcessedButton, которая описана в CommunicationPanelEmailSchema:

/**
 * Creates email message action buttons container config.
 * @protected
 * @return {Object} Email message action buttons container config.
 */
generateEmailButtonsContainerConfig: function() {
	var buttonItems = [];
	var processEmailButtonConfig = this.generateEmailProcessedButtonConfig();
	buttonItems.push(processEmailButtonConfig);
	var deleteEmailButtonConfig = this.generateDeleteEmailButtonConfig();
	buttonItems.push(deleteEmailButtonConfig);
	var emailButtonContainerConfig = {
		"className": "Terrasoft.Container",
		"classes": {"wrapClassName": ["entity-item-relation-container"]},
		"items": buttonItems
	};
	return emailButtonContainerConfig;
},
 
/**
 * Creates "process message" button config.
 * @protected
 * @return {Object} "Process message" button config.
 */
generateEmailProcessedButtonConfig: function() {
	return {
		"className": "Terrasoft.Button",
		"caption": {"bindTo": "Resources.Strings.MarkAsProcessed"},
		"style": Terrasoft.controls.ButtonEnums.style.GREEN,
		"imageConfig": {"bindTo": "Resources.Images.ApplyButtonImage"},
		"enabled": {"bindTo": "IsProcessingButtonEnabled"},
		"visible": {
			"bindTo": "IsNeedProcess",
			"bindConfig": {
				"converter": "getProcessButtonVisible"
			}
		},
		"click": {bindTo: "setIsNeedProcessFalse"},
		"markerValue": "setNeedProcessFalse"
	};
},

Но там обработчик setIsNeedProcessFalse в EmailItemSchema не просто одна функция, а несколько в цепочке, одна вызывает другие:

/**
 * Sets and saves IsNeedProcess value for message.
 * @param {Function} [callback] Callback function.
 * @param {Object} [scope] Callback function scope.
 */
setIsNeedProcessFalse: function(callback, scope) {
	this.set("IsProcessingButtonEnabled", false);
	var chain = [];
	chain.push(this.updateIsNeedProcess);
	chain.push(this._onSetIsNeedProcessFalse, function() {
		this.Ext.callback(callback, scope);
	});
 
	this.set("IsNeedProcess", false);
	this.Terrasoft.chain.apply(this, chain);
},
...
/**
 * Updates IsNeedProcess value for current user EmailMessageData instances.
 * @param {Function} [callback] Callback function.
 * @param {Object} [scope] Callback function scope.
 */
updateIsNeedProcess: function(callback, scope) {
	var update = this.getIsNeedProcessUpdate();
	if (this.Ext.isEmpty(update)) {
		this.Ext.callback(callback, scope);
		return;
	}
	update.execute(function() {
		this.Ext.callback(callback, scope);
	}, this);
},
...
/**
 * Handle response of save entity request.
 * @private
 * @param {Object} [response] Response of save entity request.
 * @param {Function} [callback] Callback function.
 * @param {Object} [scope] Callback function scope.
 */
_handleSaveRequestResponse: function(response, callback, scope) {
	if (response && response.success) {
		this.fireEvent("entitySaved", this);
		this.set("CurrentColumnValue", null);
	}
	this.Ext.callback(callback, scope);
},
/**
 * Set IsNeedProcess to false.
 * @private
 * @param {Function} [callback] Callback function.
 * @param {Object} [scope] Callback function scope.
 */
_onSetIsNeedProcessFalse: function(callback, scope) {
	this.saveEntity(function(response) {
		this._handleSaveRequestResponse(response, callback, scope);
	}, this);
},

Если ругается на .apply, видимо, ожидает для Вашей кнопки аналогичной логики. Хотя, там же рядом справа DeleteEmailButton, там без этого всего:

/**
 * Creates "delete" button config.
 * @protected
 * @return {Object} "Delete" button config.
 */
generateDeleteEmailButtonConfig: function() {
	return {
		"className": "Terrasoft.Button",
		"style": Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
		"imageConfig": {"bindTo": "Resources.Images.DeleteEmailButtonImage"},
		"click": {bindTo: "onDeleteEmail"},
		"markerValue": "deleteEmail"
	};
},
...
/**
 * Removes email message from emails collection.
 * @param {Terrasoft.BaseViewModel} model Email message model instance.
 */
onDeleteEmail: function(model) {
	this.unsubscribeModelEvents(model);
	var collection = this.get("EmailCollection");
	collection.remove(model);
},

Не сравнивали в отладке Вашу кнопку с кнопкой удаления?

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

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

CommunicationPanelEmailSchema. Проверю свою догадку и отпишусь о происходящем. Просто изначально не заметил эту привязку. Даже не осознал до конца как я натолкнулся на нее. Но теперь уже немного понятно куда идти

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

Если просто Вашу функцию onSkipEmail перенести в EmailItemSchema, то всё работает, пишет в консоли «It's working».

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

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

CommunicationPanelEmailSchema (потому что надо было работать с коллекцией писем, не был уверен что смогу это провернуть в EmailItemSchema)

 

Если кому-то поможет - полученный код ниже

 

EmailItemSchema:

messages: {
	"MessageSkipEmail": {
		mode: Terrasoft.MessageMode.BROADCAST,
		direction: Terrasoft.MessageDirectionType.BIDIRECTIONAL
	}
},
methods: {
	/**
	 * Initializes starter values.
	 * @protected
	 * @overridden
	 */
	init: function () {
		this.callParent(arguments);
		// Регистрация сообщения.
		this.sandbox.registerMessages(this.messages);
	},
	onSkipEmail: function() {
		// Регистрация сообщения.
		var EmailId = this.get("Id");
		this.sandbox.publish("MessageSkipEmail", {Id: EmailId}, ["EmailItemSchema"]);
	}
},

CommunicationPanelEmailSchema

messages: {
	"MessageSkipEmail": {
		mode: Terrasoft.MessageMode.BROADCAST,
		direction: Terrasoft.MessageDirectionType.BIDIRECTIONAL
	}
},
methods: {
	init: function () {
		this.callParent(arguments);
		// Регистрация сообщения.
		Terrasoft.ServerChannel.on(Terrasoft.EventName.ON_MESSAGE, this.onMyBpFinish, this);
		this.sandbox.subscribe("MessageSkipEmail", function(args) { this.skipingEmail(args.Id);},
			this, ["EmailItemSchema"]);
	},
	skipingEmail: function(EmailId) {
		var collection = this.get("EmailCollection");
		var foundItem = collection.collection.items.find(item => item.id === EmailId);
		var args = {
		// Имя процесса, который необходимо запустить.
			sysProcessName: "UsrSkipEmail",
		// Объект со значением входящего параметра ContactParameter для процесса CustomProcess.
			parameters: {
				ID: EmailId
			}
		};
				// Запуск пользовательского бизнес-процесса.
		ProcessModuleUtilities.executeProcess(args);
		collection.remove(foundItem); /** Выкидываем уже обработанное письмо из списка*/
	},
	generateEmailButtonsContainerConfig: function() {
		var buttonItems = [];
		var processEmailButtonConfig = this.generateEmailProcessedButtonConfig();
		buttonItems.push(processEmailButtonConfig);
		/** Добавляем новую кнопку */
		var skipEmailButtonConfig = this.generateSkipEmailButtonConfig();
		buttonItems.push(skipEmailButtonConfig);
		var deleteEmailButtonConfig = this.generateDeleteEmailButtonConfig();
		buttonItems.push(deleteEmailButtonConfig);
		var emailButtonContainerConfig = {
			"className": "Terrasoft.Container",
			"classes": {"wrapClassName": ["entity-item-relation-container"]},
			"items": buttonItems
		};
		return emailButtonContainerConfig;
	},
	/** НОВАЯ КНОПКА */
	generateSkipEmailButtonConfig: function() {
		return {
			"className": "Terrasoft.Button",
			//"style": 
			"caption": "Игнорировать",
			"click": {bindTo: "onSkipEmail"},
			"markerValue": "skipingEmail",
			"enabled": {"bindTo": "IsProcessingButtonEnabled"},
			"visible": {
				"bindTo": "IsNeedProcess",
				"bindConfig": {
					"converter": "getProcessButtonVisible"
				}
			},
		};
	},

А в самом БП происходит магия изменения БД, чтобы не запустились скрытые процессы, привязанные к "IsNeedProcess" в EmailMessageData

 

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

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

Есть две функции выполняющие getEntityCollection, для запроса групп текущего пользователя и для подсчета его активностей и обращений.

 

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

 

Читал про Terrasoft.chain , но не очень понятно, как именно передавать результат без return

Нравится

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

Есть деталь в разделе, на которой есть действие "Удалить всех согласующих"

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

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

Код ниже на скринах

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

и 

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

Нравится

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

Добрый день.

Реализуйте доступ на эту функциональность через доступ на операции.

Пример реализации можно посмотреть, как реализован доступ на действие 'Экспорт в Excel'.

Добрый день.

Реализуйте доступ на эту функциональность через доступ на операции.

Пример реализации можно посмотреть, как реализован доступ на действие 'Экспорт в Excel'.

Я бы сделал проверку на админа через добавления доступа по операциям

init: function() {

    this.callParent(arguments);

    RightUtilities.checkCanExecuteOperation({

        operation: "IsSysAdminUser"

    }, function(result) {

        this.set("IsSysAdminUser", result);

    }, this);

}

После этого можно попробовать указать привязку visible к атрибуту IsSysAdminUser. 

Если это не будет работать, тогда

init: function() {

    this.callParent(arguments);

    

    RightUtilities.checkCanExecuteOperation({

        operation: "IsSysAdminUser"

    }, function(result) {

        this.set("IsSysAdminUser", result);

        this.removeMenuItem();

    }, this);

},

removeMenuItem: function() {

    var toolsButtonMenu = this.get("ToolsButtonMenu");

    if (toolsButtonMenu !== undefined && !this.get("IsSysAdminUser")) {

        for (var key in toolsButtonMenu.collection.map) {

            if (toolsButtonMenu.collection.map[key].values.Caption.bindTo === "Resources.Strings.DeleteMenuCaption") {//Пример проверки

                toolsButtonMenu.removeByKey(key);

            }

        }

    }

},

addRecordOperationsMenuItems: function(toolsButtonMenu) {

    this.callParent(arguments);

    

    //добавление элементов

    

    //после добавления

    this.removeMenuItem();

}

Вместо доступа по оцерациям, можно проверить через esq сделав выборку по таблице SysAdminUnitInRole, в SysAdminUnit = id текущего пользователя, в SysAdminUnitRole = 83A43EBC-F36B-1410-298D-001E8C82BCAD (это id из таблицы SysAdminUnit). В функции получения результата esq также this.set("IsSysAdminUser", ); this.removeMenuItem();

Завязываться на роль админа прямо в коде — будет работать, но идеологически некрасиво. Рано или поздно захочется дать кому-то ещё и придётся переписывать код. Куда лучше создать отдельную операцию с «говорящим» названием, проверять наличие прав на неё, а в разделе настройки прав дать право на неё группе админов.

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

Коллеги, добрый день. Версия 7.15.3.

 

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

Как можно найти шаблон, по которому создано письмо?

Нравится

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

Денис, как именно создаёте письмо по шаблону? Действием или кодом? Если Вы сами создаёте, то зачем его отдельно вычислять? Сделать в активности скрытое справочное поле и дать ссылку на шаблон туда, тегом пометить активность, ещё как-то.

Александр, письмо с помощью стандартного блочка "Отправить email" бизнес-процесса оптравляется https://academy.terrasoft.ua/documents/technic-bpms/7-16/element-proces…

 

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

 

 

Там шаблон задаётся как параметр элемента. Если он задан статически, то что мешает посмотреть? А если вычисляется в скрипте или берётся из какого-то параметра, то можно тоже где-то зафиксировать.

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

 

Здесь можно, да. Проблема в том, что при отправке создаётся активность с типом Email.

 

И шаблон нужно найти  и связать с этой самой активностью, которая создаётся при отправке автоматического email, причём, скорее всего это нужно делать в процессе, который запускается по сигналу от создания активности. Потому что в основном процессе, где отправляется письмо, её (активность) не найти -  параметр "Id задачи" в элементе "Отправить email" тут не помогает, там пустое значение после отправки.

Судя по комментарию тут https://community.terrasoft.ru/ideas/pozvolit-svyazyvat-pisma-otpravlen… при отправке письма автоматически происходит запрос в какой-то сервис, который и отправляет письмо, и где создаётся активность. При этом процесс, в котором было отправлено письмо, идёт дальше, поэтому id задачи там и не доступен.

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

 

 

Смородинов Денис пишет:

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

Данный блок срабатывает только при значении [Как выполняется отправка] =>Отправить email вручную

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

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

Доброго дня!

Прошу помощи с проблемой.

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

У обращения есть текстовая колонка "textCase". У Конфигурационной единицы есть текстовая колонка "textConfItem". Нужно, чтобы при выборе в детали Конфигурационные единицы (по колонке Обращение) выбирались лишь те КЕ, у которых это значение колонки "textConfItem" равно значению колонки "textCase" связанного обращения.

 

В ConfItemCaseEditPage поместил следующий код:

        attributes: {

            "ConfItem": {

                "dataValueType": Terrasoft.DataValueType.LOOKUP,

                "lookupListConfig": {

                    "filters": [

                        function() {

                            var textCase = this.get("[Case:Id].textCase");

                            var serviceFiltersGroup = Terrasoft.createFilterGroup();

                            serviceFiltersGroup.logicalOperation = Terrasoft.core.enums.LogicalOperatorType.OR;

                            serviceFiltersGroup.addItem(Terrasoft.createColumnFilterWithParameter(

                                Terrasoft.ComparisonType.EQUAL,"[ConfItem:Id].textConfItem", textCase));

                            return serviceFiltersGroup;

                            

                            

                        }

                    ]

                }

            }

        },

 

но это не помогло, возможно в коде что-то не так, а возможно из-за коробочного изменения механизма добавления в деталь (при нажатии на + сразу открывается карточка выбора, а не ConfItemCaseEditPage)

Нравится

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

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

А почему у Вас группа фильтров serviceFiltersGroup связана условием  OR? Вам нужно объединить с каким-то другим условием?

Не смотрели, при открытии окна выбора запрос к веб-серверу идёт с Вашим фильтром?

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

Да, предлагает выбрать все записи.

OR здесь просто на будущее, условия да, будут.

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

Фильтры смотреть у запроса к методу SelectQuerry у DataService примерно тут:

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

У Вас, по идее, должен быть один Ваш фильтр вместо него.

 

А почему бы просто не настроить деталь и связь с разделом в мастере стандартными средствами? Там можно указать и текстовые поля:

Александр, спасибо.

Изначально, наверно, неправильно объяснил.

Суть в том, что фильтр этот нужно ставить не в саму деталь, а на справочник выбора в эту деталь (lookupListConfig)

Но фильтр этот нужно поставить как бы ЧЕРЕЗ объект.

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

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

Всем доброго дня. Версия 7.15.

 

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

Нравится

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

Денис, звонки хранятся в таблице Call, также есть отдельная SysActiveCall. Если звонок ещё идёт, EndDate не заполнено. Если не по контакту, а по оператору, попробуйте фильтровать по CreatedById или ModifiedById.

Денис, звонки хранятся в таблице Call, также есть отдельная SysActiveCall. Если звонок ещё идёт, EndDate не заполнено. Если не по контакту, а по оператору, попробуйте фильтровать по CreatedById или ModifiedById.

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

Добрый день. Столкнулись со следующей проблемой, что есть много писем и после обработки одного письма из списка - обновляется весь список писем и надо перейти к обратно к последнему. Понял как реализовать прокрутку, но никак не получается запустить ее после полной загрузки (писем более 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);

 

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