Журналирование (логирование, протоколирование) изменений записей регистров сведе #794542


#0 by a2a4
Наработки для хранения. В сети найти быстрее чем у себя :) Почему именно так. 1. Контроль необходим лишь для случаев расследования некорректного занесения данных (а это редкие, единичные случаи). Поэтому отметаем относительно сложные механизмы с выводом в внешний файл или специально предназначенные справочники или иные объекты базы данных. Просто пишем дополнительную информацию в журнал регистрации. 2.  Осуществление записи в журнал (журналирование) в принципе возможно: - в объектах (документах, справочниках и проч. где изменяются регистры сведений); - в модуле набра записей конкретного регистра сведений; - при помощи механизма подписок в каком-либо общем модуле. Универсально использовать механизм подписок. Во-первых, в этом случае вы "поймаете" абсолютно все изменения, как выполненные интерактивно так и программно (включая изменения пришедшие по обмену). Во-вторых, очень просто добавить/удалить журналирование какого-либо регистра сведений (просто добавляя/удаляя значения в источнике подписки на события). 3. Есть два ключевых события при изменении регистра сведений - ПередЗаписью и ПриЗаписи. Они имеют следующее различие. В событии ПередЗаписью есть возможность получить предыдущее значение (читая из базы данных). А для события ПриЗаписи "Процедура-обработчик вызывается после записи объекта в базу данных, но до окончания транзакции записи." 4. Установив РежимТранзакцииЗаписиЖурналаРегистрации.Транзакционная в процедуре ЗаписьЖурналаРегистрации получаем следующее. Во-первых, при отмене транзакции запись в журнале регистрации будет серого цвета, то есть выделяться визуально. Во-вторых, будет легче понимать записи журнала (особенно оба прохода при изменении регистров). Для тех кто не в курсе - изменение записи регистра сведений осуществляется платформой 1с8 в два прохода - удаление предыдущей записи и добавление новой записи регистра сведений. ЗА ИСКЛЮЧЕНИЕМ РЯДА СЛУЧАЕВ ПРОГРАММНОГО ИЗМЕНЕНИЯ ДАННЫХ **. 5. Процедуру ЗаписьЖурналаРегистрации более корректно поместить в самом конце процедуры ПриЗаписи обработчика подписки на событие в виде Если Не Отказ Тогда. Так как в принципе в любом месте до этого может взвестить флаг Отказ=Истина и журналировать то, чего не произошло, бессмысленно. Для упрощения в данной публикации всё реализовано в одной процедуре. Но если вдруг собрались журналировать регистр сведений подчиненный регистратору, то перенсить процедуру ЗаписьЖурналаРегистрации в ПриЗаписи, так как в ряде случаев документ не будет проведен (а значит изменений регистра сведений не будет), а запись в журнале регистрации появится (пусть и с статусом транзакции Отменена). Желающие могут  создать еще одну подписку на событие, с событием ПриЗаписи, и полностью совпадающим источником, и перенести в обработчик этой подписки на событие последний блок Если ... КонецЕсли. При этом СтрокиЖурнала передавать через ДополнительныеСвойства. 6. В ряде случаев возможно ограничивать журналирование. Например если регулярно удаляются тысячами строки регистров. И в подобном случае достаточно вывести в журнал одну запись, что удалено N записей регистра сведений по следующему отбору. В процедуре для этого введена переменная ПорогДетальнойРегистрации. 7. В записях журнала регистрации, в подробных сведениях дополнительно выводится код объектов. Если в этом нет необходимости, то достаточно закомментировать блоки Попытка ... КонецПопытки в двух местах. 8. Существует также два варианта вывода информации. Либо значения всех реквизитов и ресурсов либо только тех, которые имеют не пустые значения. Выбор осуществляется при помощи переменной ВыводНеЗаполненныхЗначенийРеквизитовРесурсов.
#1 by a2a4
Возможно некоторые заметили, что изменение данных регистра сведений записывается в журнал регистрации двумя записями. Почему это так. Изначально было желание выводить дополнительную информацию в следующем виде: Сотрудник = "Иванов"->"Иванчук", Отработано = "8"->"6" то есть наименование измерения/реквизита/ресурса и его значения - предыдущее и новое. Все наглядно и сразу понятно с первого взгляда. НО, не возможно. Вернее очень сложно реализовать. ИМХО, овчинка выделки не стоит.  (если кто-то сможет реализовать подобное - буду рад посмотреть). 1. Где реализовывать сравнение. •    Во всех модулях объектов, в которых меняются данные регистра. В этом случае нужен тщательный контроль за измением конфигурации (на случай возникновения нового места изменения регистра). Практически, забывается через 1-2 года. Плюс невозможность отследить изменения через внешние обработки. •    В событиях ПередЗаписью и ПриЗаписи (как в модуле набора записей так и обработчиках подписки на события). Универсально, но возникает проблема в п.2 2. Как получить одновременно и "старые" и "новые" данные. Изменение записей регистров сведений в большинстве случаев происходит за два прохода **. И если при первом проходе можно получить только "старые" данные (например запросом к БД), то при втором проходе только "новые" данные ***. Связать эти два прохода стандартными методами 1с8 невозможно (общее у них только номер транзакции). Напрашивается стандартное решение - при первом проходе сохранять предыдущие данные (в какой-либо переменной для временного хранения данных (глобальная переменную, константа, регистр сведений, хранилище значения (ПоместитьВоВременноеХранилище) и т.д.)). При этом возникают задачи. •    Как определить что выполняется - просто удаление или первый проход при изменении данных. При "чистом удалении" надо сразу записывать в журнал регистрации, а при изменении данных - сохранять для "второго прохода". Вроде был найден выход - метод Модифицированность. В большинстве случаев при обычном удалении она в событии ПередЗаписью равна Истина, а при изменении в событии ПередЗаписью она равна Ложь. Но в ряде случаев программного "чистого" удаления ориентироваться на метод Модифицированность некорректно***. Либо еще одно решение - при любом удалении сохранять в переменную. При "втором проходе" очищать переменную, а на случай "чистого удаления" запустить регламентированное задание или обработчик ожидания, который при наличии данных в переменной сделает запись в журнал регистрации. Но в этом случае не будет привязки к транзакции и надо будет отдельно отразить какой пользователь сделал изменение. •    Как обеспечить однозначно соответствие между первым и вторым проходом. Можно по отбору (списку измерений) записи регистра сведений, но в регистре сведений могут изменить и значение измерения. 3. Как выполнять сравнеие. При изменении одной записи регистра проблем не существует. Если изменяется несколько записей, то может встать вопрос соответствия предыдущих и новых записей при изменении измерений регистра сведений. В ином случае делаем соответствие по отбору (списку измерений) записей регистров сведений. 4. Кроме того, если есть обмены данными (особенно РИБ) по которым приходят измененные значения регистра сведений, то получаем следующие исходные. Все изменения происходят в одной транзакции. Если было изменение измерения в записи регистра сведений, то по обмену придут два объекта - удаление предыдущей записи и добавление измененной записи (и как определить что это изменение одной записи). В итоге, не получается получить код, который бы корректно отрабатывал 100% возможных вариантов. Поэтому "наглядный и понятный" вариант записи в журнал регистрации не получился. Примечания: * В процессе записи регистра сведений порядок событий следующий ПередЗаписью (в модуле набора записей)->ПередЗаписью (обработчик подписки на событие)->ПриЗаписи (в модуле набора записей)->ПриЗаписи (обработчик подписки на событие). ** При изменении данных регистров сведений "... в общем случае, используются два набора записей: один предназначен для удаления "старой" записи, другой - для записи данных, определенных менеджером записи (или набором записей). Это проявляется, например, в том, что при выполнении записи могут дважды вызываться события ПередЗаписью и ПриЗаписи объекта РегистрСведенийНаборЗаписей, сначала для пустого набора записей удаляющего "старую" запись, а затем для набора записей с новыми данными". Иными словами изменение записи регистра сведений платформа 1с8 осуществляет за два прохода - удаление предыдущих значений и запись новых значений.  ЗА ИСКЛЮЧЕНИЕМ РЯДА СЛУЧАЕВ ПРОГРАММНОГО ИЗМЕНЕНИЯ ДАННЫХ.
#2 by a2a4
Интерактивное изменение значений регистров несколько отличается от некоторых случаев программного изменения. В частности при следующем коде запись в БД будет осуществляться за один проход.
#3 by a2a4
И по поводу признака Модифицированность. В событиях ПередЗаписью и ПриЗаписи. В большинстве случаев Модифицированность=Ложь. Кроме Создание нового. ПередЗаписью    Модифицированность=Истина Удаление. Удаление и/или изменение при помощи кода
#4 by Лефмихалыч
сюда сложи лучше читабельнее будет
Тэги: 1С 8
Ответить:
Комментарии доступны только авторизированным пользователям

В этой группе 1С