При разработке и сопровождении конфигураций на платформе 1С:Предприятие нередко возникает задача определить, когда именно и кем был в последний раз изменен конкретный элемент справочника или документ. Начиная с релиза платформы 8.3.11, разработчикам доступен удобный штатный механизм «История данных» (Data History), позволяющий легко считывать всю хронологию изменений через менеджер истории. Однако в версиях платформы 8.3.10 и более ранних данный функционал отсутствует «из коробки» на уровне платформы.
Разберем основные технические подходы к решению этой задачи на платформе 8.3.10, проанализируем примеры программного кода, выявим их достоинства, недостатки и ограничения.
Если в конфигурации заранее не велся специализированный учет изменений, то единственным источником сведений о прошлых изменениях является системный Журнал регистрации. Платформа 1С предоставляет программный метод ВыгрузитьЖурналРегистрации, с помощью которого можно получить события изменения объекта.
Рассмотрим структуру вызова метода и сформируем отбор по конкретной ссылке на элемент справочника:
// Создаем структуру отбора для журнала регистрации
Отбор = Новый Структура;
Отбор.Вставить("Данные", СсылкаНаЭлемент);
// Указываем список интересующих событий
МассивСобытий = Новый Массив;
МассивСобытий.Добавить("_$Data$_.Update"); // Изменение элемента
МассивСобытий.Добавить("_$Data$_.New"); // Создание элемента
Отбор.Вставить("Событие", МассивСобытий);
// Создаем таблицу значений для выгрузки результата
ТаблицаЖурнала = Новый ТаблицаЗначений;
// Выгружаем последнюю 1 запись (параметр Количество = 1)
ВыгрузитьЖурналРегистрации(ТаблицаЖурнала, Отбор, "Дата, Пользователь, ИмяПользователя, Событие", , 1);
Если ТаблицаЖурнала.Количество() > 0 Тогда
ДатаПоследнегоИзменения = ТаблицаЖурнала[0].Дата;
Пользователь = ТаблицаЖурнала[0].Пользователь;
ИмяПользователя = ТаблицаЖурнала[0].ИмяПользователя;
КонецЕсли;
Разберем по шагам, как работает этот фрагмент кода:
Структура и передаем в ключ Данные прямую ссылку на нужный элемент справочника._$Data$_.Update отвечает за перезапись объекта, а _$Data$_.New — за первичное создание.ВыгрузитьЖурналРегистрации, передав в качестве лимита последнюю запись (параметр Количество = 1), что исключает необходимость считывать всю историю событий за весь период.Ограничения данного способа:
Если конфигурация создана на базе Библиотеки Стандартных Подсистем (БСП) (к ним относятся типовые конфигурации 1С:Бухгалтерия, 1С:Управление торговлей, 1С:ERP и др.), мы можем воспользоваться встроенным механизмом версионирования. При включенной настройке версионирования для справочника данные о каждой версии сохраняются в регистре сведений ВерсииОбъектов.
Посмотрим на пример запроса к регистру сведений ВерсииОбъектов:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| Версии.ДатаВерсии КАК ДатаИзменения,
| Версии.АвторВерсии КАК Автор
|ИЗ
| РегистрСведений.ВерсииОбъектов КАК Версии
|ГДЕ
| Версии.Объект = &Ссылка
|УПОРЯДОЧИТЬ ПО
| Версии.НомерВерсии УБЫВ";
Запрос.УстановитьПараметр("Ссылка", СсылкаНаЭлемент);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Если Выборка.Следующий() Тогда
ДатаПоследнегоИзменения = Выборка.ДатаИзменения;
АвторИзменения = Выборка.Автор;
КонецЕсли;
Преимущества и особенности подхода:
Если информационная база снята с поддержки или находится в режиме доработки, целесообразно предусмотреть хранение даты изменения на уровне структуры метаданных.
Рассмотрим два варианта реализации:
ДатаИзменения с типом Дата (состав: Дата и время). В модуле объекта в обработчике события ПередЗаписью прописываем:
Процедура ПередЗаписью(Отказ)
ДатаИзменения = ТекущаяДатаСеанса();
КонецПроцедуры
ПередЗаписью с источником СправочникОбъект и записываем текущую дату и автора в непериодический независимый регистр сведений.Проанализируем частую ошибку: попытку извлечь дату последнего изменения из уникального идентификатора объекта (GUID). В платформе 1С идентификаторы формируются по стандарту UUIDv1, который содержит временную метку момента создания ссылки.
С помощью побитового разбора УникальныйИдентификатор можно программно вычислить точную дату создания элемента. Однако при последующих перезаписях и модификациях элемента его GUID остается неизменным, поэтому определить дату последнего изменения данным методом невозможно.
Выясним, как решается аналогичная задача в версиях платформы 8.3.11 и новее. В них реализована штатная функциональность ИсторияДанных. При включении свойства «История данных» для объекта метаданных получить данные можно одной командой:
ВыборкаВерсий = ИсторияДанных.ВыбратьВерсии(СсылкаНаЭлемент);
Если ВыборкаВерсий.Следующий() Тогда
ДатаИзменения = ВыборкаВерсий.Дата;
Пользователь = ВыборкаВерсий.Пользователь;
КонецЕсли;
Для проектов на платформе 8.3.10 оптимальным выбором без доработки конфигурации остается программная выборка из журнала регистрации через ВыгрузитьЖурналРегистрации либо использование подсистемы версионирования БСП.