На днях прилетела интересная задачка от клиента. Как то так произошло (намеренно или случайно), что некоторые документы стали распроведенными. И теперь для того, чтобы их вычислить нужно сравнить 2 версии документа. Последнюю и предпоследнюю. Текущую и предыдущую. Кому как нравиться 🙂

Сравнение версий объектов — иллюстрация

Начнем с того, что в БСП есть механизм версионирования объектов. Который хранит версии документов в регистре «ВерсииОбъектов». Но сравнить простым запросом данные мы не можем, так как разработчики этой подсистемы решили хранить данные в хранилище значений в формате XML. Что в общем то логично, так как структура данных может поменяться.

Ну ок. Должны же быть какие то готовые методы, чтобы получить реквизиты документа по номеру версии.

В БСП версии 3.1.3.561 мы можем обратиться к функции ВерсионированиеОбъектов.РазборВерсии(Ссылка, НомерВерсии) и получить значения реквизитов и другую служебную информацию.

Ну например:


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

Передав ссылку и номер версии, мы уже получили контрагента. Но давайте вернемся к задаче сравнения двух последних версий документа.

Маленький дисклеймер. Качество кода фуфло, оптимальностью даже и не пахнет, делал на для решения одноразовой проблемы клиента.


&НаКлиенте
Процедура Сделать(Команда)
	
	ТабДок = СделатьНаСервере();
	ТабДок.ТолькоПросмотр = Истина;
	ТабДок.Показать();
	
КонецПроцедуры 

&НаСервере
Функция ПолучитьМакетНаСервере()
	ОтчетОбъект = РеквизитФормыВЗначение("Объект");
	Макет = ОтчетОбъект.ПолучитьМакет("Макет");
	Возврат Макет;
КонецФункции

&НаСервере
Функция СделатьНаСервере()

	ТабДок = Новый ТабличныйДокумент;
	
	МассивПодозрительныхДокументов = ПолучитьПодозрительныеДокументыНаСервере();
	
	Если МассивПодозрительныхДокументов.Количество() = 0 Тогда
		Возврат ТабДок;					
	КонецЕсли;  
	
	Макет = ПолучитьМакетНаСервере(); 
	ОбластьСтроки = Макет.ПолучитьОбласть("Строка");
		
	Для каждого Документ Из МассивПодозрительныхДокументов Цикл
		
		ОбластьСтроки.Параметры.Документ = Документ;
	    ОбластьСтроки.Параметры.ДокументСсылка = Документ;
		
		ТабДок.Вывести(ОбластьСтроки);
		
	КонецЦикла;
	
	Возврат ТабДок;
	
КонецФункции

&НаСервере
Функция ПолучитьПодозрительныеДокументыНаСервере()
	
// Получили все непроведённые документы и непомеченные документы и соединили с
// версиями объектов
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ
	|	РеализацияТоваровУслуг.Ссылка КАК Ссылка
	|ПОМЕСТИТЬ ВТ_Реализации
	|ИЗ
	|	Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
	|ГДЕ
	|	РеализацияТоваровУслуг.Дата МЕЖДУ &ДатаНачала И &ДатаОкончания
	|	И РеализацияТоваровУслуг.Проведен = ЛОЖЬ
	|	И РеализацияТоваровУслуг.ПометкаУдаления = ЛОЖЬ
	|;
	|
	|////////////////////////////////////////////////////////////////////////////////
	|ВЫБРАТЬ
	|	ВерсииОбъектов.Объект КАК Объект,
	|	ВерсииОбъектов.НомерВерсии КАК НомерВерсии
	|ИЗ
	|	РегистрСведений.ВерсииОбъектов КАК ВерсииОбъектов
	|ГДЕ
	|	ВерсииОбъектов.Объект В
	|			(ВЫБРАТЬ
	|				ВТ_Реализации.Ссылка КАК Ссылка
	|			ИЗ
	|				ВТ_Реализации КАК ВТ_Реализации)
	|
	|УПОРЯДОЧИТЬ ПО
	|	НомерВерсии УБЫВ
	|ИТОГИ ПО
	|	Объект";
	
	Запрос.УстановитьПараметр("ДатаНачала", Период.ДатаНачала);
	Запрос.УстановитьПараметр("ДатаОкончания", Период.ДатаОкончания);
	
	МассивПодозрительныхОбъектов = Новый Массив;
	
	Выборка = Запрос.Выполнить().Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);	
	Пока Выборка.Следующий() Цикл
		
		ВыборкаДетальныеЗаписи = Выборка.Выбрать();
		
		МассивРеквизитовВерсийОбъекта = Новый Массив;
		
		Счетчик = 0;
		Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
			
			Если Счетчик = 2 Тогда
				Прервать;
			КонецЕсли;
			
			МассивРеквизитовВерсийОбъекта.Добавить(ВерсионированиеОбъектов.РазборВерсии(ВыборкаДетальныеЗаписи.Объект, ВыборкаДетальныеЗаписи.НомерВерсии).Реквизиты); 
			Счетчик = Счетчик + 1;
			
		КонецЦикла;
		
		Если МассивРеквизитовВерсийОбъекта.Количество() > 1 Тогда
			ЗначениеПоследнее = МассивРеквизитовВерсийОбъекта[0].Найти("Posted", "НаименованиеРеквизита").ЗначениеРеквизита;
			ЗначениеПредПоследнее = МассивРеквизитовВерсийОбъекта[1].Найти("Posted", "НаименованиеРеквизита").ЗначениеРеквизита;
			
			Если ЗначениеПоследнее <> ЗначениеПредПоследнее Тогда
				МассивПодозрительныхОбъектов.Добавить(Выборка.Объект);				
			КонецЕсли;
			
		КонецЕсли;
				
	КонецЦикла;
	
	Возврат МассивПодозрительныхОбъектов;
	
КонецФункции

Posted — английский вариант слова Проведен.

Ну вот и всё. Получили значения реквизитов, сравнили между собой и вывели в табличный документ. Если нужно модифицировать, то за основу можете взять мою обработку.