Универсальная история изменения документов и справочников, позволяет сохранять изменения только тех реквизитов документов, справочников, а также их табличных частей, которые действительно изменились. Те реквизиты которые не изменились не попадают в историю. Это позволяет отслеживать кто, когда и что именно изменил в документе или справочнике. Не имеет ссылок на объекты метаданных, что позволяет удалять объекты метаданных, помеченных на удаление, через обработку удаление помеченных на удаление, без проверки на ссылание этого объекта в этом справочнике.
Чтобы эту историю внедрить в Вашу конфигурацию, необходимо:
- Создать Справочник ИзмененияДокументов со следующими параметрами:
-
Создать ФормуСписка и ФормуЭлемента Справочника, в форме элемента сделать её только для просмотра.
-
В общем модуле, который выполняется на клиенте, либо создав новый, разместить экспортируемую процедуру:
Длина наименования 150, Длина кода 20, Тип Кода Строка.
Реквизиты Справочника:
Пользователь - Тип:СправочникСсылка.Пользователи
GUID_Объекта - Тип:Строка, Длина: 36
ДатаИзменения - Дата, Состав даты: Дата и время
Табличная часть "Изменения" справочника, содержит Реквизиты:
Реквизит - Тип:Строка, Длина:200
ЗначениеДо - Тип: Строка, неограниченная
ЗначениеПосле - Тип: Строка, неограниченная
Процедура ЗаписатьИзмененияДокументаВСправочникИзмененияДокументов(Объект) ЭКСПОРТ
Если Объект.ЭтоНовый() Тогда
ID = Новый УникальныйИдентификатор;
Если Сред(Объект.Метаданные().ПолноеИмя(), 1, Найти(Объект.Метаданные().ПолноеИмя(), ".")-1) = "Документ" Тогда
Объект.УстановитьСсылкуНового(Документы[Объект.Метаданные().Имя].ПолучитьСсылку(ID));
ИначеЕсли Сред(Объект.Метаданные().ПолноеИмя(), 1, Найти(Объект.Метаданные().ПолноеИмя(), ".")-1) = "Справочник" Тогда
Объект.УстановитьСсылкуНового(Справочники[Объект.Метаданные().Имя].ПолучитьСсылку(ID));
КонецЕсли;
КонецЕсли;
Изменения = Истина;
ДатаИзм = ТекущаяДата();
//Изменения реквизитов
ЗапросПроверкаРеквизитов = Новый Запрос;
ЗапросПроверкаРеквизитов.Текст = "ВЫБРАТЬ
| *
|ИЗ
| " + Сред(Объект.Метаданные().ПолноеИмя(), 1, Найти(Объект.Метаданные().ПолноеИмя(), ".")) + Объект.Метаданные().Имя + " КАК ОбъектМетаданных
|ГДЕ
| ОбъектМетаданных.Ссылка = &Ссылка";
ЗапросПроверкаРеквизитов.УстановитьПараметр("Ссылка", Объект.Ссылка);
ВыборкаПроверкаРеквизитов = ЗапросПроверкаРеквизитов.Выполнить().Выбрать();
Если ВыборкаПроверкаРеквизитов.Следующий() Тогда
Для Каждого Рек Из Объект.Метаданные().Реквизиты Цикл
Если Объект[Рек.Имя] <> ВыборкаПроверкаРеквизитов[Рек.Имя] Тогда
Если Изменения Тогда
НовЭлемент = Справочники.ИзмененияДокументов.СоздатьЭлемент();
НовЭлемент.Наименование = Строка(Объект.Ссылка);
НовЭлемент.GUID_Объекта = Объект.Ссылка.УникальныйИдентификатор();
НовЭлемент.Пользователь = ПараметрыСеанса.ТекущийПользователь.Ссылка;
НовЭлемент.ДатаИзменения = ДатаИзм;
Изменения = Ложь;
КонецЕсли;
НовСтр = НовЭлемент.Изменения.Добавить();
НовСтр.Реквизит = Рек.Имя;
НовСтр.ЗначениеДо = Строка(ВыборкаПроверкаРеквизитов[Рек.Имя]);
НовСтр.ЗначениеПосле = Строка(Объект[Рек.Имя]);
Если НовЭлемент.Изменения.Количество() = 99999 Тогда
НовЭлемент.Записать();
Изменения = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если ВыборкаПроверкаРеквизитов.ПометкаУдаления <> Объект.ПометкаУдаления Тогда
Если Изменения Тогда
НовЭлемент = Справочники.ИзмененияДокументов.СоздатьЭлемент();
НовЭлемент.Наименование = Строка(Объект.Ссылка);
НовЭлемент.GUID_Объекта = Объект.Ссылка.УникальныйИдентификатор();
НовЭлемент.Пользователь = ПараметрыСеанса.ТекущийПользователь.Ссылка;
НовЭлемент.ДатаИзменения = ДатаИзм;
Изменения = Ложь;
КонецЕсли;
НовСтр = НовЭлемент.Изменения.Добавить();
НовСтр.Реквизит = "ПометкаУдаления";
НовСтр.ЗначениеДо = Строка(ВыборкаПроверкаРеквизитов.ПометкаУдаления);
НовСтр.ЗначениеПосле = Строка(Объект.ПометкаУдаления);
КонецЕсли;
Иначе
Для Каждого Рек Из Объект.Метаданные().Реквизиты Цикл
Если Изменения Тогда
НовЭлемент = Справочники.ИзмененияДокументов.СоздатьЭлемент();
НовЭлемент.Наименование = Строка(Объект.Ссылка);
НовЭлемент.GUID_Объекта = Объект.Ссылка.УникальныйИдентификатор();
НовЭлемент.Пользователь = ПараметрыСеанса.ТекущийПользователь.Ссылка;
НовЭлемент.ДатаИзменения = ДатаИзм;
Изменения = Ложь;
КонецЕсли;
НовСтр = НовЭлемент.Изменения.Добавить();
НовСтр.Реквизит = Рек.Имя;
НовСтр.ЗначениеДо = "";
НовСтр.ЗначениеПосле = Строка(Объект[Рек.Имя]);
Если НовЭлемент.Изменения.Количество() = 99999 Тогда
НовЭлемент.Записать();
Изменения = Истина;
КонецЕсли;
КонецЦикла;
КонецЕсли;
//Проверка на изменение табличных частей документа
Для Каждого ТЧ из Объект.Метаданные().ТабличныеЧасти Цикл
ЗапросПроверкаТЧ = Новый Запрос;
ЗапросПроверкаТЧ.Текст = "ВЫБРАТЬ
| *
|ИЗ
| " + Сред(Объект.Метаданные().ПолноеИмя(), 1, Найти(Объект.Метаданные().ПолноеИмя(), ".")) + Объект.Метаданные().Имя + "." + ТЧ.Имя + " КАК ОбъектМетаданных
|ГДЕ
| ОбъектМетаданных.Ссылка = &Ссылка
|УПОРЯДОЧИТЬ ПО
| НомерСтроки";
ЗапросПроверкаТЧ.УстановитьПараметр("Ссылка", Объект.Ссылка);
ВыборкаПроверкаТЧ = ЗапросПроверкаТЧ.Выполнить().Выбрать();
Для Каждого СтрТЧ Из Объект[ТЧ.Имя] Цикл
Если ВыборкаПроверкаТЧ.Следующий() Тогда
Для Каждого Рек Из Объект.Метаданные().ТабличныеЧасти[ТЧ.Имя].Реквизиты Цикл
Если СтрТЧ[Рек.Имя] <> ВыборкаПроверкаТЧ[Рек.Имя] Тогда
Если Изменения Тогда
НовЭлемент = Справочники.ИзмененияДокументов.СоздатьЭлемент();
НовЭлемент.Наименование = Строка(Объект.Ссылка);
НовЭлемент.GUID_Объекта = Объект.Ссылка.УникальныйИдентификатор();
НовЭлемент.Пользователь = ПараметрыСеанса.ТекущийПользователь.Ссылка;
НовЭлемент.ДатаИзменения = ДатаИзм;
Изменения = Ложь;
КонецЕсли;
НовСтр = НовЭлемент.Изменения.Добавить();
НовСтр.Реквизит = ТЧ.Имя + ":" + Строка(СтрТЧ.НомерСтроки) + " - " + Рек.Имя;
НовСтр.ЗначениеДо = Строка(ВыборкаПроверкаТЧ[Рек.Имя]);
НовСтр.ЗначениеПосле = Строка(СтрТЧ[Рек.Имя]);
Если НовЭлемент.Изменения.Количество() = 99999 Тогда
НовЭлемент.Записать();
Изменения = Истина;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Иначе
Для Каждого Рек Из Объект.Метаданные().ТабличныеЧасти[ТЧ.Имя].Реквизиты Цикл
Если Изменения Тогда
НовЭлемент = Справочники.ИзмененияДокументов.СоздатьЭлемент();
НовЭлемент.Наименование = Строка(Объект.Ссылка);
НовЭлемент.GUID_Объекта = Объект.Ссылка.УникальныйИдентификатор();
НовЭлемент.Пользователь = ПараметрыСеанса.ТекущийПользователь.Ссылка;
НовЭлемент.ДатаИзменения = ДатаИзм;
Изменения = Ложь;
КонецЕсли;
НовСтр = НовЭлемент.Изменения.Добавить();
НовСтр.Реквизит = ТЧ.Имя + ":" + Строка(СтрТЧ.НомерСтроки) + " - " + Рек.Имя;
НовСтр.ЗначениеДо = "";
НовСтр.ЗначениеПосле = Строка(СтрТЧ[Рек.Имя]);
Если НовЭлемент.Изменения.Количество() = 99999 Тогда
НовЭлемент.Записать();
Изменения = Истина;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
КонецЦикла;
Если Не Изменения Тогда
НовЭлемент.Записать();
КонецЕсли;
КонецПроцедуры
И в нужном документе/справочнике в модуле объекта вконце процедуры ПередЗаписью() размещаем следующее:
#Если Клиент Тогда
Если Не Отказ Тогда
НашиДороботки.ЗаписатьИзмененияДокументаВСправочникИзмененияДокументов(ЭтотОбъект);
КонецЕсли;
#КонецЕсли
4. На форме документа/Элемента объекта метаданных документа/справочника, для которого необходимо отслеживать историю изменений, можно разместить кнопку "История изменений", которая будет отбирать из справочника только те элементы которые по данному документу/справочнику. Для этого разместим кнопку на командной панели(ну или где Вам угодно) и в обработчике нажатия на кнопку написать следующее:
Процедура ДействияФормыИсторияИзменений(Кнопка)
ФормаИзменений = Справочники.ИзмененияДокументов.ПолучитьФормуСписка();
ФормаИзменений.СправочникСписок.Отбор.GUID_Объекта.ВидСравнения = ВидСравнения.Равно;
ФормаИзменений.СправочникСписок.Отбор.GUID_Объекта.Использование = Истина;
ФормаИзменений.СправочникСписок.Отбор.GUID_Объекта.Значение = Строка(ЭтотОбъект.Ссылка.УникальныйИдентификатор());
ФормаИзменений.Открыть();
КонецПроцедуры
Обновляем информационную базу и все. При каждом изменении в справочник добавляются элементы (изменения которые внесли пользователи). Думаю данная история изменений будет кому-то интересна и удобна.