Штатный журнал регистрации в 1С:Предприятие 7.7 имеет ряд существенных ограничений. Он фиксирует лишь факт изменения объекта, но не дает детальной информации о том, какой именно реквизит был изменен, какое значение было «до» и какое стало «после». Кроме того, при интенсивной работе файл .log быстро разрастается, что приводит к критическим тормозам системы. Разберем, как можно реализовать полноценный аудит изменений, который будет отвечать требованиям безопасности и производительности.
Самый простой и распространенный способ — это внедрение специализированных функций непосредственно в модули объектов (справочников и документов). Проанализируем, как это реализовать технически. Основная идея заключается в вызове глобальной процедуры в предопределенном событии ПриЗаписи().
Рассмотрим пример реализации структуры такой процедуры. Для этого нам потребуется создать в Глобальном модуле функции, которые будут сравнивать текущее состояние объекта с тем, что уже записано в базе данных. Посмотрим на пример кода, который может быть использован для протоколирования:
Процедура глЗаписатьПротоколИзмененийДокумента(Конт, ВарТабл = 0) Экспорт
// Конт - контекст документа, который мы проверяем
// Проверяем, является ли документ новым
Если Конт.Выбран() = 0 Тогда
Возврат;
КонецЕсли;
// Создаем объект для чтения старых данных из базы
СтарыйОбъект = СоздатьОбъект("Документ." + Конт.Вид());
СтарыйОбъект.НайтиДокумент(Конт.ТекущийДокумент());
// Перебираем реквизиты и сравниваем значения
Для Номер = 1 По Метаданные.Документ(Конт.Вид()).РеквизитШапки() Цикл
ИмяРеквизита = Метаданные.Документ(Конт.Вид()).РеквизитШапки(Номер).Идентификатор;
Если Конт.ПолучитьАтрибут(ИмяРеквизита) <> СтарыйОбъект.ПолучитьАтрибут(ИмяРеквизита) Тогда
// Записываем изменение в отдельный справочник или SQL-таблицу
глЗаписатьВЛог(Конт.ТекущийДокумент(), ИмяРеквизита, СтарыйОбъект.ПолучитьАтрибут(ИмяРеквизита), Конт.ПолучитьАтрибут(ИмяРеквизита));
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Важный момент: такой подход требует внесения изменений в каждый объект метаданных, за которым нужен контроль. Это может быть трудозатратно, но дает полный контроль над логикой записи.
Если ваша база работает под управлением MS SQL Server, мы можем задействовать мощь самой СУБД. Это наиболее производительный метод, так как нагрузка по отслеживанию изменений перекладывается с уровня приложения 1С на уровень сервера базы данных.
Проанализируем преимущества этого подхода:
.log.inserted и deleted, что позволяет легко получить значения до и после транзакции.Для реализации этого метода создается отдельная таблица в базе данных (например, AuditTrail), куда триггер будет записывать идентификатор объекта (ID), имя колонки, старое и новое значение. Выясним причину, почему это не делают все: для расшифровки имен таблиц (SC*, DH*) и реквизитов вам потребуется знание структуры 1cv7.dd или использование внешних компонент для получения метаданных.
Для расширения возможностей платформы 7.7 часто применяются компоненты FormEx и 1С++. Рассмотрим подробнее, как они помогают в решении нашей задачи.
С помощью FormEx можно перехватывать события, которые недоступны в штатном режиме. Например, мы можем фиксировать не только запись, но и просто факт открытия формы пользователем или изменение конкретного поля на форме еще до момента записи. Это позволяет понять, кто «просто любопытствовал» и просматривал конфиденциальные данные.
Компонента 1С++ позволяет выполнять прямые SQL-запросы к базе данных. Разберем по шагам, как организовать просмотр накопленных логов:
ODBCRecordset из 1С++ данные мгновенно извлекаются из SQL-таблицы и выводятся пользователю в виде удобного отчета.Это избавляет от необходимости сканировать огромные текстовые файлы журнала регистрации, что в 1С 7.7 обычно занимает очень много времени.
Если задача стоит не просто «кто поменял», а «нужна возможность откатиться к старой версии», мы должны реализовать систему версионирования. Разберем этот механизм. При каждой записи документа или справочника мы сохраняем полную копию его состояния. Чтобы не раздувать базу данных, данные можно сохранять в формате XML или сжатой строки.
Посмотрим на пример логики сохранения версии:
Процедура глСохранитьВерсиюОбъекта(Конт) Экспорт
// Преобразуем все реквизиты объекта в строку (например, через ЗначениеВСтрокуВнутр)
ТекущееСостояние = ЗначениеВСтрокуВнутр(Конт.ТекущийОбъект());
// Записываем в специальный справочник "ВерсииОбъектов"
СпрВерсии = СоздатьОбъект("Справочник.ВерсииОбъектов");
СпрВерсии.Новый();
СпрВерсии.Объект = Конт.ТекущийДокумент();
СпрВерсии.ДатаИзменения = ТекущаяДата();
СпрВерсии.Автор = ИмяПользователя();
СпрВерсии.Данные = ТекущееСостояние;
СпрВерсии.Записать();
КонецПроцедуры
Такой подход позволяет в любой момент открыть старую версию документа и сравнить ее с текущей с помощью специализированной обработки сравнения (Diff), выделяя цветом измененные строки и реквизиты.
При внедрении системы аудита важно соблюдать баланс между детальностью логов и скоростью работы. Рассмотрим несколько советов:
В заключение отметим, что выбор конкретного метода зависит от масштаба базы и квалификации администратора. Для небольших баз достаточно программных процедур в коде 1С, тогда как для крупных высоконагруженных систем единственным верным решением будет использование SQL-триггеров в связке с 1С++.