Структура подчиненности (связанные объекты)¶
Добавление Структуры подчиненности (связанные документы) в расширение¶
При добавлении нового реквизита в объект (документ, справочник) может возникнуть задача вывода связанных документов.
Если добавлять в расширение КритерииОтбора.СвязанныеДокументы, тогда в расширение будут добавлены все участвующие объекты.
Можно решить иначе - добавлением кода:
1. Добавляем в расширение процедуру ОбщийМодуль.ВариантыОтчетовПереопределяемый.ОпределитьОбъектыСКомандамиОтчетов
&После("ОпределитьОбъектыСКомандамиОтчетов")
Процедура мн_ОпределитьОбъектыСКомандамиОтчетов(Объекты)
    Объекты.Добавить(Метаданные.Документы.ОрдерНаОтражениеИзлишковТоваров);
    Объекты.Добавить(Метаданные.Документы.ОрдерНаОтражениеНедостачТоваров);
КонецПроцедуры
	2. Добавляем в расширение ОбщийМодуль.СтруктураПодчиненностиСлужебный.ИндексТиповСвязанныхОбъектов
&ИзменениеИКонтроль("ИндексТиповСвязанныхОбъектов")
Функция мн_ИндексТиповСвязанныхОбъектов()
    Индекс = Новый Соответствие;
    МетаданныеСвязанныхОбъектов = Метаданные.КритерииОтбора.СвязанныеДокументы;
    ТипыСвязанныхОбъектов = МетаданныеСвязанныхОбъектов.Тип.Типы();
    ТипПараметраКоманды = Метаданные.ОбщиеКоманды.СвязанныеДокументы.ТипПараметраКоманды;
    Для Каждого ТипСвязанногоОбъекта Из ТипыСвязанныхОбъектов Цикл
        Если Не ТипПараметраКоманды.СодержитТип(ТипСвязанногоОбъекта) Тогда
            Индекс.Вставить(ТипСвязанногоОбъекта, Истина);
        КонецЕсли;
    КонецЦикла;
#Вставка 
    //{Проект
      Индекс.Вставить(Тип("ДокументСсылка.ОрдерНаОтражениеНедостачТоваров"), Истина);   
      Индекс.Вставить(Тип("ДокументСсылка.ОрдерНаОтражениеИзлишковТоваров"), Истина);   
    // } Проект .
#КонецВставки 
    Возврат Индекс;
КонецФункции
3. Добавляем в расширение ОбщиеФормы.СвязанныеДокументы:
	- ОбъектыПоКритериюОтбора
- ВывестиРодительскиеОбъекты
&НаСервере
&ИзменениеИКонтроль("ОбъектыПоКритериюОтбора")
Функция пл_ОбъектыПоКритериюОтбора(ЗначениеКритерияОтбора)
    ШаблонЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ
    |    ПредставлениеТаблицы.Ссылка КАК Ссылка
    |ИЗ
    |    ИмяТаблицы КАК ПредставлениеТаблицы
    |ГДЕ
    |    ПредставлениеТаблицы.ИмяРеквизита = &ЗначениеКритерияОтбора";
    ШаблонЗапросаОбъединения = "ВЫБРАТЬ
    |    ПредставлениеТаблицы.Ссылка КАК Ссылка
    |ИЗ
    |    ИмяТаблицы КАК ПредставлениеТаблицы
    |ГДЕ
    |    ПредставлениеТаблицы.ИмяРеквизита = &ЗначениеКритерияОтбора";
    ЧастиЗапроса = Новый Массив;
    ТекстЧастиЗапроса = "";
    Для Каждого ЭлементСостава Из Метаданные.КритерииОтбора.СвязанныеДокументы.Состав Цикл
        Если НЕ ЭлементСостава.Тип.СодержитТип(ТипЗнч(ЗначениеКритерияОтбора)) Тогда
            Продолжить;
        КонецЕсли;
        ПутьКДанным = ЭлементСостава.ПолноеИмя();
        Если СтрНайти(ПутьКДанным, "ТабличнаяЧасть") Тогда
            ОбъектМетаданных = ЭлементСостава.Родитель().Родитель();
        Иначе
            ОбъектМетаданных = ЭлементСостава.Родитель();
        КонецЕсли;
        Если НЕ ПравоДоступа("Чтение", ОбъектМетаданных) Тогда
            Продолжить;
        КонецЕсли;
        Точка = СтрНайти(ПутьКДанным, ".", НаправлениеПоиска.СКонца);
        ИмяРеквизита = Сред(ПутьКДанным, Точка + 1);
        ИмяТаблицы = ЭлементСостава.Родитель().ПолноеИмя();
        ИмяТаблицы = СтрЗаменить(ИмяТаблицы, "ТабличнаяЧасть.", "");
        Точка = СтрНайти(ИмяТаблицы, ".", НаправлениеПоиска.СКонца);
        ПредставлениеТаблицы = Сред(ИмяТаблицы, Точка + 1);
        ТекстЧастиЗапроса = ?(ТекстЧастиЗапроса = "", ШаблонЗапроса, ШаблонЗапросаОбъединения);
        ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяТаблицы", ИмяТаблицы);
        ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ПредставлениеТаблицы", ПредставлениеТаблицы);
        ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяРеквизита", ИмяРеквизита);
        ЧастиЗапроса.Добавить(ТекстЧастиЗапроса);
    КонецЦикла;
#Вставка 
        //Проект Всеволод
        ТекстЧастиЗапроса = ?(ТекстЧастиЗапроса = "", ШаблонЗапроса, ШаблонЗапросаОбъединения);
        ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяТаблицы", "Документ.ОрдерНаОтражениеИзлишковТоваров");
        ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ПредставлениеТаблицы", "ОрдерНаОтражениеИзлишковТоваров");
        ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяРеквизита", "пл_ДокументОснование");
        ЧастиЗапроса.Добавить(ТекстЧастиЗапроса);
        ТекстЧастиЗапроса = ?(ТекстЧастиЗапроса = "", ШаблонЗапроса, ШаблонЗапросаОбъединения);
        ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяТаблицы", "Документ.ОрдерНаОтражениеНедостачТоваров");
        ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ПредставлениеТаблицы", "ОрдерНаОтражениеНедостачТоваров");
        ТекстЧастиЗапроса = СтрЗаменить(ТекстЧастиЗапроса, "ИмяРеквизита", "пл_ДокументОснование");
        ЧастиЗапроса.Добавить(ТекстЧастиЗапроса);
    // } Проект .
#КонецВставки 
    Если ЧастиЗапроса.Количество() > 0 Тогда
        Запрос = Новый Запрос;
        Разделитель = Символы.ПС + "ОБЪЕДИНИТЬ" + Символы.ПС;
        Запрос.Текст = СтрСоединить(ЧастиЗапроса, Разделитель);
        Запрос.УстановитьПараметр("ЗначениеКритерияОтбора", ЗначениеКритерияОтбора);
        Возврат Запрос.Выполнить().Выгрузить();
    Иначе
        Возврат Новый ТаблицаЗначений;
    КонецЕсли;
КонецФункции
&НаСервере
&ИзменениеИКонтроль("ВывестиРодительскиеОбъекты")
Процедура пл_ВывестиРодительскиеОбъекты(ТекущийОбъект, ДеревоРодитель, ВыведенныеОбъекты, СлужебныеОбъекты, ИндексСвязейОбъектов)
    МетаданныеОбъекта = ТекущийОбъект.Метаданные();
    СписокРеквизитов  = Новый Массив;
    Если СлужебныеОбъекты = Неопределено Тогда 
        СлужебныеОбъекты = Новый Соответствие;
    КонецЕсли;
    Если ИндексСвязейОбъектов = Неопределено Тогда 
        ИндексСвязейОбъектов = Новый Соответствие;
    КонецЕсли;
    Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
        Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда
            Продолжить;
        КонецЕсли;
        Для Каждого ТекущийТип Из Реквизит.Тип.Типы() Цикл
            МетаданныеРеквизита = МетаданныеТипаРеквизита(ТекущийТип);
            Если МетаданныеРеквизита.Метаданные = Неопределено Тогда
                Продолжить;
            КонецЕсли;
            ЗначениеРеквизита = ТекущийОбъект[Реквизит.Имя];
            Если ЗначениеЗаполнено(ЗначениеРеквизита)
                И ТипЗнч(ЗначениеРеквизита) = ТекущийТип
                И ЗначениеРеквизита <> ТекущийОбъект
                И СписокРеквизитов.Найти(ЗначениеРеквизита) = Неопределено Тогда
                СписокРеквизитов.Добавить(ЗначениеРеквизита);
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
#Вставка 
    //Проект Всеволод
    Попытка
        Если ТипЗнч(ТекущийОбъект) = Тип("ДокументСсылка.ОрдерНаОтражениеНедостачТоваров")
            или ТипЗнч(ТекущийОбъект) = Тип("ДокументСсылка.ОрдерНаОтражениеИзлишковТоваров")
            Тогда
            СписокРеквизитов.Добавить(ТекущийОбъект.пл_ДокументОснование);
        КонецЕсли;
    Исключение
    КонецПопытки;
    // } Проект .
#КонецВставки 
    Для Каждого ТабличнаяЧасть Из МетаданныеОбъекта.ТабличныеЧасти Цикл
        ИменаРеквизитов = "";
        СодержимоеТЧ = ТекущийОбъект[ТабличнаяЧасть.Имя].Выгрузить(); // ТаблицаЗначений
        Для Каждого Реквизит Из ТабличнаяЧасть.Реквизиты Цикл
            Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда
                Продолжить;
            КонецЕсли;
            Для Каждого ТекущийТип Из Реквизит.Тип.Типы() Цикл
                МетаданныеРеквизита = МетаданныеТипаРеквизита(ТекущийТип);
                Если МетаданныеРеквизита.Метаданные = Неопределено Тогда
                    Продолжить;
                КонецЕсли;
                ИменаРеквизитов = ИменаРеквизитов + ?(ИменаРеквизитов = "", "", ", ") + Реквизит.Имя;
                Прервать;
            КонецЦикла;
        КонецЦикла;
        СодержимоеТЧ.Свернуть(ИменаРеквизитов);
        Для Каждого КолонкаТЧ Из СодержимоеТЧ.Колонки Цикл
            Для Каждого СтрокаТЧ Из СодержимоеТЧ Цикл
                ЗначениеРеквизита = СтрокаТЧ[КолонкаТЧ.Имя];
                МетаданныеЗначения = МетаданныеТипаРеквизита(ТипЗнч(ЗначениеРеквизита));
                Если МетаданныеЗначения.Метаданные = Неопределено Тогда
                    Продолжить;
                КонецЕсли;
                Если ЗначениеРеквизита = ТекущийОбъект
                    Или СписокРеквизитов.Найти(ЗначениеРеквизита) <> Неопределено Тогда
                    Продолжить;
                КонецЕсли;
                СписокРеквизитов.Добавить(ЗначениеРеквизита);
            КонецЦикла;
        КонецЦикла;
    КонецЦикла;
    Если СписокРеквизитов.Количество() > 0 Тогда
        ВыводимыеОбъекты = ЗапросПоРеквизитамОбъектов(СписокРеквизитов).Выполнить().Выгрузить();
        ВыводимыеОбъекты.Сортировать("Дата");
        Для каждого ВыводимыйОбъект Из ВыводимыеОбъекты Цикл 
            Если ИндексСвязейОбъектов[ТекущийОбъект] = ВыводимыйОбъект.Ссылка Тогда 
                Продолжить;
            КонецЕсли;
            ИндексСвязейОбъектов[ТекущийОбъект] = ВыводимыйОбъект.Ссылка;
            НоваяСтрока = ДобавитьСтрокуВДерево(ДеревоРодитель, ВыводимыйОбъект, ВыведенныеОбъекты);            
            Если НоваяСтрока <> Неопределено
                И Не ДобавляемыйОбъектИмеетсяСредиРодителей(ДеревоРодитель, ВыводимыйОбъект.Ссылка) Тогда
                      a
                // @skip-check query-in-loop - Рекурсивный алгоритм обработки дерева.
                ВывестиРодительскиеОбъекты(ВыводимыйОбъект.Ссылка, НоваяСтрока, ВыведенныеОбъекты,
                СлужебныеОбъекты, ИндексСвязейОбъектов);
            ИначеЕсли СлужебныеОбъекты[ВыводимыйОбъект.Ссылка] = Неопределено Тогда 
                СлужебныеОбъекты[ВыводимыйОбъект.Ссылка] = Истина;
                // @skip-check query-in-loop - Рекурсивный алгоритм обработки дерева.
                ВывестиРодительскиеОбъекты(ВыводимыйОбъект.Ссылка, ДеревоРодитель, ВыведенныеОбъекты,
                СлужебныеОбъекты, ИндексСвязейОбъектов);
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
КонецПроцедуры
	4. Добавляем в расширение Документы.ОрдерНаОтражениеНедостачТоваров.МодульМенеджера.ДобавитьКомандыОтчетов
&После("ДобавитьКомандыОтчетов")
Процедура пл_ДобавитьКомандыОтчетов(КомандыОтчетов, Параметры)
    ИнтеграцияИСПереопределяемый.ДобавитьКомандуСтруктураПодчиненности(КомандыОтчетов);    //Всеволод
КонецПроцедуры
	Более универсальное решение с добавлением своего настраиваемого КритерияОтбора:
https://infostart.ru/1c/articles/1653703/