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