Your IP : 3.145.110.21


Current Path : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/components/bitrix/tasks.report.effective/
Upload File :
Current File : /home/bitrix/ext_www/crm.klimatlend.ua/bitrix/components/bitrix/tasks.report.effective/class.php

<?
if (!defined("B_PROLOG_INCLUDED") || B_PROLOG_INCLUDED !== true)
{
	die();
}

use Bitrix\Main\Config\Option;
use Bitrix\Main\Localization\Loc;
use Bitrix\Main\ObjectException;
use Bitrix\Main\UI\Filter;
use Bitrix\Tasks\Internals\Effective;
use Bitrix\Tasks\Util\Error\Collection;
use Bitrix\Tasks\Util\Restriction\Bitrix24Restriction\Limit\TaskLimit;
use Bitrix\Tasks\Util\Type\DateTime;
use Bitrix\Tasks\Util\User;

Loc::loadMessages(__FILE__);

CBitrixComponent::includeComponentClass("bitrix:tasks.base");

/**
 * Class TasksReportEffectiveComponent
 */
class TasksReportEffectiveComponent extends TasksBaseComponent
{
	protected $userId;
	protected $groupId;

	protected static function checkPermissions(array &$arParams, array &$arResult, Collection $errors, array $auxParams = [])
	{
		$currentUser = User::getId();
		$viewedUser = $arParams['USER_ID'];

		if (!$viewedUser)
		{
			$viewedUser = $_REQUEST['ACTION'][0]['ARGUMENTS']['userId']; //TODO 18.0.0 IN NEW REST
		}

		$isAccessible = $currentUser === (int)$viewedUser
			|| User::isSuper($currentUser)
			|| User::isBossRecursively($currentUser, $viewedUser);

		if (!$isAccessible)
		{
			$errors->add('TASKS_MODULE_ACCESS_DENIED', Loc::getMessage("TASKS_COMMON_ACCESS_DENIED"));
		}

		return $errors->checkNoFatals();
	}

	public static function getAllowedMethods()
	{
		return [
			'getEfficiencyData',
		];
	}

	protected function checkParameters()
	{
		// todo
		$arParams = &$this->arParams;

		static::tryParseStringParameter($arParams['FILTER_ID'], 'GRID_EFFECTIVE');
		static::tryParseStringParameter($arParams['PATH_TO_USER_PROFILE'], '/company/personal/user/#user_id#/');
		static::tryParseStringParameter($arParams['PATH_TO_EFFECTIVE_DETAIL'], '/company/personal/user/#user_id#/tasks/effective/show/');
		static::tryParseStringParameter($arParams['PATH_TO_TASK_ADD'], '/company/personal/user/'.User::getId().'/tasks/task/edit/0/');
		static::tryParseStringParameter($arParams['USE_PAGINATION'], true);
		static::tryParseStringParameter($arParams['DEFAULT_PAGE_SIZE'], $this->defaultPageSize);
		static::tryParseArrayParameter($arParams['PAGE_SIZES'], $this->pageSizes);

		$this->userId = ($this->arParams['USER_ID'] ?: User::getId());
		$this->groupId = ($this->arParams['GROUP_ID'] ?: 0);

		return $this->errors->checkNoFatals();
	}

	protected function getData()
	{
		$this->arResult['FILTERS'] = static::getFilterList();
		$this->arResult['PRESETS'] = static::getPresetList();

		$this->arResult['EFFECTIVE_DATE_START'] = $this->getEfficiencyDate();

		$this->arResult['JS_DATA']['userId'] = $this->userId;
		$this->arResult['JS_DATA']['efficiencyData'] = static::getEfficiencyData($this->userId);

		if (TaskLimit::isLimitExceeded())
		{
			$this->arResult['TASK_LIMIT_EXCEEDED'] = true;
			$efficiencyData = $this->getDefaultEfficiencyData();
		}
		else
		{
			$this->arResult['TASK_LIMIT_EXCEEDED'] = false;
			$efficiencyData = static::getEfficiencyData($this->arParams['USER_ID']);
		}

		$this->arResult['JS_DATA']['efficiencyData'] = $efficiencyData;
	}

	/**
	 * @return array
	 * @throws ObjectException
	 */
	private function getDefaultEfficiencyData(): array
	{
		$date = new DateTime();
		$month = $date->getMonthGmt();
		$month = ($month < 10? '0'.$month : $month);

		return [
			'EFFICIENCY' => 75,
			'COMPLETED' => 20,
			'VIOLATIONS' => 25,
			'IN_PROGRESS' => 100,
			'GRAPH_DATA' => [
				[
					'DATE' => '2019-'.$month.'-01',
					'EFFECTIVE' => 100,
				],
				[
					'DATE' => '2019-'.$month.'-03',
					'EFFECTIVE' => 25,
				],
				[
					'DATE' => '2019-'.$month.'-06',
					'EFFECTIVE' => 50,
				],
				[
					'DATE' => '2019-'.$month.'-09',
					'EFFECTIVE' => 0,
				],
				[
					'DATE' => '2019-'.$month.'-12',
					'EFFECTIVE' => 33,
				],
				[
					'DATE' => '2019-'.$month.'-15',
					'EFFECTIVE' => 10,
				],
				[
					'DATE' => '2019-'.$month.'-18',
					'EFFECTIVE' => 100,
				],
				[
					'DATE' => '2019-'.$month.'-21',
					'EFFECTIVE' => 30,
				],
				[
					'DATE' => '2019-'.$month.'-24',
					'EFFECTIVE' => 75,
				],
				[
					'DATE' => '2019-'.$month.'-27',
					'EFFECTIVE' => 100,
				],
				[
					'DATE' => '2019-'.$month.'-30',
					'EFFECTIVE' => 25,
				],
			],
			'GRAPH_MIN_PERIOD' => 'DD',
		];
	}

	/**
	 * @return string
	 */
	public static function getFilterId(): string
	{
		return Effective::getFilterId();
	}

	/**
	 * @return array
	 */
	public static function getPresetList(): array
	{
		return Effective::getPresetList();
	}

	/**
	 * @return string
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ArgumentNullException
	 * @throws \Bitrix\Main\ArgumentOutOfRangeException
	 * @throws \Bitrix\Main\ObjectException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	private function getEfficiencyDate(): string
	{
		$format = 'Y-m-d H:i:s';
		$dateFromDb = Option::get('tasks', 'effective_date_start');

		if ($dateFromDb === '')
		{
			$currentDate = (new Datetime())->format($format);
			$firstRecordTime = Effective::getFirstRecordTime();
			$dateToSet = ($firstRecordTime ? $firstRecordTime->format($format) : $currentDate);

			Option::set('tasks', 'effective_date_start', $dateToSet);
			$dateFromDb = $dateToSet;
		}

		$date = new DateTime($dateFromDb, $format);

		return Loc::getMessage('TASKS_EFFECTIVE_DATE_FORMAT', [
			'#DAY#' => $date->format('d'),
			'#MONTH_NAME#' => Loc::getMessage('TASKS_MONTH_'.(int)$date->format('m')),
			'#YEAR_IF_DIFF#' => ((int)$date->format('Y') !== (int)date('Y') ? $date->format('Y') : ''),
		]);
	}

	/**
	 * @return array
	 */
	public static function getFilterList(): array
	{
		return [
			'GROUP_ID' => [
				'id' => 'GROUP_ID',
				'name' => Loc::getMessage('TASKS_FILTER_COLUMN_GROUP_ID'),
				'type' => 'custom_entity',
				'default' => true,
				'selector' => [
					'TYPE' => 'group',
					'DATA' => [
						'ID' => 'group',
						'FIELD_ID' => 'GROUP_ID'
					],
				],
			],
			'DATETIME' => [
				'id' => 'DATETIME',
				'name' => Loc::getMessage('TASKS_FILTER_COLUMN_DATE'),
				'type' => 'date',
				'default' => true,
				'exclude' => [
					Filter\DateType::NONE,
					Filter\DateType::TOMORROW,
					Filter\DateType::PREV_DAYS,
					Filter\DateType::NEXT_DAYS,
					Filter\DateType::NEXT_WEEK,
					Filter\DateType::NEXT_MONTH
				],
			],
		];
	}

	/**
	 * @param $userId
	 * @return array
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	public static function getEfficiencyData($userId): array
	{
		$filter = static::processFilter();

		$datesRange = Effective::getDatesRange();
		$dateFrom = $datesRange['FROM'];
		$dateTo = $datesRange['TO'];

		$groupId = 0;
		$groupByHour = false;

		if (array_key_exists('>=DATETIME', $filter))
		{
			$dateFrom = new DateTime($filter['>=DATETIME']);
		}
		if (array_key_exists('<=DATETIME', $filter))
		{
			$dateTo = new DateTime($filter['<=DATETIME']);
		}
		if (array_key_exists('GROUP_ID', $filter))
		{
			$groupId = $filter['GROUP_ID'];
		}
		if (isset($filter['::']) && $filter['::'] === 'BY_DAY')
		{
			unset($filter['::']);
			$groupByHour = true;
		}

		$tasksCounters = Effective::getCountersByRange($dateFrom, $dateTo, $userId, $groupId);
		$graphData = static::getGraphData($dateFrom, $dateTo, $userId, $groupId, $groupByHour);

		$efficiency = 100;
		$violations = $tasksCounters['VIOLATIONS'];
		$inProgress = $tasksCounters['IN_PROGRESS'];

		if ($inProgress > 0)
		{
			$efficiency = (int)round(100 - ($violations / $inProgress) * 100);
		}
		else if ($violations > 0)
		{
			$efficiency = 0;
		}

		if ($efficiency < 0)
		{
			$efficiency = 0;
		}

		return [
			'EFFICIENCY' => $efficiency,
			'COMPLETED' => $tasksCounters['COMPLETED'],
			'VIOLATIONS' => $tasksCounters['VIOLATIONS'],
			'IN_PROGRESS' => $tasksCounters['IN_PROGRESS'],
			'GRAPH_DATA' => $graphData,
			'GRAPH_MIN_PERIOD' => ($groupByHour? 'hh' : 'DD'),
		];
	}

	/**
	 * @param $dateFrom
	 * @param $dateTo
	 * @param $userId
	 * @param $groupId
	 * @param $groupByHour
	 * @return array
	 * @throws \Bitrix\Main\ArgumentException
	 * @throws \Bitrix\Main\ObjectPropertyException
	 * @throws \Bitrix\Main\SystemException
	 */
	private static function getGraphData($dateFrom, $dateTo, $userId, $groupId, $groupByHour): array
	{
		$graphData = [];
		$graphDataRes = Effective::getEfficiencyForGraph($dateFrom, $dateTo, $userId, $groupId, ($groupByHour? 'HOUR' : ''));

		foreach ($graphDataRes as $row)
		{
			$row['DATE'] = ($groupByHour ? $row['HOUR'] : $row['DATE']->format('Y-m-d'));
			$row['EFFECTIVE'] = round($row['EFFECTIVE']);

			$graphData[] = $row;
		}

		return $graphData;
	}

	/**
	 * @return array
	 * @throws \Bitrix\Main\ObjectException
	 */
	private static function processFilter(): array
	{
		static $filter = [];

		if (!$filter)
		{
			$filterList = static::getFilterList();
			$rawFilter = static::getFilterOptions()->getFilter($filterList);

			if (!array_key_exists('FILTER_APPLIED', $rawFilter) || $rawFilter['FILTER_APPLIED'] != true)
			{
				return [];
			}

			foreach ($filterList as $item)
			{
				switch ($item['type'])
				{
					case 'custom_entity':
						if ($rawFilter[$item['id']])
						{
							$filter[$item['id']] = $rawFilter[$item['id']];
						}
						break;

					case 'date':
						$fromKey = $item['id'].'_from';
						$toKey = $item['id'].'_to';

						if (array_key_exists($fromKey, $rawFilter) && !empty($rawFilter[$fromKey]))
						{
							$filter['>='.$item['id']] = $rawFilter[$fromKey];
						}
						if (array_key_exists($toKey, $rawFilter) && !empty($rawFilter[$toKey]))
						{
							$filter['<='.$item['id']] = $rawFilter[$toKey];
						}
						if (static::checkByDayFiltering($rawFilter, $item, $filter))
						{
							$filter['::'] = 'BY_DAY';
						}
						break;
				}
			}
		}

		return $filter;
	}

	/**
	 * @param $rawFilter
	 * @param $item
	 * @param $filter
	 * @return bool
	 * @throws \Bitrix\Main\ObjectException
	 */
	private static function checkByDayFiltering($rawFilter, $item, $filter): bool
	{
		$dateTypesForDayFiltering = [
			Filter\DateType::YESTERDAY,
			Filter\DateType::CURRENT_DAY,
			Filter\DateType::EXACT,
		];
		$rangeType = Filter\DateType::RANGE;

		$dateSel = $rawFilter[$item['id'].'_datesel'];
		$dateFrom = new DateTime($filter['>='.$item['id']]);
		$dateTo = new DateTime($filter['<='.$item['id']]);

		return in_array($dateSel, $dateTypesForDayFiltering, true)
			|| ($dateSel === $rangeType && $dateFrom->format('Y-m-d') === $dateTo->format('Y-m-d'));
	}

	/**
	 * @return Filter\Options
	 */
	private static function getFilterOptions(): Filter\Options
	{
		static $instance = null;

		if (!$instance)
		{
			$instance = new Filter\Options(static::getFilterId(), static::getPresetList());
		}

		return $instance;
	}
}