История данных – платформенный механизм хранения истории изменений. Удобен тем, что можно хранить историю изменений регистров сведений, бизнес-процессов, задач, планов обмена, констант, планов видов характеристик, планов счетов, планов видов расчета, а не только справочников и документов.
Информация на сайте ИТС довольно скудная, хочу поделиться опытом.
Если необходимо получить список метаданных, использующих историю, то сначала получаем список всех метаданных, по которым эта история может храниться (поддерживается платформой):
Функция СписокМетаданныхДляОбхода()
ТЗ = Новый ТаблицаЗначений;
ТЗ.Колонки.Добавить("ИмяОбъектаМетаданных");
ТЗ.Колонки.Добавить("ИмяОбъектаДляЗапроса");
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "ПланыОбмена";
НоваяСтрока.ИмяОбъектаДляЗапроса = "ПланОбмена";
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "Константы";
НоваяСтрока.ИмяОбъектаДляЗапроса = "Константа";
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "Справочники";
НоваяСтрока.ИмяОбъектаДляЗапроса = "Справочник";
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "Документы";
НоваяСтрока.ИмяОбъектаДляЗапроса = "Документ";
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "ПланыВидовХарактеристик";
НоваяСтрока.ИмяОбъектаДляЗапроса = "ПланВидовХарактеристик";
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "ПланыСчетов";
НоваяСтрока.ИмяОбъектаДляЗапроса = "ПланСчетов";
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "ПланыВидовРасчета";
НоваяСтрока.ИмяОбъектаДляЗапроса = "ПланВидовРасчета";
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "РегистрыСведений";
НоваяСтрока.ИмяОбъектаДляЗапроса = "РегистрСведений";
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "БизнесПроцессы";
НоваяСтрока.ИмяОбъектаДляЗапроса = "БизнесПроцесс";
НоваяСтрока = ТЗ.Добавить();
НоваяСтрока.ИмяОбъектаМетаданных = "Задачи";
НоваяСтрока.ИмяОбъектаДляЗапроса = "Задача";
Возврат ТЗ;
КонецФункции
После получения массива, можем получить объекты метаданных, в которых включено использование истории:
Функция СписокОбъектовИспользующихИсторию()
СписокМетаданных = СписокМетаданныхДляОбхода();
Для Каждого СтрокаТаблицы Из СписокМетаданных Цикл
Для Каждого ОбМетаданных Из Метаданные[СтрокаТаблицы.ИмяОбъектаМетаданных] Цикл
МассивОбъектов = Новый Массив;
Если ОбМетаданных.ИсторияДанных = Метаданные.СвойстваОбъектов.ИспользованиеИсторииДанных.Использовать Тогда
МассивОбъектов.Добавить(ОбМетаданных);
КонецЕсли;
КонецЦикла;
СтрокаТаблицы.МассивОбъектов = МассивОбъектов;
КонецЦикла;
Возврат СписокМетаданных;
КонецФункции
А теперь подводный камень.
Если очень хочется получить историю изменений с отбором по изменению всех полей, кроме некоторых, выполним следующую последовательность:
Создадим функцию, которая возвращает массив полей для отбора по истории изменений:
Функция МассивИменПолей(ОбъектМетаданных, ТипОбъектаМетаданных)
ИзмененияПолей = Новый Массив;
Если ТипОбъектаМетаданных = "Документы" или ТипОбъектаМетаданных = "Справочники" Тогда
Для Каждого Реквизит Из ОбъектМетаданных.Реквизиты Цикл
Если Реквизит.Имя = "Комментарий" Тогда
Продолжить;
КонецЕсли;
Если Реквизит.Имя = "Ответственный" Тогда
Продолжить;
КонецЕсли;
ИзмененияПолей.Добавить(Реквизит.Имя);
КонецЦикла;
Для Каждого ТЧ Из ОбъектМетаданных.ТабличныеЧасти Цикл
Для Каждого РеквизитТЧ Из ТЧ.Реквизиты Цикл
ИзмененияПолей.Добавить(ТЧ.Имя + "." + РеквизитТЧ.Имя);
КонецЦикла;
КонецЦикла;
Для Каждого Реквизит Из ОбъектМетаданных.СтандартныеРеквизиты Цикл
Если Реквизит.Имя = "Ссылка" Тогда
Продолжить;
КонецЕсли;
ИзмененияПолей.Добавить(Реквизит.Имя);
КонецЦикла;
КонецЕсли;
Возврат ИзмененияПолей;
КонецФункции
Здесь нужно обратить внимание, что при добавлении нескольких элементов в массив, проверка будет выполняться через И (должны быть изменены все поля из массива в версии, тогда она будет присутствовать в результирующей таблице).
Далее получаем версии с отбором:
Отбор = Новый Структура; // создаем структуру для отбора
Отбор.Вставить("Метаданные", Элемент.Метаданные); // добавляем в него метаданные из массива, полученного ранее
ТЗВерсий = ИсторияДанных.ВыбратьВерсии(Отбор); // выбираем версии без отбора по измененным полям
Отбор.Вставить("ИзменениеЗначенийПолей", МассивИменПолей()); // с таким массивом история версий вернет только те версии, в которых изменялись ВСЕ реквизиты из массива
ТЗВерсий = ИсторияДанных.ВыбратьВерсии(Отбор); // Здесь вернется в лучшем случае одна версия(или версия, где менялись ВСЕ реквизиты). Или ни одной, если какой-то реквизит был добавлен в конфигурацию после добавления объекта в базу
Поэтому, если нужно отобрать «лишние» версии, лучше выбрать сначала все версии по объекту или метаданным, а далее получить версии, в которых изменены только те поля, по которым не требуется сравнивать версии и удалить их из результирующей таблицы.
МассивНенужныхПолей1 = Новый Массив;
МассивНенужныхПолей.Добавить("НеотслеживамоеПоле1");
МассивНенужныхПолей2= Новый Массив;
МассивНенужныхПолей2.Добавить("НеотслеживамоеПоле2");
МассивДвухНенужныхПолей = Новый Массив; //если два неотслеживаемых поля изменены в одной версии
МассивДвухНенужныхПолей.Добавить("НеотслеживамоеПоле2");
МассивДвухНенужныхПолей.Добавить("НеотслеживамоеПоле3");
Отбор = Новый Структура;
Отбор.Вставить("Метаданные", Элемент.Метаданные);
Отбор.Вставить("ИзменениеЗначенийПолей", МассивНенужныхПолей1);
ТЗВерсий1 = ИсторияДанных.ВыбратьВерсии(Отбор);
ВерсииКУдалению = Новый Массив;
Для Каждого СтрокаВерсии Из ТЗВерсий1 Цикл
Если СтрокаВерсии.НомерВерсии = 1 Тогда Продолжить; КонецЕсли;
РазличиеВерсий = ИсторияДанных.ПолучитьРазличияВерсий(СтрокаВерсии.Данные, СтрокаВерсии.НомерВерсии, СтрокаВерсии.НомерВерсии-1);
Если РазличиеВерсий.Количество() = 1 Тогда
ВерсииКУдалению.Добавить(Новый Структура("Данные, НомерВерсии", СтрокаВерсии.Данные, СтрокаВерсии.НомерВерсии));
КонецЕсли;
КонецЦикла;
Отбор.Вставить("ИзменениеЗначенийПолей", МассивНенужныхПолей2);
ТЗВерсий2 = ИсторияДанных.ВыбратьВерсии(Отбор);
Для Каждого СтрокаВерсии Из ТЗВерсий2 Цикл
Если СтрокаВерсии.НомерВерсии = 1 Тогда Продолжить; КонецЕсли;
РазличиеВерсий = ИсторияДанных.ПолучитьРазличияВерсий(СтрокаВерсии.Данные, СтрокаВерсии.НомерВерсии, СтрокаВерсии.НомерВерсии-1);
Если РазличиеВерсий.Количество() = 1 Тогда
ВерсииКУдалению.Добавить(Новый Структура("Данные, НомерВерсии", СтрокаВерсии.Данные, СтрокаВерсии.НомерВерсии));
КонецЕсли;
КонецЦикла;
Отбор.Вставить("ИзменениеЗначенийПолей", МассивДвухНенужныхПолей);
ТЗВерсийПоДвумПолям = ИсторияДанных.ВыбратьВерсии(Отбор);
Для Каждого СтрокаВерсии Из ТЗВерсийПоДвумПолям Цикл
Если СтрокаВерсии.НомерВерсии = 1 Тогда Продолжить; КонецЕсли;
РазличиеВерсий = ИсторияДанных.ПолучитьРазличияВерсий(СтрокаВерсии.Данные, СтрокаВерсии.НомерВерсии, СтрокаВерсии.НомерВерсии-1);
Если РазличиеВерсий.Количество() = 2 Тогда
ВерсииКУдалению.Добавить(Новый Структура("Данные, НомерВерсии", СтрокаВерсии.Данные, СтрокаВерсии.НомерВерсии));
КонецЕсли;
КонецЦикла;
Для Каждого ЛишнняяВерсия Из ВерсииКУдалению Цикл
СтрокаВерсииКУдалению = ТЗВерсий.НайтиСтроки(ЛишнняяВерсия);
ТЗВерсий.Удалить(СтрокаВерсииКУдалению[0]);
КонецЦикла;
Надеюсь, эта информация будет кому-то полезна.
Вступайте в нашу телеграмм-группу Инфостарт