Проект

Общее

Профиль

Структура подчиненности (связанные объекты) » История » Версия 4

Версия 3 (Всеволод Дорофеев, 15.09.2025 17:24) → Версия 4/5 (Всеволод Дорофеев, 15.09.2025 17:24)

h1. Структура подчиненности (связанные объекты)

h3. Добавление Структуры Структура подчиненности (связанные документы) в расширение

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

1. Добавляем в расширение процедуру ОбщийМодуль.ВариантыОтчетовПереопределяемый.ОпределитьОбъектыСКомандамиОтчетов

<pre>
&После("ОпределитьОбъектыСКомандамиОтчетов")
Процедура мн_ОпределитьОбъектыСКомандамиОтчетов(Объекты)

Объекты.Добавить(Метаданные.Документы.ОрдерНаОтражениеИзлишковТоваров);
Объекты.Добавить(Метаданные.Документы.ОрдерНаОтражениеНедостачТоваров);

КонецПроцедуры
</pre>

2. Добавляем в расширение ОбщийМодуль.СтруктураПодчиненностиСлужебный.ИндексТиповСвязанныхОбъектов

<pre>
&ИзменениеИКонтроль("ИндексТиповСвязанныхОбъектов")
Функция мн_ИндексТиповСвязанныхОбъектов()

Индекс = Новый Соответствие;

МетаданныеСвязанныхОбъектов = Метаданные.КритерииОтбора.СвязанныеДокументы;
ТипыСвязанныхОбъектов = МетаданныеСвязанныхОбъектов.Тип.Типы();
ТипПараметраКоманды = Метаданные.ОбщиеКоманды.СвязанныеДокументы.ТипПараметраКоманды;

Для Каждого ТипСвязанногоОбъекта Из ТипыСвязанныхОбъектов Цикл

Если Не ТипПараметраКоманды.СодержитТип(ТипСвязанногоОбъекта) Тогда
Индекс.Вставить(ТипСвязанногоОбъекта, Истина);
КонецЕсли;

КонецЦикла;
#Вставка
//{Проект
Индекс.Вставить(Тип("ДокументСсылка.ОрдерНаОтражениеНедостачТоваров"), Истина);
Индекс.Вставить(Тип("ДокументСсылка.ОрдерНаОтражениеИзлишковТоваров"), Истина);

// } Проект .
#КонецВставки
Возврат Индекс;

КонецФункции
</pre>

3. Добавляем в расширение ОбщиеФормы.СвязанныеДокументы:
* ОбъектыПоКритериюОтбора
* ВывестиРодительскиеОбъекты

<pre>

&НаСервере
&ИзменениеИКонтроль("ОбъектыПоКритериюОтбора")
Функция пл_ОбъектыПоКритериюОтбора(ЗначениеКритерияОтбора)

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

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

ЧастиЗапроса = Новый Массив;
ТекстЧастиЗапроса = "";

Для Каждого ЭлементСостава Из Метаданные.КритерииОтбора.СвязанныеДокументы.Состав Цикл

Если НЕ ЭлементСостава.Тип.СодержитТип(ТипЗнч(ЗначениеКритерияОтбора)) Тогда
Продолжить;
КонецЕсли;

ПутьКДанным = ЭлементСостава.ПолноеИмя();

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

Если НЕ ПравоДоступа("Чтение", ОбъектМетаданных) Тогда
Продолжить;
КонецЕсли;

Точка = СтрНайти(ПутьКДанным, ".", НаправлениеПоиска.СКонца);
ИмяРеквизита = Сред(ПутьКДанным, Точка + 1);

ИмяТаблицы = ЭлементСостава.Родитель().ПолноеИмя();
ИмяТаблицы = СтрЗаменить(ИмяТаблицы, "ТабличнаяЧасть.", "");

Точка = СтрНайти(ИмяТаблицы, ".", НаправлениеПоиска.СКонца);
ПредставлениеТаблицы = Сред(ИмяТаблицы, Точка + 1);

ТекстЧастиЗапроса = ?(ТекстЧастиЗапроса = "", ШаблонЗапроса, ШаблонЗапросаОбъединения);
ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяТаблицы", ИмяТаблицы);
ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ПредставлениеТаблицы", ПредставлениеТаблицы);
ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяРеквизита", ИмяРеквизита);

ЧастиЗапроса.Добавить(ТекстЧастиЗапроса);

КонецЦикла;
#Вставка
//Проект Всеволод
ТекстЧастиЗапроса = ?(ТекстЧастиЗапроса = "", ШаблонЗапроса, ШаблонЗапросаОбъединения);
ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяТаблицы", "Документ.ОрдерНаОтражениеИзлишковТоваров");
ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ПредставлениеТаблицы", "ОрдерНаОтражениеИзлишковТоваров");
ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяРеквизита", "пл_ДокументОснование");

ЧастиЗапроса.Добавить(ТекстЧастиЗапроса);

ТекстЧастиЗапроса = ?(ТекстЧастиЗапроса = "", ШаблонЗапроса, ШаблонЗапросаОбъединения);
ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяТаблицы", "Документ.ОрдерНаОтражениеНедостачТоваров");
ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ПредставлениеТаблицы", "ОрдерНаОтражениеНедостачТоваров");
ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяРеквизита", "пл_ДокументОснование");

ЧастиЗапроса.Добавить(ТекстЧастиЗапроса);

// } Проект .
#КонецВставки
Если ЧастиЗапроса.Количество() > 0 Тогда
Запрос = Новый Запрос;
Разделитель = Символы.ПС + "ОБЪЕДИНИТЬ" + Символы.ПС;
Запрос.Текст = СтрСоединить(ЧастиЗапроса, Разделитель);
Запрос.УстановитьПараметр("ЗначениеКритерияОтбора", ЗначениеКритерияОтбора);
Возврат Запрос.Выполнить().Выгрузить();
Иначе
Возврат Новый ТаблицаЗначений;
КонецЕсли;

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

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

МетаданныеОбъекта = ТекущийОбъект.Метаданные();
СписокРеквизитов = Новый Массив;

Если СлужебныеОбъекты = Неопределено Тогда
СлужебныеОбъекты = Новый Соответствие;
КонецЕсли;

Если ИндексСвязейОбъектов = Неопределено Тогда
ИндексСвязейОбъектов = Новый Соответствие;
КонецЕсли;

Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл

Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда
Продолжить;
КонецЕсли;

Для Каждого ТекущийТип Из Реквизит.Тип.Типы() Цикл

МетаданныеРеквизита = МетаданныеТипаРеквизита(ТекущийТип);
Если МетаданныеРеквизита.Метаданные = Неопределено Тогда
Продолжить;
КонецЕсли;

ЗначениеРеквизита = ТекущийОбъект[Реквизит.Имя];
Если ЗначениеЗаполнено(ЗначениеРеквизита)
И ТипЗнч(ЗначениеРеквизита) = ТекущийТип
И ЗначениеРеквизита <> ТекущийОбъект
И СписокРеквизитов.Найти(ЗначениеРеквизита) = Неопределено Тогда

СписокРеквизитов.Добавить(ЗначениеРеквизита);
КонецЕсли;
КонецЦикла;

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

СписокРеквизитов.Добавить(ТекущийОбъект.пл_ДокументОснование);

КонецЕсли;
Исключение
КонецПопытки;
// } Проект .
#КонецВставки
Для Каждого ТабличнаяЧасть Из МетаданныеОбъекта.ТабличныеЧасти Цикл

ИменаРеквизитов = "";
СодержимоеТЧ = ТекущийОбъект[ТабличнаяЧасть.Имя].Выгрузить(); // ТаблицаЗначений
Для Каждого Реквизит Из ТабличнаяЧасть.Реквизиты Цикл

Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда
Продолжить;
КонецЕсли;

Для Каждого ТекущийТип Из Реквизит.Тип.Типы() Цикл
МетаданныеРеквизита = МетаданныеТипаРеквизита(ТекущийТип);
Если МетаданныеРеквизита.Метаданные = Неопределено Тогда
Продолжить;
КонецЕсли;

ИменаРеквизитов = ИменаРеквизитов + ?(ИменаРеквизитов = "", "", ", ") + Реквизит.Имя;
Прервать;
КонецЦикла;

КонецЦикла;

СодержимоеТЧ.Свернуть(ИменаРеквизитов);
Для Каждого КолонкаТЧ Из СодержимоеТЧ.Колонки Цикл

Для Каждого СтрокаТЧ Из СодержимоеТЧ Цикл

ЗначениеРеквизита = СтрокаТЧ[КолонкаТЧ.Имя];
МетаданныеЗначения = МетаданныеТипаРеквизита(ТипЗнч(ЗначениеРеквизита));
Если МетаданныеЗначения.Метаданные = Неопределено Тогда
Продолжить;
КонецЕсли;

Если ЗначениеРеквизита = ТекущийОбъект
Или СписокРеквизитов.Найти(ЗначениеРеквизита) <> Неопределено Тогда
Продолжить;
КонецЕсли;

СписокРеквизитов.Добавить(ЗначениеРеквизита);
КонецЦикла;
КонецЦикла;
КонецЦикла;

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

Если ИндексСвязейОбъектов[ТекущийОбъект] = ВыводимыйОбъект.Ссылка Тогда
Продолжить;
КонецЕсли;

ИндексСвязейОбъектов[ТекущийОбъект] = ВыводимыйОбъект.Ссылка;

НоваяСтрока = ДобавитьСтрокуВДерево(ДеревоРодитель, ВыводимыйОбъект, ВыведенныеОбъекты);
Если НоваяСтрока <> Неопределено
И Не ДобавляемыйОбъектИмеетсяСредиРодителей(ДеревоРодитель, ВыводимыйОбъект.Ссылка) Тогда
a
// @skip-check query-in-loop - Рекурсивный алгоритм обработки дерева.
ВывестиРодительскиеОбъекты(ВыводимыйОбъект.Ссылка, НоваяСтрока, ВыведенныеОбъекты,
СлужебныеОбъекты, ИндексСвязейОбъектов);

ИначеЕсли СлужебныеОбъекты[ВыводимыйОбъект.Ссылка] = Неопределено Тогда

СлужебныеОбъекты[ВыводимыйОбъект.Ссылка] = Истина;
// @skip-check query-in-loop - Рекурсивный алгоритм обработки дерева.
ВывестиРодительскиеОбъекты(ВыводимыйОбъект.Ссылка, ДеревоРодитель, ВыведенныеОбъекты,
СлужебныеОбъекты, ИндексСвязейОбъектов);

КонецЕсли;
КонецЦикла;
КонецЕсли;

КонецПроцедуры

</pre>

4. Добавляем в расширение Документы.ОрдерНаОтражениеНедостачТоваров.МодульМенеджера.ДобавитьКомандыОтчетов

<pre>

&После("ДобавитьКомандыОтчетов")
Процедура пл_ДобавитьКомандыОтчетов(КомандыОтчетов, Параметры)

ИнтеграцияИСПереопределяемый.ДобавитьКомандуСтруктураПодчиненности(КомандыОтчетов); //Всеволод

КонецПроцедуры

</pre>