Не восстанавливается версия. УТ 11.5

Между версиями был добавлен реквизит. Поэтому при попытке восстановить документ Заказ покупателя пишет:

Не удалось перейти на выбранную версию.
Возможная причина: версия объекта была записана в другой версии программы.
Техническая информация об ошибке: Ошибка преобразования данных XML

Нашел решение на Мисте.

Но там есть нюанс, надо передавать ссылку.

По идее, ее можно получить из XML представления объекта, тогда код был бы компактнее, но нужно было срочно, поэтому воспользовался готовым решением:



Функция дор_ВосстановитьОбъектПоXML(ДанныеОбъекта, ТекстСообщенияОбОшибке, Ссылка)
	//Осипов 2023-09-21 исправил     
	//https://forum.mista.ru/topic.php?id=885123
	
	УстановитьПривилегированныйРежим(Истина);
	
	ДвоичныеДанные = ДанныеОбъекта;
	Если ТипЗнч(ДанныеОбъекта) = Тип("Структура") Тогда
		ДвоичныеДанные = ДанныеОбъекта.Объект;
	КонецЕсли;
	
	ЧтениеFastInfoSet = Новый ЧтениеFastInfoSet;
	ЧтениеFastInfoSet.УстановитьДвоичныеДанные(ДвоичныеДанные);
	
	
	Попытка
		ЧтениеFastInfoSet.УстановитьДвоичныеДанные(ДвоичныеДанные);    
		ЧтениеFastInfoSet.Прочитать();
		ЧтениеFastInfoSet.УстановитьДвоичныеДанные(ДвоичныеДанные);
	Исключение
		ИмяЗИП = КаталогВременныхФайлов() + Лев(Новый УникальныйИдентификатор(), 8) + ".zip";
		ДвоичныеДанные.Записать(ИмяЗИП);
		ФайлАрхива = Новый ЧтениеZIPФайла(ИмяЗИП);
		ИмяФайлаXML = КаталогВременныхФайлов() + ФайлАрхива.Элементы[0].ПолноеИмя;
		ФайлАрхива.Извлечь(ФайлАрхива.Элементы[0], КаталогВременныхФайлов(), РежимВосстановленияПутейФайловZIP.НеВосстанавливать);
		ФайлАрхива.Закрыть();
		Текст = Новый ТекстовыйДокумент;
		Текст.Прочитать(ИмяФайлаXML);
		
		ЧтениеFastInfoSet = Новый ЧтениеXML;
		ЧтениеFastInfoSet.УстановитьСтроку(Текст.ПолучитьТекст());
		
		Текст = "";
		УдалитьФайлы(ИмяФайлаXML);
		УдалитьФайлы(ИмяЗИП);
	КонецПопытки;
	ФлагИсключение = Ложь;
	
	Попытка
		Объект = ПрочитатьXML(ЧтениеFastInfoSet);
	Исключение
		ФлагИсключение = Истина;
	КонецПопытки;
	
	Если ФлагИсключение Тогда
		ФлагИсключение = Ложь;
		Попытка
			Результат = РазборПредставленияОбъектаXML(ДвоичныеДанные, Ссылка);
			
			Объект=Ссылка.ПолучитьОбъект();
			//Шапка
			Для Каждого Реквизит из Результат.Реквизиты Цикл
				ИмяРеквизита = Реквизит.НаименованиеРеквизита;
				Если ИмяРеквизита = "Ref" Тогда
					Продолжить;
				КонецЕсли;
				Если ИмяРеквизита = "DeletionMark" Тогда
					Объект.ПометкаУдаления = Реквизит.ЗначениеРеквизита;
				КонецЕсли;
				Если ИмяРеквизита = "Date" Тогда
					Объект.Дата = Реквизит.ЗначениеРеквизита;
				КонецЕсли;
				Если ИмяРеквизита = "Number" Тогда
					Объект.Номер = Реквизит.ЗначениеРеквизита;
				КонецЕсли;
				Если ИмяРеквизита = "Posted" Тогда
					Объект.Проведен = Реквизит.ЗначениеРеквизита;
				КонецЕсли;
				Если  Объект.Метаданные().Реквизиты.Найти(ИмяРеквизита) = Неопределено Тогда
				Иначе
					Объект[ИмяРеквизита] = Реквизит.ЗначениеРеквизита;
				КонецЕсли;
			КонецЦикла;
			//ТабличныеЧасти
			Для Каждого ТабЧастьСоответствие Из Результат.ТабличныеЧасти Цикл
				ИмяТЧ = ТабЧастьСоответствие.Ключ;
				ТЗ = ТабЧастьСоответствие.Значение;
				Если ТЗ <> Неопределено и ТЗ.Количество() > 0 Тогда
					Если Объект.Метаданные().ТабличныеЧасти.Найти(ИмяТЧ) <> Неопределено Тогда
						Объект[ИмяТЧ].Очистить();
						
						Для Каждого СтрокаТЗ Из ТЗ Цикл
							НоваяСтрока = Объект[ИмяТЧ].Добавить();
							ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТЗ);
						КонецЦикла;
					КонецЕсли;
				КонецЕсли;
			КонецЦикла;
		Исключение
			ФлагИсключение = Истина;
		КонецПопытки;
	КонецЕсли;
	
	Если ФлагИсключение Тогда
		ТекстСообщенияОбОшибке = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
		Возврат Неопределено;
	КонецЕсли;
	
	Возврат Объект;    
КонецФункции

&ИзменениеИКонтроль("ПерейтиНаВерсиюСервер")
Функция дор_ПерейтиНаВерсиюСервер(Ссылка, НомерВерсии, ТекстСообщенияОбОшибке, ОтменаПроведения)

	Если Не Пользователи.ЭтоПолноправныйПользователь() Тогда
		ВызватьИсключение НСтр("ru = 'Недостаточно прав для выполнения операции.'");
	КонецЕсли;

	Блокировка = Новый БлокировкаДанных;
	ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ВерсииОбъектов");
	ЭлементБлокировки.УстановитьЗначение("Объект", Ссылка);

	ЭлементБлокировки = Блокировка.Добавить(Ссылка.Метаданные().ПолноеИмя());
	ЭлементБлокировки.УстановитьЗначение("Ссылка", Ссылка);

	ИдентификаторОшибки = "ОшибкаВосстановления";

	НачатьТранзакцию();
	Попытка
		Блокировка.Заблокировать();
		ЗаблокироватьДанныеДляРедактирования(Ссылка);

		ПользовательскоеПредставлениеНомера = НомерВерсииВИерархии(Ссылка, НомерВерсии);
		Информация = СведенияОВерсииОбъекта(Ссылка, НомерВерсии);

		ДополнительныеРеквизиты = Неопределено;
		Если ТипЗнч(Информация.ВерсияОбъекта) = Тип("Структура") Тогда
			Если Информация.ВерсияОбъекта.Свойство("ДополнительныеРеквизиты", ДополнительныеРеквизиты) Тогда
				НайденныеРеквизиты = ДополнительныеРеквизиты.НайтиСтроки(Новый Структура("Идентификатор", Неопределено));
				Для Каждого Реквизит Из НайденныеРеквизиты Цикл
					ДополнительныеРеквизиты.Удалить(Реквизит);
				КонецЦикла;
			КонецЕсли;
		КонецЕсли;

		ТекстСообщенияОбОшибке = "";
#Удаление
		Объект = ВосстановитьОбъектПоXML(Информация.ВерсияОбъекта, ТекстСообщенияОбОшибке);
#КонецУдаления
#Вставка
		Объект = дор_ВосстановитьОбъектПоXML(Информация.ВерсияОбъекта, ТекстСообщенияОбОшибке, Ссылка);
#КонецВставки


		Если Не ПустаяСтрока(ТекстСообщенияОбОшибке) Тогда
			ОтменитьТранзакцию();
			Возврат "ОшибкаВосстановления";
		КонецЕсли;

		Объект.ДополнительныеСвойства.Вставить("ВерсионированиеОбъектовКомментарийКВерсии",
		СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = 'Выполнен переход к версии №%1 от %2'"),
		ПользовательскоеПредставлениеНомера,
		Формат(Информация.ДатаВерсии, "ДЛФ=DT")));

		РежимЗаписи = Неопределено;

		Если ОбщегоНазначения.ЭтоДокумент(Объект.Метаданные()) И Объект.Метаданные().Проведение = Метаданные.СвойстваОбъектов.Проведение.Разрешить Тогда
			Если Объект.Проведен И Не ОтменаПроведения Тогда
				РежимЗаписи = РежимЗаписиДокумента.Проведение;
			ИначеЕсли Не Объект.Ссылка.Пустая() Тогда
				РежимЗаписи = РежимЗаписиДокумента.ОтменаПроведения;
			КонецЕсли;
			ИдентификаторОшибки = "ОшибкаПроведения";
		КонецЕсли;

		Если Ссылка.ПолучитьОбъект() <> Неопределено Тогда
			ЗаписатьДанныеТекущейВерсии(Ссылка);
		КонецЕсли;

		ВыполняетсяЗаписьОбъекта(Истина);
		Если ЗначениеЗаполнено(РежимЗаписи) Тогда
			Объект.Записать(РежимЗаписи);
		Иначе
			Объект.Записать();
		КонецЕсли;
		Если ЗначениеЗаполнено(ДополнительныеРеквизиты) Тогда
			Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.Свойства") Тогда
				МодульУправлениеСвойствамиСлужебный = ОбщегоНазначения.ОбщийМодуль("УправлениеСвойствамиСлужебный");
				МодульУправлениеСвойствамиСлужебный.ПриВосстановленииВерсииОбъекта(Объект, ДополнительныеРеквизиты);
			КонецЕсли;
			ВерсионированиеОбъектовПереопределяемый.ПриВосстановленииВерсииОбъекта(Объект, ДополнительныеРеквизиты);
		КонецЕсли;
		ВыполняетсяЗаписьОбъекта(Ложь);

		ЗаписатьВерсиюОбъекта(Объект);
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВыполняетсяЗаписьОбъекта(Ложь);
		ТекстСообщенияОбОшибке = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
		Возврат ИдентификаторОшибки;
	КонецПопытки;

	Возврат "ВосстановлениеВыполнено";

КонецФункции

Почему 1С не реализует такой механизм — непонятно…

Среда: 11.5.12.53 Объем: 0.5 час

fixin

Программирую на 1С с 1999 года. В 1С просто Гений. В 2020 году ушел из офиса на вольные хлеба фриланса. Принимаю заказы.

Читайте также:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *