Как доработать структуру подчиненности документов в 1С:Управление торговлей 10.3

Программист 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В типовой конфигурации «Управление торговлей 10.3» пользователи часто сталкиваются с тем, что дерево связей между документами (структура подчиненности) отображается не в полном объеме. Особенно остро эта проблема встает при создании документов на основании тех типов, для которых в типовом решении связи не прописаны жестко. Например, при вводе ПеремещениеТоваров на основании другого перемещения связь может отображаться только «вниз» или не отображаться вовсе. Рассмотрим подробно, как работает этот механизм и как его можно доработать под свои нужды.

Принцип работы структуры подчиненности в УТ 10.3

Прежде чем приступать к коду, проанализируем, на чем базируется построение дерева в обычном приложении. В отличие от современных решений на управляемых формах, где часто используются регистры сведений, в 10.3 задействованы два основных механизма:

  1. Критерии отбора: В конфигураторе существует объект КритерииОтбора.СвязанныеДокументы. Он определяет, по каким реквизитам платформа должна искать связи.
  2. Общая форма структуры подчиненности: Динамически строит дерево, используя данные критериев отбора и рекурсивный обход документов.

Если вы добавили новый реквизит (например, ДокументОснование) и заполнили его, но документ не появился в дереве — скорее всего, вы забыли включить этот реквизит в состав критерия отбора или алгоритм формы не видит корень цепочки.

Шаг 1. Подготовка метаданных и заполнение основания

Для начала разберем ситуацию, когда нам нужно связать документы типа ПеремещениеТоваров между собой. Рассмотрим процедуру ОбработкаЗаполнения в модуле объекта документа. Нам необходимо убедиться, что ссылка на документ-родитель записывается в соответствующий реквизит.

Если у документа нет стандартного реквизита для связи, добавим реквизит ДокументОснование с типом СоставнойТип (включающий нужные нам типы документов) и пропишем код заполнения:


Процедура ОбработкаЗаполнения(Основание)
    Если ТипЗнч(Основание) = Тип("ДокументСсылка.ПеремещениеТоваров") Тогда
        // Заполнение данных из родительского перемещения
        ДокументОснование = Основание.Ссылка;
    ИначеЕсли ТипЗнч(Основание) = Тип("ДокументСсылка.ПоступлениеТоваровУслуг") Тогда
        ДокументОснование = Основание.Ссылка;
    КонецЕсли;
КонецПроцедуры

Важный момент: Чтобы платформа автоматически подхватывала эту связь, зайдите в Конфигуратор, найдите КритерииОтбора.СвязанныеДокументы и на вкладке «Состав» отметьте созданный вами реквизит ДокументОснование у документа ПеремещениеТоваров.

Шаг 2. Программная доработка формы структуры подчиненности

Иногда настройки критериев отбора недостаточно, особенно если требуется специфический вывод или если дерево отображается только в одну сторону. Рассмотрим ситуацию: когда мы стоим на «нижнем» документе, мы видим цепочку вверх, но когда стоим на «верхнем» — не видим подчиненные. Выясним причину: стандартный механизм может не всегда корректно определять связи, если они не являются типовыми.

Проанализируем решение, связанное с модификацией общей формы ФормаСтруктурыПодчиненности. Нам необходимо добавить процедуру, которая будет принудительно искать документы, где в поле ДокументОснование указана ссылка на текущий документ.

Добавим в модуль формы следующую процедуру:


Процедура ВывестиПоОснованию(СтрокаДерева)
    ТекущийДокумент = СтрокаДерева.Ссылка;
    СписокДокументов = Новый СписокЗначений;

    // Поиск документов, в которых есть реквизит ДокументОснование
    Для Каждого Док Из Метаданные.Документы Цикл
        Если Док.Реквизиты.Найти("ДокументОснование") <> Неопределено Тогда
            Если Док.ВводитсяНаОсновании.Содержит(Метаданные.НайтиПоТипу(ТипЗнч(ТекущийДокумент))) Тогда
                СписокДокументов.Добавить(Док.Имя);
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;

    Для Каждого Стр Из СписокДокументов Цикл
        Запрос = Новый Запрос;
        Запрос.УстановитьПараметр("ИскомаяСсылка", ТекущийДокумент);
        Запрос.Текст = "ВЫБРАТЬ
                       |    Т.Ссылка КАК Ссылка,
                       |    Т.Проведен КАК Проведен,
                       |    Т.ПометкаУдаления КАК ПометкаУдаления
                       |ИЗ
                       |    Документ." + Стр.Значение + " КАК Т
                       |ГДЕ
                       |    Т.ДокументОснование = &ИскомаяСсылка";
        
        Выборка = Запрос.Выполнить().Выбрать();
        Пока Выборка.Следующий() Цикл
            Если мУжеВСписке[Выборка.Ссылка] = Неопределено Тогда
                НоваяСтрока = СтрокаДерева.Строки.Добавить();
                НоваяСтрока.Ссылка = Выборка.Ссылка;
                НоваяСтрока.ДокументПредставление = Строка(Выборка.Ссылка);
                НоваяСтрока.Проведен = Выборка.Ссылка.Проведен;
                НоваяСтрока.ПометкаУдаления = Выборка.Ссылка.ПометкаУдаления;
                мУжеВСписке.Вставить(Выборка.Ссылка, Истина);
            КонецЕсли;
        КонецЦикла;
    КонецЦикла;
КонецПроцедуры

Обратите внимание: Выполнение запроса внутри цикла (Для Каждого Стр Из СписокДокументов) — это ресурсозатратная операция. В крупных базах рекомендуется предварительно собрать имена всех таблиц и объединить их в один запрос через ОБЪЕДИНИТЬ ВСЕ.

Шаг 3. Внедрение вызовов в алгоритм построения дерева

Чтобы наша новая процедура заработала, внесем изменения в типовые процедуры формы. Нам нужно модифицировать ВывестиДеревоДокументов и ВывестиПодчиненныеДокументы.

В процедуре ВывестиДеревоДокументов добавим вызов после отрисовки родительских веток:


Процедура ВывестиДеревоДокументов()
    Попытка
        ДеревоДокументов.Строки.Очистить();
        мДерево = ДеревоДокументов;
        мУжеВСписке.Очистить();
        
        ВывестиРодительскиеДокументы(ДокументСсылка);
        ЭлементыФормы.ДеревоДокументов.ТекущаяСтрока = мДерево;
        
        // Наш допиленный вызов
        ВывестиПоОснованию(мДерево); 
        
        ВывестиПодчиненныеДокументы(мДерево);
        
        // Повторный вызов для полной глубины дерева
        ВывестиПоОснованию(мДерево); 
    Исключение
        // Обработка ошибок
    КонецПопытки;
КонецПроцедуры

Также не забудем вызвать нашу функцию внутри рекурсии ВывестиПодчиненныеДокументы, чтобы дерево раскрывалось на всю глубину связей.

Упрощенное решение проблемы «однобокости»

Проанализируем более простой вариант решения проблемы, когда дерево не показывает всю структуру при открытии из документа-наследника. Часто проблема заключается в том, что алгоритм «поднимается» к родителям, но «забывает» отрисовать их других детей.

Достаточно добавить одну строку в конец процедуры ВывестиРодительскиеДокументы(ДокументСсылка):


// В самом конце процедуры ВывестиРодительскиеДокументы
ВывестиПодчиненныеДокументы(СтрокаДерева);

Это заставит механизм после нахождения самого верхнего родителя заново запустить процесс поиска всех подчиненных ему документов, что эффективно «развернет» дерево во все стороны, независимо от того, из какой точки цепочки оно было вызвано.

Рекомендации по оптимизации

Рассмотрим несколько важных аспектов, которые помогут избежать ошибок при доработке структуры подчиненности:

Таким образом, доработка структуры подчиненности в УТ 10.3 сводится к правильной настройке состава критериев отбора и, при необходимости, к небольшому вмешательству в логику обхода дерева в общей форме. Это значительно повышает удобство работы бухгалтеров и менеджеров, позволяя им видеть полную картину товародвижения.

← На главную