При работе с типовыми конфигурациями 1С (например, «Бухгалтерия предприятия 3.0») часто возникает необходимость проанализировать историю изменений документов. В Библиотеке Стандартных Подсистем (БСП) для этого предназначен регистр сведений ВерсииОбъектов. Однако при попытке прочитать данные напрямую из ресурса ВерсияОбъекта разработчики сталкиваются с тем, что там хранится зашифрованная строка или набор некорректных символов.
Рассмотрим подробно, почему возникает эта проблема, как правильно извлекать данные из регистра и какое решение будет наиболее эффективным для задач аналитики.
В ресурсе ВерсияОбъекта данные хранятся в типе ХранилищеЗначения. Внутри него находится сериализованный объект в формате XML, который перед сохранением сжимается алгоритмом Deflate. Если просто попытаться декодировать Base64-строку из файла или структуры, то на выходе получится сжатый двоичный поток. При попытке отобразить его как обычный текст программа выведет несчитываемый набор символов.
Проанализируем штатный механизм работы подсистемы «Версионирование объектов». Для получения разницы между версиями или распаковки содержимого версии не нужно писать собственные алгоритмы распаковки. В БСП предусмотрены готовые функции в общем модуле ВерсионированиеОбъектов.
Для прочтения состава конкретной версии используем следующий алгоритм:
ВерсияОбъекта с помощью метода Получить().ЧтениеXML или используем функции общего модуля БСП.Пример кода для программного чтения сохраненной версии объекта:
// Получаем ХранилищеЗначения из регистра
ДвоичныеДанныеВерсии = Выборка.ВерсияОбъекта.Получить();
Если ЗначениеЗаполнено(ДвоичныеДанныеВерсии) Тогда
// Используем штатную функцию БСП для получения структуры данных версии
ДанныеВерсии = ВерсионированиеОбъектов.ПрочитатьВерсиюОбъекта(СсылкаНаДокумент, НомерВерсии);
КонецЕсли;
Если требуется получить готовое сравнение двух версий, вызываем процедуру подготовки данных для отчета из модуля ВерсионированиеОбъектов, которая вернет дерево или таблицу с сопоставленными реквизитами.
Выясним, с какими ограничениями можно столкнуться, если использовать данный регистр для постоянного отслеживания активности пользователей (например, для подсчета количества отредактированных документов за день):
ВерсияОбъекта имеет тип ХранилищеЗначения. Язык запросов 1С не умеет работать с содержимым хранилища данных. Чтобы проанализировать реквизиты, придется выбирать все записи в выборку и распаковывать каждую версию в цикле на сервере.Если перед нами стоит задача фиксировать конкретные изменения реквизитов для аналитических отчетов, лучшим решением будет создание собственного легкого регистра сведений и подписки на событие.
Разберем по шагам реализацию этого подхода:
АналитикаОбработкиДокументов с измерениями Документ, Пользователь, Дата и ресурсом КоличествоИзменений (или реквизитом ИзмененныеРеквизиты).ПередЗаписью для необходимых документов.Пример кода в модуле подписки на событие:
Процедура ДокументПередЗаписьюПроверкаИзменений(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
Если Источник.ОбменДанными.Загрузка Или Не Источник.Модифицированность() Тогда
Возврат;
КонецЕсли;
// Получаем текущие данные объекта из базы для сравнения
ЗначенияВБазе = СсылкаНаОбъектПолучитьЗначения(Источник.Ссылка);
Если ЗначенияВБазе <> Неопределено Тогда
// Проверяем изменение конкретного реквизита, например "СуммаDocument"
Если Источник.СуммаДокумента <> ЗначенияВБазе.СуммаДокумента Тогда
// Записываем факт изменения в наш аналитический регистр
ЗаписатьФактИзменения(Источник.Ссылка, Пользователи.АвторизованныйПользователь());
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Преимущества такого подхода: данные записываются в плоском виде, легко индексируются СУБД, а итоговый отчет по работе пользователей строится одним простым и быстрым запросом без распаковки ХранилищеЗначения.