Pull to refresh

Мой опыт внедрения модуля учета рабочего времени в 1С: Битрикс

1С-Bitrix
Awaiting invitation
Как обычно бывает, даже зная досконально техническое руководство, возникают нюансы, над которыми надо подумать. Либо решить самому, либо искать помощи в интернете. Внесу свою лепту в копилку знаний Хабрахабра.

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


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

Приведу пример из практики.

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

При использовании корпоративного портала логически подразумевается, что это система закрытая и доступ к ней осуществляется только внутри сети компании или через VPN. Если сотрудник находится в офисе заказчика, зачастую он не может самостоятельно начать рабочий день, поэтому подобная проблема актуальна для большинства компаний, внедряющих корпоративный портал.

Как технически оформить данную задачу?


Для решения данной задачи необходимо кастомизировать стандартный отчет о рабочем времени корпоративного портала битрикс.

1. Для начала необходимо создать копию компонента timeman.report в собственном пространстве имен. Это важно! Т.к. вы можете потерять свои изменения при обновлении версии битрикс, если будете менять стандартные компоненты.
2. Обязательно учтите права пользователей, т.к. данный функционал по логике должен быть доступен лишь ограниченному кругу лиц. Для этого создайте системную группу и добавьте в нее пользователя, после чего сделайте завязку на эту группу в компоненте.

image

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

Проблема с принудительным открытием рабочего дня.

Итак, сотрудник отдела кадров открывает рабочий день за сотрудника принудительно, и кажется, что все хорошо. Но через некоторое время оказывается, что у него до сих пор открыт прошлый рабочий день. Сотрудник отдела кадров звонит программисту и описывает проблему, программист проверяет записи в системной таблице и видит, что данные обновлены. Так почему же тогда мы видим другие результаты?

Большинство сейчас скажет: «Надо сбросить кэш». И будут правы, проблема действительно в этом, но есть тонкость.
Даже если попытаться сбросить кэш с помощью стандартной кнопки сброса кэша в битрикс это не приведет к положительному результату. Если вы перелогинитесь, данные обновятся, но это не решает суть проблемы.

Проблему можно решить, используя механизм управления кэшем напрямую в коде. Для этого используем следующую конструкцию

$CACHE_MANAGER->Clean('TIMEMAN_USER_'.$arFields['USER_ID'].'|'.FORMAT_DATETIME, 'b_timeman_entries');


С помощью данного метода мы можем очистить кэш таблицы b_timeman_entries для пользователя с определенным ID. Данная таблица хранит информацию о рабочем времени зарегистрированных пользователей портала.

Способы управления рабочим временем принудительно.

1. Первый способ — это использование класса CTimeManEntry. При этом необходимо понимать, какие комбинации параметров использует битрикс для управления рабочем временем.

Открыть рабочий день вы можете, например, так:
$arFields['USER_ID']=$_POST['users'];
$arFields['DATE_START']=$_POST['date_fld'];
$arFields['ACTIVE']='Y';
$arFields['IP_OPEN']=$_POST['ip'];
CTimeManEntry::Add($arFields);


Закрыть так:

$arFields['USER_ID']=$_POST['users'];
$arFields['DATE_FINISH']=$_POST['date_fld'];
$arFields['PAUSED']='N';
$arFields['IP_CLOSE']=$_POST['ip'];
$res= CTimeManEntry::GetList($arOrder = array('ID'=>'DESC'), $arFilter = array('USER_ID'=>$arFields["USER_ID"]), $arGroupBy = false, $arNavStartParams = false, $arSelectFields = array());
if($ob = $res->GetNext())
{
	CTimeManEntry::Update($ob['ID'], $arFields);
}

Но у этого способа есть минус: вам необходимо тонко понимать, какие комбинации параметров надо использовать для открытия, закрытия, приостановки и возобновления рабочего дня.

Оптимально использовать этот способ в случае, если вам необходимо массово обновить записи о рабочем времени, например, при интеграции со внешними системами для контроля управления доступом, такими как Parsec. Это ускорит процесс обновления данных, особенно если их много.

2. Есть второй способ, который оптимально использовать при редактировании записей о рабочем дне у конкретного сотрудника, т.е. не массово. Для решения данной задачи существует класс CTimeManUser. Данный класс имеет простые методы, позволяющие управлять рабочим временем определенного пользователя. Но надо учитывать, что функционально данные методы более сложны и будут в большинстве случаев выполняться дольше, чем методы первого способа при массовом обновлении, несмотря на похожий механизм доступа к данным у обоих методов.

Пример из практики:
1. Метод CTimeManUser::OpenDay(), который открывает рабочий день, использует внутри вызовы класса CTimeManEntry, который мы рассмотрели выше.
Открыть рабочий день можно, например, так

If(CModule::IncludeModule('timeman')) //подключаем модуль рабочего времени
{
   $TimemanUser = new CTimeManUser($UserID);
   $userSettings = $TimemanUser->GetSettings(); //получаем настройки пользователя
   if($userSettings["UF_TIMEMAN"]) //ведётся ли учет времени
   {
      $TimemanUser->OpenDay(); //открываем день
   }
}


Это наиболее простой и стандартный способ открытия рабочего дня, но схему всегда можно развить. Например, опираясь на состояние CTimeManUser::State()

Метод возвращает следующие значения:

CLOSED – рабочий день закрыт, доступно открытие дня
OPENED — рабочий день открыт, доступно закрытие или пауза;
PAUSED — рабочий день открыт, но поставлен на паузу, доступно закрывать или продолжать день
EXPIRED — рабочий день истек, возникает в случае если пользователь забыл закрыть рабочий день.

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

image

Важно!
Для того, чтобы исключить ситуацию, когда рабочий день находиться в статусе EXPIRED можно использовать принудительное закрытие дня через периодическое задание cron. Зачастую требования бизнеса заказчика подразумевают, что такие ситуации необходимо исключать. В этом случае данные по незакрытым рабочим дням надо обновить принудительно, например, в 23:00.

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

Еще один способ на крайний случай.

Использовать прямой доступ к таблицам и обновить данные с помощью единственного запроса. Как правило, его использовать не рекомендуется, т.к. есть готовое API. Но один плюс очевиден: обновление будет практически мгновенным, даже если рабочий день забыли закрыть 5000 сотрудников компании.

Даты в полях DATE_START и DATE_FINISH завязаны на часовые пояса, поэтому если вдруг захотите использовать подобный метод не забудьте учесть часовой пояс иначе получите неправильное время.

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

Мы рассмотрели основные особенности и проблемы, возникающие при работе с модулем рабочего времени. В следующих статьях я приведу другие решения проблем при внедрении корпоративного портала. Если есть вопросы, пишите в комментариях.
Tags:php1c-битриксbitrix24
Hubs:1С-Bitrix
You can’t comment this post because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.