gifts2017

Готовое решение для протоколирования записи и удаления данных в регистре сведений

Опубликовал megatrend - (megatrend) в раздел Администрирование - Журнал регистрации

Представляю написанную мной процедуру, которая, будучи своевременно встроена в программу 1С Предприятие 8.2, позволит отследить внесение изменений (запись/удаление) в любом регистре сведений (или в нескольких регистрах одновременно).

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

Результатом работы процедуры являются записи в журнале регистрации, в которых кратко записывается суть производимых с регистром сведений изменений (одна-две строки в журнале регистрации на каждую транзакцию в регистре). При написании процедуры я руководствовался принципом : результат работы процедуры в журнале регистрации должен быть хорошо читаем и быстро осознаваем человеком.

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

Программный код написан в стиле этюда : в тесте процедуры закомментирован код, который позволит ещё более усовершенствовать работу этой процедуры (в частности : получить информацию, которая будет вытеснена из регистра после записи набора). Мне это усовершенствование на практике пока не потребовалось, поэтому данная ветка на момент написания этой статьи не получила развитие.

О практической пользе этой процедуры. Эта процедура, будучи своевременно встроена в базу 1С Зарплата и управление персоналом 8.2, реально помогла мне отследить порчу конкретным пользователем штатного расписания в базе 1С Зарплата и Управление персоналом 8.2 и переклассифицировать инцидент «порча данных штатного расписания» из разряда «программный сбой» в «ошибку пользователя».

 

Процедура ЖурнализированиеРегистраСведенийПередЗаписью(Источник, Отказ, Замещение) Экспорт

   
НаборЗаписей = Источник;

   
ТаблицаДляПечати1 = НаборЗаписей.Выгрузить();

   
ОписаниеИзменений1 = "";

   
СсылкаДляОтраженияВЖурналеРегистрации1 = Неопределено;

    Если
ТаблицаДляПечати1.Количество() = 0 Тогда
       
// в регистр пишется пустой набор записей, т.е. происходит удаление из регистра сведений по наложенному в наборе отбору

       
ЧтоПроисходит1 = "Удаление в регистре сведений";

       
МетаданныеНабора = НаборЗаписей.Метаданные();

       
ИмяРегистра = МетаданныеНабора.ПолноеИмя();

       
// Формируем текст условия блока ГДЕ основного запроса,
        // в соответствии с установленным отбором для набора записей

       
Запрос = Новый Запрос;

       
СписокПолейУсловияОтбораТекст = "";
       
Итерация = 0;
        Для каждого
ЭлементОтбора Из НаборЗаписей.Отбор Цикл
            Если не
ЭлементОтбора.Использование Тогда
                Продолжить;
            КонецЕсли;

            Если
Итерация = Тогда
               
ОписаниеИзменений1 = ОписаниеИзменений1 + "Отбор : ";
            Иначе
               
СписокПолейУсловияОтбораТекст = СписокПолейУсловияОтбораТекст  + " И ";
            КонецЕсли;

           
СписокПолейУсловияОтбораТекст = СписокПолейУсловияОтбораТекст +" Набор." + ЭлементОтбора.Имя + " = &" + ЭлементОтбора.Имя;

           
// здесь нужно сохранить в журнале регистрации значения отборов
           
ОписаниеИзменений1 = ОписаниеИзменений1 + "" + ЭлементОтбора.Имя + " = " + СокрЛП(Формат(ЭлементОтбора.Значение, "ДФ=dd.MM.yyyy")) + "" + Символы.ПС;

            Если
СсылкаДляОтраженияВЖурналеРегистрации1 = Неопределено Тогда
                Если
ТипЗнч(ЭлементОтбора.Значение) <> Тип("Дата") Тогда // дата в качестве представления объекта не нужна! лучше любой ссылочный тип
                   
СсылкаДляОтраженияВЖурналеРегистрации1 = ЭлементОтбора.Значение;
                КонецЕсли;
            КонецЕсли;
           
Запрос.УстановитьПараметр(ЭлементОтбора.Имя, ЭлементОтбора.Значение);

           
Итерация = 1;
        КонецЦикла;

        Если
Итерация = 1 Тогда
           
СписокПолейУсловияОтбораТекст = " ГДЕ " + СписокПолейУсловияОтбораТекст;
        КонецЕсли;

       
Запрос.Текст = "ВЫБРАТЬ * ИЗ " + ИмяРегистра + " КАК Набор
        | "
+ СписокПолейУсловияОтбораТекст + "";

       
// ТаблицаДляПечати1 = Запрос.Выполнить().Выгрузить();
        // а тут лежат старые данные в регистре (которые перетираются!!!)
        // их можно анализировать и печатать

   
Иначе // записывается непустой набор записей

       
ЧтоПроисходит1 = "Запись в регистр сведений";

        Для каждого
Запись1 Из ТаблицаДляПечати1 Цикл

            Для каждого
Колонка1 Из ТаблицаДляПечати1.Колонки Цикл

               
ЗначениеКолонки1 = Запись1[Колонка1.Имя];
                Если
ЗначениеЗаполнено(ЗначениеКолонки1) Тогда // печатаем почти все значения непустых измерений, ресурсов, реквизитов!

                   
ТипЗнач1 = ТипЗнч(ЗначениеКолонки1);

                   
МожноПечататьПолноеЗначениеКолонки1 = Истина;
                    Если
ТипЗнач1 = Тип("Число") Тогда
                        Если
ЗначениеКолонки1 > 1000 Тогда
                           
// защита данных в журнале регистрации : не печатаем числовые значения колонок, если они превышают 1000 !
                            // например, это могут быть вилки окладов!
                           
МожноПечататьПолноеЗначениеКолонки1 = Ложь;
                        КонецЕсли;
                    КонецЕсли;

                    Если
МожноПечататьПолноеЗначениеКолонки1 Тогда
                       
ОписаниеИзменений1 = ОписаниеИзменений1 + Колонка1.Имя + " = " + Формат(ЗначениеКолонки1, "ДФ=dd.MM.yyyy") + Символы.ПС;

                        Если
СсылкаДляОтраженияВЖурналеРегистрации1 = Неопределено Тогда
                            Если
ТипЗнач1 <> Тип("Дата") Тогда
                               
СсылкаДляОтраженияВЖурналеРегистрации1 = ЗначениеКолонки1;
                            КонецЕсли;
                        КонецЕсли;

                    Иначе
                       
ОписаниеИзменений1 = ОписаниеИзменений1 + Колонка1.Имя + " > 1000" + Символы.ПС;
                    КонецЕсли;

                КонецЕсли;
            КонецЦикла;

            Прервать;
// прочтём только первую запись

       
КонецЦикла;

        Если
ТаблицаДляПечати1.Количество() > 1 Тогда

           
// по остальным записям - укажем только полное количество записей

           
ОписаниеИзменений1 = "Всего записей набора = " + ТаблицаДляПечати1.Количество() + "; первая запись :" + Символы.ПС + ОписаниеИзменений1;

        КонецЕсли;

    КонецЕсли;

   
ЗаписьЖурналаРегистрации(ЧтоПроисходит1, УровеньЖурналаРегистрации.Предупреждение, МетаданныеНабора, СсылкаДляОтраженияВЖурналеРегистрации1, СокрЛП(ОписаниеИзменений1));

КонецПроцедуры

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
ЖурнализированиеРегистраСведенийПередЗаписью.txt
.txt 4,34Kb
20.03.13
22
.txt 4,34Kb 22 Скачать

См. также

Вознаграждение за ответ
Сумма: 0 $m
Добавили:
Серж а (ASV085) (0.50 $m)
Подписаться Добавить вознаграждение

Комментарии

1. Дмитрий Елисеев (w-divin) 20.03.13 18:35
Полезненько... спасибки...
megatrend; +1 Ответить
2. Сергей (sstar90) 21.03.13 10:01
спасибо, сам задумывался над этим
megatrend; +1 Ответить
3. Алекс Одинэсник (Alex1Cnic) 27.11.13 10:19
О как раз то что доктор прописал.... У меня тоже аналогичная задачка есть: добавлять в журнал регистрации дополнительные данные. Супер! Плюсую!
megatrend; +1 Ответить
4. Dmitry Bas (b-dm) 27.10.14 18:09
Чудесная вещь. сейчас проверим :-) А в текстовом файле выложено то же самое что написано в публикации ?)
5. megatrend - (megatrend) 27.10.14 22:28
(4) b-dm, да, файл не отличается от статьи.
6. Mary Maksimova (primara) 13.05.15 16:33
Спасибо, очень помогло!
megatrend; +1 Ответить
7. Серж а (ASV085) 25.06.15 09:35
Спасибо, как раз нужно было на регистр сведений вести запись в журанал, кто его меняет, а кто его портит.
megatrend; +1 Ответить
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа