Skip to content

Commit

Permalink
Merge pull request #27 from gromdron/intranet_helpers
Browse files Browse the repository at this point in the history
Absence
  • Loading branch information
gromdron authored Dec 22, 2023
2 parents bb2251a + d8fac95 commit 99bc46d
Showing 1 changed file with 214 additions and 0 deletions.
214 changes: 214 additions & 0 deletions docs/05_Модуль_Интранет/30_Отсутствия.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
# Отсутствия

[TOC]

В интранет модуле имеется сущность "Отсутствие" необходимое для контроля состояния сотрудника во времени (в отпуске, на больничном и т.п.). С точки зрения технического воплощения "Отсутствие" разбито на 2 части - одна обеспечивается модулем "Интранет" и представлена через инструмент "График отсутствий", а вторая является подсистемой модуля "Календарь". В этой статье мы рассмотрим "Отстутствие" с точки зрения "Графика отсутствий".

>График отсутствий — это инструмент, который помогает организовать рабочий процесс и следить за отсутствием сотрудников на рабочем месте. Он полезен для планирования проектов и распределения задач: всегда видно, когда сотрудники недоступны по различным причинам — отпуск, больничный или командировка.
## Архитектура

С точки зрения архитектуры "Отсутствие" - это элемент инфоблока "График отсутствий". По-умолчанию располагается в типе инфоблоков "Оргструктура".

>Инфоблок "График отсутствий" - может быть сконфигурирован в настройках модуля Интранет. Что это значит? Это значит что вы можете взять любой инфоблок, создать необходимые свойства и в настройках модуля Интранет указать что он является "хранителем" отсутствий.
Отсутствие характеризуется следующими полями:
- Отсутствующий сотрудник (Код свойства: `USER`, привязка к пользователю)
- Тип отсутствия (Код свойства: `ABSENCE_TYPE`, список)
- Причина отсутствия (Поле `NAME` - название инфоблока, строка)
- Период отсутствия: Начало и Окончание (Поля `ACTIVE_FROM` и `ACTIVE_TO` - дата)

>Примечание к справочнику "Тип отсутствия": не смотря на то что в инфоблоке есть список который омжно дополнять и редактировать, нужно помнить что не все подсистемы модуля Интранет воспринимают новые поля. Может оказаться так что новый добавленный тип не будет учитываться как отсутствие без уважительной причины, отпуск или другое. Дополнять список можно, но не рекомендуется.
## API

Мы уже знаем что отсутствие это запись инфоблока, но у каждого сайта в рамках установки это может быть свой инфоблок, поэтому перед началом работы нужно получить идентификатор инфоблока для конкретного сайта. Они хранятся в настройках (`b_options`, `b_option_site`) с кодом модуля `intranet` и названием `iblock_absence`

```php
use \Bitrix\Main\Config\Option;

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

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

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

```php

use Bitrix\Intranet\UserAbsence;

/**
* @var int Absence iblock id
*/
$iblockId = UserAbsence::getIblockId();
```

>Помните что `UserAbsence::getIblockId` при повреждении записей в `b_options` может вернуть `0`
### Типы отсутствий

Для получения всех типов отсутствий помимо методов инфоблока можно воспользоваться методом `\Bitrix\Intranet\UserAbsence::getVacationTypes`:

```php
use \Bitrix\Intranet\UserAbsence;

$vacationTypes = UserAbsence::getVacationTypes();
```

Пример содержимого:
```php
$vacationTypes = [
'VACATION' => [
'ID' => 'VACATION',
'ENUM_ID' => '1',
'NAME' => 'отпуск ежегодный',
'ACTIVE' => true,
],
'ASSIGNMENT' => [
'ID' => 'ASSIGNMENT',
'ENUM_ID' => '2',
'NAME' => 'командировка',
'ACTIVE' => false,
]
];
```

Описание полей:
- `ID` (`string`) - Символьный код типа отсутствия
- `ENUM_ID` (`string`) - Идентификатор типа отсутствия
- `NAME` (`string`) - Название отсутствия
- `ACTIVE` (`bool`) - Является ли отсутствие отпуском

### Отсутствия текущего месяца

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

```php
use \Bitrix\Intranet\UserAbsence;

$currentMonthAbsences = UserAbsence::getCurrentMonth();
```

Результирующий массив имеет многомерную структуру: ID сотрудника -> Порядковый номер отсутствия (с 0) -> Отсутствие.
Пример:

```php
$currentMonthAbsences = [
1 => [
0 => [
"ID" => 2,
"USER_ID" => 1,
"ENTRY_TYPE" => "VACATION",
"ENTRY_TYPE_ID" => 1,
"ENTRY_TYPE_VALUE" => "отпуск ежегодный",
"IS_VACATION" => true,
"DATE_FROM_TS" => 1703451600
"DATE_TO_TS" => 1703538000
],
]
]
```

Описание структуры:
- `ID` (`int`) - Идентификатор отсутствия (элмента инфоблока)
- `USER_ID` (`int`) - Идентификатор сотрудника
- `ENTRY_TYPE` (`string`) - Симв.код типа отсутствия
- `ENTRY_TYPE_ID` (`int`) - Идентификатор типа отсутствия
- `ENTRY_TYPE_VALUE` (`string`) - Название типа отсутствия
- `IS_VACATION` (`bool`) - Является отпуском
- `DATE_FROM_TS` (`int`) - Временная метка начала
- `DATE_TO_TS` (`int`) - Временная метка окончания


### Проверка отсутствия

Существует так же способ проверить отсутствие пользователя в момент выполнения кода `CIntranetUtils::IsUserAbsent($USER_ID)`:

```php

/**
* @var int Employee identifier to check absence
*/
$userId = 123;

/**
* @var bool True if user is absent
*/
$isUserAbsence = \CIntranetUtils::IsUserAbsent($userId);
```


И его более сложный аналог - проверка отсутствия в определнный момент `\CIntranetUtils::GetAbsenceData($arParams = array(), $MODE = BX_INTRANET_ABSENCE_ALL)`.
Метод принимает на вход 2 аргумента:
- `$arParams` (`array`) - параметры конфигурирующие запрос
- `$mode` (`int`) - режим запроса

На текущий момент поддерживается 2 режима работы:
- `BX_INTRANET_ABSENCE_ALL` - отсутствия И из календаря И из графика отсутствий
- `BX_INTRANET_ABSENCE_HR` - отсутствия ТОЛЬКО из графика отсутствий

Параметры конфигурирующие запрос:
- `DATE_START` (`string`) - дата начала в формате сайта (Для РФ: `d.m.Y H:i:s`)
- `DATE_FINISH` (`string`) - дата окончания в формате сайта (Для РФ: `d.m.Y H:i:s`)
- `USERS` (`array`) - Массив идентификаторов сотрудников для поиска. Пустой массив - без фильтра по сотрудникам
- `PER_USER` (`bool`) - Группировать результат по сотрудникам


Например, для получения отсутствия зарегистрированного для сотрудника ID:1 в пределах дат 10.10.2023 - 12.10.2023 можно использовать такой код:
```php
$absenceList = \CIntranetUtils::GetAbsenceData([
'DATE_START' => '10.10.2023 00:00:00',
'DATE_FINISH' => '12.10.2023 23:59:59',
'USERS' => [1],
]);
```

### События

Отдельных событий на создание/редактирование/удаления отсутствий нет - следует использовать события информационных блоков для работы.

Однако в подсистеме существует несколько полезных событий которые можно использовать в своей работе.

#### Начало и Окончание

Подсистема выбрасывает события начала (`OnStartAbsence`) и окончания отпуска (`OnEndAbsence`).

| Параметр | Значение |
| :----------: | --------------------------- |
| USER_ID | ID сотрудника (число) |
| ABSENCE_TYPE | Тип отпуска (число) |
| START | Дата начала (строка) |
| END | Дата окончания (строка) |
| DURATION | Длительность (число, сек.) |

Возвращаемые значения не обрабатываются.

Пример подписки на событие:
```php
use \Bitrix\Main\Event;
use \Bitrix\Main\EventResult;
use \Bitrix\Main\EventManager;

$eventManager = EventManager::getInstance();

$eventManager->addEventHandler(
'crm',
'OnStartAbsence',
function( Event $event )
{
\Bitrix\Main\Diag\Debug::dumpToFile(
$event->getParameters(),
date('d.m.Y H:i:s'),
str_replace($_SERVER['DOCUMENT_ROOT'], '', __DIR__.'/log.log')
);

return new EventResult();
}
);
```

0 comments on commit 99bc46d

Please sign in to comment.