Организационная структура

Организационная структура (Оргструктура, структура компании) – это организационная схема, которая показывает отношения между подразделениями компании, а также распределяет роли (руководитель-подчиненный)в ней. Многие инструменты Битрикс24 работают, основываясь на структуре компании. Так, например, только руководители видят отчёты подчиненных и время, которое они отработали за определенный период. Настраивая права доступа, вы можете дать права не отдельным сотрудникам, а сразу распределить их по отделам. Так сотрудники будут видеть только нужную информацию, не будут отвлекаться на посторонний шум, а также не будут иметь доступа к конфиденциальной информации.

В формировании организационной структуры участвую 2 структурные единицы - Подразделение и Сотрудник. В данной статье мы будем рассматривать работу “Подразделений”

Архитектура

Подразделения представляю собой древовидный классификатор построенный на базе разделов информационного блока “Оргструктура”. На одном портале может быть только одно корневое подразделение. В отличие от Отсутствий информационный блок для Оргструктуры единый для всего портала.

Каждое подразделение характеризуется следующими свойствами:

  • Активность (Да/Нет)
  • Название подразделения (строка)
  • Руководитель (привязка к сотруднику)
  • Вышестоящее подразделение: (привязка к разделам инфоблока Оргструктуры)

Дополнительно, каждое подразделение (раздел инфоблока) имеет следующие свойства:

  • Учет рабочего времени
  • Максимальное время начала рабочего дня
  • Минимальное время завершения рабочего дня
  • Минимальная продолжительность рабочего дня
  • Отчет за день
  • Шаблоны отчета
  • Свободный график

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

API

Поскольку организационная структура построена на базе разделов информационного блока “Оргструктура”, API для CRUD-действий аналогичной работе с инфоблоками. Перед началом работы с API инфоблоков нужно получить идентификатор инфоблока для конкретного сайта. Они хранятся в настройках (b_options, b_option_site) с кодом модуля intranet и названием iblock_structure

use \Bitrix\Main\Config\Option;

// General (default)
$iblockId = Option::get('intranet', 'iblock_structure', '-1');

// Specific site absence iblock id
$siteCo1StructureId = Option::get('intranet', 'iblock_structure', '-1', 'co1');

// Old api
$iblockId = \COption::GetOptionInt('intranet', 'iblock_structure', -1);

Обратите внимание на трюк со значением по-умолчанию -1. Дело в том что при работе с инфоблоками пустое значение (равное нулю) в getList будет проигнорировано. Этот трюк позволяет не беспокоиться в случае технической ошибки и снизить ущерб.

Обратите внимание: в Битрикс24 модуль intranet автоматически подключен к порталу, поэтому методы интранета можно вызывать без подключения модуля

Получение дерева

Несмотря на то что архитектурно дерево подразделений устроено на базе информационных блоков, работать с чтением напрямую из инфоблока не рекомендуется и нет такой необходимости. Существует метод для получения объемного и полного дерева подразделений - CIntranetUtils::GetStructure().

Пример возвращаемой структуры:

/**
 * @var array Cached structure
 */
$structure = \CIntranetUtils::GetStructure();

/**
 * The same as:
 */
$structure = [
    "TREE" => [
        0 => ["1"],
        1 => ["2", "4", "3"]
    ],
    "DATA" => [
        1 => [
            "ID"                => "1",
            "NAME"              => "DEMO",
            "IBLOCK_SECTION_ID" => 0,
            "UF_HEAD"           => NULL,
            "SECTION_PAGE_URL"  => "#SITE_DIR#company/structure.php?set_filter_structure=Y&structure_UF_DEPARTMENT=#ID#",
            "DEPTH_LEVEL"       => "1",
            "EMPLOYEES"         => ["1"]
        ],
        2 => [
            "ID"                => "2",
            "NAME"              => "Бухгалтерия",
            "IBLOCK_SECTION_ID" => "1",
            "UF_HEAD"           => NULL,
            "SECTION_PAGE_URL"  => "#SITE_DIR#company/structure.php?set_filter_structure=Y&structure_UF_DEPARTMENT=#ID#",
            "DEPTH_LEVEL"       => "2",
            "EMPLOYEES"         => ["3"]
        ],
        4 => [
            "ID"                => "4",
            "NAME"              => "Отдел маркетинга и рекламы",
            "IBLOCK_SECTION_ID" => "1",
            "UF_HEAD"           => NULL,
            "SECTION_PAGE_URL"  => "#SITE_DIR#company/structure.php?set_filter_structure=Y&structure_UF_DEPARTMENT=#ID#",
            "DEPTH_LEVEL"       => "2",
            "EMPLOYEES"         => []
        ],
        3 => [
            "ID"                => "3",
            "NAME"              => "Отдел продаж",
            "IBLOCK_SECTION_ID" => "1",
            "UF_HEAD"           => NULL,
            "SECTION_PAGE_URL"  => "#SITE_DIR#company/structure.php?set_filter_structure=Y&structure_UF_DEPARTMENT=#ID#",
            "DEPTH_LEVEL"       => "2",
            "EMPLOYEES"         => ["4"]
        ],
    ],
];

CIntranetUtils::GetStructure() всегда возвращает структуру из двух элементов:

  • Ключ THREE - содержит ассоциативный массив, где ключи это ID родительского подразделения, а значения это массив из ID вложенных подразделений
  • Ключ DATA - содержит ассоциативный массив, где ключи это идентификаторы подразделений, а значения это структура описывающая подразделение

Разберем структуру ключа DATA:

  • ID (string) - строковое представление идентификатора подразделения
  • NAME (string) - название подразделения
  • IBLOCK_SECTION_ID (int|string) - 0 или строковое представление идентификатора родительского подразделения
  • UF_HEAD (null|string) - null или строковое представление идентификатора сотрудника который является руководителем подразделения
  • SECTION_PAGE_URL (string) - шаблон ссылки на детальную страницу подразделения.
  • DEPTH_LEVEL (string) - Уровень вложенности подразделения (от 1 и выше)
  • EMPLOYEES (array) - Массив строковых представлений идентификаторов сотрудников которые входят в данное подразделение

Дочерние подразделения

Существует несколько способов получить дочерние подразделения для указанного.

Массовый способ: если у вас есть список подразделений и вам нужно получить общий список всех вложенных подразделений, то лучше воспользоваться методом CIntranetUtils::GetIBlockSectionChildren($arSections), где $arSections - массив идентификаторов подразделений. Метод использует запросы в цикле, поэтому старайтесь избегать большого количества подразделений в списке.

Пример поиска:


$searchSections = [1, 2, 3];

/**
 * @var array List of department ids
 */
$result = \CIntranetUtils::GetIBlockSectionChildren($searchSections);

/*
$result = [
    0 => 1,
    1 => 2,
    2 => 3,
    5 => 4
];
 */

Обратите внимание на измененный порядок ключей - он получается в результате комбинации array_unique + array_merge, когда подразделения 2 и 3 вложенные в подразделение 1 были запрошены дополнительно. Никогда не опирайтесь на ключи этого метода

Точечный способ: если у вас есть конкретное подразделение и вы хотите получить либо дерево вложенных, либо плоскую структуру, то можете воспользоваться методом \CIntranetUtils::GetDeparmentsTree($section_id = 0, $bFlat = false).

Пример:

// Non flat

$result = \CIntranetUtils::GetDeparmentsTree(1);

/*
$result = [
    1 => ["2", "4", "3"]
];
 */

// Flat
$result = \CIntranetUtils::GetDeparmentsTree(1, true);
/*
$result = ["2", "4", "3"];
 */

Обратите внимание на вывод в зависимости от параметра $bFlat

Сотрудники подразделения

Для получения списка сотрудников подразделения можно воспользоваться методом: \Bitrix\Intranet\Util::getDepartmentEmployees( $params ). Структура $params представляет собой ассоциативный массив, который состоит из следующих ключей:

  • DEPARTMENTS (array) - список идентификаторов подразделений, для которых выполняется поиск
  • RECURSIVE (string) - Y / N (по-умолчанию N) - нужно ли вычислять сотрудников вложенных подразделений
  • ACTIVE (string) - Y / N включать в список только действующих сотрудников (флаг активности = да)
  • SKIP (int) - идентификатор сотрудника, которого не нужно включать в список.
  • SELECT (array) - набор полей, которые нужно запросить из базы данных

Результатом работы метода будет наследник CDBResult, который можно итерировать. Пример:

use \Bitrix\Intranet\Util;

$resUsers = Util::getDepartmentEmployees([
    'DEPARTMENTS' => [1],
    'RECURSIVE'   => 'N',
]);

while( $arUser = $resUsers->fetch() )
{
    var_dump($arUser);
}

В настоящий момент функция CIntranetUtils::getDepartmentEmployees($arDepartments, $bRecursive = false, $bSkipSelf = false, $onlyActive = 'Y', $arSelect = null) которая оставлена для обратной совместимости и является прокси-функцией в исходную \Bitrix\Intranet\Util::getDepartmentEmployees и ее использование не рекомендуется.

Полезная литература

Структура компании Связь структуры компании с инструментами Битрикс24