• Модуль: crm
  • Путь к файлу: ~/bitrix/modules/crm/lib/integration/report/handler/lead.php
  • Класс: Bitrix\Crm\Integration\Report\Handler\Lead
  • Вызов: Lead::prepare
public function prepare()
{
	$userPermission = \CCrmPerms::GetCurrentUserPermissions();
	if (!\CCrmAuthorizationHelper::CheckReadPermission(\CCrmOwnerType::Lead, 0, $userPermission))
	{
		return false;
	}

	/** @var DropDown $grouping */
	$groupingField = $this->getFormElement('groupingBy');
	$groupingValue = $groupingField ? $groupingField->getValue() : null;

	$calculateField = $this->getFormElement('calculate');
	$calculateValue = $calculateField ? $calculateField->getValue() : null;

	$disableSuccessStatesField = $this->getFormElement('disableSuccessStates');
	$disableSuccessStatesValue = $disableSuccessStatesField ? $disableSuccessStatesField->getValue() : false;

	$query = new Query(LeadTable::getEntity());

	switch ($groupingValue)
	{
		case self::GROUPING_BY_DATE:
			$query->registerRuntimeField(new ExpressionField('DATE_CREATE_DAY', "DATE_FORMAT(%s, '%%Y-%%m-%%d 00:00')", 'DATE_CREATE'));
			$query->addSelect('DATE_CREATE_DAY');
			$query->addGroup('DATE_CREATE_DAY');
			break;
		case self::GROUPING_BY_STATE:
			$query->addSelect('FULL_HISTORY.STATUS_ID', 'STATUS_KEY');
			$query->addGroup('FULL_HISTORY.STATUS_ID');

			$statusNameListByStatusId = [];
			foreach ($this->getStatusList() as $status)
			{
				$statusNameListByStatusId[$status['STATUS_ID']] = $status['NAME'];
			}

			break;
		case self::GROUPING_BY_SOURCE:
			$query->addGroup('SOURCE_ID');
			$query->addSelect('SOURCE_ID');

			$sourceNameListByStatusId = [];
			foreach ($this->getSourceNameList() as $source)
			{
				$sourceNameListByStatusId[$source['STATUS_ID']] = $source['NAME'];
			}
			break;
		case self::GROUPING_BY_RESPONSIBLE:
			$query->addGroup('ASSIGNED_BY_ID');
			$query->addSelect('ASSIGNED_BY_ID');
			break;
	}

	switch ($calculateValue)
	{
		case self::WHAT_WILL_CALCULATE_LEAD_DATA_FOR_FUNNEL:
		case self::WHAT_WILL_CALCULATE_SUCCESS_LEAD_DATA_FOR_FUNNEL:
			$query->addSelect(Query::expr()->max('OPPORTUNITY_ACCOUNT'), 'MAX_OPPORTUNITY_ACCOUNT');
			$query->addSelect('FULL_HISTORY.OWNER_ID', 'FULL_HISTORY_OWNER_ID');
			$query->addSelect(Query::expr()->min('FULL_HISTORY.IS_SUPPOSED'), 'FULL_HISTORY_IS_SUPPOSED');
			$query->addSelect(Query::expr()->max('FULL_HISTORY.SPENT_TIME'), 'FULL_HISTORY_SPENT_TIME');
			$query->addSelect(Query::expr()->max('ACCOUNT_CURRENCY_ID'), 'MAX_ACCOUNT_CURRENCY_ID');
			break;
		default:
			$query->addSelect(new \Bitrix\Main\Entity\ExpressionField('VALUE', 'COUNT(DISTINCT %s)', 'FULL_HISTORY.OWNER_ID'));
	}

	switch ($calculateValue)
	{
		case self::WHAT_WILL_CALCULATE_GOOD_LEAD_COUNT:
			$query->whereIn('FULL_HISTORY.STATUS_SEMANTIC_ID', ['P', 'S']);
			break;
		case self::WHAT_WILL_CALCULATE_ACTIVE_LEAD_COUNT:
			$query->where('FULL_HISTORY.STATUS_SEMANTIC_ID', 'P');
			break;
		case self::WHAT_WILL_CALCULATE_CONVERTED_LEAD_COUNT:
		case self::WHAT_WILL_CALCULATE_SUCCESS_LEAD_DATA_FOR_FUNNEL:
			$query->where('FULL_HISTORY.STATUS_SEMANTIC_ID', 'S');
			break;
		case self::WHAT_WILL_CALCULATE_LOST_LEAD_COUNT:
			$query->where('FULL_HISTORY.STATUS_SEMANTIC_ID', 'F');
			break;
		case self::WHAT_WILL_CALCULATE_LEAD_CONVERSION:
		case self::WHAT_WILL_CALCULATE_LEAD_LOSES:
			$query->addGroup('FULL_HISTORY.STATUS_SEMANTIC_ID');
			$query->addSelect('FULL_HISTORY.STATUS_SEMANTIC_ID', 'STATUS_SEMANTIC_ID_VALUE');
			break;
	}

	$this->addToQueryFilterCase($query);
	$this->addPermissionsCheck($query);

	switch ($calculateValue)
	{
		case self::WHAT_WILL_CALCULATE_SUCCESS_LEAD_DATA_FOR_FUNNEL:
		case self::WHAT_WILL_CALCULATE_LEAD_DATA_FOR_FUNNEL:
			$querySql = "SELECT 
							res.STATUS_KEY,
							(SUM(res.FULL_HISTORY_SPENT_TIME) / SUM(CASE WHEN res.FULL_HISTORY_IS_SUPPOSED = 'N' AND res.FULL_HISTORY_SPENT_TIME IS NOT NULL THEN 1 ELSE 0 END)) as SPENT_TIME,  
							COUNT(DISTINCT res.FULL_HISTORY_OWNER_ID) as VALUE, 
							SUM(res.MAX_OPPORTUNITY_ACCOUNT) as SUM, 
							MAX_ACCOUNT_CURRENCY_ID as ACCOUNT_CURRENCY_ID FROM(";
			$querySql .= $query->getQuery();
			$querySql .= ") as res GROUP BY res.STATUS_KEY";
			$results = Application::getConnection()->query($querySql);
			break;
		default:
			$results = $query->exec()->fetchAll();
	}

	$amountLeadCount = 0;
	$amountLeadSum = 0;
	switch ($calculateValue)
	{
		case self::WHAT_WILL_CALCULATE_LEAD_CONVERSION:
			$allLeadCount = [];
			$successLeadCount = [];
			$successAmountLeadCount = 0;
			$groupingFieldName = 'withoutGrouping';

			switch ($groupingValue)
			{
				case self::GROUPING_BY_RESPONSIBLE:
					$allLeadCount = $this->getLeadAmountCountByResponsible();
					$allAmountLeadCount = array_sum($allLeadCount);
					break;
				default:
					$allLeadCount['withoutGrouping'] = $this->getLeadAmountCount();
					$allAmountLeadCount = $allLeadCount['withoutGrouping'];
			}

			foreach ($results as $result)
			{
				switch ($groupingValue)
				{
					case self::GROUPING_BY_RESPONSIBLE:
						$groupingFieldName = 'ASSIGNED_BY_ID';
						$groupingFieldValue = $result[$groupingFieldName];
						break;
					default:
						$groupingFieldValue = 'withoutGrouping';
				}

				if ($result['STATUS_SEMANTIC_ID_VALUE'] == 'S')
				{
					$successLeadCount[$groupingFieldValue] += $result['VALUE'];
					$successAmountLeadCount += $result['VALUE'];
				}
			}
			$results = [];

			foreach ($allLeadCount as $groupingKey => $count)
			{
				if (!empty($successLeadCount[$groupingKey]))
				{
					$results[] = [
						$groupingFieldName => $groupingKey,
						'VALUE' => $count > 0 ? ($successLeadCount[$groupingKey] / $count) * 100 : 0
					];
				}
				else
				{
					$results[] = [
						$groupingFieldName => $groupingKey,
						'VALUE' => 0
					];
				}
			}

			$amountLeadCount = $allAmountLeadCount ? (($successAmountLeadCount / $allAmountLeadCount) * 100) : 0;

			break;
		case self::WHAT_WILL_CALCULATE_LEAD_LOSES:
			$allLeadCount = [];
			$loseLeadCount = [];
			$losesAmountLeadCount = 0;
			$groupingFieldName = 'withoutGrouping';

			switch ($groupingValue)
			{
				case self::GROUPING_BY_RESPONSIBLE:
					$allLeadCount = $this->getLeadAmountCountByResponsible();
					$allAmountLeadCount = array_sum($allLeadCount);
					break;
				default:
					$allLeadCount['withoutGrouping'] = $this->getLeadAmountCount();
					$allAmountLeadCount = $allLeadCount['withoutGrouping'];
			}

			foreach ($results as $result)
			{
				switch ($groupingValue)
				{
					case self::GROUPING_BY_RESPONSIBLE:
						$groupingFieldName = 'ASSIGNED_BY_ID';
						$groupingFieldValue = $result[$groupingFieldName];
						break;
					default:
						$groupingFieldValue = 'withoutGrouping';
				}

				if ($result['STATUS_SEMANTIC_ID_VALUE'] == 'F')
				{
					$loseLeadCount[$groupingFieldValue] += $result['VALUE'];
					$losesAmountLeadCount += $result['VALUE'];
				}
			}
			$results = [];

			foreach ($allLeadCount as $groupingKey => $count)
			{
				if (!empty($loseLeadCount[$groupingKey]))
				{
					$results[] = [
						$groupingFieldName => $groupingKey,
						'VALUE' => $count > 0 ? ($loseLeadCount[$groupingKey] / $count) * 100 : 0
					];
				}
				else
				{
					$results[] = [
						$groupingFieldName => $groupingKey,
						'VALUE' => 0
					];
				}
			}

			$amountLeadCount = $allAmountLeadCount ? (($losesAmountLeadCount / $allAmountLeadCount) * 100) : 0;
			break;
	}

	$leadCalculatedValue = [];
	$percentageMetricsList = [
		self::WHAT_WILL_CALCULATE_LEAD_CONVERSION,
		self::WHAT_WILL_CALCULATE_LEAD_LOSES,
	];

	$statusNum = 0;
	foreach ($results as $result)
	{
		if (!in_array($calculateValue, $percentageMetricsList))
		{
			$statusNum++;
			if ($this->getView()->getKey() !== ColumnFunnel::VIEW_KEY)
			{
				$amountLeadCount += $result['VALUE'];
			}
		}

		switch ($groupingValue)
		{
			case self::GROUPING_BY_DATE:
				$leadCalculatedValue[$result['DATE_CREATE_DAY']]['value'] = $result['VALUE'];
				$leadCalculatedValue[$result['DATE_CREATE_DAY']]['title'] = $result['DATE_CREATE_DAY'];
				break;
			case self::GROUPING_BY_STATE:
				if ($statusNum === 1)
				{
					$leadCountAndSum = $this->getLeadAmountCountAndSum();
					$amountLeadCount = $leadCountAndSum['COUNT'];
					$amountLeadSum = $leadCountAndSum['SUM'];
				}

				$leadCalculatedValue[$result['STATUS_KEY']]['value'] = $result['VALUE'];
				$leadCalculatedValue[$result['STATUS_KEY']]['additionalValues']['sum']['VALUE'] = 0;
				$leadCalculatedValue[$result['STATUS_KEY']]['additionalValues']['sum']['currencyId'] = \CCrmCurrency::GetAccountCurrencyID();

				if ($result['SUM'])
				{
					$leadCalculatedValue[$result['STATUS_KEY']]['additionalValues']['sum'] = [
						'VALUE' => $result['SUM'],
						'currencyId' => !empty($result['ACCOUNT_CURRENCY_ID']) ? $result['ACCOUNT_CURRENCY_ID'] : null
					];
				}

				$statusSemanticId = \CCrmLead::GetSemanticID($result['STATUS_KEY']);
				if (!PhaseSemantics::isFinal($statusSemanticId))
				{
					$leadCalculatedValue[$result['STATUS_KEY']]['additionalValues']['avgSpentTime']['VALUE'] = (int)$result['SPENT_TIME'];
				}
				$leadCalculatedValue[$result['STATUS_KEY']]['title'] = !empty($statusNameListByStatusId[$result['STATUS_KEY']]) ? $statusNameListByStatusId[$result['STATUS_KEY']] : '';
				$leadCalculatedValue[$result['STATUS_KEY']]['color'] = $this->getStatusColor($result['STATUS_KEY']);
				break;
			case self::GROUPING_BY_SOURCE:
				$leadCalculatedValue[$result['SOURCE_ID']]['value'] = $result['VALUE'];
				$leadCalculatedValue[$result['SOURCE_ID']]['title'] = !empty($sourceNameListByStatusId[$result['SOURCE_ID']]) ? $sourceNameListByStatusId[$result['SOURCE_ID']] : '';
				break;
			case self::GROUPING_BY_RESPONSIBLE:
				if ($result['ASSIGNED_BY_ID']  == 0)
				{
					continue 2;
				}
				//TODO optimise here
				$userInfo = $this->getUserInfo($result['ASSIGNED_BY_ID']);
				$leadCalculatedValue[$result['ASSIGNED_BY_ID']]['value'] = $result['VALUE'];
				$leadCalculatedValue[$result['ASSIGNED_BY_ID']]['title'] = $userInfo['name'];
				$leadCalculatedValue[$result['ASSIGNED_BY_ID']]['logo'] = $userInfo['icon'];
				$leadCalculatedValue[$result['ASSIGNED_BY_ID']]['targetUrl'] = $userInfo['link'];
				break;
			default:
				$leadCalculatedValue['withoutGrouping'] = $result['VALUE'];
				break;
		}
	}

	if ($groupingValue === self::GROUPING_BY_STATE && isset($statusNameListByStatusId) && $calculateValue !==self::WHAT_WILL_CALCULATE_SUCCESS_LEAD_DATA_FOR_FUNNEL)
	{
		$sortedLeadCountListByStatus = [];
		foreach ($statusNameListByStatusId as $statusId => $statusName)
		{
			if (!empty($leadCalculatedValue[$statusId]))
			{
				$sortedLeadCountListByStatus[$statusId] = $leadCalculatedValue[$statusId];
			}
			else
			{
				$sortedLeadCountListByStatus[$statusId] = [
					'value' => 0,
					'title' => $statusName,
					'color' => $this->getStatusColor($statusId)
				];
			}
		}
		$leadCalculatedValue = $sortedLeadCountListByStatus;
	}

	$leadCalculatedValue['amount']['count'] = $amountLeadCount;
	$leadCalculatedValue['amount']['sum'] = $amountLeadSum;

	if ($calculateValue !== self::WHAT_WILL_CALCULATE_SUCCESS_LEAD_DATA_FOR_FUNNEL)
	{
		$leadCalculatedValue['amount']['successPassTime'] = $this->getLeadPassingTime();
	}

	if ($disableSuccessStatesValue)
	{
		unset($leadCalculatedValue['CONVERTED']);
	}

	//replace converted value to the end in column funnel
	if ($calculateValue === self::WHAT_WILL_CALCULATE_LEAD_DATA_FOR_FUNNEL)
	{
		if (!empty($leadCalculatedValue['CONVERTED']))
		{
			$convertedValue = $leadCalculatedValue['CONVERTED'];
			unset($leadCalculatedValue['CONVERTED']);

			$leadCalculatedValue['CONVERTED'] = $convertedValue;
		}
	}

	return $leadCalculatedValue;
}