В процессе сопровождения информационных баз 1С регулярно возникает ситуация: реквизиты документа или справочника изменены, в журнале регистрации зафиксирован пользователь и факт записи объекта, однако сам сотрудник не может вспомнить, какие именно данные он скорректировал. Стандартный журнал регистрации фиксирует лишь факт события («Данные. Изменение»), но не хранит предыдущие значения реквизитов и состав строк табличных частей.
Разберем, какими инструментами можно решить данную задачу, начиная от штатных подсистем БСП и платформенных механизмов и заканчивая разработкой собственной подсистемы аудита для нетиповых конфигураций.
В большинстве современных конфигураций (1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей 11, 1С:Бухгалтерия предприятия 3.0, 1С:ЗУП 3), а также в ряде конфигураций предыдущих поколений (например, в УПП) уже присутствует готовый механизм — подсистема «Версионирование объектов» Библиотеки стандартных подсистем (БСП).
Данный механизм использует регистр сведений ВерсииОбъектов. Принцип его работы заключается в следующем:
ВерсииОбъектов с типом ХранилищеЗначения.Рассмотрим, как включить и настроить версионирование в пользовательском режиме:
Особенности и подводные камни механизма БСП:
ВерсииОбъектов может вырасти на десятки гигабайт. Обязательно настроим регламентное задание «Очистка устаревших версий объектов».ОбменДанными.Загрузка = Истина. Это штатное поведение для обменов и пакетных обработок, но о нем нужно помнить при расследовании инцидентов.ВерсииОбъектов не попадают.Если мы работаем на современных версиях платформы «1С:Предприятие 8.3», проанализируем встроенный механизм ядра — «История данных». В отличие от БСП, этот механизм реализован непосредственно платформой СУБД/сервера 1С и не требует хранения полных XML-копий объектов.
Главное преимущество платформенной истории данных — сохранение исключительно дельты (разницы между версиями). Это многократно экономит дисковое пространство и снижает нагрузку на сервер при сериализации.
Для включения механизма в конфигураторе выполним следующие шаги:
ИсторияДанных и установим его в значение Использовать.Для программной работы с историей платформа предоставляет специальный менеджер ИсторияДанных. Посмотрим на пример чтения версий объекта:
// Получаем историю версий конкретного документа
МассивВерсий = ИсторияДанных.ВыбратьВерсии(СсылкаНаДокумент);
Для Каждого ЗаписьВерсии Из МассивВерсий Цикл
НомерВерсии = ЗаписьВерсии.НомерВерсии;
ДатаВерсии = ЗаписьВерсии.Дата;
Автор = ЗаписьВерсии.Пользователь;
// Получаем состояние данных на момент конкретной версии
ДанныеВерсии = ИсторияДанных.ПолучитьВерсию(СсылкаНаДокумент, НомерВерсии);
КонецЦикла;
Если перед нами стоит задача фиксировать изменения в старых конфигурациях (например, 1С:Управление торговлей 10.3 или самописных базах на обычных формах), где нет БСП и платформенной истории данных, разработаем собственный механизм на базе подписки на события.
Проанализируем ключевые правила разработки такого алгоритма, чтобы не заблокировать работу пользователей:
ПередЗаписью для источника ДокументОбъект или СправочникОбъект.Источник.Ссылка.ПолучитьОбъект(), так как это приведет к повторному считыванию всей структуры объекта в память и создаст избыточную нагрузку. Считываем только нужные реквизиты через запрос к базе по ссылке.Посмотрим на пример базовой реализации сравнения реквизитов шапки в обработчике подписки:
Процедура ПриЗаписиДокументаПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
// Пропускаем запись, если это обмен данными или новый объект
Если Источник.ОбменДанными.Загрузка Или Источник.ЭтоНовый() Тогда
Возврат;
КонецЕсли;
// Считываем текущее состояние объекта из базы запросом
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Док.Контрагент КАК Контрагент,
| Док.СуммаДокумента КАК СуммаДокумента
|ИЗ
| Документ.РеализацияТоваровУслуг КАК Док
|ГДЕ
| Док.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
Выборка = Запрос.Выполнить().Выбрать();
Если Выборка.Следующий() Тогда
// Сравниваем реквизиты шапки
Если Выборка.Контрагент <> Источник.Контрагент Тогда
ЗафиксироватьИзменение(Источник.Ссылка, "Контрагент", Выборка.Контрагент, Источник.Контрагент);
КонецЕсли;
Если Выборка.СуммаДокумента <> Источник.СуммаДокумента Тогда
ЗафиксироватьИзменение(Источник.Ссылка, "СуммаДокумента", Выборка.СуммаДокумента, Источник.СуммаДокумента);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Процедура ЗафиксироватьИзменение записывает полученную пару значений «Было / Стало» в специализированный непериодический регистр сведений вместе с текущей датой и значением функции ПользователиИнформационнойБазы.ТекущийПользователь().
Таким образом, для современных конфигураций оптимальным выбором является включение версионирования БСП или платформенной истории данных, а собственную разработку целесообразно применять только в условиях жестких архитектурных ограничений устаревших систем.