Добрый день, всем!

Помогите, может кому-то удалось решить такую проблему с напоминаниями. У пользователя появляется окно напоминаний. Не закрывая этого окна пользователь самостоятельно переходит в нужный раздел и удаляет это напоминание (точнее напоминание само удаляется после установки визы). При этом при попытке следующего вызова этого же окна напоминаний (по таймеру) появляется ошибка и окно напоминаний принимает вид (pusto.jpg). Если у пользователя появляются другие напоминания, то окно напоминаний после этого всё равно появляется пустое до следующего перезапуска системы. Проблема древняя, никаких доработок не производилось.

Судя по отладчику, неизвестное исключение возникает в RefreshDataset при закрытии датасета. Стек вызова TimerOnTimer-ShowTimerWindow-RefreshDataset.

В своем блоге https://community.terrasoft.ua/blogs/2284 Анатолий пытался решить похожую ситуацию, но в скрипте scr_Main в функции GetAreRemindingsExist() у меня совершенно другой код:

function GetAreRemindingsExist() {
        Main.RemindingsDataset.Close();
        var SelectQuery = Main.RemindingsDataset.SelectQuery;
        var PrimarySelect = GetSelectQueryPrimarySelect(SelectQuery);
        EnableFilter(PrimarySelect.Filters, 'ContactID', true);
        var ContactParameter = SelectQuery.Parameters.ItemsByName('ContactID');
        ContactParameter.ValAsGUID = Connector.CurrentUser.ContactID;
        EnableFilter(PrimarySelect.Filters, 'RemindTime', true);
        EnableFilter(PrimarySelect.Filters, 'TimeUpdated', false);
        var RemindTimeParameter = SelectQuery.Parameters.ItemsByName('RemindTime');
        var today = new Date(System.Now());
        RemindTimeParameter.Value = today.getVarDate();
        Main.RemindingsDataset.Open();
        var SubjectTypeIDsArray =
                GetFieldValuesArray(Main.RemindingsDataset, 'SubjectTypeID');
        var RemindingsSubjectTypeCodesArray =
                GetRemindingsSubjectTypeCodesArray(SubjectTypeIDsArray);
        Main.RemindingsDataset.Close();
        return RemindingsSubjectTypeCodesArray;
}
Может что в нем нужно исправить?

PS. Решение всегда закрывать окно напоминаний, конечно, полезное, но не приемлимое для пользователей.

Нравится

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

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

Первое что приходит в голову - скорее всего не очищается корректно memory dataset mds_Reminding.
Каким образом вы удаляете напоминание после установки визы? Удаляете только с таблицы (ds_Reminding) ?

Скриншот отладчика в момент ошибки можете предоставить?

Дмитрий, удаление визы происходит с помощью функции RemoveObjectFromVising скрипта scr_VisaUtils. Есть ли такая функция в базовой конфигурации я не знаю, скорее всего это были доработки. Судя по тексту, действительно не происходит очистки memory dataset. Подскажите, пожалуйста, как правильно произвести его очистку. На всякий случай прикладываю текст своей функции

function RemoveObjectFromVising(ParentItemID, ShowInfo, CurrVisaID){
	if (IsEmptyValue(CurrVisaID)) {
		var DeleteQuery = GetSingleItemByCode('dq_RemoveFromVising');
	} else {
		var DeleteQuery = GetSingleItemByCode('dq_RemoveFromVisingByVisa');
	}
	var Parameters = DeleteQuery.Parameters;
	if (IsEmptyValue(ShowInfo)) {
		ShowInfo = true;
	}
	SetParameterValue(Parameters, 'SubjectID', ParentItemID);
	SetParameterValue(Parameters, 'Description', YourVisaIsNeeded);
	if (!IsEmptyValue(CurrVisaID)) {
		SetParameterValue(Parameters, 'VisaID', CurrVisaID);
	}
	DeleteQuery.Execute();
	if (ShowInfo) {
		ShowInformationDialog("Удалено напоминание о необходимости визирования документа.");
	}
}

Ошибка возникает в разных местах в зависимости от того есть новое напоминание для этого контакта или нет. Поэтому прикрепляю два скриншота.

В связи с тем, что картинки потеряли свое качество при сохранении, прикрепляю те же картинки не сжатые до 600х600 в архиве.

Здравствуйте.
В этой же функции попробуйте очистить и mds. Примерно так:

var SubjectID = CurrVisaID;
var Dataset = Services.GetNewItemByUSI('mds_Reminding');
Dataset.Locate('SubjectID', SubjectID);
Dataset.Delete();

Дмитрий, я правильно понимаю, что это мы открываем пустой датасет и пытаемся в нем что-то найти? А как добраться до нужного нам датасета? Как с ним работать (что еще доступно кроме Open, Locate, Delete, Close). Как сделать Locate по нескольким полям (условиям)?

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

Получить доступ к открытому экземпляру mds_Reminding можно через окно напоминаний:

1

т.е.

var MDS = DatasetLink.Dataset;

Попробуйте для dlData объявить событие OnDatasetBeforeDelete, и в нем удалить аналогичную запись из этого датасета:

function dlDataOnDatasetBeforeDelete(Dataset, DoDelete) {
	var MDS = DatasetLink.Dataset;
	var SubjectID = Dataset('SubjectID');
	MDS.Locate(SubjectID, 'SubjectID'); 
	MDS.Delete();
}

Дмитрий, я извиняюсь, но мне кажется что своим неточным высказыванием я ввёл Вас в заблуждение. Под окном напоминаний имелось ввиду окно реестра напоминаний wnd_RemindingsGridArea, а не wnd_RemindingEdit. У реестра напоминаний memory dataset и не привязан. Это уточнение влияет на указанный способ решения проблемы или есть другие варианты?

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

Добрый день!
Ручному обновлению датагрида эквивалентно выражение RefreshDataset(Dataset);
Базовый метод RefreshDataset находится в scr_DB.

Обратитесь непосредственно к MemoryDataset из метода RefreshDataset.

Что-то я не понимаю((

Установил точку останова в базовом методе RefreshDataset из scr_DB. При ручном обновлении окна реестра Напоминаний не происходит остановки. Зато остановка происходит когда обновление окна реестра Напоминаний срабатывает по таймеру. Так и должно быть?

Когда возникает ошибка (посты #2,#3) датасет закрывается, но открыться не может, потому что Connector.DBEngine.GetSelectQuerySQLText(Dataset.SelectQuery) возвращает пустую строку, то есть запрос по каким-то причинам не сформирован. Что это может быть?

Возможно ли каким-то образом из любого скрипта проверить открыто(активно) ли окно реестра Напоминаний, чтобы вызвать его датасету обновление? (Хотя бы получить переменную Main.RemindingsDataset из скрипта scr_Main). И вообще, возможно ли найти любое окно в приложении (по USI, например) и проверить его активность?

"Фильковский Павел" написал:Обратитесь непосредственно к MemoryDataset из метода RefreshDataset

Не пойму, к какому MemoryDataset обращаться, если у окна реестра Напоминаний нет такового, а только Dataset = ds_Remindings? Если это то что мне необходимо, та как получить этот Dataset из скрипта scr_VisaUtils, например?

Добпый день!

Обратиться к окну напоминаний и его датасету можно по аналогии как это сделано в сервисе scr_Main в функции function ShowTimerWindow():

	if (!Connector.IsDBConnected){
		return;
	}
	var RemindingsSubjectTypeCodesArray = GetAreRemindingsExist();
	var RemindingsDataset;
	Main.RemindingsForm = Connector.Attributes('RemindingsWindow');
	if (Assigned(Main.RemindingsForm)) {
		RemindingsDataset = 
			Main.RemindingsForm.ComponentsByName('dlData').Dataset;
		SetAttribute(RemindingsDataset, 'RemindingsSubjectTypeCodesArray',
				RemindingsSubjectTypeCodesArray);
		var OldRemindingsCount = RemindingsDataset.RecordsCount;
		RefreshDataset(RemindingsDataset);
		var NewRemindingsCount = RemindingsDataset.RecordsCount;
		if (NewRemindingsCount > OldRemindingsCount) {
			Main.RemindingsForm.BringToFront();
		}
	}

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

function TimerOnTimer(Timer) {
	ShowTimerWindow();
	PrepareTimer();
}

А в скрипте окна напоминания реализовать его инициализацию:

function IntitializeTimer() {
	// TimerInterval -- интервал времени срабатывания таймера, в минутах
	var TimerInterval = Timer.Interval;
 
	if (Connector.Attributes.IsValueExists('TimerInterval')) {
		TimerInterval = Connector.Attributes('TimerInterval') * 60000;
	}		
	Main.TimerInterval = TimerInterval;
	PrepareTimer();
}
 
function GetMilliseconds() {
    var NowDate;
    var Milliseconds;
    NowDate = new Date(System.Now());
    Milliseconds = NowDate.getSeconds() * 1000 + NowDate.getMilliseconds();
	return Milliseconds;
}
 
function PrepareTimer() {
	// Выравнивание до минут
	var Interval = Main.TimerInterval - GetMilliseconds();
	if (Interval <= 0) {
		Interval = Main.TimerInterval;
	}
	Timer.Interval = Interval; 
}

Вызов IntitializeTimer() поместить в обработчик событя OnPrepare окна напоминания.

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

function RefreshRemindingsWindow(){
	if (!Connector.IsDBConnected){
		return;
	}
	VisaUtils.RemindingsForm = Connector.Attributes('RemindingsWindow');
	if (Assigned(VisaUtils.RemindingsForm)) {
		var RemindingsDataset = VisaUtils.RemindingsForm.ComponentsByName('dlData').Dataset;
		RefreshDataset(RemindingsDataset);
	}
}

Отлично! Рады помочь! :smile:
Спасибо и Вам за обратный "feedback" с примером Вашей реализации поставленной задачи.

Приятной работы.

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