v8: Проверка модифицированности объектов Некотрое время назад мне поставили задачу : пользователю нужно быстро узнать, кто редактировал документ(интерактивно, всякие плановые перепроведения и ночные обработчики не в счёт).
Мысли были следующие:
1.Конечно же журнал регистрации и соответственно, КонсольАнализаЖурналаРегистрации.epf -штука очень тормозная.
2. Ведение своего журнала изменений.
Вариантов было два(изначально)
1. Использовать свойство формы документа(справочника и т.д. ) Модифицированность и метод самого объекта БД(речь опять же о документе либо элементе справочника) Модифицированность().
Этот способ не подошёл мне по некоторым причинам : свойство формы менятся во многих типовых документах в ПриОткрытии() ну и т.д.
Метод объекта не срабатывал во многих случаях потому что документ намеренно модифицировался.(это уже я сам постарался)
2. Итак, у меня остался ещё один вариант :
в ПередЗаписью() во всех формах документов я поместил следующий код:
Если ЭтоНовый() тогда
ЭтотОбъект.Автор = глТекущийПользователь;
ИначеЕсли ПроверитьМодифицированностьПередЗаписью(ЭтотОбъект) тогда
ЭтотОбъект.Автор = глТекущийПользователь;
КонецЕсли;
//автор - естественно реквизит документа, есть у всех документов
сама функция ПроверитьМодифицированностьПередЗаписью(Объект) была размещена в одном из общих модулей :
Функция ПроверитьМодифицированностьПередЗаписью(ЭтотОбъект) Экспорт
//проверка реквизитов
Текст = "ВЫБРАТЬ
| ";
Для каждого Реквизит из ЭтотОбъект.Метаданные().Реквизиты цикл
Текст = Текст + ЭтотОбъект.Метаданные().Имя + "." + Реквизит.Имя + ",
| ";
КонецЦикла;
Текст = Текст + ЭтотОбъект.Метаданные().Имя + ".Номер,
| " + ЭтотОбъект.Метаданные().Имя + ".Дата
| ";
////уберём запятую
//Текст = СтрЗаменить(Текст,Реквизит.Имя + ",",Реквизит.Имя);
Текст = Текст + " ИЗ
| Документ." + ЭтотОбъект.Метаданные().Имя + " КАК " + ЭтотОбъект.Метаданные().Имя + "
| ГДЕ " + ЭтотОбъект.Метаданные().Имя + ".Ссылка = &Ссылка";
Запрос = Новый Запрос;
Запрос.Текст = Текст;
Запрос.УстановитьПараметр("Ссылка",ЭтотОбъект.Ссылка);
ШапкаДокумента = Запрос.Выполнить().Выгрузить();
Для каждого РеквизитВКолонке из ШапкаДокумента.Колонки цикл
Если ШапкаДокумента[0][РеквизитВКолонке.Имя] <> ЭтотОбъект[РеквизитВКолонке.Имя] тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
//проверка табчастей
Для каждого ТабЧасть из ЭтотОбъект.Метаданные().ТабличныеЧасти цикл
Запрос.Текст = "";
Текст = "ВЫБРАТЬ
| ";
Для каждого РеквизитТабЧасти из ТабЧасть.Реквизиты цикл
Текст = Текст + ЭтотОбъект.Метаданные().Имя + "." + РеквизитТабЧасти.Имя + ",
| ";
КонецЦикла;
//Текст = СтрЗаменить(Текст,РеквизитТабЧасти.Имя + ",",РеквизитТабЧасти.Имя);
Текст = Текст + ЭтотОбъект.Метаданные().Имя + ".НомерСтроки
| ИЗ
| Документ." + ЭтотОбъект.Метаданные().Имя + "." + Табчасть.Имя + " КАК " + ЭтотОбъект.Метаданные().Имя + "
| ГДЕ " + ЭтотОбъект.Метаданные().Имя + ".Ссылка = &Ссылка
| УПОРЯДОЧИТЬ ПО
| " + ЭтотОбъект.Метаданные().Имя + ".НомерСтроки";
Запрос.Текст = Текст;
Запрос.УстановитьПараметр("Ссылка",ЭтотОбъект.Ссылка);
ТабЧастьДокумента = Запрос.Выполнить().Выбрать();
КоличествоСтрокВБазе = Запрос.Выполнить().Выгрузить().Количество();
Пока ТабЧастьДокумента.Следующий() цикл
Если КоличествоСтрокВБазе <> ЭтотОбъект[ТабЧасть.Имя].Количество() тогда
//проверим, иначе вернём сразу истина
Возврат Истина;
иначе
Если ЭтотОбъект[ТабЧасть.Имя].Количество() > 0 тогда
Для каждого РеквизитТабЧасти из ТабЧасть.Реквизиты цикл
Если ТабЧастьДокумента[РеквизитТабЧасти.Имя] <> ЭтотОбъект[ТабЧасть.Имя][ТабЧастьДокумента.НомерСтроки-1][РеквизитТабЧасти.Имя] тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Иначе
Возврат Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецЦикла; //по табчастям
Возврат Ложь;
КонецФункции
Вот собственно и всё. Конечно можно доработать эту функцию, чтобы она сохраняла внесённые изменения куда-нибудь=)
От Гения 1С: Ничто не ново под луной.
Более ранние вещи на эту тему здесь:
Книга знаний: v8: Парциальная регистрация изменений в базе данных
Книга знаний: v8: Функция сравнения двух объектов одного типа
Хотя следует отметить, что автор использует запрос вместо получить объект, хотя это не дает никаких преимуществ, т.к. все равно сравниваются все поля объекта + еще тратится время на компиляцию запроса по сравнению с ПолучитьОбъект().
|