Не раз приходилось дорабатывать возможности отчета "Связанные документы" ("Структура подчиненности" в девичестве). Для этого достаточно было изменить критерий отбора "Связанные документы", добавив новые типы, изменив состав. С появлением расширений и расширением их возможностей это стало сделать невозможно. На Инфостарте уже есть подобная статья //infostart.ru/1c/articles/1653703, в которой предлагается добавлять критерии отбора в расширение. Давайте попробуем доработать отчет "Связанные документы" в расширении с минимальными изменениями типового отчета и максимальными возможностями.
Более подробно изучив механизм работы отчета, стало понятно, что необходимо изменить только процедуру ВывестиРодительскиеОбъекты(), функцию ОбъектыПоКритериюОтбора(), реквизиты формы в общей форме СвязанныеДокументы и функцию ИндексТиповСвязанныхОбъектов() в общем модуле СтруктураПодчиненностиСлужебный.
Добавим в общий модуль СтруктураПодчиненностиСлужебный новые функции для программного расширения состава критерия отбора и дополним типовую функцию получения типов объектов, в которых необходимо выводить кнопки отчета "Связанные документы".
&Вместо("ИндексТиповСвязанныхОбъектов")
Функция _ИндексТиповСвязанныхОбъектов()
ИндексТипов = ПродолжитьВызов();
ДобавленныеТипы = ОбщегоНазначения.ВыгрузитьКолонку(_ПолучитьДанныеСвязанныхДокументов(), "Тип");
Для каждого Тип Из ДобавленныеТипы Цикл
ИндексТипов.Вставить(Тип, Истина);
КонецЦикла;
Возврат ИндексТипов;
КонецФункции
Функция _ПолучитьДанныеСвязанныхДокументов() Экспорт
СоставСвязанныеДокументы = _СоставСвязанныеДокументы();
ДанныеСвязанныхДокументов = Новый Массив;
Для каждого ОбъектМетаданных Из СоставСвязанныеДокументы Цикл
ОбъектМетаданныхПолноеИмя = ОбъектМетаданных.ПолноеИмя();
МетаданныеДерево = СтрРазделить(ОбъектМетаданныхПолноеИмя, ".");
Тип = Тип(МетаданныеДерево[0] + "Ссылка." + МетаданныеДерево[1]);
ДанныеСвязанныхДокументов.Добавить(Новый Структура("Тип, ПолноеИмя", Тип, ОбъектМетаданныхПолноеИмя));
КонецЦикла;
Возврат ДанныеСвязанныхДокументов
КонецФункции
Функция _СоставСвязанныеДокументы()
ОбъектыМетаданных = Новый Массив;
//ОбъектыМетаданных.Добавить(Метаданные.Документы.ЗаказКлиента.Реквизиты.ДокументОснование);
Возврат ОбъектыМетаданных
КонецФункции
В процедуре ВывестиРодительскиеОбъекты() достаточно строку с проверкой принадлежности объекта метаданных составу критерия отбора заменить на специально обученную функцию
_СвязанныеДокументыСодержитРеквизит(), дополнительно передавая в неё переменную ДобавленныеМетаданные, в которой будут метаданные добавленные в СтруктураПодчиненностиСлужебный. При получении добавленных метаданных все необходимые данные для расширения возможностей отчета кэшируются в создаваемых реквизитах формы.
&НаСервере
&ИзменениеИКонтроль("ВывестиРодительскиеОбъекты")
Процедура _ВывестиРодительскиеОбъекты(ТекущийОбъект, ДеревоРодитель, ВыведенныеОбъекты, СлужебныеОбъекты, ИндексСвязейОбъектов)
//..
#Вставка
Если СлужебныеОбъекты["_ДобавленныеМетаданные"] = Неопределено Тогда
СлужебныеОбъекты.Вставить("_ДобавленныеМетаданные", _ПолучитьДобавленныеМетаданные());
КонецЕсли;
_ДобавленныеМетаданные = СлужебныеОбъекты["_ДобавленныеМетаданные"];
#КонецВставки
Для Каждого Реквизит Из МетаданныеОбъекта.Реквизиты Цикл
#Удаление
Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда
#КонецУдаления
#Вставка
Если Не СвязанныеДокументыСодержитРеквизит(Реквизит, _ДобавленныеМетаданные) Тогда
#КонецВставки
Продолжить;
КонецЕсли;
//..
КонецПроцедуры
&НаСервере
Функция _ПолучитьДобавленныеМетаданные()
_СоздатьДанныеСвязанныхДокументов();
ДобавленныеМетаданные = Новый Массив;
Для каждого ПолноеИмя Из ЭтаФорма._ДанныеСвязанныхДокументовМетаданные Цикл
ДобавленныеМетаданные.Добавить(ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ПолноеИмя));
КонецЦикла;
Возврат ДобавленныеМетаданные
КонецФункции
&НаСервере
Функция _СвязанныеДокументыСодержитРеквизит(Реквизит, ДобавленныеМетаданные)
Если Метаданные.КритерииОтбора.СвязанныеДокументы.Состав.Содержит(Реквизит) Тогда
Возврат Истина
Иначе
ЕстьВСвязанныхДокументах = Не ДобавленныеМетаданные.Найти(Реквизит) = Неопределено;
Возврат ЕстьВСвязанныхДокументах
КонецЕсли;
КонецФункции
&НаСервере
Процедура _СоздатьДанныеСвязанныхДокументов()
Если Не ОбщегоНазначенияКлиентСервер.ЕстьРеквизитИлиСвойствоОбъекта(ЭтаФорма, "_ДанныеСвязанныхДокументовМетаданные") Тогда
НовыеРеквизиты = Новый Массив;
НовыеРеквизиты.Добавить(Новый РеквизитФормы("_ДанныеСвязанныхДокументовМетаданные", Новый ОписаниеТипов("СписокЗначений")));
НовыеРеквизиты.Добавить(Новый РеквизитФормы("_ДанныеСвязанныхДокументовТипы", Новый ОписаниеТипов("СписокЗначений")));
НовыеРеквизиты.Добавить(Новый РеквизитФормы("_ДанныеСвязанныхДокументовТекстЗапроса", Новый ОписаниеТипов("Строка")));
ИзменитьРеквизиты(НовыеРеквизиты);
ШаблонЗапроса =
"ВЫБРАТЬ
| Таблица.Ссылка
|ИЗ
| &Таблица КАК Таблица
|ГДЕ
| &Отбор = &ЗначениеКритерияОтбора";
ТекстЗапроса = "";
МассивЗапросов = Новый Массив;
ДанныеСвязанныхДокументов = СтруктураПодчиненностиСлужебный._ПолучитьДанныеСвязанныхДокументов();
Для каждого ДанныеПоОбъектуМетаданных Из ДанныеСвязанныхДокументов Цикл
ЭтаФорма._ДанныеСвязанныхДокументовМетаданные.Добавить(ДанныеПоОбъектуМетаданных.ПолноеИмя);
МетаданныеДерево = СтрРазделить(ДанныеПоОбъектуМетаданных.ПолноеИмя, ".");
ЭтаФорма._ДанныеСвязанныхДокументовТипы.Добавить(Тип(МетаданныеДерево[0] + "Ссылка." + МетаданныеДерево[1]));
ТаблицаМассив = Новый Массив;
ТаблицаМассив.Добавить(МетаданныеДерево[0]);
ТаблицаМассив.Добавить(МетаданныеДерево[1]);
//Если это реквизит ТЧ
Если МетаданныеДерево.Количество() = 6 Тогда
ТаблицаМассив.Добавить(МетаданныеДерево[3]);
КонецЕсли;
ТекстЗапроса = СтрЗаменить(ШаблонЗапроса, "&Таблица", СтрСоединить(ТаблицаМассив, "."));
ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&Отбор", "Таблица." + МетаданныеДерево[МетаданныеДерево.ВГраница()]);
МассивЗапросов.Добавить(ТекстЗапроса);
КонецЦикла;
ЭтаФорма._ДанныеСвязанныхДокументовТекстЗапроса = СтрСоединить(МассивЗапросов, Символы.ПС + "ОБЪЕДИНИТЬ" + Символы.ПС);
КонецЕсли;
КонецПроцедуры
В функции ОбъектыПоКритериюОтбора():
- проверку принадлежности типа критерию отбора заменим на функцию _СвязанныеДокументыСодержитТип();
- дополним текст запроса поиска по объектам метаданных текстом запроса с добавленными объектами метаданных в функции _СоставСвязанныеДокументы() общего модуля СтруктураПодчиненностиСлужебный.
&НаСервере
&ИзменениеИКонтроль("ОбъектыПоКритериюОтбора")
Функция _ОбъектыПоКритериюОтбора(ЗначениеКритерияОтбора)
#Удаление
Если Не Метаданные.КритерииОтбора.СвязанныеДокументы.Тип.СодержитТип(ТипЗнч(ЗначениеКритерияОтбора)) Тогда
#КонецУдаления
#Вставка
Если Не СвязанныеДокументыСодержитТип(ТипЗнч(ЗначениеКритерияОтбора)) Тогда
#КонецВставки
Возврат Неопределено;
КонецЕсли;
УстановитьПривилегированныйРежим(Истина);
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| СвязанныеДокументы.Ссылка
|ИЗ
| КритерийОтбора.СвязанныеДокументы(&ЗначениеКритерияОтбора) КАК СвязанныеДокументы";
#Вставка
Если ЗначениеЗаполнено(ЭтаФорма._ДанныеСвязанныхДокументовТекстЗапроса) Тогда
МассивЗапросов = Новый Массив;
Если ЗначениеКритерияОтбора.Метаданные().РасширениеКонфигурации() = Неопределено Тогда
МассивЗапросов.Добавить(Запрос.Текст);
КонецЕсли;
МассивЗапросов.Добавить(ЭтаФорма._ДанныеСвязанныхДокументовТекстЗапроса);
Запрос.Текст = СтрСоединить(МассивЗапросов, Символы.ПС + "ОБЪЕДИНИТЬ" + Символы.ПС);
КонецЕсли;
#КонецВставки
Запрос.УстановитьПараметр("ЗначениеКритерияОтбора", ЗначениеКритерияОтбора);
Возврат Запрос.Выполнить().Выгрузить();
КонецФункции
&НаСервере
Функция _СвязанныеДокументыСодержитТип(Тип)
Если Метаданные.КритерииОтбора.СвязанныеДокументы.Тип.СодержитТип(Тип) Тогда
Возврат Истина
Иначе
ТипНайден = Не ЭтаФорма._ДанныеСвязанныхДокументовТипы.НайтиПоЗначению(Тип) = Неопределено;
Возврат ТипНайден
КонецЕсли;
КонецФункции
И последним пунктом нужно изменить тип реквизитов на Произвольный формы "СвязанныеДокументы", в которых будут содержатся ссылки объектов.
В итоге были изменены: 1 процедура, 1 функция и 4 реквизита. Ни один новый объект метаданных не был добавлен в расширение. Такая реализация позволяет добавлять в отчет "Связанные документы" объекты метаданных из основной конфигурации и любых расширений одной строкой. Теперь, как и раньше, необходимо изменить только "состав" критерия отбора (функцию _СоставСвязанныеДокументы()
в СтруктураПодчиненностиСлужебный).
Буду рад вашим предложениям по улучшению получившегося функционала.
Тестировал на УТ 11.5.8.410, платформа 8.3.23.1739.
UPD 31.10.2023: Благодарю tedweb за дополнение в комментариях. Доработал функционал для большей универсальности. Теперь новые объекты метаданных к механизму "Связанные документы" подключаются полностью программно. Все кто уже скачал расширение могут написать в личку и я вышлю вам новое расширение.