Как отслеживать историю изменения реквизитов и табличных частей в 1С?

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

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

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

Типовое версионирование объектов в БСП

В большинстве современных конфигураций (1С:ERP, 1С:Комплексная автоматизация, 1С:Управление торговлей 11, 1С:Бухгалтерия предприятия 3.0, 1С:ЗУП 3), а также в ряде конфигураций предыдущих поколений (например, в УПП) уже присутствует готовый механизм — подсистема «Версионирование объектов» Библиотеки стандартных подсистем (БСП).

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

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

Рассмотрим, как включить и настроить версионирование в пользовательском режиме:

  1. Перейдем в раздел Администрирование → Общие настройки → История изменений (или Версионирование объектов).
  2. Установим флаг Хранить историю изменений.
  3. По гиперссылке перейдем к списку объектов и определим режим версионирования для нужных документов и справочников:
    • Версионировать при записи — снимок создается при каждом сохранении объекта;
    • Версионировать при проведении — актуально для документов, позволяет избежать создания лишних версий до момента проведения;
    • Не версионировать — запись истории отключена.
  4. Настроим срок хранения версий (например, за последний месяц или за последний год), чтобы предотвратить бесконтрольный рост объема базы данных.

Особенности и подводные камни механизма БСП:

  1. Быстрый рост размера базы данных. Поскольку каждая версия сохраняет XML-снимок всего объекта целиком, при активной перезаписи тяжелых документов (например, документов реализации или заказов с сотнями строк) регистр ВерсииОбъектов может вырасти на десятки гигабайт. Обязательно настроим регламентное задание «Очистка устаревших версий объектов».
  2. Пропуск при программной записи. Механизм БСП по умолчанию не сохраняет версии, если запись выполняется с установленным флагом ОбменДанными.Загрузка = Истина. Это штатное поведение для обменов и пакетных обработок, но о нем нужно помнить при расследовании инцидентов.
  3. Отсутствие контроля движений. Версионируются исключительно реквизиты и табличные части самого документа. Движения по регистрам накопления и бухгалтерии в регистр ВерсииОбъектов не попадают.

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

Если мы работаем на современных версиях платформы «1С:Предприятие 8.3», проанализируем встроенный механизм ядра — «История данных». В отличие от БСП, этот механизм реализован непосредственно платформой СУБД/сервера 1С и не требует хранения полных XML-копий объектов.

Главное преимущество платформенной истории данных — сохранение исключительно дельты (разницы между версиями). Это многократно экономит дисковое пространство и снижает нагрузку на сервер при сериализации.

Для включения механизма в конфигураторе выполним следующие шаги:

  1. Откроем свойства нужного объекта метаданных (документа или справочника).
  2. Найдем свойство ИсторияДанных и установим его в значение Использовать.
  3. При необходимости настроим состав версионируемых реквизитов и табличных частей в свойствах конкретных полей.

Для программной работы с историей платформа предоставляет специальный менеджер ИсторияДанных. Посмотрим на пример чтения версий объекта:


// Получаем историю версий конкретного документа
МассивВерсий = ИсторияДанных.ВыбратьВерсии(СсылкаНаДокумент);

Для Каждого ЗаписьВерсии Из МассивВерсий Цикл
    НомерВерсии = ЗаписьВерсии.НомерВерсии;
    ДатаВерсии  = ЗаписьВерсии.Дата;
    Автор       = ЗаписьВерсии.Пользователь;
    
    // Получаем состояние данных на момент конкретной версии
    ДанныеВерсии = ИсторияДанных.ПолучитьВерсию(СсылкаНаДокумент, НомерВерсии);
КонецЦикла;

Разработка собственного аудита изменений (для устаревших баз без БСП)

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

Проанализируем ключевые правила разработки такого алгоритма, чтобы не заблокировать работу пользователей:

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

Посмотрим на пример базовой реализации сравнения реквизитов шапки в обработчике подписки:


Процедура ПриЗаписиДокументаПередЗаписью(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
    
    // Пропускаем запись, если это обмен данными или новый объект
    Если Источник.ОбменДанными.Загрузка Или Источник.ЭтоНовый() Тогда
        Возврат;
    КонецЕсли;
    
    // Считываем текущее состояние объекта из базы запросом
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    Док.Контрагент КАК Контрагент,
        |    Док.СуммаДокумента КАК СуммаДокумента
        |ИЗ
        |    Документ.РеализацияТоваровУслуг КАК Док
        |ГДЕ
        |    Док.Ссылка = &Ссылка";
    
    Запрос.УстановитьПараметр("Ссылка", Источник.Ссылка);
    Выборка = Запрос.Выполнить().Выбрать();
    
    Если Выборка.Следующий() Тогда
        // Сравниваем реквизиты шапки
        Если Выборка.Контрагент <> Источник.Контрагент Тогда
            ЗафиксироватьИзменение(Источник.Ссылка, "Контрагент", Выборка.Контрагент, Источник.Контрагент);
        КонецЕсли;
        
        Если Выборка.СуммаДокумента <> Источник.СуммаДокумента Тогда
            ЗафиксироватьИзменение(Источник.Ссылка, "СуммаДокумента", Выборка.СуммаДокумента, Источник.СуммаДокумента);
        КонецЕсли;
    КонецЕсли;

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

Процедура ЗафиксироватьИзменение записывает полученную пару значений «Было / Стало» в специализированный непериодический регистр сведений вместе с текущей датой и значением функции ПользователиИнформационнойБазы.ТекущийПользователь().

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

← На главную