Книга знаний

1С:Предприятие / v8 / Объекты конфигурации / Справочники

v8: Регистрация изменений в справочнике

Регистрация изменений данных в справочнике в журнал регистрацииАвтор статьи: Rovan | Редакторы: Волшебник
Последняя редакция №5 от 22.02.06 | История
URL: http://kb.mista.ru/article.php?id=93

Ключевые слова: регистрация изменений, журнал регистрации, история изменения, версионность


Процедура глЗаписатьПротоколИзмененийСправочника(Конт, ИмяПоля = "", ТабЧасть = Неопределено, НомерСтрокиТЧ = 0 ) Экспорт
    Если ИмяПоля <> "" Тогда
        Если ТабЧасть <> Неопределено Тогда
            Если НомерСтрокиТЧ < 1 или
                 НомерСтрокиТЧ > Конт[ТабЧасть].Количество() или
                 НомерСтрокиТЧ > Конт.Ссылка[ТабЧасть].Количество() Тогда
                Возврат;
            КонецЕсли;    
                
            НовоеЗначение  = Конт[ТабЧасть][НомерСтрокиТЧ-1][ИмяПоля]; 
            СтароеЗначение = Конт.Ссылка[ТабЧасть][НомерСтрокиТЧ-1][ИмяПоля];
        Иначе
            НовоеЗначение  = Конт[ИмяПоля]; 
            СтароеЗначение = Конт.Ссылка[ИмяПоля];
        КонецЕсли;
         
        Если НовоеЗначение <> СтароеЗначение Тогда
            ЗаписьЖурналаРегистрации( "Данные.Изменение",
                УровеньЖурналаРегистрации.Информация, 
                "Справочник." + Конт.Метаданные().Имя,     Конт.Ссылка, 
                ?( ТабЧасть = Неопределено, "", "ТабЧасть: " + ТабЧасть + ", стр №" + НомерСтрокиТЧ + ", " ) +
                "Поле <" + ИмяПоля + "> С <" + СтароеЗначение + "> на <" + НовоеЗначение + ">" );
        КонецЕсли;
            



        Возврат;
    КонецЕсли;
    
    Если ПустоеЗначение( Конт ) или
         ПустоеЗначение( Конт.Ссылка ) или
         Конт.ЭтоНовый() Тогда
        Возврат;
    КонецЕсли;
    
    глЗаписатьПротоколИзмененийСправочника(Конт, "Код" );
    глЗаписатьПротоколИзмененийСправочника(Конт, "Наименование" );
    
    Для каждого КонкретныйРеквизит из Конт.Метаданные().Реквизиты Цикл
        глЗаписатьПротоколИзмененийСправочника(Конт, КонкретныйРеквизит.Имя );
    КонецЦикла;
    
    Для каждого ТекТаблЧасть из Конт.Метаданные().ТабличныеЧасти Цикл
        БылоСтрок  = Конт.Ссылка[ТекТаблЧасть.Имя].Количество();
        СталоСтрок = Конт[ТекТаблЧасть.Имя].Количество();
        
        Для СчетСтрок = 1 по Макс( БылоСтрок, СталоСтрок ) Цикл
            Если СчетСтрок > БылоСтрок Тогда
                ЗаписьЖурналаРегистрации( "Данные.Изменение", УровеньЖурналаРегистрации.Информация, 
                    "Справочник." + Конт.Метаданные().Имя, Конт.Ссылка, 
                    "ТабЧасть: " + ТекТаблЧасть.Имя + ", Добавлена строка № " + СчетСтрок );
             ИначеЕсли СчетСтрок > СталоСтрок Тогда
                ЗаписьЖурналаРегистрации( "Данные.Изменение", УровеньЖурналаРегистрации.Информация, 
                    "Справочник." + Конт.Метаданные().Имя, Конт.Ссылка, 
                    "ТабЧасть: " + ТекТаблЧасть.Имя + ", Удалена строка № " + СчетСтрок );
             Иначе
                Для каждого КонкретныйРеквизит из Конт.Метаданные().ТабличныеЧасти[ТекТаблЧасть.Имя].Реквизиты Цикл
                    глЗаписатьПротоколИзмененийСправочника( Конт, КонкретныйРеквизит.Имя, ТекТаблЧасть.Имя, СчетСтрок );
                КонецЦикла;
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
КонецПроцедуры

Процедура глПередЗаписью(ЭтотОбъект, Отказ) Экспорт
   глЗаписатьПротоколИзмененийСправочника( ЭтотОбъект );    
КонецПроцедуры

//В любом справочнике пишем:
Процедура ПередЗаписью(Отказ)
    глПередЗаписью(ЭтотОбъект,Отказ);
КонецПроцедуры

//Дополнительно - По привычке из 7-ки
Функция ПустоеЗначение(вхЗначение) Экспорт 
    Возврат обЗначениеНеЗаполнено( вхЗначение );
КонецФункции 

//Встроенная в торговлю
Функция обЗначениеНеЗаполнено(Значение) Экспорт

    Результат = Ложь;
    ТипЗначения = ТипЗнч(Значение);

    // Сначала примитивные типы
    Если Значение = Неопределено Тогда
        Результат = Истина;
    ИначеЕсли Значение = NULL Тогда
        Результат = Истина;
    ИначеЕсли ТипЗначения = Тип("Строка") Тогда
        Если СокрЛП(Значение) = "" Тогда
            Результат = Истина;
        КонецЕсли; 
    ИначеЕсли ТипЗначения = Тип("Число") Тогда
        Если Значение = 0 Тогда
            Результат = Истина;
        КонецЕсли; 
    ИначеЕсли ТипЗначения = Тип("Дата") Тогда
        Если Значение = Дата('00010101') Тогда
            Результат = Истина;
        КонецЕсли; 
    ИначеЕсли ТипЗначения = Тип("Булево") Тогда
        Результат = Ложь; // Булево будем считать не пустым
        
    // Для остальных будем считать значение пустым, если оно равно
    // дефолтному значению своего типа
    Иначе
        Если Значение = Новый(ТипЗначения) Тогда
            Результат = Истина;
        КонецЕсли; 
    КонецЕсли; 

    Возврат Результат;
    
КонецФункции // обЗначениеНеЗаполнено()




Другой вариант - сериализовать старый элемент справочника (документ) в XML-значение с помощью функции XMLСтрока и сохранить его в виде файла, или в базе данных. Затем можно будет десериализовать этот объект с помощью функции XMLЗначение и получить версию объекта на предыдущий момент времени.

Это все будет работать, если структура данных не менялась.

Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика