Skip to content

Commit

Permalink
Merge pull request #28 from gromdron/intranet_structure
Browse files Browse the repository at this point in the history
Intranet: structure
  • Loading branch information
gromdron authored Dec 25, 2023
2 parents 99bc46d + 312ac00 commit 8c6d57a
Showing 1 changed file with 213 additions and 0 deletions.
213 changes: 213 additions & 0 deletions docs/05_Модуль_Интранет/05_Оргструктура.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# Организационная структура

[TOC]

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

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

## Архитектура

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

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

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

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

## API

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

```php
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()`.

Пример возвращаемой структуры:
```php
/**
* @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` - массив идентификаторов подразделений.
Метод использует запросы в цикле, поэтому старайтесь избегать большого количества подразделений в списке.

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

$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)`.

Пример:

```php
// 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`, который можно проитерировать.
Пример:

```php
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` и ее использование не рекомендуется.


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

[Структура компании](https://helpdesk.bitrix24.ru/open/17961850/)
[Связь структуры компании с инструментами Битрикс24](https://helpdesk.bitrix24.ru/open/18002680)

0 comments on commit 8c6d57a

Please sign in to comment.