Your IP : 216.73.216.170


Current Path : /home/bitrix/ext_www/vt.yacl.site/local/php_interface/
Upload File :
Current File : /home/bitrix/ext_www/vt.yacl.site/local/php_interface/tools.php

<?
// сборник функций без определенной привязки
use jamesiarmes\PhpEws\Enumeration\ImportanceChoicesType;
use jamesiarmes\PhpEws\Enumeration\TaskStatusType;

function okp($data = NULL) {
    $backtrace = debug_backtrace()[0];
    $file = str_replace($_SERVER['DOCUMENT_ROOT'], '', $backtrace['file']);
    $line = str_replace($_SERVER['DOCUMENT_ROOT'], '', $backtrace['line']);
    echo $file . ', ' . $line . ': ';
    if (is_array($data) or is_object($data)) {
        echo '<pre>';
        print_r($data);
        echo '</pre>';
    } else {
        var_dump($data);
        echo "<br/>";
    }
}

function oklog($data, $file = "oklog") {
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . '/logs/' . $file . '.log', date('d.m.Y H:i:s: '), FILE_APPEND);
    file_put_contents($_SERVER['DOCUMENT_ROOT'] . '/logs/' . $file . '.log', print_r($data, true) . "\n", FILE_APPEND);
}

function getUserIdByEmail($email, $checkActive = false) {
    if (!$email)
        return false;
    $filter = [
        '=EMAIL' => $email,
    ];
    if ($checkActive) {
        $filter['ACTIVE'] = 'Y';
    }
    $user = \Bitrix\Main\UserTable::getList([
        'filter' => $filter,
        'select' => ['ID']
    ])->fetch();
    return $user['ID'];
}

function getUserLinkById($userId, $withoutLink = false, $order = ['LAST_NAME', 'NAME']) {
    if (!$userId)
        return false;
    $userList = \Bitrix\Main\UserTable::getList([
        'filter' => ['ID' => $userId],
        'select' => array_merge(['ID'], $order)
    ])->fetchAll();
    $result = [];
    foreach ($userList as $userInfo) {
        $data = [];
        foreach ($order as $field) {
            $data[] = $userInfo[$field];
        }
        if ($withoutLink) {
            $result[] = implode(' ', $data);
        } else {
            $result[] = '<a href="/company/personal/user/' . $userInfo['ID'] . '/">' . implode(' ', $data) . '</a>';
        }
    }
    return implode(', ', $result);
}

function getUserPhoto($userId, $asHtml = false) {
    if (!$userId)
        return false;
    $user = \Bitrix\Main\UserTable::getList([
        'filter' => ['ID' => $userId],
        'select' => ['PERSONAL_PHOTO', 'NAME']
    ])->fetch();
    $defaultPhoto = 'data:image/svg+xml;charset=US-ASCII,%3Csvg%20viewBox%3D%220%200%2089%2089%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Ccircle%20fill%3D%22%23535C69%22%20cx%3D%2244.5%22%20cy%3D%2244.5%22%20r%3D%2244.5%22/%3E%3Cpath%20d%3D%22M68.18%2071.062c0-3.217-3.61-16.826-3.61-16.826%200-1.99-2.6-4.26-7.72-5.585-1.734-.483-3.383-1.233-4.887-2.223-.33-.188-.28-1.925-.28-1.925l-1.648-.25c0-.142-.14-2.225-.14-2.225%201.972-.663%201.77-4.574%201.77-4.574%201.252.695%202.068-2.4%202.068-2.4%201.482-4.3-.738-4.04-.738-4.04.388-2.625.388-5.293%200-7.918-.987-8.708-15.847-6.344-14.085-3.5-4.343-.8-3.352%209.082-3.352%209.082l.942%202.56c-1.85%201.2-.564%202.65-.5%204.32.09%202.466%201.6%201.955%201.6%201.955.093%204.07%202.1%204.6%202.1%204.6.377%202.556.142%202.12.142%202.12l-1.786.217c.024.58-.023%201.162-.14%201.732-2.1.936-2.553%201.485-4.64%202.4-4.032%201.767-8.414%204.065-9.193%207.16-.78%203.093-3.095%2015.32-3.095%2015.32H68.18z%22%20fill%3D%22%23FFF%22/%3E%3C/svg%3E';
//    if (strpos('йцкнгшщзхъфвпрлджчсмтьб', mb_substr($user['NAME'], mb_strlen($user['NAME']) - 1)) !== false) {
//        $defaultPhoto = PATH_BUILD . '/new/img/unknown.jpg';
//    }
    $src = $user['PERSONAL_PHOTO'] ? CFile::GetPath($user['PERSONAL_PHOTO']) : $defaultPhoto;
    if ($user['PERSONAL_PHOTO']) {
        $imgInfo = CFile::GetByID($user['PERSONAL_PHOTO'])->Fetch();
        $html =  '<img data-width="' . $imgInfo['WIDTH'] . '" data-height="' . $imgInfo['HEIGHT'] . '" src="' . $src . '" alt="User">';
    } else {
        $html = '<img src="' . $src . '">';
    }

    return $asHtml ? $html : $src;
}

function getUserPhotoLinkById($userId) {
    if (!$userId)
        return false;
    $userList = \Bitrix\Main\UserTable::getList([
        'filter' => ['ID' => $userId, 'ACTIVE' => 'Y'],
        'select' => ['LAST_NAME', 'NAME', 'ID', 'PERSONAL_PHOTO']
    ])->fetchAll();
    $result = [];
    foreach ($userList as $userInfo) {
        if (!empty($userInfo['PERSONAL_PHOTO'])) {
            $userAvatar = '';
            $img = 'style="background-image: url(\'' . CFile::GetPath($userInfo['PERSONAL_PHOTO']) . '\')"';
        } else {
            $img = 'style="background-image: url(\'/build/assets/img/noimage.svg\'); background-color: #0092db;"';
            $userAvatar = 'tasks-grid-avatar-empty';
        }
        $result[] = '<a href="/company/personal/user/' . $userInfo['ID'] . '/" class="tasks-grid-username"><span class="tasks-grid-avatar '.$userAvatar.'" ' . $img . '></span><span class="tasks-grid-username-inner ">' . $userInfo['LAST_NAME'] . ' ' . $userInfo['NAME'] . '</span></a>';
//        $result[] = '<a href="/company/personal/user/' . $userInfo['ID'] . '/"></a>';
    }
    return implode(', ', $result);
}

function getUserPhotoTimesheetLinkById($userId, $baseUrl = false) {
    if (!$userId)
        return false;
    if (!$baseUrl) {
        $baseUrl = '/projects/timesheet/';
    }
    $userList = \Bitrix\Main\UserTable::getList([
        'filter' => ['ID' => $userId, 'ACTIVE' => 'Y'],
        'select' => ['LAST_NAME', 'NAME', 'ID', 'PERSONAL_PHOTO'],
        'order' => ['LAST_NAME' => 'ASC'],
    ]);
    $result = [];
    while ($userInfo = $userList->fetch()) {
        if (!empty($userInfo['PERSONAL_PHOTO'])) {
            $img = 'style="background-image: url(\'' . CFile::GetPath($userInfo['PERSONAL_PHOTO']) . '\')"';
        } else {
            $img = 'style="background-image: url(\'/build/assets/img/noimage.svg\'); background-color: #0092db;"';
        }
        $result[] = '<a href="' . $baseUrl . $userInfo['ID'] . '/" class="timesheet-grid-username"><span class="timesheet-grid-avatar" ' . $img . '></span><span class="tasks-grid-username-inner ">' . $userInfo['LAST_NAME'] . ' ' . $userInfo['NAME'] . '</span></a>';
//        $result[] = '<a href="/company/personal/user/' . $userInfo['ID'] . '/"></a>';
    }
    return implode('<br/>', $result);
}

function getUserLinkWithTaskStatus($userId, $taskId, $baseUrl = false, $withImg = false) {
    if (!$userId || !$taskId)
        return false;
    if (!$baseUrl) {
        $baseUrl = '/company/personal/user/';
    }

    $userList = \Bitrix\Main\UserTable::getList([
        'filter' => ['ID' => $userId, 'ACTIVE' => 'Y'],
        'select' => ['LAST_NAME', 'NAME', 'ID', 'PERSONAL_PHOTO'],
        'order' => ['LAST_NAME' => 'ASC'],
    ]);
    $result = [];
    while ($userInfo = $userList->fetch()) {
        $url = $baseUrl . $userInfo['ID'] . '/';
        if (!empty($userInfo['PERSONAL_PHOTO'])) {
            $img = 'style="background-image: url(\'' . CFile::GetPath($userInfo['PERSONAL_PHOTO']) . '\'); width: 20px; height: 20px; background-size: cover; display: inline-block; margin-right: 14px;"';
        } else {
            $img = 'style="background-image: url(\'/build/assets/img/noimage.svg\');  background-color: #0092db; width: 20px; height: 20px; background-size: cover; display: inline-block; margin-right: 14px;"';
        }
        $pts = new ProjectTaskStatus($taskId, $userInfo['ID']);
        $userLink = '<a style="white-space: nowrap;" href="' . $url . '">' . ($withImg ? '<span ' . $img . '></span>' : '') . $userInfo['LAST_NAME'] . '&nbsp;' . $userInfo['NAME'] . '</a>&nbsp;-&nbsp;' . $pts->getStatusName(true);
        $result[] = $userLink;

//        $result[] = '<a href="/company/personal/user/' . $userInfo['ID'] . '/"></a>';
    }
    return implode('<br/>', $result);
}


function getUserInfoById($userId, $fields = ['ID', 'NAME', 'WORK_POSITION', 'LAST_NAME']) {
    if (!$userId)
        return false;
    $userInfo = \Bitrix\Main\UserTable::getList([
        'filter' => ['ID' => $userId, 'ACTIVE' => 'Y'],
        'select' => $fields
    ])->fetch();
    return $userInfo;
}


function getDepartmentNameById($sectionId) {
    if (!$sectionId)
        return false;
    \Bitrix\Main\Loader::includeModule('iblock');
    $sectionList = \Bitrix\Iblock\SectionTable::getList([
        'filter' => ['ID' => $sectionId, 'ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT],
        'select' => ['NAME', 'ID']
    ])->fetchAll();
    $result = [];
    foreach ($sectionList as $sectionInfo) {
        $result[] = $sectionInfo['NAME'];
    }
    return implode(', ', $result);
}

function getDepartmentHead($sectionId) {
    if (!$sectionId)
        return false;
    \Bitrix\Main\Loader::includeModule('iblock');
    $entity = \Bitrix\Iblock\Model\Section::compileEntityByIblock(IBLOCK_DEPARTMENT);
    $sectionInfo = $entity::getList([
        'filter' => ['ID' => $sectionId, 'ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT],
        'select' => ['NAME', 'ID', 'UF_HEAD']
    ])->fetch();

    return $sectionInfo['UF_HEAD'];
}

function getDepartmentName($sectionId) {
    if (!$sectionId)
        return false;
    \Bitrix\Main\Loader::includeModule('iblock');
    $entity = \Bitrix\Iblock\Model\Section::compileEntityByIblock(IBLOCK_DEPARTMENT);
    $sectionInfo = $entity::getList([
        'filter' => ['ID' => $sectionId, 'ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT],
        'select' => ['NAME']
    ])->fetch();

    return $sectionInfo['NAME'];
}

function getUserFieldEnumValueById($id) {
    $sort = ['SORT' => 'ASC'];
    $filter = ['ID' => $id];
    $statusInfo = CUserFieldEnum::GetList($sort, $filter)->Fetch();
    return $statusInfo['VALUE'];
}

function makeCurrentFilesArray($inputFileCode) {
    unset($arFiles, $TMPFILE);
    $arFiles = array();  // Массив всех файлов в свойстве []
    $TMPFILE = array(); // Временный массив для текщего файла
    if(is_array($_FILES[$inputFileCode])) {
        foreach($_FILES[$inputFileCode]['tmp_name'] as $key => $val) {
            if(file_exists($val)) {
                foreach($_FILES[$inputFileCode] as $namekey => $nameval) {
                    $TMPFILE[$namekey] = $nameval[$key];
                }
                $arFiles[] = array('VALUE' => $TMPFILE, 'DESCRIPTION' => $TMPFILE['name']);
            }
        }
    }
    return $arFiles;
}

function emailIsInWhiteList(&$to) {
    if (defined('EMAIL_WHITE_LIST')) {
        $emailTo = $to;
        $allEmails = explode(',', $emailTo);
        $acceptedMails = [];
        foreach ($allEmails as $email) {
            $email = str_replace(' ', '', $email);
            $pattern = '/[a-zA-Z0-9]+@[a-zA-Z0-9\.]+/';
            $res = preg_match($pattern, $email, $matches);
            if ($res) {
                $email = $matches[0];
            }
            if (strpos(EMAIL_WHITE_LIST, $email) !== false) {
                $acceptedMails[] = $email;
            }
        }
        if (!empty($acceptedMails)) {
            $to = implode(', ', $acceptedMails);
            return true;
        } else {
            oklog($emailTo, 'email.error');
            oklog($acceptedMails, 'email.error');
            return false;
        }
    } else {
        return true;
    }
}

function syncProjectGroupAccess($projectId) {
    \Bitrix\Main\Loader::includeModule('iblock');
    \Bitrix\Main\Loader::includeModule('socialnetwork');
    $filter = ['IBLOCK_ID' => IBLOCK_PROJECT, 'ID' => $projectId];
    $select = ['ID', 'NAME', 'PROPERTY_ACCESS'];
    $projectInfo = CIBlockElement::GetList([], $filter, false, false, $select)->GetNext();
    $accessUsers = $projectInfo['PROPERTY_ACCESS_VALUE'];
    $groupId = Project::getGroupId($projectId);
    $groupUserList = CSocNetUserToGroup::GetList(
        array("USER_ID" => "ASC"),
        array(
            "GROUP_ID" => $groupId,
            "USER_ACTIVE" => "Y"
        ),
        false,
        false,
        array("ID", "USER_ID")
    );
    $groupUsers = [];
    while ($user = $groupUserList->GetNext()) {
        $groupUsers[] = $user['USER_ID'];
        $groupUserLinks[$user['USER_ID']] = $user['ID'];
    }
    foreach ($accessUsers as $userId) {
        if (!in_array($userId, $groupUsers)) {
            CSocNetUserToGroup::Add(
                array(
                    "USER_ID" => $userId,
                    "GROUP_ID" => $groupId,
                    "ROLE" => SONET_ROLES_USER,
                    "=DATE_CREATE" => $GLOBALS["DB"]->CurrentTimeFunction(),
                    "=DATE_UPDATE" => $GLOBALS["DB"]->CurrentTimeFunction(),
                    "INITIATED_BY_TYPE" => SONET_INITIATED_BY_USER,
                    "INITIATED_BY_USER_ID" => CUser::GetID(),
                    "MESSAGE" => false,
                )
            );
        }
    }
    foreach ($groupUsers as $userId) {
        if (!in_array($userId, $accessUsers)) {
            if (!empty($groupUserLinks[$userId])) {
                CSocNetUserToGroup::Delete($groupUserLinks[$userId]);
            }
        }
    }
}

function getRemainingTaskTime($taskId) {
    $taskData = CTaskItem::getInstance($taskId, 1)->getData();
    $timeRemain = $taskData['TIME_ESTIMATE'] - $taskData['TIME_SPENT_IN_LOGS'];
    if ($timeRemain <= 0)
        return 0;
    $res = CTasks::GetList([], ['PARENT_ID' => $taskId], ['ID', 'TITLE', 'TIME_SPENT_IN_LOGS', 'TIME_ESTIMATE']);
//    while (!empty($res)) {
    $currentDepthTasks = [];
    while ($task = $res->Fetch()) {
        $timeRemain -= $task['TIME_ESTIMATE'];
        $currentDepthTasks[] = $task['ID'];
    }
//        if (!empty($currentDepthTasks)) {
//            $res = CTasks::GetList([], ['PARENT_ID' => $currentDepthTasks], ['ID', 'TITLE', 'TIME_SPENT_IN_LOGS', 'TIME_ESTIMATE']);
//        } else {
//            break;
//        }
//    }
    return $timeRemain > 0 ? $timeRemain : 0;
}

function getSpentTaskTime($taskId, $asHtml = true) {
    $taskData = CTaskItem::getInstance($taskId, 1)->getData();
    if (!isset($taskData['TIME_SPENT_IN_LOGS'])) {
        $taskData = CTaskItem::getInstance($taskId, 1)->getData();
    }
    $timeSpent = $taskData['TIME_SPENT_IN_LOGS'];
    $res = CTasks::GetList([], ['PARENT_ID' => $taskId], ['ID', 'TITLE', 'TIME_SPENT_IN_LOGS', 'TIME_ESTIMATE']);
    $counter = 0;
    while (!empty($res)) {
        if (++$counter > 10)
            break;
        $currentDepthTasks = [];
        while ($task = $res->Fetch()) {
            $timeSpent += $task['TIME_SPENT_IN_LOGS'];
            $currentDepthTasks[] = $task['ID'];
        }
        if (!empty($currentDepthTasks)) {
            $res = CTasks::GetList([], ['PARENT_ID' => $currentDepthTasks], ['ID', 'TITLE', 'TIME_SPENT_IN_LOGS', 'TIME_ESTIMATE']);
        } else {
            break;
        }
    }
    if (!$asHtml)
        return ['timeEstimated' => $taskData['TIME_ESTIMATE'], 'timeSpent' => $timeSpent];
//    okp($taskId . ': ' . $timeSpent);
    return formatSecondsToHoursWithMinutes($timeSpent) . ' / ' . formatSecondsToHoursWithMinutes($taskData['TIME_ESTIMATE']);
}

function formatSecondsToHoursWithMinutes($seconds) {
    return sprintf(
        '%02d:%02d',
        floor($seconds / 3600),    // hours
        round($seconds / 60) % 60    // minutes
    );
}

function formatSecondsToHours($seconds) {
    return str_replace('.', ',', sprintf(
        '%01.4f',
        round($seconds / 3600, 4)
    ));
}

function formatSecondsToMinutes($seconds) {
    return round($seconds / 60);
}

function getUserDays($seconds) {
    return round($seconds / (8 * 3600), 2);
}

function isExtranetExecutor() {
    global $USER;
    return in_array(20, $USER->GetUserGroupArray());
}

function getProdHours($dateFrom, $dateTo, $hourCalendar) {
    $result = 0;
    for ($day = strtotime($dateFrom); $day <= strtotime($dateTo); $day += (86400)) {
        $result += $hourCalendar[date('m.d', $day)];
    }
    return $result;
}

function makeHourCalendar($year) {
    $year = intval($year);
    if (!$year) {
        return false;
    }
    $xmlCal = file_get_contents($_SERVER['DOCUMENT_ROOT'] . '/local/production_calendar/calendar_' . $year . '.xml');
    if (empty($xmlCal)) {
        return false;
    }
    /*
        days - праздники/короткие дни/рабочие дни (суббота либо воскресенье)
        d - день (формат ММ.ДД)
        t - тип дня: 1 - выходной день, 2 - рабочий и сокращенный (может быть использован для любого дня недели), 3 - рабочий день (суббота/воскресенье)
        h - номер праздника (ссылка на атрибут id тэга holiday)
        суббота и воскресенье считаются выходными, если нет тегов day с атрибутом t=2 и t=3 за этот день
    */

    $sxe = new SimpleXMLElement($xmlCal);
    $calendar = [];
    foreach($sxe->days->day as $day) {
        $attrs = $day->attributes();
        switch ($attrs['t']) {
            case '1':
                // okp((string)$attrs['d']);
                $calendar['holidays'][(string)$attrs['d']] = (string)$attrs['d'];
                break;
            case '2':
                // okp((string)$attrs['d']);
                $calendar['shortdays'][(string)$attrs['d']] = (string)$attrs['d'];
                break;
            case '3':
                // okp((string)$attrs['d']);
                $calendar['fulldays'][(string)$attrs['d']] = (string)$attrs['d'];
                break;
            default:
                okp($attrs);
                break;
        }
    }

    $yearStart = strtotime('01.01.' . $year);
    $hourCalendar = [];
    for ($day = $yearStart; $day < strtotime('01.01.' . ($year + 1)); $day += (86400)) {
        $dayWord = date('m.d', $day);
        switch (date('N', $day)) {
            case '1':
            case '2':
            case '3':
            case '4':
                if (!empty($calendar['holidays'][$dayWord])) {
                    $hourCalendar[$dayWord] = 0;
                } elseif(!empty($calendar['shortdays'][$dayWord])) {
                    $hourCalendar[$dayWord] = 7;
                } else {
                    $hourCalendar[$dayWord] = 8;
                }
                break;
            case '5':
                if (!empty($calendar['holidays'][$dayWord])) {
                    $hourCalendar[$dayWord] = 0;
                } elseif(!empty($calendar['fulldays'][$dayWord])) {
                    $hourCalendar[$dayWord] = 8;
                } else {
                    $hourCalendar[$dayWord] = 6.75;
                }
                break;
            case '6':
            case '7':
                if (!empty($calendar['shortdays'][$dayWord])) {
                    $hourCalendar[$dayWord] = 7;
                } elseif(!empty($calendar['fulldays'][$dayWord])) {
                    $hourCalendar[$dayWord] = 8;
                } else {
                    $hourCalendar[$dayWord] = 0;
                }
                break;

        }
    }

    return $hourCalendar;
}

/*
Отчеты могут выгружать -
исполнители только по себе.
РП - по себе и только по своим проектам.
Токтамысов ДЖ(ФД), Фролов АА (ЗГД ПП), Калугин ОЮ (ГД) - по всем,
Руководители - по себе и своим подчиненным.
*/
function getAllowedUsersForReports() {
    global $USER;
    $userId = $USER->GetID();
    $allowedUsers = [];
    if (!Project::isResSubGenDir() && !Project::isAllTaskViewer() && !Project::isGenDir()) {
        $projectFilter = ['IBLOCK_ID' => IBLOCK_PROJECT, 'ACTIVE' => 'Y', 'PROPERTY_RP' => $userId];
        $projectSelect = ['ID', 'IBLOCK_ID', 'PROPERTY_ACCESS', 'PROPERTY_RP', 'PROPERTY_SYSTEM_GROUP_ID'];
        $projectList = CIBlockElement::GetList([], $projectFilter, false, false, $projectSelect);
        while($project = $projectList->GetNext()) {
            $allowedUsers = array_merge($allowedUsers, $project['PROPERTY_ACCESS_VALUE']);
        }
        $allowedUsers = array_unique($allowedUsers);
        $departmentFilter = ['IBLOCK_ID' => IBLOCK_DEPARTMENT, 'ACTIVE' => 'Y', 'UF_HEAD' => $userId];
        $departmentSelect = ['ID', 'IBLOCK_ID', 'NAME'];
        $departmentList = CIBlockSection::GetList([], $departmentFilter, false, $departmentSelect);
        while($department = $departmentList->GetNext()) {
            $userList = \Bitrix\Main\UserTable::getList([
                'filter' => ['ACTIVE' => 'Y', 'UF_DEPARTMENT' => [$department['ID']]],
                'select' => ['ID'],
            ]);
            $result = [];
            while ($userInfo = $userList->fetch()) {
                $allowedUsers[] = $userInfo['ID'];
            }
        }
        $allowedUsers[] = $userId;
        $allowedUsers = array_unique($allowedUsers);
    } else {
        $userList = \Bitrix\Main\UserTable::getList([
            'filter' => ['!UF_DEPARTMENT' => false, 'ACTIVE' => 'Y'],
            'select' => ['LAST_NAME', 'NAME', 'ID', 'PERSONAL_PHOTO'],
            'order' => ['LAST_NAME' => 'ASC', 'NAME' => 'ASC'],
        ]);
        while ($userInfo = $userList->fetch()) {
            $allowedUsers[] = $userInfo['ID'];
        }
    }
    $returnedUsers = [];
    $userList = \Bitrix\Main\UserTable::getList([
        'filter' => ['ID' => $allowedUsers, 'ACTIVE' => 'Y'],
        'select' => ['ID'],
        'order' => ['LAST_NAME' => 'ASC', 'NAME' => 'ASC'],
    ]);
    while ($userInfo = $userList->fetch()) {
        $returnedUsers[] = $userInfo['ID'];
    }
    return $returnedUsers;

}

function getAllowedProjectsForReports($idOnly = false, $idNames = false) {
    global $USER;
    $userId = $USER->GetID();
    $allowedProjects = [];
    $projectFilter = ['IBLOCK_ID' => IBLOCK_PROJECT, 'ACTIVE' => 'Y', 'PROPERTY_ACCESS' => $userId];
    $projectSelect = ['ID', 'IBLOCK_ID', 'NAME', 'PROPERTY_RP', 'PROPERTY_SYSTEM_GROUP_ID'];
    $projectList = CIBlockElement::GetList(['NAME' => 'ASC'], $projectFilter, false, false, $projectSelect);
    while($project = $projectList->GetNext()) {
        if (!$idOnly && !$idNames) {
            $allowedProjects[$project['ID']] = $project;
        } elseif ($idNames) {
            $allowedProjects[$project['ID']] = $project['NAME'];
        } else {
            $allowedProjects[$project['ID']] = $project['ID'];
        }
    }
    return $allowedProjects;
}

function getNoticePopupData() {
    global $USER;
    $userId = $USER->GetID();
    $helper = new HighloadBlockHelper(HLBLOCK_NOTICE);
    $noticeList = $helper->getList([
        'order' => ['UF_SORT' => 'ASC', 'ID' => 'ASC'],
        'select' => ['*'],
        'filter' => []
    ])->fetchAll();
    $showPopup = false;
    foreach ($noticeList as &$notice) {
        switch ($notice['UF_ENTITY']) {
            case 'TASK':
                $fieldInfo = CUserFieldEnum::GetList([], [
                    'ID' => $notice['UF_STATUS'],
                ])->Fetch();
                $notice['status'] = $fieldInfo['XML_ID'];
                $taskFilter = [
                    'STATUS' => $notice['status'],
                    '<=CHANGED_DATE' => ConvertTimeStamp(time() - $notice['UF_TIME'] * 3600),
                    '::SUBFILTER-1' => [
                        '::LOGIC' => 'OR',
                        '::SUBFILTER-1' => [
                            'RESPONSIBLE_ID' => $userId,
                            'UF_PROJECT' => false
                        ],
                        '::SUBFILTER-2' => [
                            'ACCOMPLICE' => $userId,
                            '!UF_PROJECT' => false
                        ],
                    ],
                ];
                $taskList = CTasks::GetList(['CHANGED_DATE' => 'ASC'], $taskFilter);
                $notice['taskFilter'] = $taskFilter;
                while ($task = $taskList->Fetch()) {
                    $notice['tasks'][] = $task;
                    $showPopup = true;
                }
//                okp($fieldInfo);
                break;
            case 'PROJECT':
                $filter = ['UF_HEAD' => $userId, 'IBLOCK_ID' => IBLOCK_DEPARTMENT];
                $res = CIBlockSection::GetList([], $filter);
                $currentDepartments = [];
                $notice['filter'] = $filter;
                $notice['BRANCHES'] = $currentDepartments;
                while ($branch = $res->Fetch()) {
                    $currentDepartments[] = $branch['ID'];
                }
                $isResourceManager = false;
                if (!empty($currentDepartments)) {
                    $isResourceManager = true;
                }
                if ($isResourceManager) {
                    $taskFilter = [
                        '<=CHANGED_DATE' => ConvertTimeStamp(time() - $notice['UF_TIME'] * 3600),
                        'RESPONSIBLE_ID' => $userId,
                        '!UF_PROJECT' => false,
                        '!CREATED_BY' => $userId,
                        '!REAL_STATUS' => CTasks::STATE_COMPLETED
                    ];
                    $taskList = CTasks::GetList(['CHANGED_DATE' => 'ASC'], $taskFilter);
                    $notice['taskFilter'] = $taskFilter;
                    while ($task = $taskList->Fetch()) {
                        $showPopup = true;
                        $notice['tasks'][] = $task;
                    }
                }
                $projectFilter = [
                    'PROPERTY_ACCESS' => $userId,
                    'IBLOCK_ID' => IBLOCK_PROJECT,
                    'ACTIVE' => 'Y'
                ];
                $projectList = CIBlockElement::GetList([], $projectFilter, false, false, ['ID']);
                $logHelper = new HighloadBlockHelper(HLBLOCK_PROJECT_LOG);
                while ($projectInfo = $projectList->Fetch()) {
                    $projectId = $projectInfo['ID'];
                    $role = ProjectRoles::getRole($projectId, $userId, true);
                    if ($role == 'RESPONSIBLE' || $role == 'ACCEPTOR' || $role == 'RP_ASSIGNEE') {
                        if ($role == 'ACCEPTOR') {
                            $acceptionStatusMap = Project::getAcceptionStatuses();
                            $acceptHelper = new HighloadBlockHelper(HLBLOCK_PROJECT_ACCEPTION_LIST);
                            $acception = $acceptHelper->getList([
                                'filter' => ['UF_PROJECT' => $projectId, 'UF_USER_ID' => $userId],
                                'select' => ['ID', 'UF_USER_ID', 'UF_STATUS']
                            ])->fetch();
                            if ($acception['UF_STATUS'] == $acceptionStatusMap['DECLINED'] || $acception['UF_STATUS'] == $acceptionStatusMap['ACCEPTED']) {
                                continue;
                            }
                        }

                        $log = $logHelper->getList([
                            'select' => ['*'],
                            'filter' => [
                                'UF_PROJECT' => $projectId,
                                'UF_WHERE' => 'Этап цепочки согласований',
                            ],
                            'order' => ['UF_DATE' => 'desc'],
                            'limit' => 1
                        ])->fetch();
                        if ($log['UF_DATE'] instanceof Bitrix\Main\Type\DateTime)
                            $log['UF_DATE'] = $log['UF_DATE']->toString();
                        if (time() - strtotime($log['UF_DATE']) > 3600 * $notice['UF_TIME']) {
                            $projectInfo['log'] = $log;
                            $projectInfo['role'] = $role;
                            $notice['projects'][] = $projectInfo;
                            $showPopup = true;
                        }
                    }
                }
//                if (in_array($userId, array_unique([Project::getResSubGenDir(), Project::getGenDir(), Project::getFinSubGenDir(), Project::getCommersant()]))) {
//
//                }
                break;
        }
    }
    $noticeList['showPopup'] = $showPopup;
    return $noticeList;
}

function getNoticePopup($noticeList) {
    global $USER;
    $userId = $USER->GetID();
    ?>
    <div class="popup-notice" id="notice-popup">
        <div class="border-icon-title">
            <div class="border-icon-img"><img src="/local/assets/img/block-icon-note.png" alt=""></div>
            <h3>Уведомления</h3>
        </div>
        <?// okp($noticeList);?>
        <div class="notice-row">
            <?
            foreach ($noticeList as $key => $noticeInfo) {
                ?>
                <div class="notice-col notice-col-<?=$noticeInfo['UF_COLOR'];?>">
                    <div class="notice-col-title"><strong><?=$noticeInfo['UF_NAME'];?></strong></div>
                    <?
                    if ($noticeInfo['UF_ENTITY'] == 'TASK') {
                        if (empty($noticeInfo['tasks'])) {
                            ?><span class="notice-empty"><?=$noticeInfo['UF_NO_ELEMENTS'];?></span><?
                        }?>
                        <div class="notice-col-list" id="notice-col-list-<?=$key?>">
                            <?
                            foreach ($noticeInfo['tasks'] as $taskData) {
                                ?>
                                <div class="notice-col-item">
                                    <div class="notice-col-content">
                                        <div class="notice-col-name"><a href="#" data-href="/company/personal/user/<?=$userId?>/tasks/task/view/<?=$taskData['ID'];?>/"><?=$taskData['TITLE'];?></a></div>
                                        <div class="notice-col-text"><?=$taskData['DESCRIPTION'];?></div>
                                    </div>
                                    <div class="notice-col-time">
                                        <div class="notice-col-days"><?=FormatDate('-ddiff', strtotime($taskData['CHANGED_DATE']));?></div>
                                        <div class="notice-col-date"><?=$taskData['CHANGED_DATE'];?></div>
                                    </div>
                                </div>
                                <?
                            }
                            ?>
                        </div>
                    <?} elseif ($noticeInfo['UF_ENTITY'] == 'PROJECT') {
                        if (empty($noticeInfo['tasks']) && empty($noticeInfo['projects'])) {
                            ?><span class="notice-empty"><?=$noticeInfo['UF_NO_ELEMENTS'];?></span><?
                        }?>
                        <div class="notice-col-list" id="notice-col-list-<?=$key?>">
                            <?
                            foreach ($noticeInfo['tasks'] as $taskData) {
                                ?>
                                <div class="notice-col-item">
                                    <div class="notice-col-content">
                                        <div class="notice-col-name"><a href="#" data-href="/company/personal/user/<?=$userId?>/tasks/task/view/<?=$taskData['ID'];?>/"><?=$taskData['TITLE'];?></a></div>
                                        <div class="notice-col-text">Требуется назначить исполнителей и/или время выполнения для задачи</div>
                                    </div>
                                    <div class="notice-col-time">
                                        <div class="notice-col-days"><?=FormatDate('-ddiff', strtotime($taskData['CHANGED_DATE']));?></div>
                                        <div class="notice-col-date"><?=$taskData['CHANGED_DATE'];?></div>
                                    </div>
                                </div>
                                <?
                            }
                            foreach ($noticeInfo['projects'] as $projectData) {

                                ?>
                                <div class="notice-col-item">
                                    <div class="notice-col-content">
                                        <div class="notice-col-name"><?=getUserLinkById($projectData['log']['UF_AUTHOR']);?></div>
                                        <div class="notice-col-text">Проект <?=Project::getProjectLink($projectData['ID'], true, 'notice-large-link')?> перешел на этап «<?=substr($projectData['log']['UF_WHAT'], 1);?>».</div>
                                    </div>
                                    <?/*<div class="notice-col-time">
                                <div class="notice-col-days"><?=FormatDate('-ddiff', strtotime($projectData['log']['UF_DATE']));?></div>
                            </div>*/?>
                                </div>
                                <?
                            }
                            ?>
                        </div>
                    <?}?>
                </div>
            <?}?>
        </div>
    </div>
    <?
}

function getGreetingsPopup() {
    global $USER;
    $helper = new HighloadBlockHelper(16);
    $greeting = $helper->getList([
        'select' => ['UF_GREETING'],
        'runtime' => array('RAND'=>array('data_type' => 'float', 'expression' => array('RAND()'))),
        'order' => array('RAND'=>'ASC'),
        'limit' => 1,
    ])->fetch()['UF_GREETING'];

//    if ($_GET['greetings'] == 'Y') {
//        $greeting = str_replace('#USER#', 'Денис Сергеевич', $greeting);
//    } else {
    $greeting = str_replace('#USER#', getUserLinkById($USER->GetID(), true, ['NAME', 'SECOND_NAME']), $greeting);
//    }
    $greeting = TxtToHTML($greeting);
    $helper = new VoteEditHelper();
    $activeVote = $helper->getActiveVote();
    $communityInviteSent = true; //CUserOptions::GetOption('community', 'invite_sent', false);
    ?>
    <div class="start-hello">
        <div class="start-hello-holder"><img src="/build/new/img/hello-icon.svg" alt>
            <div class="start-hello-text"><?=$greeting?>
                <?
                if (!$communityInviteSent) {
                    CUserOptions::SetOption('community', 'invite_sent', true);
                    ?>
                    <p>Предлагаем присоединиться к Росгео Комьюнити</p>
                    <a href="https://community.rosgeologia.corp" class="button button-inverse">Принять приглашение</a>
                    <a href="#" onclick="$.magnificPopup.close(); return false;" class="button button-beige">Отказаться</a>
                <?} elseif ($activeVote) {?>
                    <p>Предлагаем пройти участие в опросе «<?=$activeVote['TITLE']?>»</p>
                    <a href="/poll/?id=<?=$activeVote['ID'];?>" class="button button-inverse">Принять участие</a>
                    <a href="#" onclick="$.magnificPopup.close(); return false;" class="button button-beige">Отказаться</a>
                <?}?>
            </div>
        </div>
    </div>
    <?
}

function getLastViewNameClass($projectData, $prefix = ' project-list-status') {
    $step = $projectData['PROP']['STEP']['VALUE_XML_ID'];
//    okp(Project::getStepCodes());
    if (!$step) {
        $step = Project::getStepCodes()[$projectData['PROPERTY_STEP_ENUM_ID']];
    }
//    okp($step);
//    okp($projectData);
    $projectId = $projectData['ID'];
    global $USER;
    $userId = $USER->GetID();
    $helper = new HighloadBlockHelper(HLBLOCK_PROJECT_VIEW);
    $fields = ['UF_USER' => $userId, 'UF_PROJECT' => $projectId];
    $lastView = $helper->getList([
        'filter' => $fields,
        'select' => ['*'],
        'order' => ['UF_DATE' => 'desc']
    ])->fetch();
    if ($lastView['UF_DATE'] instanceof \Bitrix\Main\Type\DateTime) {
        $lastView['UF_DATE'] = $lastView['UF_DATE']->toString();
    }
    $extraNameClass = '';
    if ($step == 'PROJECT_CLOSED' || strpos($step, '_ARCHIVE') !== false) {
        $extraNameClass = $prefix . '-completed';
    } else {
        if (empty($lastView)) {
            $extraNameClass .= $prefix . '-new';
        }
        $lastModified = strtotime($projectData['TIMESTAMP_X']);
        $lastViewed = $lastView['UF_DATE'] ? strtotime($lastView['UF_DATE']) : false;
        if ($lastViewed && $lastModified - $lastViewed > 3 * 86400 || !$lastViewed && time() - strtotime($projectData['DATE_CREATE']) > 3 * 86400) {
            $extraNameClass .= $prefix . '-overdue';
        }
    }
    return $extraNameClass;
}

function getNotShowCompletedEntityCheckbox($entity = 'tasks', $entityName = 'задачи') {
    $checked = \Bitrix\Main\Config\Option::get('tasks', 'not_show_closed_' . $entity . '_' . $GLOBALS['USER']->GetID(), 'N') == 'Y';
    if ($_GET['not_show_closed_' . $entity . '_form'] == 'Y') {
        $checked = $_GET['not_show_closed_' . $entity . ''];
    }
    return '<form action="" method="GET" class="tasks-list-filter-small">
                <div class="tasks-list-filter-checkbox">
                    <input type="checkbox" id="not_show_closed_' . $entity . '" name="not_show_closed_' . $entity . '" ' . ($checked ? 'checked' : '') . ' onclick="$(this).closest(\'form\').submit();"/>
                    <label for="not_show_closed_' . $entity . '">Не отображать завершенные ' . $entityName . '</label>
                    <input type="hidden" name="not_show_closed_' . $entity . '_form" value="Y"/>
                </div>
            </form>';
}

function getShowOnlyCompletedEntityCheckbox($entity = 'tasks', $entityName = 'задачи') {
    $checked = $_GET['show_only_closed_' . $entity . ''];
    return '<form action="" method="GET" class="tasks-list-filter-small">
                <div class="tasks-list-filter-checkbox">
                    <input type="checkbox" id="show_only_closed_' . $entity . '" name="show_only_closed_' . $entity . '" ' . ($checked ? 'checked' : '') . ' onclick="$(this).closest(\'form\').submit();"/>
                    <label for="show_only_closed_' . $entity . '">Завершенные ' . $entityName . '</label>
                    <input type="hidden" name="show_only_closed_' . $entity . '_form" value="Y"/>
                </div>
            </form>';
}

function getShowOnlyOverdueEntityCheckbox($entity = 'tasks', $entityName = 'задачи') {
    $checked = $_GET['show_only_overdue_' . $entity . ''];
    return '<form action="" method="GET" class="tasks-list-filter-small">
                <div class="tasks-list-filter-checkbox">
                    <input type="checkbox" id="show_only_overdue_' . $entity . '" name="show_only_overdue_' . $entity . '" ' . ($checked ? 'checked' : '') . ' onclick="$(this).closest(\'form\').submit();"/>
                    <label for="show_only_overdue_' . $entity . '">Просроченные ' . $entityName . '</label>
                    <input type="hidden" name="show_only_overdue_' . $entity . '_form" value="Y"/>
                </div>
            </form>';
}

function getNotShowCompletedTasksCheckbox() {
    return getNotShowCompletedEntityCheckbox('tasks');
}

function getProjectTasksFilters() {
    return '<div class="project-tasks-filters-container">' . getShowOnlyOverdueEntityCheckbox() . getShowOnlyCompletedEntityCheckbox() . getNotShowCompletedEntityCheckbox() . '</div>';
}

function getTaskLink($taskId, $taskTitle, $userId = false) {
    global $USER;
    if (!$userId) {
        $userId = $USER->GetID();
    }

    $link = '<a href="/company/personal/user/' . $userId . '/tasks/task/view/' . $taskId . '/">' . $taskTitle . '</a>';
    return $link;
}

function getExecutorTaskStatusCode($status) {
    switch ($status) {
        case CTasks::STATE_IN_PROGRESS:
            $userStatus = 'IN_PROGRESS';
            break;
        case CTasks::STATE_DEFERRED:
            $userStatus = 'PAUSED';
            break;
        case CTasks::STATE_COMPLETED:
            $userStatus = 'DONE';
            break;
        case CTasks::STATE_PENDING:
            $userStatus = 'NONE';
            break;
        default:
            $userStatus = '';
            break;
    }
    return $userStatus;
}

function isImage($url)
{
    $params = array('http' => array(
        'method' => 'HEAD'
    ));
    $ctx = stream_context_create($params);
    $fp = @fopen($url, 'rb', false, $ctx);
    if (!$fp)
        return false;  // Problem with url

    $meta = stream_get_meta_data($fp);
    if ($meta === false)
    {
        fclose($fp);
        return false;  // Problem reading data from url
    }

    $wrapper_data = $meta["wrapper_data"];
    if(is_array($wrapper_data)){
        foreach(array_keys($wrapper_data) as $hh){
            if (substr($wrapper_data[$hh], 0, 19) == "Content-Type: image") // strlen("Content-Type: image") == 19
            {
                fclose($fp);
                return true;
            }
        }
    }

    fclose($fp);
    return false;
}

function addFileLog(\Bitrix\Disk\File $file, $description = '') {
    $fileArray = $file->toArray();
    global $USER;
    $helper = new HighloadBlockHelper(10);
    $realPath = CFile::GetPath($fileArray['FILE_ID']);
    $md5 = md5_file($_SERVER['DOCUMENT_ROOT'] . $realPath);
    $urlManager = \Bitrix\Disk\Driver::getInstance()->getUrlManager();
    $path = $urlManager->getPathFileDetail($file);
    $storage = \Bitrix\Disk\Storage::loadById($fileArray['STORAGE_ID']);
    $projectId = $storage->getEntityId();
    if (strpos($projectId, 'PROJECT') === false) {
        return true;
    }
    $projectId = str_replace('PROJECT_', '', $projectId);
    if ($file->isDeleted()) {
        $folder = 'Корзина';
    } else {
        $folder = str_replace($fileArray['NAME'], '', $path);
        $folder = preg_replace('/(\/projects\/all\/[A-Za-z_0-9]+\/disk\/file)/', '', $folder);
    }
    $fields = [
        'UF_FL_PROJECT' => $projectId,
        'UF_FL_CREATE' => date('d.m.Y H:i:s'),
        'UF_FL_AUTHOR' => $USER->GetID(),
        'UF_FL_FILENAME' => $fileArray['NAME'],
        'UF_FL_FOLDER' => $folder,
        'UF_FL_PATH' => $path,
        'UF_FL_SIZE' => $fileArray['SIZE'],
        'UF_FL_MD5' => $md5,
        'UF_FL_DESCRIPTION' => $description,
        'UF_FL_FILE_ID' => $fileArray['ID']
    ];
    $helper->add($fields);

    $realFolder = $folder;
    if ($file->isDeleted()) {
        $realFolder = '/trashcan/';
    }
    $realFolder = Project::getProjectLink($projectId, false) . 'disk' . $realFolder;
    foreach(Project::getRpAndAssistant($projectId) as $userTo) {
        global $USER;
        $message = "В проекте " . Project::getProjectLink($projectId) .
            " $description <a href=\"" . $realFolder . '">' . $fileArray['NAME'] . "</a>.";
        Project::notify($USER->GetID(), $userTo, $message);
    }

}

function getDocFlowStatus($statusId, $statusText) {
    return $statusText ? $statusText : \Bitrix\Iblock\ElementTable::getList(['filter' => ['ID' => $statusId], 'select' => ['NAME']])->fetch()['NAME'];
}

function getDocFlowLink($id, $asHtml = true, $class = '') {
    if (!$id) {
        return false;
    }
    $link = '/docflow/flow/' . $id . '/';
    \Bitrix\Main\Loader::includeModule('iblock');
    $name = \Bitrix\Iblock\ElementTable::getList(['filter' => ['ID' => $id], 'select' => ['NAME']])->fetch()['NAME'];

    if ($asHtml) {
        return '<a href="' . $link . '"' . ($class ? ' class="' . $class . '"' : '') . '>' . $name . '</a>';
    } else {
        return $link;
    }
}

function getUserByLogin($userLogin, $select = ['ID']) {
    if (!$userLogin)
        return false;
    $userInfo = \Bitrix\Main\UserTable::getList([
        'filter' => ['LOGIN' => $userLogin],
        'select' => $select
    ])->fetch();
    return $userInfo;
}

function getFirstHead($userId = false) {
    global $USER;
    if (!$userId)
        $userId = $USER->GetID();

    \Bitrix\Main\Loader::includeModule('iblock');
    $entity = \Bitrix\Iblock\Model\Section::compileEntityByIblock(IBLOCK_DEPARTMENT);
    $sectionInfo = $entity::getList([
        'filter' => ['ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT, 'UF_HEAD' => $userId],
        'select' => ['NAME', 'ID', 'UF_HEAD']
    ])->fetch();
    if (!$sectionInfo) {
        $userDepartments = getUserInfoById($userId, ['UF_DEPARTMENT'])['UF_DEPARTMENT'];
        if (!empty($userDepartments)) {
            $head = false;
            $count = 0;
            while (!$head) {
                if (!empty($userDepartments)) {
                    foreach ($userDepartments as $section) {
                        $head = getDepartmentHead($section);
                        if ($head)
                            break;
                    }
                    if ($head)
                        return $head;

                    $userSectionsInfo = $entity::getList([
                        'filter' => ['ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT, '@ID' => $userDepartments],
                        'select' => ['IBLOCK_SECTION_ID']
                    ])->fetchAll();
                    $userDepartments = [];
                    foreach ($userSectionsInfo as $section) {
                        $userDepartments[] = $section['IBLOCK_SECTION_ID'];
                    }
                } else {
                    return false;
                }
                if (++$count > 10) {
                    return false;
                }
            }
        }
        return false;
    } else {
        return $userId;
    }
}

function isFirstHead($userId = false) {
    global $USER;
    if (!$userId)
        $userId = $USER->GetID();

    return $userId == getFirstHead($userId);
}


function getUserDepartments($userId = false) {
    if (!$userId) {
        global $USER;
        $userId = $USER->GetID();
    }
    $userDeparmentsIds = \Bitrix\Main\UserTable::getList(['filter' => ['=ID' => $userId], 'select' => ['UF_DEPARTMENT']])->fetch()['UF_DEPARTMENT'];

    \Bitrix\Main\Loader::includeModule('iblock');
    $sectionList = \Bitrix\Iblock\SectionTable::getList([
        'filter' => ['ID' => $userDeparmentsIds, 'ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT],
        'select' => ['NAME', 'ID']
    ])->fetchAll();
    $result = [];
    foreach ($sectionList as $sectionInfo) {
        $result[] = $sectionInfo['NAME'];
    }
    return implode(' - ', $result);
}

function getUserDepartmentsChain($userId = false) {
    if (!$userId) {
        global $USER;
        $userId = $USER->GetID();
    }

    $userDeparmentsIds = \Bitrix\Main\UserTable::getList(['filter' => ['=ID' => $userId], 'select' => ['UF_DEPARTMENT']])->fetch()['UF_DEPARTMENT'];

    \Bitrix\Main\Loader::includeModule('iblock');
    $section = \Bitrix\Iblock\SectionTable::getList([
        'filter' => ['ID' => $userDeparmentsIds, 'ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT],
        'select' => ['NAME', 'ID', 'IBLOCK_SECTION_ID', 'DEPTH_LEVEL'],
        'order' => ['DEPTH_LEVEL' => 'desc'],
        'limit' => 1
    ])->fetch();
    $departments = [];
    while ($section['DEPTH_LEVEL'] > 1) {
        if (strpos(strtoupper($section['NAME']), 'ОТДЕЛ') !== false) {
            $section['DEPTH_LEVEL'] = 5;
        }
        if (strpos(strtoupper($section['NAME']), 'ДЕПАРТАМЕНТ') !== false) {
            $section['DEPTH_LEVEL'] = 4;
        }
        if (strpos(strtoupper($section['NAME']), 'ДИРЕКЦИЯ') !== false) {
            $section['DEPTH_LEVEL'] = 3;
        }
        if (strpos(strtoupper($section['NAME']), 'БЛОК') === 0) {
            $section['DEPTH_LEVEL'] = 2;
        }
        if (strpos(strtoupper($section['NAME']), 'ЦЕНТР РАЗВИТИЯ ЦИФРОВЫХ ТЕХНОЛОГИЙ') !== false) {
            $section['DEPTH_LEVEL'] = 3;
        }
        $departments[$section['DEPTH_LEVEL']] = $section;
        if ($section['DEPTH_LEVEL'] == 2) {
            break;
        }
        $oldSection = $section;
        $section = \Bitrix\Iblock\SectionTable::getList([
            'filter' => ['ID' => $oldSection['IBLOCK_SECTION_ID'], 'ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT],
            'select' => ['NAME', 'ID', 'IBLOCK_SECTION_ID', 'DEPTH_LEVEL'],
        ])->fetch();
    }

    return $departments;
}

function getSystemTaskFields() {
    return [
        'UF_TASK_WEBDAV_FILES',
        'UF_BRANCH',
        'UF_PROD_CAL',
        'UF_PERCENT',
        'UF_TIME_SPENT',
        'UF_EXTRA_USER',
        'UF_MAIL_MESSAGE',
        'UF_COWORKER_BIRTHDAY',
    ];
}

function getTaskParents($taskId) {
    $taskInfo = \Bitrix\Tasks\Internals\TaskTable::getList(['filter' => ['=ID' => $taskId], 'select' => ['ID', 'PARENT_ID', 'TITLE']])->fetch();
    $parentId = $taskInfo['PARENT_ID'];
    $line = [];
    global $USER;
    $userId = $USER->GetID();
    while ($parentId > 0) {
        $taskInfo = \Bitrix\Tasks\Internals\TaskTable::getList(['filter' => ['=ID' => $parentId], 'select' => ['ID', 'PARENT_ID', 'TITLE']])->fetch();
        $parentId = $taskInfo['PARENT_ID'];
        $line[] =  '<a href="/company/personal/user/' . $userId . '/tasks/task/view/' . $taskId . '/">' . $taskInfo['TITLE'] . '</a>';
    }
    krsort($line);
    return implode(' &rarr;&nbsp;', $line);
}

function checkTaskTitle($title) {
    require_once $_SERVER["DOCUMENT_ROOT"] . '/local/composer/vendor/autoload.php';
    $dir = $_SERVER["DOCUMENT_ROOT"] . '/local/composer/vendor/cijic/phpmorphy/libs/phpmorphy/dicts';
    $morphy = new phpMorphy($dir, 'ru_RU', ['graminfo_as_text' => false]);
    $newTitle = mb_ereg_replace('[^а-яА-Я]+', ' ', $title);
    $newTitle = mb_ereg_replace('[ ]{2,}', ' ', $newTitle);
    $wordList = explode(' ', $newTitle);

    foreach ($wordList as $word) {
        $speechParts = ($morphy->getPartOfSpeech(mb_strtoupper($word)));
        foreach ($speechParts as $part) {
            if ($part == 21 && mb_strlen($word) >= 4 && strtoupper($word) != 'ОТЧЕТ' && strtoupper($word) != 'ОТЧЁТ') {
                return true;
            }
        }
    }
    return false;
}

function getTaskGroupByElements() {
    $allowed = [
        'UF_PROJECT',
//        'UF_ACTIVITY_LIST',
        'UF_ACTIVE_LIST_DICT',
        'UF_PRIORITET',
        'UF_STAGE',
    ];
    $list = \Bitrix\Main\UserFieldTable::getList([
        'filter' => [
            'ENTITY_ID' => 'TASKS_TASK',
            'LANG_ID' => 'ru',
            '@FIELD_NAME' => $allowed,
        ],
        runtime => [
            'LANG' => array(
                'data_type' => 'Bitrix\Main\UserFieldLangTable',
                'reference' => array(
                    '=this.ID' => 'ref.USER_FIELD_ID',
                )
            ),
        ],
        'select' => [
            'FIELD_NAME',
            'LANG_ID' => 'LANG.LANGUAGE_ID',
            'LANG_LABEL' => 'LANG.EDIT_FORM_LABEL',
        ]
    ])->fetchAll();
    return $list;
}

function getTaskFieldValueName($fieldName, $value, $asHtml = true) {
    $result = '';
    if ($value === 0)
        return '';
    switch ($fieldName) {
        case 'UF_PROJECT':
            $result = Project::getProjectLink($value);
            break;
        case 'UF_STAGE':
            $helper = new HighloadBlockHelper(HLBLOCK_TASK_STAGES);
            $result = $helper->getList(['filter' => ['=ID' => $value], 'select' => ['UF_NAME']])->fetch()['UF_NAME'];
            break;
        case 'UF_ACTIVE_LIST_DICT':
            $result = getActivityName($value);
            break;
        default:
            $result = \CUserFieldEnum::GetList([],['ID' => $value])->Fetch()['VALUE'];
            break;
    }
    return $result;
}

function getActivityName($id) {
    $id = intval($id);
    if (!$id) {
        return 'Не указано';
    }
    $helper = new HighloadBlockHelper(HLBLOCK_ACTIVITY_LIST);
    $result = $helper->getList([
        'filter' => ['=ID' => $id],
        'select' => ['UF_NAME']
    ])->fetch()['UF_NAME'];
    return $result ? $result : 'Не указано';
}

function getClientTime($time = null, $forDB = false) {
    if (!$time) {
        $time = time();
    }
    if (!$forDB) {
        return $time - CTimeZone::GetCookieValue() * 60 - date('Z');
    } else {
        return $time + CTimeZone::GetCookieValue() * 60 + date('Z');
    }
}


function getUserExchangeCalendarEvents($id) {
    if (!$id) {
        echo "не указан id!";
        return false;
    }
    require_once $_SERVER["DOCUMENT_ROOT"] . '/local/php_interface/include/classes/morev/bootstrap.php';

    try {
        global $DB;
        $email = getUserInfoById($id, ['EMAIL'])['EMAIL'];
        $helper = new HighloadBlockHelper(HLBLOCK_EXCHANGE_CALENDAR_LOG);
        $handler = \App\Lib\Instance\InstanceFabric::getEWSHandler();
        $bitrix = \App\Lib\Instance\InstanceFabric::getBitrixHandler(true);
        oklog('Начало работы', 'exchange/user_' . $id);
        $newEvents = $handler->fetchNewEvents([$email]);
        oklog(date('d.m.Y H:i:s') . '. Получено ' . count($newEvents) . ' встреч,' . " созданных за последние сутки", 'exchange/user_' . $id);
        $count = [
            'new' => 0,
            'exist' => 0
        ];
        foreach ($newEvents as $event) {
            if ($event instanceof \App\Lib\Elements\Calendar\CalendarEvent) {
                $upperTitle = mb_strtoupper($event->getSubject());
                if (mb_strpos($upperTitle, 'CANCELED:') !== false || mb_strpos($upperTitle, 'ОТМЕНЕНО:') !== false || mb_strpos($upperTitle, 'УДАЛЕН ') !== false || mb_strpos($upperTitle, 'УДАЛЁН ') !== false) {
                    oklog($id . ': ' . $upperTitle, 'exchange_canceled');
                    continue;
                } else {
                    oklog($id . ': ' . $upperTitle, 'exchange_non_canceled');
                }
                $subject = $event->getSubject();
                $subject = str_replace('\\', '', $subject);
                $recordFields = [
                    'UF_TITLE' => $subject,
//                    'UF_TIME_CREATED' => \Bitrix\Main\Type\DateTime::createFromTimestamp(strtotime($event->getCreatedTime())),
                    'UF_DATE' => \Bitrix\Main\Type\Date::createFromTimestamp(strtotime($event->getStartTime())),
//                    'UF_TIME_START' => \Bitrix\Main\Type\DateTime::createFromTimestamp(strtotime($event->getStartTime())),
                    'UF_USER' => $id,
                ];
                $record = $helper->getList([
                    'filter' => $recordFields,
                    'select' => ['ID', 'UF_TASK']
                ])->fetch();
                oklog($recordFields, 'user/' . $id . '/record.log');
                oklog($record, 'user/' . $id . '/record.log');
                if (!$record) {
                    $recordFields['UF_TIME_CREATED'] = \Bitrix\Main\Type\DateTime::createFromTimestamp(strtotime($event->getCreatedTime()));
                    $recordFields['UF_TIME_START'] = \Bitrix\Main\Type\DateTime::createFromTimestamp(strtotime($event->getStartTime()));
                    $recordId = $helper->add($recordFields)->getId();
                } else {
                    $recordId = $record['ID'];
                }
                if (!$recordId) {
                    oklog('Не удалось найти или создать запись по событию', 'exchange/user_' . $id);
                    oklog($recordFields, 'exchange/user_' . $id);
                    continue;
                } else {
                    if (!$record && !$record['UF_TASK']) {
                        $ewsTask = $handler->createNewTaskFromEvent($event);
                        $ewsTask->setDelegator($ewsTask->getUserEmail());
                        $created = $bitrix->createBitrixTask($ewsTask);
                        if ($created > 0) {
                            $helper->update($recordId, ['UF_TASK' => $created, 'UF_LAST_MODIFIED' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time())]);
                        }
                        ++$count['new'];
                    } else {
                        ++$count['exist'];
                    }
                }
            }
        }
        oklog("Создано {$count['new']} новых задач", 'exchange/user_' . $id);
        oklog("Создано ранее {$count['exist']} задач", 'exchange/user_' . $id);

        global $USER;
        $USER->Update($id, ['UF_EX_SYNC_CALENDAR_TIME' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time())]);
        return true;

    } catch (Exception $e) {
        oklog($e->getFile() . ', ' . $e->getLine() . ': ' . $e->getMessage(), 'sync_calendar_new.error');
        return false;
    }
}


function fillBitrixTaskFields($responsibleId, $creatorId, App\Lib\Elements\Task\Task $exchangeTask) {
    $handler = App\Lib\Instance\InstanceFabric::getEWSHandler();
    $task = $handler->getTask($exchangeTask->getId());

    $bitrixTaskFields = array(
        "TITLE" => $task->getSubject(),
        'RESPONSIBLE_ID' => $responsibleId,
        'CREATED_BY' => $creatorId,
        "DESCRIPTION" => $task->getBodyText(),
        "PRIORITY" => $task->getImportance() == ImportanceChoicesType::LOW ? 0 :
            ($task->getImportance() == ImportanceChoicesType::NORMAL ? 1 : 2),
        "DURATION_PLAN" => $task->getActualWork(),
        "DURATION_TYPE" => 'mins',
    );
    switch ($task->getStatus()) {
        case TaskStatusType::NOT_STARTED:
            $bitrixTaskFields["STATUS"] = 1;
            break;
        case TaskStatusType::WAITING_ON_OTHERS:
            $bitrixTaskFields["STATUS"] = 2;
            break;
        case TaskStatusType::IN_PROGRESS:
            $bitrixTaskFields["STATUS"] = 3;
            break;
        case TaskStatusType::COMPLETED:
            $bitrixTaskFields["STATUS"] = 5;
            break;
        case TaskStatusType::DEFERRED:
            $bitrixTaskFields["STATUS"] = 6;
    }
    if ($task->getDueDate() != null && !$task->isFromEvent()) {
        $bitrixTaskFields["DEADLINE"] = \DateTime::createFromFormat("Y-m-d\TH:i:s\Z", $task->getDueDate())->modify(
                "+3 hours"
            )->format("d.m.Y").' 21:00:00';
    }

    if ($task->getStartTime() != null) {
        $bitrixTaskFields["START_DATE_PLAN"] = \DateTime::createFromFormat(
            "Y-m-d\TH:i:s\Z",
            $task->getStartTime()
        )->modify(
            "+3 hours"
        )->format("d.m.Y H:i:s");
    }

    $bitrixTaskFields['TITLE'] = "Outlook: ".$bitrixTaskFields["TITLE"];

    return $bitrixTaskFields;
}

function getUserExchangeTasks($id) {
    if (!$id) {
        echo "не указан id!";
        return false;
    }
    require_once $_SERVER["DOCUMENT_ROOT"] . '/local/php_interface/include/classes/morev/bootstrap.php';

    try {
        $email = getUserInfoById($id, ['EMAIL'])['EMAIL'];
        $helper = new HighloadBlockHelper('ExchangeTasksLog');
        $handler = \App\Lib\Instance\InstanceFabric::getEWSHandler();
        $bitrix = \App\Lib\Instance\InstanceFabric::getBitrixHandler(true);
        echo 'Пользователь №' . $id . '. Начало работы - ' . date('d.m.Y H:i:s') . "\n";
        $fetchedTasks = $handler->fetchAllTasks([$email]);
        echo date('d.m.Y H:i:s') . '. Получено ' . count($fetchedTasks) . ' задач' . "" . "\n";
        oklog($fetchedTasks, 'tasks/all_' . $id);
        foreach ($fetchedTasks as $task) {
            if ($task instanceof  App\Lib\Elements\Task\Task) {
                okp($id . ' -> ' . $task->getUniqueIdForSystem());
                if (!$task->getDelegator()) {
                    if (!$task->getDisplayTo()) {
                        // задача вида сам -> себе
                        // ищем, есть ли в логе
                        $taskInLog = $helper->getList([
                            'filter' => [
                                'UF_XML_ID' => $task->getUniqueIdForSystem(),
                                'UF_CREATOR' => $id,
                                'UF_RESPONSIBLE' => $id,
                                '!UF_TASK' => false,
                            ],
                            'select' => ['ID']
                        ])->fetch();
                        if (!empty($taskInLog)) {
                            okp('continued');
                            continue;
                        }
                        // просто создаем задачу :)
                        $logFields = [
                            'UF_XML_ID' => $task->getUniqueIdForSystem(),
                            'UF_CREATOR' => $id,
                            'UF_RESPONSIBLE' => $id,
                            'UF_LAST_MODIFIED' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time()),
                            'UF_TITLE' => $task->getSubject(),
                        ];
                        $logId = $helper->add($logFields)->getId();

                        $obTasks = new CTasks();
                        $taskId = $obTasks->Add(fillBitrixTaskFields($id, $id, $task));
                        if ($logId) {
                            $helper->update($logId, [
                                'UF_TASK' => $taskId,
                                'UF_LAST_MODIFIED' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time())
                            ]);
                            $bitrix->getBitrixConnector()->connectElements($taskId, $task->getId()->Id);
                        }
                    } else {
                        // задача вида сам -> кому-то
                        // если все создано уже, то идем дальше
                        $taskInLog = $helper->getList([
                            'filter' => [
                                'UF_XML_ID' => $task->getUniqueIdForSystem(),
                                'UF_CREATOR' => $id,
//                                '!UF_TASK' => false,
                            ],
                            'select' => ['ID']
                        ])->fetch();
                        if (!empty($taskInLog)) {
                            okp('continued');
                            continue;
                        }
                        // чекаем, есть ли в логе эта задача без создателя,
                        $logFields = [
                            'UF_XML_ID' => $task->getUniqueIdForSystem(),
                            'UF_CREATOR' => false,
                        ];
                        $existLogRecords = $helper->getList(['filter' => $logFields, 'select' => ['*']])->fetchAll();
                        // заполняем во всех таких создателя и создаем в битриксе,
                        foreach ($existLogRecords as $logRecord) {
                            $helper->update($logRecord['ID'], [
                                'UF_CREATOR' => $id,
                                'UF_LAST_MODIFIED' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time())
                            ]);
                            $obTasks = new CTasks();
                            $taskId = $obTasks->Add(fillBitrixTaskFields($logRecord['UF_RESPONSIBLE'], $id, $task));
                            if ($taskId > 0) {
                                $helper->update($logRecord['ID'], [
                                    'UF_TASK' => $taskId,
                                    'UF_LAST_MODIFIED' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time())
                                ]);
                                $bitrix->getBitrixConnector()->connectElements($taskId, $task->getId()->Id);
                            } else {
                                okp($obTasks->getLastOperationResultData());
                            }
                        }
                        // далее создаем N-<кол-во задач без создателя> без ответственного в логе
                        for ($count = mb_substr_count($task->getDisplayTo(), ';') + 1 - count($existLogRecords); $count > 0; --$count) {
                            $helper->add([
                                'UF_XML_ID' => $task->getUniqueIdForSystem(),
                                'UF_CREATOR' => $id,
                                'UF_LAST_MODIFIED' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time()),
                                'UF_TITLE' => $task->getSubject(),
                            ]);
                        }
                    }
                } else {
                    // задача вида кто-то тебе
                    // если все создано уже, то идем дальше
                    $taskInLog = $helper->getList([
                        'filter' => [
                            'UF_XML_ID' => $task->getUniqueIdForSystem(),
                            'UF_RESPONSIBLE' => $id,
//                            '!UF_TASK' => false,
                        ],
                        'select' => ['ID']
                    ])->fetch();
                    if (!empty($taskInLog)) {
                        okp('continued');
                        continue;
                    }
                    // ищем в логе задачу с данным айди без ответственного, заполняем ответственного текущим юзером,
                    $logFields = [
                        'UF_XML_ID' => $task->getUniqueIdForSystem(),
                        '!UF_CREATOR' => false,
                        'UF_RESPONSIBLE' => false,
                    ];
                    $logRecord = $helper->getList(['filter' => $logFields, 'select' => ['*']])->fetch();
                    oklog($logRecord,'tasks/non-delegator');
                    if (empty($logRecord)) {
                        $helper->add([
                            'UF_XML_ID' => $task->getUniqueIdForSystem(),
                            'UF_RESPONSIBLE' => $id,
                            'UF_LAST_MODIFIED' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time()),
                            'UF_TITLE' => $task->getSubject(),
                        ]);
                    } else {
                        $obTasks = new CTasks();
                        $taskId = $obTasks->Add(fillBitrixTaskFields($id, $logRecord['UF_CREATOR'], $task));
                        if ($taskId > 0) {
                            $helper->update($logRecord['ID'], [
                                'UF_TASK' => $taskId,
                                'UF_RESPONSIBLE' => $id,
                                'UF_LAST_MODIFIED' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time())
                            ]);
                            $bitrix->getBitrixConnector()->connectElements($taskId, $task->getId()->Id);
                        } else {
                            okp($obTasks->getLastOperationResultData());
                        }
                    }
                    // создаем задачу в битриксе
                }
            }
        }
        global $USER;
        $USER->Update($id, ['UF_EX_SYNC_TASKS_TIME' => \Bitrix\Main\Type\DateTime::createFromTimestamp(time())]);
        return true;

    } catch (Exception $e) {
        okp($e->getFile() . ', ' . $e->getLine() . ': ' . $e->getMessage());
        return false;
    }
}

function isDQModerator($userId = false) {
    global $USER;
    if ($USER->IsAdmin()) {
        return true;
    }
    if (!$userId) {
        $userId = $USER->GetID();
    }
    $userId = intval($userId);

    $helper = new HighloadBlockHelper('DQRights');
    $hasRights = $helper->getList(['filter' => ['=UF_USER' => $userId]])->fetch();
    return !empty($hasRights);
}

function getDQRightsTypeList() {
    \Bitrix\Main\Loader::includeModule('highloadblock');
    $levelFieldId = \Bitrix\Main\UserFieldTable::getList(['filter' => ['FIELD_NAME' => 'UF_LEVEL', '=%ENTITY_ID' => 'HLBLOCK%'], 'select' => ['*'], 'limit' => 5])->fetch()['ID'];
    $rightsTypeList = CUserFieldEnum::GetList([],['USER_FIELD_ID' => $levelFieldId]);
    $rightsType = [];
    while ($item = $rightsTypeList->Fetch()) {
        $rightsType[$item['XML_ID']] = $item['ID'];
    }
    return $rightsType;
}

function getDQRights($userId = false) {
    if (!$userId) {
        global $USER;
        $userId = $USER->GetID();
    }
    $rightsHelper = new HighloadBlockHelper('DQRights');
    $rightsType = getDQRightsTypeList();
    $rights = $rightsHelper->getList(['filter' => ['=UF_USER' => $userId, 'UF_LEVEL' => $rightsType['add']], 'select' => ['*']])->fetchAll();
    $totalRights = [];
    $addRights = $queueRights = [
        'sc' => [],
        'type' => []
    ];
    foreach ($rights as $rightsItem) {
        if (empty($rightsItem['UF_SC'])) {
            $addRights['sc'] = ['*'];
        }
        $addRights['sc'] = array_merge($addRights['sc'], $rightsItem['UF_SC']);
        if (empty($rightsItem['UF_TYPE'])) {
            $addRights['type'] = ['*'];
        }
        $addRights['type'] = array_merge($addRights['type'], $rightsItem['UF_TYPE']);
    }
    $totalRights['add'] = $addRights;
    $rights = $rightsHelper->getList(['filter' => ['=UF_USER' => $userId, 'UF_LEVEL' => $rightsType['queue']], 'select' => ['*']])->fetchAll();
    foreach ($rights as $rightsItem) {
        if (empty($rightsItem['UF_SC'])) {
            $queueRights['sc'] = ['*'];
        }
        $queueRights['sc'] = array_merge($queueRights['sc'], $rightsItem['UF_SC']);
        if (empty($rightsItem['UF_TYPE'])) {
            $queueRights['type'] = ['*'];
        }
        $queueRights['type'] = array_merge($queueRights['type'], $rightsItem['UF_TYPE']);
    }
    $totalRights['queue'] = $queueRights;
    return $totalRights;
}


function getDQRightsFilterQueue($userId = false) {
    if (!$userId) {
        global $USER;
        $userId = $USER->GetID();
    }
    $rightsHelper = new HighloadBlockHelper('DQRights');
    $rightsType = getDQRightsTypeList();
    $rights = $rightsHelper->getList(['filter' => ['=UF_USER' => $userId, 'UF_LEVEL' => $rightsType['queue']], 'select' => ['*']])->fetchAll();

    $filter = [
        'LOGIC' => 'OR'
    ];
    foreach ($rights as $rightsItem) {
        $filterItem = [];
        if (empty($rightsItem['UF_SC'])) {
            $filterItem['!UF_SC'] = false;
        } else {
            $filterItem['@UF_SC'] = $rightsItem['UF_SC'];
        }

        if (empty($rightsItem['UF_TYPE'])) {
            $filterItem['!UF_TYPE'] = false;
        } else {
            $filterItem['@UF_TYPE'] = $rightsItem['UF_TYPE'];
        }

        $filter[] = $filterItem;
    }
    return $filter;
}

function getDepartmentMainSubsidiaryCompany($departmentId) {
    $entity = \Bitrix\Iblock\Model\Section::compileEntityByIblock(IBLOCK_DEPARTMENT);
    $dzoRootId = '512';
    $dzoRootSection = $entity::getList([
        'filter' => ['ID' => $dzoRootId, 'ACTIVE' => 'Y'],
        'select' => ['ID', 'NAME', 'LEFT_MARGIN', 'RIGHT_MARGIN']
    ])->fetch();
    $department = $entity::getList([
        'filter' => ['ID' => $departmentId],
        'select' => ['ID', 'NAME', 'LEFT_MARGIN', 'RIGHT_MARGIN']
    ])->fetch();
    if (!$department || !$dzoRootSection || $department['LEFT_MARGIN'] < $dzoRootSection['LEFT_MARGIN'] || $department['RIGHT_MARGIN'] > $dzoRootSection['RIGHT_MARGIN']) {
        return false;
    }
    $subdeps = $entity::getList([
        'filter' => [
            'ACTIVE' => 'Y',
            'IBLOCK_SECTION_ID' => $dzoRootId,
        ],
        'select' => ['ID', 'NAME', 'LEFT_MARGIN', 'RIGHT_MARGIN']
    ])->fetchAll();
    foreach ($subdeps as $subsidiaryCompanyMainDepartment) {
        if ($department['LEFT_MARGIN'] > $subsidiaryCompanyMainDepartment['LEFT_MARGIN'] &&
            $department['RIGHT_MARGIN'] < $subsidiaryCompanyMainDepartment['RIGHT_MARGIN']) {
            if ($subsidiaryCompanyMainDepartment['ID'] = 1470) {
                $subsubDeps = $entity::getList([
                    'filter' => [
                        'ACTIVE' => 'Y',
                        'IBLOCK_SECTION_ID' => $subsidiaryCompanyMainDepartment['ID'],
                    ],
                    'select' => ['ID', 'NAME', 'LEFT_MARGIN', 'RIGHT_MARGIN']
                ])->fetchAll();
                foreach ($subsubDeps as $subsubSection) {
                    if ($department['LEFT_MARGIN'] > $subsubSection['LEFT_MARGIN'] &&
                        $department['RIGHT_MARGIN'] < $subsubSection['RIGHT_MARGIN']) {
                        return $subsidiaryCompanyMainDepartment['NAME'] . ' - ' . $subsubSection['NAME'];
                    }
                }
            }
            return $subsidiaryCompanyMainDepartment['NAME'];
        }
    }
}


function getAllManagers($userId) {
    $managers = [];
    $userDepartments = getUserInfoById($userId, ['UF_DEPARTMENT'])['UF_DEPARTMENT'];
    foreach ($userDepartments as $sectionId) {
        $isFirstSection = false;
        while (!$isFirstSection) {
            $headId = getDepartmentHead($sectionId);
            if ($headId > 0) {
                $newManagers = [$headId];
                $helper = new HighloadBlockHelper(HLBLOCK_SUBORDINATE);
                $directorList = $helper->getList(['filter' => ['UF_MAIN' => $headId], 'select' => ['UF_SUB']])->fetchAll();
                foreach ($directorList as $director) {
                    $newManagers[] = $director['UF_SUB'];
                }
                $managers = array_merge($managers, $newManagers);
                sort($managers);
                $managers = array_unique($managers);
            }
            $entity = \Bitrix\Iblock\Model\Section::compileEntityByIblock(IBLOCK_DEPARTMENT);
            $sectionInfo =  $entity::getList(['filter' => ['ID' => $sectionId], 'select' => ['ID', 'IBLOCK_SECTION_ID']])->fetch();
            if (!$sectionInfo['IBLOCK_SECTION_ID']) {
                $isFirstSection = true;
            } else {
                $sectionId = $sectionInfo['IBLOCK_SECTION_ID'];
            }
        }
    }

    return $managers;
}

function getUserDepartmentsChainIds($userId = false) {
    if (!$userId) {
        global $USER;
        $userId = $USER->GetID();
    }

    $userDeparmentsIds = \Bitrix\Main\UserTable::getList(['filter' => ['=ID' => $userId], 'select' => ['UF_DEPARTMENT']])->fetch()['UF_DEPARTMENT'];

    \Bitrix\Main\Loader::includeModule('iblock');
    $sectionList = \Bitrix\Iblock\SectionTable::getList([
        'filter' => ['ID' => $userDeparmentsIds, 'ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT],
        'select' => ['NAME', 'ID', 'IBLOCK_SECTION_ID', 'DEPTH_LEVEL'],
        'order' => ['DEPTH_LEVEL' => 'desc'],
    ])->fetchAll();
    $departments = [];
    foreach ($sectionList as $section) {
        while ($section['DEPTH_LEVEL'] >= 1 && $section) {
            $departments[$section['ID']] = $section['ID'];
            $oldSection = $section;
            $section = \Bitrix\Iblock\SectionTable::getList([
                'filter' => ['ID' => $oldSection['IBLOCK_SECTION_ID'], 'ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT],
                'select' => ['NAME', 'ID', 'IBLOCK_SECTION_ID', 'DEPTH_LEVEL'],
            ])->fetch();
        }
    }
    return $departments;
}

function canVoteAny() {
    $helper = new VoteEditHelper();
    global $USER;
    $userId = $USER->GetID();
    foreach ($helper->getCurrentVotes() as $vote) {
        if ($helper->checkRights($vote['ID'], $userId)) {
            return true;
        }
    }
    return false;
}

function getFilePath($fileId) {
    if ($fileId <= 0) {
        return false;
    } else {
        $file = \Bitrix\Main\FileTable::getList([
            'filter' => ['=ID' => $fileId],
            'select' => ['EXTERNAL_ID']
        ])->fetch();
        return '/download/?id=' . $fileId . '&xml=' . $file['EXTERNAL_ID'];
    }
}

function getStatusCodes1CMap($namesOnly = true) {
    $helper = new HighloadBlockHelper('StatusCodes1C');
    $codes = [];
    foreach ($helper->getList([])->fetchAll() as $item) {
        $codes[$item['UF_CODE']] = $namesOnly ? $item['UF_NAME'] : $item;
    }
    return $codes;
}

function getOkrUserLinkById($userId, $withoutLink = false, $linkParams = '', $glue = ', ', $tagType = 'a') {
    if (!$userId)
        return false;
    $userList = \Bitrix\Main\UserTable::getList([
        'filter' => ['ID' => $userId],
        'select' => ['LAST_NAME', 'NAME', 'ID', 'PERSONAL_PHOTO']
    ])->fetchAll();
    $result = [];
    foreach ($userList as $userInfo) {
        if ($withoutLink) {
            $result[] = $userInfo['LAST_NAME'] . ' ' . $userInfo['NAME'];
        } else {
            $img = '<img src="data:image/svg+xml;charset=US-ASCII,%3Csvg%20viewBox%3D%220%200%2089%2089%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Ccircle%20fill%3D%22%23535C69%22%20cx%3D%2244.5%22%20cy%3D%2244.5%22%20r%3D%2244.5%22/%3E%3Cpath%20d%3D%22M68.18%2071.062c0-3.217-3.61-16.826-3.61-16.826%200-1.99-2.6-4.26-7.72-5.585-1.734-.483-3.383-1.233-4.887-2.223-.33-.188-.28-1.925-.28-1.925l-1.648-.25c0-.142-.14-2.225-.14-2.225%201.972-.663%201.77-4.574%201.77-4.574%201.252.695%202.068-2.4%202.068-2.4%201.482-4.3-.738-4.04-.738-4.04.388-2.625.388-5.293%200-7.918-.987-8.708-15.847-6.344-14.085-3.5-4.343-.8-3.352%209.082-3.352%209.082l.942%202.56c-1.85%201.2-.564%202.65-.5%204.32.09%202.466%201.6%201.955%201.6%201.955.093%204.07%202.1%204.6%202.1%204.6.377%202.556.142%202.12.142%202.12l-1.786.217c.024.58-.023%201.162-.14%201.732-2.1.936-2.553%201.485-4.64%202.4-4.032%201.767-8.414%204.065-9.193%207.16-.78%203.093-3.095%2015.32-3.095%2015.32H68.18z%22%20fill%3D%22%23FFF%22/%3E%3C/svg%3E" alt>';
            if ($userInfo['PERSONAL_PHOTO'] > 0) {
                $img = '<img src="' . CFile::GetPath($userInfo['PERSONAL_PHOTO']) . '" alt/>';
            }
            $result[] = '<' . $tagType . ' data-tippy data-tippy-content="' . $userInfo['LAST_NAME'] . ' ' . $userInfo['NAME'] . '" ' .
                            $linkParams .
                            ' href="/company/personal/user/' . $userInfo['ID'] . '/">' . $img . '</' . $tagType . '>';
        }
    }
    return implode($glue, $result);
}

function getUserPhotoById($userId, $imgParams = '') {
    if (!$userId)
        return false;
    $userInfo = \Bitrix\Main\UserTable::getList([
        'filter' => ['ID' => $userId],
        'select' => ['PERSONAL_PHOTO']
    ])->fetch();
    $img = '<img src="data:image/svg+xml;charset=US-ASCII,%3Csvg%20viewBox%3D%220%200%2089%2089%22%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%3E%3Ccircle%20fill%3D%22%23535C69%22%20cx%3D%2244.5%22%20cy%3D%2244.5%22%20r%3D%2244.5%22/%3E%3Cpath%20d%3D%22M68.18%2071.062c0-3.217-3.61-16.826-3.61-16.826%200-1.99-2.6-4.26-7.72-5.585-1.734-.483-3.383-1.233-4.887-2.223-.33-.188-.28-1.925-.28-1.925l-1.648-.25c0-.142-.14-2.225-.14-2.225%201.972-.663%201.77-4.574%201.77-4.574%201.252.695%202.068-2.4%202.068-2.4%201.482-4.3-.738-4.04-.738-4.04.388-2.625.388-5.293%200-7.918-.987-8.708-15.847-6.344-14.085-3.5-4.343-.8-3.352%209.082-3.352%209.082l.942%202.56c-1.85%201.2-.564%202.65-.5%204.32.09%202.466%201.6%201.955%201.6%201.955.093%204.07%202.1%204.6%202.1%204.6.377%202.556.142%202.12.142%202.12l-1.786.217c.024.58-.023%201.162-.14%201.732-2.1.936-2.553%201.485-4.64%202.4-4.032%201.767-8.414%204.065-9.193%207.16-.78%203.093-3.095%2015.32-3.095%2015.32H68.18z%22%20fill%3D%22%23FFF%22/%3E%3C/svg%3E" alt>';
    if ($userInfo['PERSONAL_PHOTO'] > 0) {
        $img = '<img src="' . CFile::GetPath($userInfo['PERSONAL_PHOTO']) . '" alt/>';
    }
    return $img;
}

function getOkrTaskLink($taskId, $userId = false) {
    if (!$userId) {
        global $USER;
        $userId = $USER->GetID();
    }
    if (!$taskId) {
        return '';
    }

    return "/company/personal/user/$userId/tasks/task/view/$taskId/";
}

function getBarColor($percent) {
    if ($percent < 20) {
        $color = '#d44f68';
    } elseif ($percent < 40) {
        $color = '#da7d58';
    } elseif ($percent < 60) {
        $color = '#ecb969';
    } elseif ($percent < 80) {
        $color = '#f7eb65';
    } else {
        $color = '#99c45a';
    }

    return $color;
}

function getTaskToolBar($taskData) {
    $helper = new HighloadBlockHelper('KeyValues');
    if ($taskData['UF_KEY_ID'] > 0) {
        $keyValue = $helper->getList([
            'filter' => ['UF_TASK' => $taskData['ID'], 'UF_KEY' => $taskData['UF_KEY_ID']],
            'select' => ['UF_VALUE_CURRENT']
        ])->fetch()['UF_VALUE_CURRENT'];
        $keyValue = intval($keyValue);
        $keyPercent = ($taskData['UF_KEY_VALUE'] > 0 ? max(0, round(100 * $keyValue / $taskData['UF_KEY_VALUE'], 2)) : 0);
        return ['value' => $keyValue, 'percent' => $keyPercent];
    }
    return ['value' => 0, 'percent' => 0];
}

function getObjToolBar($obj, $userId = false) {
    if (!$obj['keyValues']) {
        $keyValuesHelper = new HighloadBlockHelper('KeyValues');
        $obj['keyValues'] = $keyValuesHelper->getList([
            'filter' => ['UF_OBJ' => $obj['ID']],
            'select' => ['*']
        ])->fetchAll();
    }
    $result = ['total' => 0];
    $helper = new HighloadBlockHelper('KeyValues');
    $objKeys = $helper->getList([
        'filter' => ['UF_OBJ' => $obj['ID'], 'UF_TASK' => false],
        'select' => ['UF_VALUE', 'UF_KEY', 'ID'],
    ])->fetchAll();
    if (!empty($objKeys)) {
        $totalCount = count($objKeys);
        $keyIds = $keyValues = [];
        foreach ($objKeys as $key) {
            $keyIds[] = $key['UF_KEY'];
            $keyValues[$key['UF_KEY']] = $key['UF_VALUE'];
        }
        $taskFilter = [
            '!ZOMBIE' => 'Y',
            'UF_OBJ' => $obj['ID'],
            '@UF_KEY_ID' => $keyIds,
            'PARENT_ID' => false
        ];
        if ($userId > 0) {
            $taskFilter['RESPONSIBLE_ID'] = $userId;
        }
        $taskList = \Bitrix\Tasks\Internals\TaskTable::getList([
            'filter' => $taskFilter,
            'select' => ['ID']
        ])->fetchAll();
        $objKeyValue = [];
        $taskIds = [];
        foreach ($taskList as $task) {
            $taskIds[] = $task['ID'];
        }
        if (!empty($taskIds)) {
            $currentValueKeys = $helper->getList([
                'filter' => ['@UF_TASK' => $taskIds],
                'select' => ['UF_KEY', 'UF_VALUE_CURRENT', 'UF_TASK'],
            ])->fetchAll();
            foreach ($currentValueKeys as $key) {
                $objKeyValue[$key['UF_KEY']] += $key['UF_VALUE_CURRENT'];
            }
            foreach ($obj['keyValues'] as $keyInfo) {
                $efficiency = $objKeyValue[$keyInfo['UF_KEY']];
                $result[$keyInfo['UF_KEY']] = intval($efficiency);
                $result['percent'][$keyInfo['UF_KEY']] = round(min(100, max(round(100 * $result[$keyInfo['UF_KEY']] / $keyInfo['UF_VALUE'], 2), 0)) / $totalCount, 2);
                $result['total'] += $result['percent'][$keyInfo['UF_KEY']];
            }
        }
    }
    return $result;
}


function getObjectivesStatuses($blockId, $onlyXmlId = true, $xmlIdKeys = false) {
    $result = [];
    $fieldId = CUserTypeEntity::GetList([],['FIELD_NAME' => 'UF_STATUS', 'ENTITY_ID' => 'HLBLOCK_' . $blockId])->Fetch();
    $list = CUserFieldEnum::GetList(['SORT' => 'ASC'], ['USER_FIELD_ID' => $fieldId['ID']]);
    while ($item = $list->Fetch()) {
        if (!$xmlIdKeys) {
            $result[$item['ID']] = $onlyXmlId ? $item['XML_ID'] : $item;
        } else {
            $result[$item['XML_ID']] = $onlyXmlId ? $item['ID'] : $item;
        }
    }
    return $result;
}

function isHeadOf($userId) {
    $userDeparmentsIds = \Bitrix\Main\UserTable::getList(['filter' => ['=ID' => $userId], 'select' => ['UF_DEPARTMENT']])->fetch()['UF_DEPARTMENT'];
    if (empty($userDeparmentsIds)) {
        return false;
    }
    global $USER;
    $entity = \Bitrix\Iblock\Model\Section::compileEntityByIblock(IBLOCK_DEPARTMENT);
    $sectionList = $entity::getList([
        'filter' => ['@ID' => $userDeparmentsIds, 'ACTIVE' => 'Y', 'IBLOCK_ID' => IBLOCK_DEPARTMENT, 'UF_HEAD' => $USER->GetID()],
        'select' => ['NAME', 'ID', 'UF_HEAD']
    ]);
    return $sectionList->getSelectedRowsCount() > 0;
}