Предоставляет доступ к функционалу версионирования данных.
Полное описание, параметры и ограничения
МенеджерИсторииДанных (DataHistoryManager)
МенеджерИсторииДанных (DataHistoryManager)
Доступен, начиная с версии 8.3.11.
Методы:
ВыбратьВерсии (SelectVersions)
ВыполнитьОбработкуПослеЗаписиВерсий (ExecuteAfterWriteVersionsProcessing)
ЗаписатьВерсию (WriteVersion)
ЗаписатьКомментарий (WriteComment)
ОбновитьИсторию (UpdateHistory)
ПолучитьДанныеВерсии (GetVersionData)
ПолучитьМетаданные (GetMetadata)
ПолучитьНастройки (GetSettings)
ПолучитьРазличияВерсий (GetVersionDiff)
СформироватьПоВерсии (GenerateFromVersion)
УдалитьВерсии (DeleteVersions)
УдалитьИзОбработкиПослеЗаписиВерсий (DeleteFromAfterWriteVersionsProcessing)
УстановитьНастройки (SetSettings)
Описание:
Предоставляет доступ к функционалу версионирования данных.
Доступность:
Сервер, толстый клиент, внешнее соединение.
Использование в версии:
Доступен, начиная с версии 8.3.11.
Методическая информация
Практические примеры
Создать две реальные собственные версии количества, сравнить, импортировать один снимок и удалить только его
Настройки применяются к единственному собственному учебному справочнику. Реальные записи1→3 дают реальные номера; импорт7 не записывает текущий объект, восстановленный черновик не сохраняется.
Где и как запускать
Полный клиентский общий модуль УчебнаяИстория85 в толстом обычном клиенте отдельной файловой ИБ УчебнаяИсторияВерсий85. Только будущий ручной учебный запуск; фактических запусков0.
Подготовка
Только НОВАЯ отдельная файловая учебная ИБ8.5.1.1343, конфигурация УчебнаяИсторияВерсий85, совместимостьНеИспользовать, основной режим запуска ОбычноеПриложение. Запускайте толстый клиент обычного приложения, не серверную рабочую ИБ. Native8.5 ограничивает ИнформацияОЗаписиВерсииИсторииДанных и ее свойства толстым клиентом; обработчик на кластерном сервере этим уроком не обещается.
Единственный справочник УчебныеТовары: неиерархический, без владельцев и табличных частей, НаименованиеСтрока50, КодСтрока9; реквизиты МаркерUUID(Строка36) и Количество(Число9,0,неотрицательное). Других справочников, документов, регистров, разделителей, планов обмена, подписок, фоновых заданий и расширений нет. Изначально0элементов.
В Конфигураторе для справочника и полей МаркерUUID, Количество, Наименование включите использование истории данных. Общий модуль УчебнаяИстория85: Клиент(обычное приложение)=Истина, Сервер=Ложь, Глобальный=Ложь, Привилегированный=Ложь. Полностью вставьте основной модуль, не внутрь другой процедуры.
Заранее создайте своего настоящего учебного пользователя с административными правами для этого пустого стенда и именем/полным именем без секретов. Войдите им; импорт берет его фактический UUID и имена через ПользователиИнформационнойБазы, а не вымышляет автора.
Создайте собственную обработку с обычной формой. Строковые реквизиты Операция и UUIDОпыта, булевый ПодтвержденСвойОпыт; кнопку Выполнить свяжите с обработчиком Выполнить(Кнопка). Вставьте полный дополнительный модуль формы. UUIDОпыта один раз получите выражением Строка(Новый УникальныйИдентификатор), сохраните в своем журнале опыта.
В модуль менеджера справочника УчебныеТовары вставьте полный дополнительный модуль с обработчиком ОбработкаПослеЗаписиВерсийИсторииДанных и его собственными проверками. Он не обращается к клиентскому общему модулю. Не вызывайте событие вручную с самодельным объектом: настоящую коллекцию предоставляет платформа.
Никакие изменения схемы/F7/объекты/настройки/версии/диалоги здесь не создавались и не запускались. Это полный авторский план самостоятельного будущего запуска только в своем стенде; runtimeVerifiedScenarios=0.
Порядок отдельных операций: СоздатьДвеВерсии85, Прочитать85, Комментарий85. Для очереди по выбору СнятьПервуюИзОчереди85, затем ОбработатьОчередь85. Для миграционного снимка ИмпортироватьСнимок85, затем только явно УдалитьТолькоИмпорт85. Нельзя удалять все версии/метаданные или пропускать данные в API удаления.
Только один оператор/сеанс изменяет опыт. После исключения нет автоматического повторения/отката/очистки: сначала прочитайте реальные оставшиеся записи. Повторное СоздатьДвеВерсии85 отклоняет даже частично созданный собственный объект.
Функция Выполнить85(Операция, UUIDОпыта, Подтверждение) Экспорт
ПроверитьОпыт85(UUIDОпыта, Подтверждение);
Если СтрРазделить("СоздатьДвеВерсии85,Прочитать85,Комментарий85,ИмпортироватьСнимок85,СнятьПервуюИзОчереди85,ОбработатьОчередь85,УдалитьТолькоИмпорт85", ",").Найти(Операция) = Неопределено Тогда
ВызватьИсключение "Неизвестная отдельная учебная операция истории";
КонецЕсли;
Ссылка = НайтиСвойЕдинственныйОбъект85(UUIDОпыта, Истина);
Если Операция = "СоздатьДвеВерсии85" Тогда
Если Ссылка <> Неопределено Тогда
ВызватьИсключение "Нельзя перезаписывать уже начатый собственный опыт";
КонецЕсли;
Настройки = Новый НастройкиИсторииДанных;
Настройки.Использование = Истина;
Поля = Новый Соответствие;
Поля.Вставить("МаркерUUID", Истина);
Поля.Вставить("Количество", Истина);
Поля.Вставить("Наименование", Истина);
Настройки.ИспользованиеПолей = Поля;
ИсторияДанных.УстановитьНастройки(Метаданные.Справочники.УчебныеТовары, Настройки);
ПрочитанныеНастройки = ИсторияДанных.ПолучитьНастройки(Метаданные.Справочники.УчебныеТовары);
Если ПрочитанныеНастройки = Неопределено Или Не ПрочитанныеНастройки.Использование
Или ПрочитанныеНастройки.ИспользованиеПолей.Получить("МаркерUUID") <> Истина
Или ПрочитанныеНастройки.ИспользованиеПолей.Получить("Количество") <> Истина
Или ПрочитанныеНастройки.ИспользованиеПолей.Получить("Наименование") <> Истина Тогда
ВызватьИсключение "Применение own-профиля не подтверждено; остановитесь без записи данных";
КонецЕсли;
Свой = Справочники.УчебныеТовары.СоздатьЭлемент();
Свой.МаркерUUID = UUIDОпыта;
Свой.Наименование = "Уч85 " + UUIDОпыта;
Свой.Количество = 1;
Свой.ЗаписьИсторииДанных.КомментарийВерсии = "own-history85-first:" + UUIDОпыта;
Свой.ЗаписьИсторииДанных.ВыполнятьОбработкуПослеЗаписиВерсии = Истина;
Свой.ЗаписьИсторииДанных.ОбновлятьИсториюСразуПослеЗаписи = Ложь;
Свой.Записать();
Ссылка = Свой.Ссылка;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Обновление истории не вызывается внутри транзакции";
КонецЕсли;
ИсторияДанных.ОбновитьИсторию(Ссылка, Ложь, Ложь);
ПроверитьКоличествоВерсий85(ПолучитьСвоиВерсии85(Ссылка, UUIDОпыта), 1);
Свой = Ссылка.ПолучитьОбъект();
Свой.Количество = 3;
Свой.ЗаписьИсторииДанных.КомментарийВерсии = "own-history85-second:" + UUIDОпыта;
Свой.ЗаписьИсторииДанных.ВыполнятьОбработкуПослеЗаписиВерсии = Истина;
Свой.ЗаписьИсторииДанных.ОбновлятьИсториюСразуПослеЗаписи = Ложь;
Свой.Записать();
ИсторияДанных.ОбновитьИсторию(Ссылка, Ложь, Ложь);
Версии = ПолучитьСвоиВерсии85(Ссылка, UUIDОпыта);
ПроверитьКоличествоВерсий85(Версии, 2);
Возврат СтрШаблон("Own-объектUUID=%1; фактические номера=%2,%3; количество1→3; очередь пока не обрабатывалась",
Строка(Ссылка.УникальныйИдентификатор()), Версии[0].НомерВерсии, Версии[1].НомерВерсии);
КонецЕсли;
Если Ссылка = Неопределено Тогда
ВызватьИсключение "Сначала создайте обе реальные own-версии";
КонецЕсли;
Версии = ПолучитьСвоиВерсии85(Ссылка, UUIDОпыта);
Если Версии.Количество() < 2 Тогда
ВызватьИсключение "Обе исходные собственные версии должны существовать";
КонецЕсли;
Первая = Версии[0].НомерВерсии;
Вторая = Версии[1].НомерВерсии;
Если Операция = "Прочитать85" Тогда
Снимок1 = ИсторияДанных.ПолучитьДанныеВерсии(Ссылка, Первая);
Снимок2 = ИсторияДанных.ПолучитьДанныеВерсии(Ссылка, Вторая);
Если Снимок1.Количество <> 1 Или Снимок2.Количество <> 3 Тогда
ВызватьИсключение "Исторический собственный переход1→3 не подтвержден";
КонецЕсли;
МетаданныеВерсии = ИсторияДанных.ПолучитьМетаданные(Ссылка, Вторая);
Если ТипЗнч(МетаданныеВерсии) <> Тип("Структура") Или Не МетаданныеВерсии.Свойство("Поля")
Или Не МетаданныеВерсии.Поля.Свойство("Количество") Тогда
ВызватьИсключение "Фактические метаданные версии не содержат ожидаемое own-поле";
КонецЕсли;
Различия = ИсторияДанных.ПолучитьРазличияВерсий(Ссылка, Вторая, Первая);
Если Различия = Неопределено Или Не Различия.Свойство("Количество") Тогда
ВызватьИсключение "Own-различия количества не найдены";
КонецЕсли;
Изменение = Различия.Количество;
Если Изменение.ЗначениеДоИзменения <> 1 Или Изменение.ЗначениеПослеИзменения <> 3 Тогда
ВызватьИсключение "Native before/after перепутаны или история изменилась";
КонецЕсли;
Черновик = ИсторияДанных.СформироватьПоВерсии(Ссылка, Первая);
Если Черновик.МаркерUUID <> UUIDОпыта Или Черновик.Количество <> 1
Или Ссылка.ПолучитьОбъект().Количество <> 3 Тогда
ВызватьИсключение "Не подтвержден отдельный незаписанный own-черновик первой версии";
КонецЕсли;
Возврат "Снимки1→3 и различия подтверждены. Черновик содержит1, текущий объект3: восстановление в базу не выполнялось";
ИначеЕсли Операция = "Комментарий85" Тогда
ИсторияДанных.ЗаписатьКомментарий(Ссылка, Вторая, "own-history85-checked:" + UUIDОпыта);
После = ПолучитьСвоиВерсии85(Ссылка, UUIDОпыта);
Если После[1].НомерВерсии <> Вторая Или После[1].Комментарий <> "own-history85-checked:" + UUIDОпыта Тогда
ВызватьИсключение "Комментарий собственной фактической версии не подтвержден";
КонецЕсли;
Возврат "Изменен только комментарий своей второй версии; данные и номер не менялись";
ИначеЕсли Операция = "ИмпортироватьСнимок85" Тогда
ПроверитьКоличествоВерсий85(Версии, 2);
Пользователь = ПользователиИнформационнойБазы.ТекущийПользователь();
Если Пользователь = Неопределено Тогда
ВызватьИсключение "Заранее войдите своим реальным учебным пользователем";
КонецЕсли;
ЧерновикИмпорта = Ссылка.ПолучитьОбъект();
ЧерновикИмпорта.Количество = 7;
ИсторияДанных.ЗаписатьВерсию(ЧерновикИмпорта, ТекущаяДата(), Пользователь.УникальныйИдентификатор,
Пользователь.Имя, Пользователь.ПолноеИмя, ВидИзмененияДанных.Изменение,
"own-history85-import:" + UUIDОпыта, "", Неопределено);
После = ПолучитьСвоиВерсии85(Ссылка, UUIDОпыта);
ПроверитьКоличествоВерсий85(После, 3);
Если После[2].Комментарий <> "own-history85-import:" + UUIDОпыта
Или ИсторияДанных.ПолучитьДанныеВерсии(Ссылка, После[2].НомерВерсии).Количество <> 7
Или Ссылка.ПолучитьОбъект().Количество <> 3 Тогда
ВызватьИсключение "Не подтвержден импорт только снимка, без записи текущего объекта";
КонецЕсли;
Возврат "Создан собственный исторический импорт количества7; текущий объект остался3. НомерИмпорта=" + Строка(После[2].НомерВерсии);
ИначеЕсли Операция = "СнятьПервуюИзОчереди85" Тогда
ИсторияДанных.УдалитьИзОбработкиПослеЗаписиВерсий(Ссылка, Первая);
После = ПолучитьСвоиВерсии85(Ссылка, UUIDОпыта);
Если После[0].НомерВерсии <> Первая Тогда
ВызватьИсключение "Снятие из обработки не должно удалять собственную историческую версию";
КонецЕсли;
Возврат "Из обработки снята только первая own-версия; сама версия истории сохранена. Записей очереди API не перечисляет";
ИначеЕсли Операция = "ОбработатьОчередь85" Тогда
ИсторияДанных.ВыполнитьОбработкуПослеЗаписиВерсий(Ссылка);
Возврат "Обработка запрошена только по своему объекту. Проверьте вывод собственного обработчика; отсутствие вывода не доказывает существование очереди";
КонецЕсли;
ПроверитьКоличествоВерсий85(Версии, 3);
Импорт = Версии[2];
Если Импорт.Комментарий <> "own-history85-import:" + UUIDОпыта
Или ИсторияДанных.ПолучитьДанныеВерсии(Ссылка, Импорт.НомерВерсии).Количество <> 7 Тогда
ВызватьИсключение "Удалять разрешено только свою подтвержденную импортную версию";
КонецЕсли;
ИсторияДанных.УдалитьВерсии(Ссылка, Импорт.НомерВерсии, Импорт.НомерВерсии);
После = ПолучитьСвоиВерсии85(Ссылка, UUIDОпыта);
ПроверитьКоличествоВерсий85(После, 2);
Если После[0].НомерВерсии <> Первая Или После[1].НомерВерсии <> Вторая
Или Ссылка.ПолучитьОбъект().Количество <> 3 Тогда
ВызватьИсключение "Удаление только собственного импортного снимка не подтверждено";
КонецЕсли;
Возврат "Удалена только одна own-импортная версия по точному замкнутому интервалу; обе исходные и текущий объект3 сохранены";
КонецФункции
Процедура ПроверитьОпыт85(UUIDОпыта, Подтверждение)
ПроверитьСвойПустойСтенд();
Если ТипЗнч(Подтверждение) <> Тип("Булево") Или Не Подтверждение Тогда
ВызватьИсключение "Добровольно подтвердите только собственную новую файловую учебную ИБ";
КонецЕсли;
Если ТипЗнч(UUIDОпыта) <> Тип("Строка") Тогда
ВызватьИсключение "UUIDОпыта должен быть строкой";
КонецЕсли;
UUID = Новый УникальныйИдентификатор(UUIDОпыта);
Если UUIDОпыта <> Строка(UUID) Или UUIDОпыта = "00000000-0000-0000-0000-000000000000" Тогда
ВызватьИсключение "Нужен канонический собственный ненулевой UUID опыта";
КонецЕсли;
КонецПроцедуры
Функция НайтиСвойЕдинственныйОбъект85(UUIDОпыта, РазрешеноОтсутствие = Ложь)
Выборка = Справочники.УчебныеТовары.Выбрать();
Свой = Неопределено;
Пока Выборка.Следующий() Цикл
Если Свой <> Неопределено Или Выборка.МаркерUUID <> UUIDОпыта Или Выборка.ПометкаУдаления Тогда
ВызватьИсключение "Разрешен только один собственный UUID-элемент, без чужих данных";
КонецЕсли;
Свой = Выборка.Ссылка;
КонецЦикла;
Если Свой = Неопределено И Не РазрешеноОтсутствие Тогда
ВызватьИсключение "Сначала создайте реальный собственный элемент командой СоздатьДвеВерсии85";
КонецЕсли;
Возврат Свой;
КонецФункции
Функция ПолучитьСвоиВерсии85(Ссылка, UUIDОпыта)
Если НайтиСвойЕдинственныйОбъект85(UUIDОпыта) <> Ссылка Тогда
ВызватьИсключение "Подменена ссылка на собственный единственный элемент";
КонецЕсли;
Отбор = Новый Структура("Данные", Ссылка);
Версии = ИсторияДанных.ВыбратьВерсии(Отбор,
"Данные,НомерВерсии,Дата,Пользователь,ИмяПользователя,ПолноеИмяПользователя,ВидИзмененияДанных,Комментарий,Транзакция,Узел",
"НомерВерсии Возр", 4);
Если ТипЗнч(Версии) <> Тип("ТаблицаЗначений") Или Версии.Количество() > 3 Тогда
ВызватьИсключение "Свой новый опыт допускает не более трех подтвержденных версий";
КонецЕсли;
Для Каждого Версия Из Версии Цикл
Если Версия.Данные <> Ссылка Или Версия.НомерВерсии <= 0 Тогда
ВызватьИсключение "Получена чужая ссылка или недопустимый номер версии";
КонецЕсли;
Снимок = ИсторияДанных.ПолучитьДанныеВерсии(Ссылка, Версия.НомерВерсии);
Если ТипЗнч(Снимок) <> Тип("Структура") Или Не Снимок.Свойство("МаркерUUID")
Или Снимок.МаркерUUID <> UUIDОпыта Тогда
ВызватьИсключение "Исторические данные не принадлежат нашему реальному UUID-объекту";
КонецЕсли;
КонецЦикла;
Возврат Версии;
КонецФункции
Процедура ПроверитьКоличествоВерсий85(Версии, Ожидание)
Если Версии.Количество() <> Ожидание Тогда
ВызватьИсключение "Фактическое число own-версий отличается; повторять запись автоматически нельзя";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.Справочники[0].Имя <> "УчебныеТовары"
Или Метаданные.Справочники.УчебныеТовары.Реквизиты.Количество() <> 2
Или Метаданные.Справочники.УчебныеТовары.ТабличныеЧасти.Количество() <> 0
Или Метаданные.Справочники.УчебныеТовары.Реквизиты.Найти("МаркерUUID") = Неопределено
Или Метаданные.Справочники.УчебныеТовары.Реквизиты.Найти("Количество") = Неопределено Тогда
ВызватьИсключение "Нужен только свой единственный учебный справочник с двумя точными реквизитами";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедурыМодуль собственной обычной формы обработки
Обычная форма толстого клиента, три реквизита и кнопка из подготовки.
Обычная форма толстого клиента, три реквизита и кнопка из подготовки.
Процедура Выполнить(Кнопка)
Попытка
Ответ = УчебнаяИстория85.Выполнить85(Операция, UUIDОпыта, ПодтвержденСвойОпыт);
Исключение
Сообщить("Own-операция не подтверждена. Не повторяйте запись автоматически; сначала прочитайте фактическое состояние собственного опыта");
Возврат;
КонецПопытки;
Сообщить(Ответ);
КонецПроцедурыПолный модуль менеджера собственного справочника УчебныеТовары
Полный реальный обработчик платформенного события со всеми собственными проверками, файловая ИБ/толстый клиент; на сервере кластера не проверялся.
Полный реальный обработчик платформенного события со всеми собственными проверками, файловая ИБ/толстый клиент; на сервере кластера не проверялся.
Процедура ОбработкаПослеЗаписиВерсийИсторииДанных(ИнформацияОЗаписиВерсий)
Попытка
Количество = ИнформацияОЗаписиВерсий.Количество();
Если Количество = 0 Тогда
Сообщить("Own-пакет истории пуст; ничего не записывается");
Возврат;
КонецЕсли;
Для Индекс = 0 По Количество - 1 Цикл
Информация = ИнформацияОЗаписиВерсий.Получить(Индекс);
Если ИнформацияОЗаписиВерсий.Индекс(Информация) <> Индекс Тогда
Сообщить("Own-индекс пакета не подтвержден");
Возврат;
КонецЕсли;
Если ТипЗнч(Информация.Данные) <> Тип("СправочникСсылка.УчебныеТовары") Тогда
Продолжить;
КонецЕсли;
Объект = Информация.Данные.ПолучитьОбъект();
UUIDОпыта = Объект.МаркерUUID;
ПроверитьСвойПакет85(UUIDОпыта, Информация.Данные);
ДанныеВерсии = Информация.ДанныеВерсии;
Различия = Информация.РазличияВерсий;
Если ДанныеВерсии = Неопределено Тогда
Сообщить("Own-пакет содержит удаление: данные версии отсутствуют; поле количества не читается");
Продолжить;
КонецЕсли;
Если Не ДанныеВерсии.Свойство("МаркерUUID") Или ДанныеВерсии.МаркерUUID <> UUIDОпыта Тогда
Сообщить("Чужой исторический маркер: содержимое не выводится");
Продолжить;
КонецЕсли;
Сообщить(СтрШаблон("Own-пакет: индекс=%1/%2; версия=%3; дата=%4; вид=%5; количество=%6",
Индекс, Количество, Информация.НомерВерсии, Информация.Дата, Информация.ВидИзмененияДанных, ДанныеВерсии.Количество));
Сообщить(СтрШаблон("Автор: UUID=%1; имя=%2; полное=%3; комментарий=%4; транзакция задана=%5; узел задан=%6; различия заданы=%7",
Информация.Пользователь, Информация.ИмяПользователя, Информация.ПолноеИмяПользователя, Информация.Комментарий,
Не ПустаяСтрока(Информация.Транзакция), ЗначениеЗаполнено(Информация.Узел), Различия <> Неопределено));
КонецЦикла;
Исключение
Сообщить("Собственный пакет не подтвержден; исключение перехвачено, запись объекта или повторная постановка не выполнялись");
КонецПопытки;
КонецПроцедуры
Процедура ПроверитьСвойПакет85(UUIDОпыта, Ссылка)
ПроверитьСвойПустойСтенд();
Если ТипЗнч(UUIDОпыта) <> Тип("Строка") Тогда
ВызватьИсключение "Маркер собственного объекта должен быть строкой";
КонецЕсли;
UUID = Новый УникальныйИдентификатор(UUIDОпыта);
Если UUIDОпыта <> Строка(UUID) Или UUIDОпыта = "00000000-0000-0000-0000-000000000000" Тогда
ВызватьИсключение "В собственном пакете нужен канонический ненулевой UUID";
КонецЕсли;
Выборка = Справочники.УчебныеТовары.Выбрать();
Найден = Ложь;
Пока Выборка.Следующий() Цикл
Если Найден Или Выборка.Ссылка <> Ссылка Или Выборка.МаркерUUID <> UUIDОпыта Или Выборка.ПометкаУдаления Тогда
ВызватьИсключение "Пакет не относится к собственному единственному элементу";
КонецЕсли;
Найден = Истина;
КонецЦикла;
Если Не Найден Тогда
ВызватьИсключение "Собственный исторический объект отсутствует";
КонецЕсли;
КонецПроцедуры
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 1 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.Справочники[0].Имя <> "УчебныеТовары"
Или Метаданные.Справочники.УчебныеТовары.Реквизиты.Количество() <> 2
Или Метаданные.Справочники.УчебныеТовары.ТабличныеЧасти.Количество() <> 0
Или Метаданные.Справочники.УчебныеТовары.Реквизиты.Найти("МаркерUUID") = Неопределено
Или Метаданные.Справочники.УчебныеТовары.Реквизиты.Найти("Количество") = Неопределено Тогда
ВызватьИсключение "Нужен только свой единственный учебный справочник с двумя точными реквизитами";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
КонецПроцедурыРазбор по шагам
UUIDОпыта — признак принадлежности, а фактический UUID ссылки — другой идентификатор. Новый объект создается фабрикой только при0элементов; дальнейшие выборки допускают только этот один точныйUUID-элемент.
УстановитьНастройки применяет явный профиль к своим метаданным. ПолучитьНастройки вызывается впервые после применения; в native указано кэширование результата. Если реальные поля не подтвердились, запись объекта запрещена.
Первая запись имеетКоличество1, вторая3. ЗаписьИсторииДанных задает собственные комментарии, очередьПослеЗаписи=Истина и немедленное фоновое обновление=Ложь. ОбновитьИсторию(свояСсылка,Ложь,Ложь) вызывается после записи, вне транзакции и без автоматической обработки/20-дневной очистки.
ВыбратьВерсии отбирает обязательноДанные=свояСсылка; сортировкаНомерВерсииВозр, лимит4 позволяет обнаружить лишнюю четвертую версию. Номера берутся из настоящей таблицы, не считаются равными1/2по умолчанию.
ПолучитьДанныеВерсии даетСтруктура. ПолучитьМетаданные дает реальные поля версии. ПолучитьРазличияВерсий принимает после,затемдо; проверяются nativeЗначениеДоИзменения1 иЗначениеПослеИзменения3.
СформироватьПоВерсии возвращает отдельный объект сКоличество1. МетодЗаписать у него не вызывается: текущие данные в ИБ остаются3. Создание черновика не равно восстановлению данных базы.
ЗаписатьКомментарий меняет комментарий только своей второй фактической версии. Повторный отбор подтверждает номер/новыйкомментарий.
ЗаписатьВерсию предназначен для переноса истории. В собственном незаписанном черновике установленоКоличество7, автор/date получены реально. Транзакция="", узелНеопределено: никакой случайный идентификатор транзакции/чужой узел не подставляется.
УдалитьТолькоИмпорт85 требует ровно3версии, собственный импортный комментарий и количество7. УдалитьВерсии получает свою ссылку и одинаковый точный номер начала/конца. Повторно подтверждены обе исходные и текущие данные3.
Как проверить результат
После СоздатьДвеВерсии85 ровно2фактические версии одного объекта; обе содержат точныйМаркерUUID иКоличество1/3.
Чтение подтверждает diff1→3 и отдельный черновик1 при текущем объекте3; ни одна команда чтения не записывает черновик.
Импорт дает третью собственную версию7, но текущий объект остается3; после отдельного удаления остаются ровно исходные2с теми же номерами.
ДругойUUID, дополнительныйэлемент, дополнительнаяверсия, активная транзакция или чужие метаданные вызывают отказ до соответствующего изменения.
Ожидаемый результат
Полный собственный жизненный цикл истории с реальными объектами/автором/номерами, самостоятельным сравнением и адресным удалением только собственного импортного снимка.
На что обратить внимание
История данных не журнал регистрации и не резервная копия. Ничего не удаляется из рабочей конфигурации; очищать всю историю по метаданным в этом упражнении запрещено.
Настройки могут кэшироваться; повторное чтение не следует выдавать за независимую runtime-гарантию применения в другом сеансе. Проверки здесь статические.
ПолучитьДанныеВерсии не содержит независимые разделители; в собственной схеме разделителей нет. Нельзя переносить структуру в рабочую ИБ с разделением без отдельного проектирования.
Импорт истории и запись текущего объекта различаются. ЗаписатьВерсию не вызывает запись текущих данных; вымышленный UUID автора или произвольная строка транзакции недопустимы.
После частичной ошибки нельзя повторять создание/импорт автоматически; номер версии не является глобальным идентификатором между объектами.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.