Как реализовать историю изменений элементов справочника в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Вариант 1. Использование подсистемы «Версионирование объектов» из БСП

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

  1. Готовый функционал: не требуется создавать собственные структуры данных и интерфейсы для просмотра разницы версий.
  2. Оптимизированное хранение: данные версий сжимаются и хранятся в специальном регистре сведений РегистрСведений.ВерсииОбъектов.
  3. Гибкая настройка: можно указать, какие именно справочники нужно версионировать (например, только при записи, при проведении или по требованию пользователя).

Для подключения достаточно включить нужный справочник в состав определяемого типа ОбъектВерсионирования и настроить правила в пользовательском режиме.

Вариант 2. Платформенный механизм «История данных» (начиная с 8.3.11)

В современных версиях платформы 1С:Предприятие 8.3 присутствует штатный механизм ядра СУБД — ИсторияДанных. Разберем, чем он отличается от прикладного версионирования:

  1. Хранение дельты изменений: в отличие от полного снимка объекта, платформа сохраняет только разницу между версиями, что существенно экономит место в базе данных.
  2. Поддержка всех типов объектов: версионировать можно не только ссылочные типы (справочники, документы), но и регистры сведений.
  3. Программный интерфейс: через объект ИсторияДанных можно получать разницу версий и восстанавливать объект на нужный момент времени с помощью метода СформироватьПоВерсии().

Включить историю данных для справочника можно прямо в конфигураторе, установив свойство объекта метаданных ИсторияДанных в значение Использовать.

Вариант 3. Использование периодического регистра сведений

Если конфигурация полностью самописная и использование БСП не планируется, стандартным прикладным способом является создание периодического регистра сведений (например, ИсторияИзмененийСправочников). Проанализируем возможные варианты структуры регистра:

  1. Вариант со снимком всего объекта в ХранилищеЗначения:
    Измерения: Объект (Ссылка), Период.
    Ресурсы: ДанныеВерсии (тип ХранилищеЗначения), Пользователь (СправочникСсылка.Пользователи).
    При каждом изменении объект сериализуется в JSON или XDTO и сохраняется в сжатом виде.
  2. Вариант с пореквизитной записью:
    Измерения: Объект, Период, ИмяРеквизита (Строка).
    Ресурсы: ЗначениеБыло (Строка/ЛюбаяСсылка), ЗначениеСтало.
    Этот подход удобен для вывода простых отчетов, но усложняет обработку табличных частей.

Вариант 4. Сериализация объекта в XML при записи

Разберем пример создания дампа объекта в XML-файл или строковый поток при его записи. Посмотрим, как выгрузить текущий объект в формат XML прямо из модуля объекта или формы:


// Пример записи объекта в XML-файл при возникновении события или исключения
СтрокаСоединенияИнформационнойБазы = СтрокаСоединенияИнформационнойБазы();
ПутьКБД = Сред(СтрокаСоединенияИнформационнойБазы, 7, СтрДлина(СтрокаСоединенияИнформационнойБазы) - 8);

ЗаписьXML = Новый ЗаписьXML(); 
ЗаписьXML.ОткрытьФайл(ПутьКБД + "\" + СокрЛП(ТипЗнч(Объект)) + Объект.Код + ".xml"); 
ЗаписьXML.ЗаписатьНачалоЭлемента("Root"); 

// Сериализуем объект 1С целиком
ВыгружаемыйОбъект = Объект; 
ЗаписатьXML(ЗаписьXML, ВыгружаемыйОбъект); 

ЗаписьXML.ЗаписатьКонецЭлемента(); 
ЗаписьXML.Закрыть();

Для обратного чтения и восстановление данных из XML-файла используется следующий алгоритм:


// Чтение XML и загрузка объекта в базу
Файл = Новый ЧтениеXML();
Файл.ОткрытьФайл(ИмяФайла);

Пока Файл.Прочитать() Цикл
    ОбъектЗагрузки = ПрочитатьXML(Файл);
    ОбъектЗагрузки.Записать();
КонецЦикла;

Файл.Закрыть();

Важное предупреждение: Использовать чистую сериализацию ЗаписатьXML / ПрочитатьXML для долговременного хранения истории следует с осторожностью. При изменении структуры метаданных (например, удалении или переименовании реквизитов справочника) старые файлы XML могут перестать быть валидными для чтения.

Архитектурные рекомендации по учету истории

При реализации собственного механизма отслеживания изменений проанализируем ключевые технические нюансы:

  1. Асинхронная запись: чтобы не замедлять работу пользователей и транзакцию записи основного документа/справочника, целесообразно фиксировать факт изменения в оперативной очереди, а сам процесс выгрузки и сериализации версий выполнять через фоновое задание.
  2. Сжатие данных: если данные сохраняются в реквизитах типа ХранилищеЗначения, обязательно используйте сжатие (параметр СжатиеДанных.ОптимизацияСжатия), чтобы предотвратить раздувание размера базы СУБД.
  3. Очистка устаревших версий: заранее предусмотрите регламентную процедуру удаления версий старше определенного периода (например, хранить историю не более 1 года), иначе таблицы версионирования быстро превысят объем основных бизнес-данных.
← На главную