gifts2017

Обход подчиненных документов

Опубликовал Юрий Семенихин (human_new) в раздел Программирование - Практика программирования

Обход документов, входящих в структуру подчинённости.
Есть документ, у него ссылка на документ родитель и так до бесконечности... 

Требуется найти сумму всех документов, входящих в дерево подчиненности. 
Пример: Есть документ "Проект договора" на основании проекта договора может быть создано несколько Доп. соглашений, На основании доп соглашений могут быть созданы ещё доп соглашения(Структура подчиненности). Если сумма договора и доп соглашений превысит в общем пять миллионов, то проект должен быть согласован генеральным директором.

Можно построить дерево подчиненности, а потом его обойти, а можно обойти запросом в рекурсивном цикле.

Вот пример процедуры, которая находит сумму по всем документам проекта договора:
 
&НаСервере
Функция ПолучитьСуммуПоВсемПроектамДогНаСервере(ПроектДоговора)
	МасДог = Новый Массив;
	МасДог.Добавить(ПроектДоговора);
	ПолучитьПроектыДогРекурсивно(МасДог);
	СуммаПоВсемПроектамДог = 0;
	Для каждого Проект из МасДог Цикл
		СуммаПоВсемПроектамДог = СуммаПоВсемПроектамДог + Проект.СуммаВзаиморасчеты;
		Сообщить(Проект);
	КонецЦикла;
	Сообщить("Сумма по всем проектам = " + СуммаПоВсемПроектамДог);
	Возврат  СуммаПоВсемПроектамДог;
	
КонецФункции


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

	Запрос.УстановитьПараметр("МасДог", МасДог);

	РезультатЗапроса = Запрос.Выполнить();

	ВыборкаДетальныеЗаписи = РезультатЗапроса.Выбрать();

	Если ВыборкаДетальныеЗаписи.Количество() > 0 Тогда 
	
		Пока ВыборкаДетальныеЗаписи.Следующий() Цикл
			 МасДог.Добавить(ВыборкаДетальныеЗаписи.Ссылка);
		КонецЦикла;
		ПолучитьПроектыДогРекурсивно(МасДог); 
	//Иначе
		//Возврат МасДог;
	КонецЕсли;
		
	
КонецПроцедуры


См. также

Подписаться Добавить вознаграждение

Комментарии

1. Алексей 1 (AlX0id) 13.08.14 20:20
Не понял, в чем прикол считать сумму отдельно от рекурсии..
2. Юрий Семенихин (human_new) 13.08.14 20:48
(1) AlX0id, да там ещё условия на эти проекты будут накладываться, решил разделить. А так конечно лучше считать в рекурсии
3. Михаил Чернышев (smilebringer) 13.08.14 20:48
Поправьте меня, но для такой задачи подойдет критерий отбора, и он решит ее очень просто
4. Юрий Семенихин (human_new) 13.08.14 22:15
(3) smilebringer, Критерий отбора - это конечно клёвая вещь, но я не очень понимаю, чем она должна помощь, все равно рекурсия с запросом из критерия отбора, который тоже надо писать иначе получишь только 1 уровень подчиненности. Так и сделано в стандарте, когда выводишь структуру подчиненности. Вот если бы был вариант одним запросом, тогда конечно было бы круто.
5. Иван Устьянцев (nSpirit2) 13.08.14 22:28
Ну и чем ваше решение выгодней запросов в циклах?) Вы правда думаете что это решение адекватное в плане 1С? Можете предложить жизненный пример подобной задачи?
6. Юрий Семенихин (human_new) 14.08.14 10:14
(5) nSpirit2, так я и не настаиваю на том, что можно одним запросом получать всю иерархию, но будет ли использоваться критерий отбора или нет - тоже не вижу разницы. А на счет "в плане 1С", как раз только в 1с нужно городить огород, т.к. таблицы то нужной нет. Вот я и предложил вариант "огорода".
7. Иван Устьянцев (nSpirit2) 14.08.14 11:09
(6) human_new, Про критерии отбора вынужден согласиться. Запросы к ним совсем не оптимальны на сколько я понимаю логику их работы то фактической таблички критерия не существует и при запросе она начинает строиться это не очень быстрый механизм так то.

Я имею ввиду что при возникновении такой задачи можно заранее избежать необходимость поиска документов по бесконечному дереву. Не пытаясь решить всю задачу целиком а модифицировав конфигурацию под конкретный вариант БП клиента. Чтобы такой задачи не возникало. Ну и вы ведь понимаете что у 1с есть ограничение стека рекурсии так что бесконечное дерево рекурсией в 1с к сожалению не построить (
8. Юрий Семенихин (human_new) 14.08.14 13:51
(7) nSpirit2, это да, лучше построить табличку и хранить сразу дерево, что бы можно было спускаться к листикам, а не только подниматься к корню.
nSpirit2; +1 Ответить
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа