При работе с иерархическими структурами данных в 1С, особенно когда речь идет о связях между партнерами и их контрагентами, часто возникает задача получить не только непосредственные связи, но и учесть всю родительскую иерархию. Представьте ситуацию: у вас есть иерархический справочник партнеров, каждый из которых может быть связан с одним или несколькими контрагентами. При этом дочерние партнеры могут использовать контрагентов своих родительских партнеров.
Исходная структура данных может выглядеть следующим образом:
Партнер (Верхний уровень) - Контрагент1 (связан с Верхним Партнером) - ДочернийПартнер (подчинен Верхнему Партнеру) - (нет собственного связанного контрагента) - ВторойДочернийПартнер (подчинен ДочернемуПартнеру) - Контрагент2 (связан с ВторымДочернимПартнером)Цель состоит в том, чтобы сформировать выборку, которая для каждого партнера в этой иерархии показывала бы всех контрагентов, связанных как непосредственно с этим партнером, так и со всеми его родительскими партнерами. То есть, для приведенного примера мы хотим получить следующую таблицу:
Партнер (Верхний уровень) - Контрагент1ДочернийПартнер - Контрагент1ВторойДочернийПартнер - Контрагент1ВторойДочернийПартнер - Контрагент2Это может показаться сложной задачей, но в платформе 1С существуют эффективные механизмы для ее решения. Рассмотрим подробнее, как мы можем достичь желаемого результата.
Одним из наиболее эффективных и производительных способов решения данной задачи является использование служебного регистра сведений "ИерархияПартнеров". Этот регистр предназначен специально для работы с иерархическими данными справочника "Партнеры" и хранит их в так называемой плоской структуре. Это означает, что для каждого партнера в этом регистре уже записана информация обо всех его родителях по иерархии, включая самого партнера.
Преимущества использования "ИерархияПартнеров":
Партнер и Родитель, а также может иметь ресурс Уровень, который указывает на глубину вложенности партнера относительно его непосредственного родителя или корневого элемента иерархии.Давайте посмотрим на пример запроса, который позволяет нам получить желаемую выборку:
ВЫБРАТЬ
ИерархияПартнеров.Партнер КАК Партнер,
Контрагенты.Ссылка КАК Контрагент
ИЗ
РегистрСведений.ИерархияПартнеров КАК ИерархияПартнеров
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
ПО ИерархияПартнеров.Родитель = Контрагенты.Партнер
Разберем этот запрос по шагам:
РегистрСведений.ИерархияПартнеров, который хранит информацию о том, какой партнер (измерение Партнер) является потомком какого родителя (измерение Родитель). Важно понимать, что в данном регистре для каждого партнера есть запись, где Партнер равен Родитель (т.е. сам партнер является своим собственным "родителем" на уровне 0), а также записи со всеми его вышестоящими родителями.ВНУТРЕННЕЕ СОЕДИНЕНИЕ с таблицей Справочник.Контрагенты.ПО ИерархияПартнеров.Родитель = Контрагенты.Партнер. Это означает, что для каждого партнера из регистра иерархии мы ищем всех контрагентов, которые связаны с его родительскими элементами (включая самого партнера, если он является своим "родителем" в регистре). Таким образом, мы получаем список всех контрагентов, привязанных ко всей цепочке родителей, включая текущего партнера.Этот подход позволяет нам эффективно получить все необходимые данные для дальнейшего использования в отчетах СКД или в программном коде.
В некоторых случаях, особенно если необходимо получить потомков определенного "головного" партнера или если мы работаем в контексте динамического списка, где основной таблицей является Справочник.Партнеры, мы можем использовать оператор В ИЕРАРХИИ. Этот оператор полезен для получения всех подчиненных элементов иерархического справочника, включая сам заданный элемент. Однако, для решения нашей текущей задачи (получение контрагентов родителей) его прямое применение может быть менее очевидным, чем использование ИерархияПартнеров.
Тем не менее, мы можем использовать комбинацию подходов. Например, сначала получить всех партнеров, которые являются потомками заданного головного партнера, а затем уже связать их с контрагентами.
Рассмотрим пример, когда нам нужно получить всех партнеров, которые находятся в иерархии определенного головного партнера, а затем их контрагентов:
ВЫБРАТЬ
Партнеры.Ссылка КАК Партнер
ПОМЕСТИТЬ ВТ_ВсеПартнеры
ИЗ
Справочник.Партнеры КАК Партнеры
ГДЕ
Партнеры.Ссылка В ИЕРАРХИИ
(ВЫБРАТЬ
Иерархия.Родитель
ИЗ
РегистрСведений.ИерархияПартнеров КАК Иерархия
ГДЕ
Иерархия.Партнер = &ГоловнойПартнер
И Иерархия.Уровень = 0)
Разберем этот первый запрос:
ВТ_ВсеПартнеры, в которую помещаем ссылки на партнеров.ГДЕ Партнеры.Ссылка В ИЕРАРХИИ (...) мы используем оператор В ИЕРАРХИИ.РегистрСведений.ИерархияПартнеров запись, где Партнер = &ГоловнойПартнер и Уровень = 0 (это означает сам головной партнер как корневой элемент). Поле Родитель в этом случае будет ссылаться на самого себя, т.е. на &ГоловнойПартнер.&ГоловнойПартнер.Важно: Подход с В ИЕРАРХИИ целесообразно использовать, когда вам нужен весь набор потомков от определенной точки в иерархии, а не только контрагенты родителей. Для конкретной задачи из первого сообщения (контрагенты родителей) регистр ИерархияПартнеров в чистом виде (как в первом примере) более прямолинеен и эффективен, поскольку он уже содержит ссылки на всех родителей для каждого партнера.
После получения всех партнеров во временную таблицу, вы можете соединить ее со справочником контрагентов, чтобы получить их связи:
ВЫБРАТЬ
ВТ_ВсеПартнеры.Партнер КАК Партнер,
Контрагенты.Ссылка КАК Контрагент
ИЗ
ВТ_ВсеПартнеры КАК ВТ_ВсеПартнеры
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Контрагенты КАК Контрагенты
ПО ВТ_ВсеПартнеры.Партнер = Контрагенты.Партнер
Этот запрос покажет всех контрагентов, которые напрямую привязаны к каждому партнеру из выбранной иерархии. Однако, это не решает полностью исходную задачу, которая требует включения контрагентов родителей для дочерних партнеров. Для полной реализации исходной задачи все же лучше вернуться к первому запросу с прямым соединением ИерархияПартнеров.Родитель = Контрагенты.Партнер.
В случае, если это динамический список с основной таблицей Справочник.Партнеры, мы можем использовать регистр ИерархияПартнеров только для отбора, чтобы ограничить список партнеров, а затем уже использовать другие механизмы для получения контрагентов родителей.
В конфигурациях 1С, таких как 1С:ERP или 1С:Управление торговлей, существует функциональность, которая позволяет дочерним партнерам использовать контрагентов, привязанных к их головным (родительским) партнерам. Это реализуется через специальный флаг "Включая контрагентов-родителей".
Где находится флаг и для чего он нужен:
Этот флаг обычно расположен в карточке партнера, в разделе прикрепленных контрагентов (часто доступно по гиперссылке "Контрагенты"). Установка этого флага для дочернего партнера позволяет ему при оформлении документов (например, реализаций) выбирать в качестве контрагента любое юридическое или физическое лицо, которое привязано не только к самому дочернему партнеру, но и ко всем его родительским партнерам по иерархии. Это удобно, когда, например, филиалы или дочерние предприятия ведут деятельность от имени материнской компании, используя ее юридические реквизиты.
Программное создание и установка флага:
Если мы программно создаем подчиненного партнера (например, при переносе данных из внешней системы), нам также может потребоваться установить этот флаг. Для этого необходимо обратиться к соответствующим свойствам объекта Справочник.Партнеры. Конкретное свойство может варьироваться в зависимости от конфигурации, но обычно это булево свойство, которое управляет поведением наследования контрагентов. Возможно, потребуется использовать специальные методы или объекты, связанные с управлением контрагентами партнера, а не только базовые свойства справочника. В некоторых конфигурациях для этого может быть предусмотрен помощник по созданию партнеров, который автоматизирует установку таких параметров.
Регистр сведений ИерархияПартнеров – это ключевой элемент для работы с иерархиями в 1С без необходимости написания сложных рекурсивных запросов. Давайте рассмотрим его структуру подробнее:
Партнер: Ссылка на элемент справочника "Партнеры", который является потомком.Родитель: Ссылка на элемент справочника "Партнеры", который является предком (родителем) для данного Партнера. Важно, что для каждого партнера будет запись, где Партнер равен Родитель (т.е. сам партнер является своим собственным элементом в иерархии на уровне 0).Уровень: Числовое значение, указывающее на глубину вложенности. Уровень = 0 обычно означает, что Партнер равен Родителю (сам себе). Уровень = 1 означает непосредственного родителя, Уровень = 2 – родителя родителя и так далее.Предположим, у нас есть следующая иерархия:
А -> Б -> В
Тогда в регистре ИерархияПартнеров мы увидим следующие записи (упрощенно):
Партнер: А, Родитель: А, Уровень: 0Партнер: Б, Родитель: Б, Уровень: 0Партнер: Б, Родитель: А, Уровень: 1Партнер: В, Родитель: В, Уровень: 0Партнер: В, Родитель: Б, Уровень: 1Партнер: В, Родитель: А, Уровень: 2Именно эта плоская структура позволяет нам легко выполнять запросы, подобные рассмотренному выше, соединяя ИерархияПартнеров.Родитель с Контрагенты.Партнер, чтобы получить контрагентов всех предков.
В современных конфигурациях 1С (таких как 1С:ERP, 1С:Управление торговлей, 1С:Комплексная автоматизация) реализована концепция раздельного ведения справочников "Партнеры" и "Контрагенты". Разберем, зачем это сделано и как это влияет на работу с данными.
Связь между "Партнерами" и "Контрагентами":
Связь между этими двумя справочниками очень гибкая:
Такое разделение позволяет гибко настраивать аналитику управленческого учета, не привязываясь жестко к юридическим формам, которые используются в регламентированном учете. Иерархия в справочнике "Партнеры" является мощным инструментом для консолидированной отчетности и анализа бизнес-процессов.
При работе с иерархическими данными в 1С вопрос производительности всегда стоит остро, особенно на больших базах данных.
ИерархияПартнеров, является наиболее оптимальным решением для обеспечения высокой производительности. Они предварительно рассчитывают и хранят иерархию в плоском виде, что позволяет избежать сложных рекурсивных запросов и существенно ускоряет получение информации в отчетах СКД и других обработках.Выбор оптимального метода всегда зависит от конкретных требований к отчетности, структуры данных и производительности системы.