Как получить дату и время последнего изменения элемента справочника в платформе 1С 8.3.10 и старше?

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

При разработке и сопровождении конфигураций на платформе 1С:Предприятие нередко возникает задача определить, когда именно и кем был в последний раз изменен конкретный элемент справочника или документ. Начиная с релиза платформы 8.3.11, разработчикам доступен удобный штатный механизм «История данных» (Data History), позволяющий легко считывать всю хронологию изменений через менеджер истории. Однако в версиях платформы 8.3.10 и более ранних данный функционал отсутствует «из коробки» на уровне платформы.

Разберем основные технические подходы к решению этой задачи на платформе 8.3.10, проанализируем примеры программного кода, выявим их достоинства, недостатки и ограничения.

Способ 1. Программный опрос журнала регистрации с помощью метода ВыгрузитьЖурналРегистрации

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

Рассмотрим структуру вызова метода и сформируем отбор по конкретной ссылке на элемент справочника:


// Создаем структуру отбора для журнала регистрации
Отбор = Новый Структура;
Отбор.Вставить("Данные", СсылкаНаЭлемент);

// Указываем список интересующих событий
МассивСобытий = Новый Массив;
МассивСобытий.Добавить("_$Data$_.Update"); // Изменение элемента
МассивСобытий.Добавить("_$Data$_.New");    // Создание элемента
Отбор.Вставить("Событие", МассивСобытий);

// Создаем таблицу значений для выгрузки результата
ТаблицаЖурнала = Новый ТаблицаЗначений;

// Выгружаем последнюю 1 запись (параметр Количество = 1)
ВыгрузитьЖурналРегистрации(ТаблицаЖурнала, Отбор, "Дата, Пользователь, ИмяПользователя, Событие", , 1);

Если ТаблицаЖурнала.Количество() > 0 Тогда
    ДатаПоследнегоИзменения = ТаблицаЖурнала[0].Дата;
    Пользователь = ТаблицаЖурнала[0].Пользователь;
    ИмяПользователя = ТаблицаЖурнала[0].ИмяПользователя;
КонецЕсли;

Разберем по шагам, как работает этот фрагмент кода:

  1. Мы инициализируем объект Структура и передаем в ключ Данные прямую ссылку на нужный элемент справочника.
  2. Формируем массив системных идентификаторов событий: _$Data$_.Update отвечает за перезапись объекта, а _$Data$_.New — за первичное создание.
  3. Вызываем процедуру ВыгрузитьЖурналРегистрации, передав в качестве лимита последнюю запись (параметр Количество = 1), что исключает необходимость считывать всю историю событий за весь период.

Ограничения данного способа:

  1. Производительность: на высоконагруженных базах данных с большим объемом журнала регистрации метод может выполняться продолжительное время.
  2. Целостность данных: если администратор базы данных производил усечение или очистку журнала регистрации, информация о более ранних изменениях будет недоступна.

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

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

Посмотрим на пример запроса к регистру сведений ВерсииОбъектов:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |	Версии.ДатаВерсии КАК ДатаИзменения,
    |	Версии.АвторВерсии КАК Автор
    |ИЗ
    |	РегистрСведений.ВерсииОбъектов КАК Версии
    |ГДЕ
    |	Версии.Объект = &Ссылка
    |УПОРЯДОЧИТЬ ПО
    |	Версии.НомерВерсии УБЫВ";

Запрос.УстановитьПараметр("Ссылка", СсылкаНаЭлемент);

РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Если Выборка.Следующий() Тогда
    ДатаПоследнегоИзменения = Выборка.ДатаИзменения;
    АвторИзменения = Выборка.Автор;
КонецЕсли;

Преимущества и особенности подхода:

  1. Запрос к таблице СУБД выполняется значительно быстрее, чем сканирование файлов журнала регистрации.
  2. Механизм фиксирует данные только в том случае, если версионирование для конкретного типа объектов было заранее включено администратором в пользовательском режиме.

Способ 3. Модификация конфигурации: добавление реквизита или подписки на события

Если информационная база снята с поддержки или находится в режиме доработки, целесообразно предусмотреть хранение даты изменения на уровне структуры метаданных.

Рассмотрим два варианта реализации:

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

Важное различие: дата создания и дата изменения

Проанализируем частую ошибку: попытку извлечь дату последнего изменения из уникального идентификатора объекта (GUID). В платформе 1С идентификаторы формируются по стандарту UUIDv1, который содержит временную метку момента создания ссылки.

С помощью побитового разбора УникальныйИдентификатор можно программно вычислить точную дату создания элемента. Однако при последующих перезаписях и модификациях элемента его GUID остается неизменным, поэтому определить дату последнего изменения данным методом невозможно.

Сравнение с платформой 8.3.11 и выше

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


ВыборкаВерсий = ИсторияДанных.ВыбратьВерсии(СсылкаНаЭлемент);
Если ВыборкаВерсий.Следующий() Тогда
    ДатаИзменения = ВыборкаВерсий.Дата;
    Пользователь = ВыборкаВерсий.Пользователь;
КонецЕсли;

Для проектов на платформе 8.3.10 оптимальным выбором без доработки конфигурации остается программная выборка из журнала регистрации через ВыгрузитьЖурналРегистрации либо использование подсистемы версионирования БСП.

← На главную