Архитектура модуля и выбор сервиса

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

Готовые методы сервисов подходят для типовых задач: найти узел, получить участников или определить руководителя. Для выборки с несколькими условиями модуль предоставляет билдер — объект, который объединяет фильтры, направление и глубину обхода, сортировку и другие параметры. Связи объектов и различия между сервисами и билдерами помогают выбрать API для своей задачи.

Как связаны структура, узлы, участники и роли

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

Структура
└── Узел
    ├── Дочерний узел
    └── Участник
        ├── Пользователь
        └── Роль в узле

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

Как тип узла влияет на выборку

Узел — это объект Node, который представляет подразделение или команду в структуре компании. Узел хранит свое положение в дереве и относится к одному из типов:

  • DEPARTMENT — подразделение административной структуры,

  • TEAM — команда.

Тип узла определяет состав выборки и доступный сервис пользователей. Если запрос должен работать и с подразделениями, и с командами, передайте нужные типы в аргументе nodeTypes выбранного метода NodeService. Значение по умолчанию зависит от метода. Например, findAll() выбирает подразделения, а findChildrenByNodeIds() — подразделения и команды.

Корневой узел служит точкой начала обхода структуры. Для остальных узлов можно запрашивать родителей, непосредственных детей или потомков на заданную глубину. О способах поиска и обхода читайте в статье Узлы структуры компании.

Как участник связывает пользователя с узлом

Пользователь и участник структуры — разные объекты. Пользователь представляет учетную запись, а объект NodeMember — связь пользователя с конкретным узлом. Один пользователь может состоять в нескольких узлах и иметь отдельную роль в каждой связи.

Роль определяет положение участника внутри узла. Через роли API различает руководителя, заместителя и сотрудника. Для поиска состава узла, связей пользователя и участников с нужной ролью используйте сервисы участников. Подробные сценарии приведены в статье Участники и роли в структуре компании.

Что возвращают сервисы

Сервисы возвращают отдельные объекты Node и NodeMember, коллекции этих объектов или массивы. Формат результата и способ его проверки зависят от конкретного метода.

Результат

Когда используется

Как проверять

Node

Найден один узел

Проверить результат на null, если метод допускает отсутствие узла

NodeCollection

Найден набор узлов

Проверить количество элементов или перебрать коллекцию

NodeMember

Найдена одна связь пользователя с узлом

Проверить результат на null, если связь может отсутствовать

NodeMemberCollection

Найден набор связей участников

Проверить количество элементов или перебрать коллекцию

Индексированный массив

Метод возвращает список идентификаторов или объектов

Проверить массив на пустоту и учитывать порядок, если метод сохраняет порядок элементов

Ассоциативный массив

Результат сгруппирован или индексирован по идентификатору

Обращаться к значению по ключу и проверять наличие ключа

Не заменяйте проверку null проверкой пустой коллекции. Иначе код может принять отсутствие одного объекта за результат множественной выборки или вызвать метод коллекции у значения null.

Выбор сервиса

После подключения модуля humanresources получайте сервисы через Bitrix\HumanResources\Public\Service\Container. Выбирайте сервис по исходному объекту и ожидаемому результату. Общие сервисы работают с узлами и связями, а сервисы подразделений и команд — с соответствующей управленческой иерархией.

Задача

Метод контейнера

Сервис

Найти узел, корневой узел, родителей или потомков

getNodeService()

NodeService

Найти связи участников по узлам, пользователям или ролям

getNodeMemberService()

NodeMemberService

Связать выборку пользователей с данными их узлов

getUserService()

Общий Node\UserService

Проверить роль пользователя, получить руководителей, подчиненных или управляемые узлы в административной структуре

getUserDepartmentService()

Department\UserService

Проверить роль пользователя, получить руководителей, подчиненных, управляемые узлы или цепочки команд

getUserTeamService()

Team\UserService

Прочитать настройки полномочий узлов

getNodeSettingsService()

NodeSettingsService

Получить настройки или исключения пользователя

getUserSettingsService()

UserSettingsService

Для фильтрации через NodeService передайте параметр structureAction в метод, который принимает этот параметр. Значение null отключает фильтр по действию. Подходящий метод выберите в разделе Настроить выборку под задачу.

Для составной выборки добавьте в билдер NodeAccessFilter. Параметры фильтра описаны в разделе Ограничить выборку правами пользователя.

Сервисы подразделений и команд не взаимозаменяемы: каждый из них предоставляет операции для своего типа узла. Общий Node\UserService используйте для связей пользователя с узлами, когда логика не зависит от типа узла.

Как выбрать между сервисом и билдером

Сервис выполняет типовую операцию и заранее определяет входные данные и формат результата. Выбирайте сервис, если один метод возвращает нужный узел, связи участников, управленческую иерархию или настройки.

Билдер формирует составную выборку. Используйте NodeDataBuilder для узлов и NodeMemberDataBuilder для связей участников, если нужно объединить несколько условий:

  • тип и идентификаторы узлов,

  • направление и глубину обхода иерархии,

  • активность и доступное действие,

  • роли и идентификаторы пользователей,

  • пагинацию, набор полей и сортировку.

Билдеры возвращают те же объекты Node, NodeMember и соответствующие коллекции. О составе фильтров и примерах читайте в статье Выборки узлов и участников через билдеры.

Как читать данные от узла и от пользователя

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

От узла к участникам

Начинайте с узла, если известны подразделение или команда. Сначала получите объект Node через NodeService, затем запросите связи участников через NodeMemberService, Department\UserService или Team\UserService.

Такое направление подходит для следующих задач:

  • получить состав подразделения или команды,

  • отобрать участников по роли,

  • найти руководителя узла,

  • перейти к дочерним узлам и собрать данные по части дерева.

От пользователя к узлам

Начинайте с пользователя, если нужно определить его положение в структуре. Общий Node\UserService находит связи пользователя с узлами. Сервисы подразделений и команд дополняют этот сценарий операциями управленческой иерархии.

Такое направление подходит для следующих задач:

  • получить узлы пользователя,

  • определить его роль в узле,

  • найти руководителей или подчиненных,

  • получить узлы, которыми пользователь управляет,

  • построить цепочку управленческих связей.

О сценариях для руководителей, подчиненных и назначения сотрудников читайте в статье Пользователи и управленческая иерархия.

Как значения по умолчанию меняют результат

Значения по умолчанию могут сузить результат без ошибки. Задавайте параметры явно, если стандартное поведение не соответствует сценарию.

В таблицах ниже методы без имени класса относятся к NodeService.

Типы узлов

Метод

Значение по умолчанию

Когда задать явно

Параметр nodeTypes

findAll() и findAllByMemberEntityId()

[NodeEntityType::DEPARTMENT]

Когда нужны команды или оба типа узлов

findChildrenByNodeIds()

[NodeEntityType::DEPARTMENT,
NodeEntityType::TEAM]

Когда нужен только один тип узла

findParentsByNodeId()

null

Когда автоматический выбор типов по исходному узлу не подходит

findAllByAccessCodes()

null

Когда выборку нужно ограничить подразделениями или командами

Активность

Метод

Значение по умолчанию

Когда задать явно

Параметр activeFilter

findAll(), findAllByAccessCodes() и findChildrenByNodeIds()

NodeActiveFilter::ONLY_GLOBAL_ACTIVE

Когда нужны узлы с другим состоянием активности

Параметр nodeActiveFilter

findAllByMemberEntityId()

NodeActiveFilter::ONLY_GLOBAL_ACTIVE

Когда нужны узлы с другим состоянием активности

Параметр active

NodeMemberFilter

true

Передайте null, чтобы отключить фильтр активности связей

Глубина обхода и структура

Метод

Значение по умолчанию

Когда задать явно

Параметр depthLevel

findParentsByNodeId() и findChildrenByNodeIds()

DepthLevel::FIRST

Когда нужна цепочка глубже ближайшего уровня

findAllByName()

DepthLevel::FULL

Когда поиск нужно ограничить частью ветви

Параметр structureId

NodeFilter

null

Передайте идентификатор, если запрос должен работать с конкретной структурой

Полные наборы параметров приведены в разделах Настроить выборку под задачу, Задать фильтр узлов и Задать фильтр участников. Рекомендации по объему результата читайте в статье Производительность и частые ошибки.

Ограничения публичного API

Публичный API модуля — классы и методы пространства имен Bitrix\HumanResources\Public. Сервисы из этого пространства выполняют типовые операции чтения. Некоторые сервисы также изменяют данные. Используйте такие операции, только когда в документации указан конкретный метод.

Публичный API не предоставляет универсальных методов для следующих операций:

  • создание, переименование, перемещение и удаление узлов,

  • произвольное изменение роли участника,

  • изменение состава команды,

  • выдача прав пользователю.

Билдеры пространства имен Bitrix\HumanResources\Builder\Structure не относятся к публичному API. Они входят в отдельный поддерживаемый API для составных выборок. Билдеры только читают данные: они не создают, не изменяют и не удаляют узлы, связи участников или роли.

Методы публичного API и билдеры используют объекты, типы и перечисления из других пространств имен модуля. Считайте их частью поддерживаемого контракта, только если они описаны в этом разделе как параметры, результаты или элементы выборки. Остальные классы относятся к внутренней реализации и могут изменяться без предупреждения.

Как выбрать способ обращения к API

  1. Определите исходный объект: структуру, узел, связь участника или пользователя.

  2. Выберите сервис для готовой операции или билдер для составной выборки.

  3. Вызовите нужный метод с учетом его значений по умолчанию.

  4. Проверьте тип результата: null, отдельный объект, коллекция или массив.

Такой порядок отделяет навигацию по дереву от работы с участниками и управленческой иерархией. Сервисы выполняют типовые задачи, а билдеры дополняют их составными выборками. Исходные данные определяют способ обращения к API, а формат результата — способ проверки.