Новое ввести на основании и связи. Как все построить?

1. progersan 6 11.04.23 17:01 Сейчас в теме
Всем привет!
Бухгалтерия Предприятия КОРП 3.0. В облаке.
Можно только подключить расширение или внешнюю обработку.

Кто уже реализовывал подобную задачу? Суть в том, чтобы добавить возможность вводить на основании документа СчетНаОплатуПокупателю документа СчетНаОплатуПоставщика. Само собой мы хотим, чтобы это красиво отображалось в Связанных документах.

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

Я имею документ СчетНаОплатуПоставщика, который был создан на основании СчетНаОплатуПокупателю.

Далее, как я понял, мне нужно бы в идеале залезть в КритерииОтбора - Связанные документы.
Это можно сделать только добавив его в расширение. Делать это категорически нельзя, т.к. в расширение прилетают все документы, на которые есть ссылки. А ссылки есть на десятки документов. В итоге расширение становится больше конфигурации и конфа вообще стартует пол часа :))) Короче - не вариант.

Кто может подсказать как правильно решать подобную задачу?
Задача вообще видеть связь между документами. Что было создано на основании счета покупателя. Или наоборот.
Уже думал сделать отдельным отчетом, предварительно добавив новый реквизит в документы для обозначения связи между ними.
Прикрепленные файлы:
Найденные решения
4. progersan 6 13.04.23 09:50 Сейчас в теме
Ну вот сделал сам. Как обычно.

Нужно добавить в расширение общую форму СвязанныеДокументы, модифицировать две функции, отвечающие за подбор подчиненных и родительских документов.
Не забываем добавить рекивзит ДокументОснование у нового документа. Если такого реквизита нет. Как в моем случае.
Модифицированный код в расширении формы Связанные документы:

&НаСервере
&Вместо("ВывестиРодительскиеОбъекты")
Процедура Расш2_ВывестиРодительскиеОбъекты(ТекущийОбъект, ДеревоРодитель, ВыведенныеОбъекты, СлужебныеОбъекты, ИндексСвязейОбъектов)
	
	
	
	МетаданныеОбъекта = ТекущийОбъект.Метаданные();
	СписокРеквизитов  = Новый ТаблицаЗначений;
	СписокРеквизитов.Колонки.Добавить("Значение");
	СписокРеквизитов.Колонки.Добавить("Дата", ОбщегоНазначения.ОписаниеТипаДата(ЧастиДаты.ДатаВремя));
	
	Если СлужебныеОбъекты = Неопределено Тогда 
		СлужебныеОбъекты = Новый Соответствие;
	КонецЕсли;
	
	Если ИндексСвязейОбъектов = Неопределено Тогда 
		ИндексСвязейОбъектов = Новый Соответствие;
	КонецЕсли;
	
	ВестиУчетПоДоговорам = ПолучитьФункциональнуюОпцию("ВестиУчетПоДоговорам");
	
	Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
		
		Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда    
			//Если МетаданныеОбъекта <> Метаданные.Документы.СчетНаОплатуПокупателю  и МетаданныеОбъекта <> Метаданные.Документы.СчетНаОплатуПоставщика и Реквизит.Имя<>"ДокументОснование" Тогда			
			Если Реквизит.Имя<>"ДокументОснование" Тогда			
				Продолжить;				
			КонецЕсли;
			
		КонецЕсли;
		
		Для Каждого ТекущийТип Из Реквизит.Тип.Типы() Цикл
			
			МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип);
			Если МетаданныеРеквизита = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			
			Если Не ОбщегоНазначения.ОбъектМетаданныхДоступенПоФункциональнымОпциям(МетаданныеРеквизита)
				Или Не ПравоДоступа("Чтение", МетаданныеРеквизита) Тогда
				Продолжить;
			КонецЕсли;
			
			Если Не Метаданные.Документы.Содержит(МетаданныеРеквизита)
				И Не Метаданные.Справочники.Содержит(МетаданныеРеквизита)
				И Не Метаданные.ПланыВидовХарактеристик.Содержит(МетаданныеРеквизита) Тогда
				Продолжить;
			КонецЕсли;
			
			Если ЭтоСсылкаНаДоговор(ТекущийТип)
				И (ТекущийОбъект <> ОсновнойОбъект
					Или Не ВестиУчетПоДоговорам) Тогда
				Продолжить;
			КонецЕсли;
			
			ЗначениеРеквизита = ТекущийОбъект[Реквизит.Имя];
			Если ЗначениеЗаполнено(ЗначениеРеквизита)
				И ТипЗнч(ЗначениеРеквизита) = ТекущийТип
				И ЗначениеРеквизита <> ТекущийОбъект
				И СписокРеквизитов.Найти(ЗначениеРеквизита, "Значение") = Неопределено Тогда
				
				ЯвляетсяДокументом  = ОбщегоНазначения.ЭтоДокумент(МетаданныеРеквизита) Или ЭтоДоговор(МетаданныеРеквизита);
					
				СтрокаРеквизита = СписокРеквизитов.Добавить();
				СтрокаРеквизита.Значение = ЗначениеРеквизита;
				Если ЯвляетсяДокументом Тогда
					ДатаДокумента = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ЗначениеРеквизита, "Дата", Истина);
					СтрокаРеквизита.Дата = ДатаДокумента;
				КонецЕсли;
				
			КонецЕсли;
		КонецЦикла;
		
	КонецЦикла;
	
	Для Каждого ТЧ Из МетаданныеОбъекта.ТабличныеЧасти Цикл
		
		ИменаРеквизитов = "";
		СодержимоеТЧ = ТекущийОбъект[ТЧ.Имя].Выгрузить(); // ТаблицаЗначений
		Для Каждого Реквизит Из ТЧ.Реквизиты Цикл

			Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда      
				//Если МетаданныеОбъекта <> Метаданные.Документы.СчетНаОплатуПокупателю  и МетаданныеОбъекта <> Метаданные.Документы.СчетНаОплатуПоставщика   Тогда			
					Продолжить;	
					
				//КонецЕсли;
			КонецЕсли;	
				
			Для Каждого ТекущийТип Из Реквизит.Тип.Типы() Цикл
				
				МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип);
				Если МетаданныеРеквизита = Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				Если Не ОбщегоНазначения.ОбъектМетаданныхДоступенПоФункциональнымОпциям(МетаданныеРеквизита) 
					Или Не ПравоДоступа("Чтение", МетаданныеРеквизита) Тогда
					Продолжить;
				КонецЕсли;
				
				Если Не Метаданные.Документы.Содержит(МетаданныеРеквизита)
					И Не Метаданные.Справочники.Содержит(МетаданныеРеквизита)
					И Не Метаданные.ПланыВидовХарактеристик.Содержит(МетаданныеРеквизита) Тогда
					Продолжить;
				КонецЕсли;
				
				Если ЭтоСсылкаНаДоговор(ТекущийТип)
					И (ТекущийОбъект <> ОсновнойОбъект
						Или Не ВестиУчетПоДоговорам) Тогда
					Продолжить;
				КонецЕсли;
				
				ИменаРеквизитов = ИменаРеквизитов + ?(ИменаРеквизитов = "", "", ", ") + Реквизит.Имя;
				Прервать;
				
			КонецЦикла;
			
		КонецЦикла;
		
		СодержимоеТЧ.Свернуть(ИменаРеквизитов);
		Для Каждого КолонкаТЧ Из СодержимоеТЧ.Колонки Цикл
			
			Для Каждого СтрокаТЧ Из СодержимоеТЧ Цикл
			
				ЗначениеРеквизита = СтрокаТЧ[КолонкаТЧ.Имя];
				МетаданныеЗначения = Метаданные.НайтиПоТипу(ТипЗнч(ЗначениеРеквизита));
				Если МетаданныеЗначения = Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				Если Не ОбщегоНазначения.ОбъектМетаданныхДоступенПоФункциональнымОпциям(МетаданныеЗначения) 
					Или Не ПравоДоступа("Чтение", МетаданныеЗначения) Тогда
					Продолжить;
				КонецЕсли;
				
				Если ЗначениеРеквизита = ТекущийОбъект
					Или СписокРеквизитов.Найти(ЗначениеРеквизита, "Значение") <> Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				ЯвляетсяДокументом  = ОбщегоНазначения.ЭтоДокумент(МетаданныеЗначения) Или ЭтоДоговор(МетаданныеЗначения);
				Если Не ЯвляетсяДокументом И Не Метаданные.Справочники.Содержит(МетаданныеЗначения)
					И Не Метаданные.ПланыВидовХарактеристик.Содержит(МетаданныеЗначения) Тогда
					Продолжить;
				КонецЕсли;
				
				СтрокаРеквизита = СписокРеквизитов.Добавить();
				СтрокаРеквизита.Значение = ЗначениеРеквизита;
				Если ЯвляетсяДокументом Тогда
					ДатаДокумента = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ЗначениеРеквизита, "Дата", Истина);
					СтрокаРеквизита.Дата = ДатаДокумента;
				КонецЕсли;
				
			КонецЦикла;
		КонецЦикла;
	КонецЦикла;
	
	СписокРеквизитов.Сортировать("Дата");
	
	Для каждого ЭлементСписка Из СписокРеквизитов Цикл
		
		Выборка = ПолучитьВыборкуПоРеквизитамОбъекта(ЭлементСписка.Значение);
		
		Если Выборка.Следующий() Тогда
			
			Если ИндексСвязейОбъектов[ТекущийОбъект] = Выборка.Ссылка Тогда 
				Продолжить;
			КонецЕсли;
			
			ИндексСвязейОбъектов.Вставить(ТекущийОбъект, Выборка.Ссылка);
			
			НоваяСтрока = ДобавитьСтрокуВДерево(ДеревоРодитель, Выборка, ВыведенныеОбъекты);
			
			Если НоваяСтрока <> Неопределено
				И Не ДобавляемыйОбъектИмеетсяСредиРодителей(ДеревоРодитель, ЭлементСписка.Значение) Тогда
				
				ВывестиРодительскиеОбъекты(ЭлементСписка.Значение, НоваяСтрока, ВыведенныеОбъекты,
					СлужебныеОбъекты, ИндексСвязейОбъектов);
				
			ИначеЕсли СлужебныеОбъекты[ЭлементСписка.Значение] = Неопределено Тогда 
				
				СлужебныеОбъекты.Вставить(ЭлементСписка.Значение, Истина);
				Если ЭлементСписка.Значение = ОсновнойОбъект Тогда
					Продолжить;
				КонецЕсли;
				ВывестиРодительскиеОбъекты(ЭлементСписка.Значение, ДеревоРодитель, ВыведенныеОбъекты,
					СлужебныеОбъекты, ИндексСвязейОбъектов);
				
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
	//ПродолжитьВызов(ТекущийОбъект, ДеревоРодитель, ВыведенныеОбъекты, СлужебныеОбъекты, ИндексСвязейОбъектов);
КонецПроцедуры

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

	Для Каждого СтрокаТаблицы Из Таблица Цикл

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

		ПолноеИмяОбъекта = МетаданныеОбъекта.ПолноеИмя();
		ДополнитьКэшМетаданных(МетаданныеОбъекта, ПолноеИмяОбъекта, КэшРеквизитовОбъекта);

		МассивСсылок = КэшПоТипамОбъектов[ПолноеИмяОбъекта];
		Если МассивСсылок = Неопределено Тогда

			МассивСсылок = Новый Массив;
			КэшПоТипамОбъектов.Вставить(ПолноеИмяОбъекта, МассивСсылок);

		КонецЕсли;

		МассивСсылок.Добавить(ТекущаяСсылка);

	КонецЦикла;
	
	Если КэшПоТипамОбъектов.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;

	ШаблонПодзапроса = "ВЫБРАТЬ
		|	&Дата КАК Дата,
		|	Ссылка,
		|	&Проведен КАК Проведен,
		|	ПометкаУдаления,
		|	&СуммаДокумента КАК СуммаДокумента,
		|	&Валюта КАК Валюта,
		|	&Представление
		|ИЗ
		|	&ИмяТаблицы
		|ГДЕ
		|	Ссылка В (&ИмяОбъекта)";

	Запрос = Новый Запрос;
	ТекстЗапроса = "";
	Для Каждого КлючИЗначение Из КэшПоТипамОбъектов Цикл
		
		МассивИмениОбъекта = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(КлючИЗначение.Ключ, ".");
		Если МассивИмениОбъекта.Количество() = 2 Тогда
			ИмяОбъекта = МассивИмениОбъекта[1];
		Иначе
			Продолжить;
		КонецЕсли;

		ТекстПоТипуОбъекта = СтрЗаменить(ШаблонПодзапроса, "&Дата", КэшРеквизитовОбъекта[КлючИЗначение.Ключ]["Дата"]); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&Проведен", КэшРеквизитовОбъекта[КлючИЗначение.Ключ]["Проведен"]); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&СуммаДокумента", КэшРеквизитовОбъекта[КлючИЗначение.Ключ]["СуммаДокумента"]); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&Валюта", КэшРеквизитовОбъекта[КлючИЗначение.Ключ]["Валюта"]); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&ИмяТаблицы", КлючИЗначение.Ключ); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&ИмяОбъекта", "&" + ИмяОбъекта); 
		Запрос.УстановитьПараметр(ИмяОбъекта, КлючИЗначение.Значение);
		
		МассивДопРеквизитов = РеквизитыДляПредставления(КлючИЗначение.Ключ, ИмяОбъекта);
		ДополнитьТекстЗапросаПоРеквизитамОбъекта(ТекстПоТипуОбъекта, МассивДопРеквизитов);
		
		Если Не ПустаяСтрока(ТекстЗапроса) Тогда
			ТекстЗапроса = ТекстЗапроса + "
				|	ОБЪЕДИНИТЬ ВСЕ 
				|";		
		КонецЕсли;	
		ТекстЗапроса = ТекстЗапроса + ТекстПоТипуОбъекта;

	КонецЦикла;

	ШаблонЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	*
		|ИЗ
		|	(ВЫБРАТЬ 1 ИЗ #Подзапрос) КАК ПодчиненныеОбъекты
		|УПОРЯДОЧИТЬ ПО
		|	ПодчиненныеОбъекты.Дата";

	Запрос.Текст = СтрЗаменить(ШаблонЗапроса, "ВЫБРАТЬ 1 ИЗ #Подзапрос", ТекстЗапроса);
	Выборка = Запрос.Выполнить().Выбрать();

	Пока Выборка.Следующий() Цикл
		
		Если ИндексСвязейОбъектов[ТекущийОбъект] = Выборка.Ссылка Тогда 
			Продолжить;
		КонецЕсли;
		
		ИндексСвязейОбъектов.Вставить(ТекущийОбъект, Выборка.Ссылка);
		
		НоваяСтрока = ДобавитьСтрокуВДерево(ДеревоРодитель, Выборка, ВыведенныеОбъекты, Истина);
		
		Если НоваяСтрока <> Неопределено
			И Не ДобавляемыйОбъектИмеетсяСредиРодителей(ДеревоРодитель, Выборка.Ссылка) Тогда
			
			ВывестиПодчиненныеОбъекты(Выборка.Ссылка, НоваяСтрока, ВыведенныеОбъекты,
				СлужебныеОбъекты, ИндексСвязейОбъектов);
			
		ИначеЕсли СлужебныеОбъекты[Выборка.Ссылка] = Неопределено Тогда 
			
			СлужебныеОбъекты.Вставить(Выборка.Ссылка, Истина);
			ВывестиПодчиненныеОбъекты(Выборка.Ссылка, ДеревоРодитель, ВыведенныеОбъекты,
				СлужебныеОбъекты, ИндексСвязейОбъектов);
			
		КонецЕсли;
		
	КонецЦикла;
	
	//ПродолжитьВызов(ТекущийОбъект, ДеревоРодитель, ВыведенныеОбъекты, СлужебныеОбъекты, ИндексСвязейОбъектов);
КонецПроцедуры

&НаСервере
Процедура Расш2_ПриСозданииНаСервереПеред(Отказ, СтандартнаяОбработка)
	лДерево        = РеквизитФормыВЗначение("ДеревоПодчиненныеОбъекты");
    лНовыйОТ    = новый ОписаниеТипов(лДерево.Колонки.Ссылка.ТипЗначения,"ДокументСсылка.СчетНаОплатуПокупателю");        //СчетНаОплатуПоставщика
    лДерево.Колонки.Добавить("Ссылка2",лНовыйОТ);
    
    
    // 3. создаем РЕКВИЗИТ КОЛОНКИ (невидимая часть, справа в редакторе форм)
    МассивДобавляемыхРеквизитов = Новый Массив;
    // реквизит принадлежит дереву
    МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Ссылка2", лНовыйОТ, "ДеревоПодчиненныеОбъекты"));
    // добавляем реквизит в форму (невидимая часть, справа в редакторе форм)
    ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);    
    
    ЗначениеВРеквизитФормы(лДерево,"ДеревоПодчиненныеОбъекты");
    
    // проверим, а добавилось ли
    лДерево        = РеквизитФормыВЗначение("ДеревоПодчиненныеОбъекты");             
    лДерево        = РеквизитФормыВЗначение("ДеревоРодительскиеОбъекты");
    лНовыйОТ    = новый ОписаниеТипов(лДерево.Колонки.Ссылка.ТипЗначения,"ДокументСсылка.СчетНаОплатуПокупателю");
    лДерево.Колонки.Добавить("Ссылка2",лНовыйОТ);
    
    
    // 3. создаем РЕКВИЗИТ КОЛОНКИ (невидимая часть, справа в редакторе форм)
    МассивДобавляемыхРеквизитов = Новый Массив;
    // реквизит принадлежит дереву
    МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Ссылка2", лНовыйОТ, "ДеревоРодительскиеОбъекты"));
    // добавляем реквизит в форму (невидимая часть, справа в редакторе форм)
    ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);    
    
    ЗначениеВРеквизитФормы(лДерево,"ДеревоРодительскиеОбъекты");
    
    // проверим, а добавилось ли
    лДерево        = РеквизитФормыВЗначение("ДеревоРодительскиеОбъекты");
КонецПроцедуры

&НаСервере
&Вместо("ОбъектыПоКритериюОтбора")
Функция Расш2_ОбъектыПоКритериюОтбора(ЗначениеКритерияОтбора)
	
	Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Тип.СодержитТип(ТипЗнч(ЗначениеКритерияОтбора))  Тогда
		Возврат Неопределено;
	КонецЕсли;
		
	УстановитьПривилегированныйРежим(Истина);
	
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
                   |    СвязанныеДокументы.Ссылка КАК Ссылка
                   |ИЗ
                   |    КритерийОтбора.СвязанныеДокументы(&ЗначениеКритерияОтбора) КАК СвязанныеДокументы
                   |
                   |ОБЪЕДИНИТЬ ВСЕ
                   |
                   |ВЫБРАТЬ
                   |    СчетНаОплатуПоставщика.Ссылка
                   |ИЗ
                   |    Документ.СчетНаОплатуПоставщика КАК СчетНаОплатуПоставщика
                   |ГДЕ
                   |    СчетНаОплатуПоставщика.ДокументОснование = &ЗначениеКритерияОтбора";	
	Запрос.УстановитьПараметр("ЗначениеКритерияОтбора", ЗначениеКритерияОтбора);
	Возврат Запрос.Выполнить().Выгрузить();


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

Показать


p.s. часть кода собрана по мотивам открытых источников рунета :)
Остальные ответы
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
2. user5300 1010 12.04.23 08:01 Сейчас в теме
(1)
документ СчетНаОплатуПоставщика, который был создан на основании СчетНаОплатуПокупателю

Так документ созданный на основании будет отображаться в связанных документах (Если заполнен реквизит "ДокументОснование" в созданном документе)
3. progersan 6 12.04.23 10:26 Сейчас в теме
(2) У этих документов в конфигурации нет реквизита ДокументОснование. Если его самому добавить через расширение, то , даже при самостоятельном заполнении, структура подчиненности не дополняется этим рукоблудством.
4. progersan 6 13.04.23 09:50 Сейчас в теме
Ну вот сделал сам. Как обычно.

Нужно добавить в расширение общую форму СвязанныеДокументы, модифицировать две функции, отвечающие за подбор подчиненных и родительских документов.
Не забываем добавить рекивзит ДокументОснование у нового документа. Если такого реквизита нет. Как в моем случае.
Модифицированный код в расширении формы Связанные документы:

&НаСервере
&Вместо("ВывестиРодительскиеОбъекты")
Процедура Расш2_ВывестиРодительскиеОбъекты(ТекущийОбъект, ДеревоРодитель, ВыведенныеОбъекты, СлужебныеОбъекты, ИндексСвязейОбъектов)
	
	
	
	МетаданныеОбъекта = ТекущийОбъект.Метаданные();
	СписокРеквизитов  = Новый ТаблицаЗначений;
	СписокРеквизитов.Колонки.Добавить("Значение");
	СписокРеквизитов.Колонки.Добавить("Дата", ОбщегоНазначения.ОписаниеТипаДата(ЧастиДаты.ДатаВремя));
	
	Если СлужебныеОбъекты = Неопределено Тогда 
		СлужебныеОбъекты = Новый Соответствие;
	КонецЕсли;
	
	Если ИндексСвязейОбъектов = Неопределено Тогда 
		ИндексСвязейОбъектов = Новый Соответствие;
	КонецЕсли;
	
	ВестиУчетПоДоговорам = ПолучитьФункциональнуюОпцию("ВестиУчетПоДоговорам");
	
	Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
		
		Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда    
			//Если МетаданныеОбъекта <> Метаданные.Документы.СчетНаОплатуПокупателю  и МетаданныеОбъекта <> Метаданные.Документы.СчетНаОплатуПоставщика и Реквизит.Имя<>"ДокументОснование" Тогда			
			Если Реквизит.Имя<>"ДокументОснование" Тогда			
				Продолжить;				
			КонецЕсли;
			
		КонецЕсли;
		
		Для Каждого ТекущийТип Из Реквизит.Тип.Типы() Цикл
			
			МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип);
			Если МетаданныеРеквизита = Неопределено Тогда
				Продолжить;
			КонецЕсли;
			
			Если Не ОбщегоНазначения.ОбъектМетаданныхДоступенПоФункциональнымОпциям(МетаданныеРеквизита)
				Или Не ПравоДоступа("Чтение", МетаданныеРеквизита) Тогда
				Продолжить;
			КонецЕсли;
			
			Если Не Метаданные.Документы.Содержит(МетаданныеРеквизита)
				И Не Метаданные.Справочники.Содержит(МетаданныеРеквизита)
				И Не Метаданные.ПланыВидовХарактеристик.Содержит(МетаданныеРеквизита) Тогда
				Продолжить;
			КонецЕсли;
			
			Если ЭтоСсылкаНаДоговор(ТекущийТип)
				И (ТекущийОбъект <> ОсновнойОбъект
					Или Не ВестиУчетПоДоговорам) Тогда
				Продолжить;
			КонецЕсли;
			
			ЗначениеРеквизита = ТекущийОбъект[Реквизит.Имя];
			Если ЗначениеЗаполнено(ЗначениеРеквизита)
				И ТипЗнч(ЗначениеРеквизита) = ТекущийТип
				И ЗначениеРеквизита <> ТекущийОбъект
				И СписокРеквизитов.Найти(ЗначениеРеквизита, "Значение") = Неопределено Тогда
				
				ЯвляетсяДокументом  = ОбщегоНазначения.ЭтоДокумент(МетаданныеРеквизита) Или ЭтоДоговор(МетаданныеРеквизита);
					
				СтрокаРеквизита = СписокРеквизитов.Добавить();
				СтрокаРеквизита.Значение = ЗначениеРеквизита;
				Если ЯвляетсяДокументом Тогда
					ДатаДокумента = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ЗначениеРеквизита, "Дата", Истина);
					СтрокаРеквизита.Дата = ДатаДокумента;
				КонецЕсли;
				
			КонецЕсли;
		КонецЦикла;
		
	КонецЦикла;
	
	Для Каждого ТЧ Из МетаданныеОбъекта.ТабличныеЧасти Цикл
		
		ИменаРеквизитов = "";
		СодержимоеТЧ = ТекущийОбъект[ТЧ.Имя].Выгрузить(); // ТаблицаЗначений
		Для Каждого Реквизит Из ТЧ.Реквизиты Цикл

			Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда      
				//Если МетаданныеОбъекта <> Метаданные.Документы.СчетНаОплатуПокупателю  и МетаданныеОбъекта <> Метаданные.Документы.СчетНаОплатуПоставщика   Тогда			
					Продолжить;	
					
				//КонецЕсли;
			КонецЕсли;	
				
			Для Каждого ТекущийТип Из Реквизит.Тип.Типы() Цикл
				
				МетаданныеРеквизита = Метаданные.НайтиПоТипу(ТекущийТип);
				Если МетаданныеРеквизита = Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				Если Не ОбщегоНазначения.ОбъектМетаданныхДоступенПоФункциональнымОпциям(МетаданныеРеквизита) 
					Или Не ПравоДоступа("Чтение", МетаданныеРеквизита) Тогда
					Продолжить;
				КонецЕсли;
				
				Если Не Метаданные.Документы.Содержит(МетаданныеРеквизита)
					И Не Метаданные.Справочники.Содержит(МетаданныеРеквизита)
					И Не Метаданные.ПланыВидовХарактеристик.Содержит(МетаданныеРеквизита) Тогда
					Продолжить;
				КонецЕсли;
				
				Если ЭтоСсылкаНаДоговор(ТекущийТип)
					И (ТекущийОбъект <> ОсновнойОбъект
						Или Не ВестиУчетПоДоговорам) Тогда
					Продолжить;
				КонецЕсли;
				
				ИменаРеквизитов = ИменаРеквизитов + ?(ИменаРеквизитов = "", "", ", ") + Реквизит.Имя;
				Прервать;
				
			КонецЦикла;
			
		КонецЦикла;
		
		СодержимоеТЧ.Свернуть(ИменаРеквизитов);
		Для Каждого КолонкаТЧ Из СодержимоеТЧ.Колонки Цикл
			
			Для Каждого СтрокаТЧ Из СодержимоеТЧ Цикл
			
				ЗначениеРеквизита = СтрокаТЧ[КолонкаТЧ.Имя];
				МетаданныеЗначения = Метаданные.НайтиПоТипу(ТипЗнч(ЗначениеРеквизита));
				Если МетаданныеЗначения = Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				Если Не ОбщегоНазначения.ОбъектМетаданныхДоступенПоФункциональнымОпциям(МетаданныеЗначения) 
					Или Не ПравоДоступа("Чтение", МетаданныеЗначения) Тогда
					Продолжить;
				КонецЕсли;
				
				Если ЗначениеРеквизита = ТекущийОбъект
					Или СписокРеквизитов.Найти(ЗначениеРеквизита, "Значение") <> Неопределено Тогда
					Продолжить;
				КонецЕсли;
				
				ЯвляетсяДокументом  = ОбщегоНазначения.ЭтоДокумент(МетаданныеЗначения) Или ЭтоДоговор(МетаданныеЗначения);
				Если Не ЯвляетсяДокументом И Не Метаданные.Справочники.Содержит(МетаданныеЗначения)
					И Не Метаданные.ПланыВидовХарактеристик.Содержит(МетаданныеЗначения) Тогда
					Продолжить;
				КонецЕсли;
				
				СтрокаРеквизита = СписокРеквизитов.Добавить();
				СтрокаРеквизита.Значение = ЗначениеРеквизита;
				Если ЯвляетсяДокументом Тогда
					ДатаДокумента = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ЗначениеРеквизита, "Дата", Истина);
					СтрокаРеквизита.Дата = ДатаДокумента;
				КонецЕсли;
				
			КонецЦикла;
		КонецЦикла;
	КонецЦикла;
	
	СписокРеквизитов.Сортировать("Дата");
	
	Для каждого ЭлементСписка Из СписокРеквизитов Цикл
		
		Выборка = ПолучитьВыборкуПоРеквизитамОбъекта(ЭлементСписка.Значение);
		
		Если Выборка.Следующий() Тогда
			
			Если ИндексСвязейОбъектов[ТекущийОбъект] = Выборка.Ссылка Тогда 
				Продолжить;
			КонецЕсли;
			
			ИндексСвязейОбъектов.Вставить(ТекущийОбъект, Выборка.Ссылка);
			
			НоваяСтрока = ДобавитьСтрокуВДерево(ДеревоРодитель, Выборка, ВыведенныеОбъекты);
			
			Если НоваяСтрока <> Неопределено
				И Не ДобавляемыйОбъектИмеетсяСредиРодителей(ДеревоРодитель, ЭлементСписка.Значение) Тогда
				
				ВывестиРодительскиеОбъекты(ЭлементСписка.Значение, НоваяСтрока, ВыведенныеОбъекты,
					СлужебныеОбъекты, ИндексСвязейОбъектов);
				
			ИначеЕсли СлужебныеОбъекты[ЭлементСписка.Значение] = Неопределено Тогда 
				
				СлужебныеОбъекты.Вставить(ЭлементСписка.Значение, Истина);
				Если ЭлементСписка.Значение = ОсновнойОбъект Тогда
					Продолжить;
				КонецЕсли;
				ВывестиРодительскиеОбъекты(ЭлементСписка.Значение, ДеревоРодитель, ВыведенныеОбъекты,
					СлужебныеОбъекты, ИндексСвязейОбъектов);
				
			КонецЕсли;
		КонецЕсли;
		
	КонецЦикла;
	
	//ПродолжитьВызов(ТекущийОбъект, ДеревоРодитель, ВыведенныеОбъекты, СлужебныеОбъекты, ИндексСвязейОбъектов);
КонецПроцедуры

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

	Для Каждого СтрокаТаблицы Из Таблица Цикл

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

		ПолноеИмяОбъекта = МетаданныеОбъекта.ПолноеИмя();
		ДополнитьКэшМетаданных(МетаданныеОбъекта, ПолноеИмяОбъекта, КэшРеквизитовОбъекта);

		МассивСсылок = КэшПоТипамОбъектов[ПолноеИмяОбъекта];
		Если МассивСсылок = Неопределено Тогда

			МассивСсылок = Новый Массив;
			КэшПоТипамОбъектов.Вставить(ПолноеИмяОбъекта, МассивСсылок);

		КонецЕсли;

		МассивСсылок.Добавить(ТекущаяСсылка);

	КонецЦикла;
	
	Если КэшПоТипамОбъектов.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;

	ШаблонПодзапроса = "ВЫБРАТЬ
		|	&Дата КАК Дата,
		|	Ссылка,
		|	&Проведен КАК Проведен,
		|	ПометкаУдаления,
		|	&СуммаДокумента КАК СуммаДокумента,
		|	&Валюта КАК Валюта,
		|	&Представление
		|ИЗ
		|	&ИмяТаблицы
		|ГДЕ
		|	Ссылка В (&ИмяОбъекта)";

	Запрос = Новый Запрос;
	ТекстЗапроса = "";
	Для Каждого КлючИЗначение Из КэшПоТипамОбъектов Цикл
		
		МассивИмениОбъекта = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(КлючИЗначение.Ключ, ".");
		Если МассивИмениОбъекта.Количество() = 2 Тогда
			ИмяОбъекта = МассивИмениОбъекта[1];
		Иначе
			Продолжить;
		КонецЕсли;

		ТекстПоТипуОбъекта = СтрЗаменить(ШаблонПодзапроса, "&Дата", КэшРеквизитовОбъекта[КлючИЗначение.Ключ]["Дата"]); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&Проведен", КэшРеквизитовОбъекта[КлючИЗначение.Ключ]["Проведен"]); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&СуммаДокумента", КэшРеквизитовОбъекта[КлючИЗначение.Ключ]["СуммаДокумента"]); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&Валюта", КэшРеквизитовОбъекта[КлючИЗначение.Ключ]["Валюта"]); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&ИмяТаблицы", КлючИЗначение.Ключ); 
		ТекстПоТипуОбъекта = СтрЗаменить(ТекстПоТипуОбъекта, "&ИмяОбъекта", "&" + ИмяОбъекта); 
		Запрос.УстановитьПараметр(ИмяОбъекта, КлючИЗначение.Значение);
		
		МассивДопРеквизитов = РеквизитыДляПредставления(КлючИЗначение.Ключ, ИмяОбъекта);
		ДополнитьТекстЗапросаПоРеквизитамОбъекта(ТекстПоТипуОбъекта, МассивДопРеквизитов);
		
		Если Не ПустаяСтрока(ТекстЗапроса) Тогда
			ТекстЗапроса = ТекстЗапроса + "
				|	ОБЪЕДИНИТЬ ВСЕ 
				|";		
		КонецЕсли;	
		ТекстЗапроса = ТекстЗапроса + ТекстПоТипуОбъекта;

	КонецЦикла;

	ШаблонЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
		|	*
		|ИЗ
		|	(ВЫБРАТЬ 1 ИЗ #Подзапрос) КАК ПодчиненныеОбъекты
		|УПОРЯДОЧИТЬ ПО
		|	ПодчиненныеОбъекты.Дата";

	Запрос.Текст = СтрЗаменить(ШаблонЗапроса, "ВЫБРАТЬ 1 ИЗ #Подзапрос", ТекстЗапроса);
	Выборка = Запрос.Выполнить().Выбрать();

	Пока Выборка.Следующий() Цикл
		
		Если ИндексСвязейОбъектов[ТекущийОбъект] = Выборка.Ссылка Тогда 
			Продолжить;
		КонецЕсли;
		
		ИндексСвязейОбъектов.Вставить(ТекущийОбъект, Выборка.Ссылка);
		
		НоваяСтрока = ДобавитьСтрокуВДерево(ДеревоРодитель, Выборка, ВыведенныеОбъекты, Истина);
		
		Если НоваяСтрока <> Неопределено
			И Не ДобавляемыйОбъектИмеетсяСредиРодителей(ДеревоРодитель, Выборка.Ссылка) Тогда
			
			ВывестиПодчиненныеОбъекты(Выборка.Ссылка, НоваяСтрока, ВыведенныеОбъекты,
				СлужебныеОбъекты, ИндексСвязейОбъектов);
			
		ИначеЕсли СлужебныеОбъекты[Выборка.Ссылка] = Неопределено Тогда 
			
			СлужебныеОбъекты.Вставить(Выборка.Ссылка, Истина);
			ВывестиПодчиненныеОбъекты(Выборка.Ссылка, ДеревоРодитель, ВыведенныеОбъекты,
				СлужебныеОбъекты, ИндексСвязейОбъектов);
			
		КонецЕсли;
		
	КонецЦикла;
	
	//ПродолжитьВызов(ТекущийОбъект, ДеревоРодитель, ВыведенныеОбъекты, СлужебныеОбъекты, ИндексСвязейОбъектов);
КонецПроцедуры

&НаСервере
Процедура Расш2_ПриСозданииНаСервереПеред(Отказ, СтандартнаяОбработка)
	лДерево        = РеквизитФормыВЗначение("ДеревоПодчиненныеОбъекты");
    лНовыйОТ    = новый ОписаниеТипов(лДерево.Колонки.Ссылка.ТипЗначения,"ДокументСсылка.СчетНаОплатуПокупателю");        //СчетНаОплатуПоставщика
    лДерево.Колонки.Добавить("Ссылка2",лНовыйОТ);
    
    
    // 3. создаем РЕКВИЗИТ КОЛОНКИ (невидимая часть, справа в редакторе форм)
    МассивДобавляемыхРеквизитов = Новый Массив;
    // реквизит принадлежит дереву
    МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Ссылка2", лНовыйОТ, "ДеревоПодчиненныеОбъекты"));
    // добавляем реквизит в форму (невидимая часть, справа в редакторе форм)
    ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);    
    
    ЗначениеВРеквизитФормы(лДерево,"ДеревоПодчиненныеОбъекты");
    
    // проверим, а добавилось ли
    лДерево        = РеквизитФормыВЗначение("ДеревоПодчиненныеОбъекты");             
    лДерево        = РеквизитФормыВЗначение("ДеревоРодительскиеОбъекты");
    лНовыйОТ    = новый ОписаниеТипов(лДерево.Колонки.Ссылка.ТипЗначения,"ДокументСсылка.СчетНаОплатуПокупателю");
    лДерево.Колонки.Добавить("Ссылка2",лНовыйОТ);
    
    
    // 3. создаем РЕКВИЗИТ КОЛОНКИ (невидимая часть, справа в редакторе форм)
    МассивДобавляемыхРеквизитов = Новый Массив;
    // реквизит принадлежит дереву
    МассивДобавляемыхРеквизитов.Добавить(Новый РеквизитФормы("Ссылка2", лНовыйОТ, "ДеревоРодительскиеОбъекты"));
    // добавляем реквизит в форму (невидимая часть, справа в редакторе форм)
    ИзменитьРеквизиты(МассивДобавляемыхРеквизитов);    
    
    ЗначениеВРеквизитФормы(лДерево,"ДеревоРодительскиеОбъекты");
    
    // проверим, а добавилось ли
    лДерево        = РеквизитФормыВЗначение("ДеревоРодительскиеОбъекты");
КонецПроцедуры

&НаСервере
&Вместо("ОбъектыПоКритериюОтбора")
Функция Расш2_ОбъектыПоКритериюОтбора(ЗначениеКритерияОтбора)
	
	Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Тип.СодержитТип(ТипЗнч(ЗначениеКритерияОтбора))  Тогда
		Возврат Неопределено;
	КонецЕсли;
		
	УстановитьПривилегированныйРежим(Истина);
	
	Запрос = Новый Запрос;
	Запрос.Текст = "ВЫБРАТЬ
                   |    СвязанныеДокументы.Ссылка КАК Ссылка
                   |ИЗ
                   |    КритерийОтбора.СвязанныеДокументы(&ЗначениеКритерияОтбора) КАК СвязанныеДокументы
                   |
                   |ОБЪЕДИНИТЬ ВСЕ
                   |
                   |ВЫБРАТЬ
                   |    СчетНаОплатуПоставщика.Ссылка
                   |ИЗ
                   |    Документ.СчетНаОплатуПоставщика КАК СчетНаОплатуПоставщика
                   |ГДЕ
                   |    СчетНаОплатуПоставщика.ДокументОснование = &ЗначениеКритерияОтбора";	
	Запрос.УстановитьПараметр("ЗначениеКритерияОтбора", ЗначениеКритерияОтбора);
	Возврат Запрос.Выполнить().Выгрузить();


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

Показать


p.s. часть кода собрана по мотивам открытых источников рунета :)
Оставьте свое сообщение

Для получения уведомлений об ответах подключите телеграм бот:
Инфостарт бот