Как расширять запрос в динамических списках на управляемой форме в 1C ЗУП 3.1

Постановка задачи
Задача чисто фантазийная, с целью подвести обучаемого к источнику проблемы и показать способ её решения!
Дано: при доработке в ЗУП документа "Командировка" решили сохранять в отдельном регистре сведений страну, если сотрудник направляется в зарубежную командировку. Вся разработка ведётся в расширении, этот регистр в упрощенном виде выглядит примерно так:

Задача: добавить поле "Страна" в список доступных полей в форме журнала документов командировок.
Простое решение "в лоб"
Если мы откроем форму журнала документов "Командировки", то увидим, что источником таблицы формы является динамический список с произвольным запросом:

Копируем текст запроса, вносим в него лёгкую модификацию, добавив левое соединение и меняем программно в расширении:
&НаСервере
Процедура Расш1_ПриСозданииНаСервереПосле(Отказ, СтандартнаяОбработка)
Расш1_ДинамическийСписокМодификация();
Расш1_ПрограммноеСозданиеЭлементовФормы();
КонецПроцедуры
&НаСервере
Процедура Расш1_ДинамическийСписокМодификация()
Список.ТекстЗапроса = "ВЫБРАТЬ
| ЖурналДокументовКомандировки.Ссылка КАК Ссылка,
| ЖурналДокументовКомандировки.Дата КАК Дата,
| НАЧАЛОПЕРИОДА(ЖурналДокументовКомандировки.Дата, ДЕНЬ) КАК ДатаДокумента,
| ЖурналДокументовКомандировки.ПометкаУдаления КАК ПометкаУдаления,
| ЖурналДокументовКомандировки.Номер КАК Номер,
| ЖурналДокументовКомандировки.Проведен КАК Проведен,
| ЖурналДокументовКомандировки.Месяц КАК Месяц,
| ЖурналДокументовКомандировки.Сотрудник КАК Сотрудник,
| ЖурналДокументовКомандировки.Организация КАК Организация,
| ЖурналДокументовКомандировки.Начало КАК Начало,
| ЖурналДокументовКомандировки.Окончание КАК Окончание,
| ЖурналДокументовКомандировки.Утвержден КАК Утвержден,
| ЖурналДокументовКомандировки.Ответственный КАК Ответственный,
| ЖурналДокументовКомандировки.Комментарий КАК Комментарий,
| ВЫБОР
| КОГДА НЕ ЖурналДокументовКомандировки.ПометкаУдаления
| И НЕ ЖурналДокументовКомандировки.Утвержден
| ТОГДА ИСТИНА
| ИНАЧЕ ЛОЖЬ
| КОНЕЦ КАК ТребуетОбработки,
| ЖурналДокументовКомандировки.Тип КАК Тип,
| ВЫБОР
| КОГДА НаличиеФайлов.ЕстьФайлы ЕСТЬ NULL
| ТОГДА 0
| КОГДА НаличиеФайлов.ЕстьФайлы
| ТОГДА 1
| ИНАЧЕ 0
| КОНЕЦ КАК ЕстьФайлы,
| NULL КАК СостояниеОригиналаПервичногоДокумента,
| ИСТИНА КАК ОбщееСостояние,
| 0 КАК СостояниеОригиналПолучен,
| Расш1_НаправленияКомандировок.Страна КАК Страна
|ИЗ
| ЖурналДокументов.Командировки КАК ЖурналДокументовКомандировки
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.НаличиеФайлов КАК НаличиеФайлов
| ПО ЖурналДокументовКомандировки.Ссылка = НаличиеФайлов.ОбъектСФайлами
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Расш1_НаправленияКомандировок КАК Расш1_НаправленияКомандировок
| ПО ЖурналДокументовКомандировки.Ссылка = Расш1_НаправленияКомандировок.Командировка
|{ГДЕ
| (ИСТИНА В
| (ВЫБРАТЬ ПЕРВЫЕ 1
| ИСТИНА
| ИЗ
| РегистрСведений.СоставДокументовЗарплатаКадры КАК СоставДокументовЗарплатаКадры
| ГДЕ
| СоставДокументовЗарплатаКадры.ФизическоеЛицо = &ФизическоеЛицо
| И ЖурналДокументовКомандировки.Ссылка = СоставДокументовЗарплатаКадры.ДокументФизическогоЛица)) КАК Поле2}";
КонецПроцедуры
&НаСервере
Процедура Расш1_ПрограммноеСозданиеЭлементовФормы()
Расш1_Страна = Элементы.Добавить("расш1_Страна", Тип("ПолеФормы"), Элементы.Список);
Расш1_Страна.ПутьКДанным = "Список.Страна";
Расш1_Страна.Заголовок = "Страна";
КонецПроцедуры
Цель достигнута, получаем вполне рабочее решение (в данный момент времени).
Что же может пойти не так?
Спустя какое-то время HR подключил к ЗУП сервис "Кабинет Сотрудника" и отправил туда на ознакомление подписанный приказ:

И тут при попытке открыть список командировок начинаются довольно странные проблемы. Казалось бы, причём тут печатная форма, мы к ней вообще не прикасались? Первым делом конечно не глядя выносят вердикт что накосячили в типовой в обновлении:

Когда выясняется, что виновата всё-таки доработка, то отладчиком обнаруживается, что текст запроса изменился после вызова этого фрагмента кода, который, к слову, обнаруживается глобально почти во всех списочных формах кадровых документов ЗУП в процедуре ПриСозданииНаСервере():
// КадровыйЭДО
КадровыйЭДО.ПриСозданииНаСервереФормыСписка(ЭтотОбъект, Список);
// Конец КадровыйЭДО
После этого в запросе и появляются эти загадочные поля с именами печатных форм. Заглянем в процедуру, и обнаружим там прекрасный пример работы с "программным интерфейсом" любимого всеми конструктора запросов:
Схема = Новый СхемаЗапроса();
Схема.РежимКомпоновкиДанных = Истина;
Схема.УстановитьТекстЗапроса(Список.ТекстЗапроса);
...
Исправленное и улучшенное решение
Мы бы конечно могли перехватить в отладчике уже модифицированный КЭДО запрос, скопировать и дополнить в конфигураторе уже его, и получить вполне рабочее решение. Но, вероятно, это будет снова короткоживущая доработка - до первого существенного обновления функционала ЗУП.
Для качественного решения нам не остается другого пути, кроме как пойти стопами разработчиков ЗУПа. Скопируем из вышеуказанной процедуры общего модуля КЭДО куски кода и добавим источник с левым соединением, по образу и подобию:
&НаСервере
Процедура Расш1_ДинамическийСписокМодификация()
Схема = Новый СхемаЗапроса();
Схема.РежимКомпоновкиДанных = Истина;
Схема.УстановитьТекстЗапроса(Список.ТекстЗапроса);
Пакет = Схема.ПакетЗапросов[Схема.ПакетЗапросов.Количество() - 1];
Оператор = Пакет.Операторы[0];
Оператор.Источники.Добавить("РегистрСведений.Расш1_НаправленияКомандировок", "Расш1_НаправленияКомандировок");
ИсточникЖурналДокументовКомандировки = Оператор.Источники[0];
ИсточникЖурналДокументовКомандировки.Соединения.Добавить(
"Расш1_НаправленияКомандировок",
"ЖурналДокументовКомандировки.Ссылка = Расш1_НаправленияКомандировок.Командировка");
НовСоединение = ИсточникЖурналДокументовКомандировки.Соединения.НайтиПоПсевдониму("Расш1_НаправленияКомандировок");
НовСоединение.ОбязательноеСоединение = Истина;
НовСоединение.ТипСоединения = ТипСоединенияСхемыЗапроса.ЛевоеВнешнее;
Оператор.ВыбираемыеПоля.Добавить("Расш1_НаправленияКомандировок.Страна");
Пакет.Колонки[Оператор.ВыбираемыеПоля.Количество() - 1].Псевдоним = "Страна";
Список.ТекстЗапроса = Схема.ПолучитьТекстЗапроса();
КонецПроцедуры
К сожалению, качественной документации с полными примерами для интерфейса СхемаЗапроса я не нашёл, хотя честнее будет сказать что просто поленился искать. Как у меня получилось? Просто раскрыл отладчиком объект СхемаЗапроса и заглянул в каждый его уголок. Если вам нужно программно соорудить более сложный запрос, чем с левым соединением, то рекомендую загрузить в объект пример готового целевого запроса и заскринить подробный состав схемы в отладчике. Думаю, это самый быстрый и лёгкий способ изучения.
Частное мнение
Надо ли таким способом создавать новые запросы? НЕТ, кроме случаев разработки собственной консоли запросов, или какого-то генератора мега-запросов на все случаи жизни.
Можно ли таким способом модифицировать готовые запросы? ДА, если иного выхода нет.