• Модуль: crm
  • Путь к файлу: ~/bitrix/modules/crm/lib/statistics/dealsumstatisticentry.php
  • Класс: Bitrix\Crm\Statistics\DealSumStatisticEntry
  • Вызов: DealSumStatisticEntry::register
static function register($ownerID, array $entityFields = null, array $options = null)
{
	if(!is_int($ownerID))
	{
		$ownerID = (int)$ownerID;
	}

	if($ownerID <= 0)
	{
		throw new Main\ArgumentException('Owner ID must be greater than zero.', 'ownerID');
	}

	if(!is_array($entityFields))
	{
		$dbResult = \CCrmDeal::GetListEx(
			array(),
			array('=ID' => $ownerID, 'CHECK_PERMISSIONS' => 'N'),
			false,
			false,
			array('STAGE_ID', 'CATEGORY_ID', 'ASSIGNED_BY_ID', 'BEGINDATE', 'CLOSEDATE', 'CURRENCY_ID', 'OPPORTUNITY', 'EXCH_RATE', 'UF_*')
		);
		$entityFields = is_object($dbResult) ? $dbResult->Fetch() : null;
		if(!is_array($entityFields))
		{
			return;
		}
	}

	if(!is_array($options))
	{
		$options = array();
	}
	$forced = isset($options['FORCED']) ? $options['FORCED'] : false;

	$bindingMap = self::getCurrent()->getSlotBindingMap();

	$responsibleID = isset($entityFields['ASSIGNED_BY_ID']) ? (int)$entityFields['ASSIGNED_BY_ID'] : 0;
	$categoryID = isset($entityFields['CATEGORY_ID']) ? (int)$entityFields['CATEGORY_ID'] : 0;
	$stageID = isset($entityFields['STAGE_ID']) ? $entityFields['STAGE_ID'] : '';
	$semanticID = \CCrmDeal::GetSemanticID($stageID, $categoryID);
	$isLost = PhaseSemantics::isLost($semanticID);
	$isFinalized = PhaseSemantics::isFinal($semanticID);

	$zeroDate = new Date('0000-00-00', 'Y-m-d');
	/** @var Date $startDate */
	$startDate = self::parseDateString(isset($entityFields['BEGINDATE']) ? $entityFields['BEGINDATE'] : '');
	if($startDate === null || $startDate == $zeroDate || $startDate->getTimestamp() === false)
	{
		$startDate = isset($entityFields['DATE_CREATE']) ? self::parseDateString($entityFields['DATE_CREATE']) : null;
		if($startDate === null || $startDate == $zeroDate || $startDate->getTimestamp() === false)
		{
			$startDate = new Date();
		}
	}

	/** @var Date $endDate */
	$endDate = self::parseDateString(isset($entityFields['CLOSEDATE']) ? $entityFields['CLOSEDATE'] : '');
	if($endDate === null || $endDate == $zeroDate || $endDate->getTimestamp() === false)
	{
		$endDate = new Date('9999-12-31', 'Y-m-d');
	}

	$date = $isFinalized ? $endDate : $startDate;
	$day = (int)$date->format('d');
	$month = (int)$date->format('m');
	$quarter = $month <= 3 ? 1 : ($month <= 6 ? 2 : ($month <= 9 ? 3 : 4));
	$year = (int)$date->format('Y');

	$currencyID = isset($entityFields['CURRENCY_ID']) ? $entityFields['CURRENCY_ID'] : '';
	$accountingCurrencyID = \CCrmCurrency::GetAccountCurrencyID();
	$sum = isset($entityFields['OPPORTUNITY']) ? (double)$entityFields['OPPORTUNITY'] : 0.0;
	$binding = $bindingMap->get('SUM_TOTAL');
	if($binding === null)
	{
		$total = isset($entityFields['OPPORTUNITY']) ? (double)$entityFields['OPPORTUNITY'] : 0.0;
	}
	else
	{
		$bindingFieldName = $binding->getFieldName();
		if($bindingFieldName === '')
		{
			$bindingFieldName = 'OPPORTUNITY';
		}
		$total = isset($entityFields[$bindingFieldName]) ? (double)$entityFields[$bindingFieldName] : 0.0;

		if($bindingFieldName !== 'OPPORTUNITY' && $binding->getOption('ADD_PRODUCT_ROW_SUM') === 'Y')
		{
			$total += $sum;
		}
	}

	if($currencyID !== $accountingCurrencyID)
	{
		$accData = \CCrmAccountingHelper::PrepareAccountingData(
			array(
				'CURRENCY_ID' => $currencyID,
				'SUM' => $total,
				'EXCH_RATE' => isset($entityFields['EXCH_RATE']) ? $entityFields['EXCH_RATE'] : null
			)
		);
		if(is_array($accData))
		{
			$total = (double)$accData['ACCOUNT_SUM'];
		}
	}

	$sumSlots = array();
	$sumSlotFields = DealSumStatisticsTable::getSumSlotFieldNames();
	foreach($sumSlotFields as $fieldName)
	{
		$binding = $bindingMap->get($fieldName);
		if($binding === null)
		{
			$slotSum = 0.0;
		}
		else
		{
			$bindingFieldName = $binding->getFieldName();
			$slotSum = $bindingFieldName !== '' && isset($entityFields[$bindingFieldName])
				? (double)$entityFields[$bindingFieldName] : 0.0;

			if($binding->getOption('ADD_PRODUCT_ROW_SUM') === 'Y')
			{
				$slotSum += $sum;
			}
		}

		if($currencyID !== $accountingCurrencyID)
		{
			$accData = \CCrmAccountingHelper::PrepareAccountingData(
				array(
					'CURRENCY_ID' => $currencyID,
					'SUM' => $slotSum,
					'EXCH_RATE' => isset($entityFields['EXCH_RATE']) ? $entityFields['EXCH_RATE'] : null
				)
			);
			if(is_array($accData))
			{
				$slotSum = (double)$accData['ACCOUNT_SUM'];
			}
		}

		$sumSlots[$fieldName] = $slotSum;
	}

	$latest = self::getLatest($ownerID);
	if(is_array($latest))
	{
		if($forced)
		{
			//Remove finalizing record(s).
			//We will insert new finalizing record at the end of this method.
			DealSumStatisticsTable::deleteByFilter(
				array(
					'OWNER_ID' => $ownerID,
					'SEMANTIC_ID' => PhaseSemantics::getFinalSemantis()
				)
			);

			DealSumStatisticsTable::synchronizeSumFields(
				$ownerID,
				array_merge(array('SUM_TOTAL' => $total), $sumSlots)
			);
		}

		if(isset($latest['CREATED_DATE']) && isset($latest['START_DATE']) && isset($latest['END_DATE']))
		{
			if(!$forced
				&& $date == $latest['CREATED_DATE']
				&& $startDate == $latest['START_DATE']
				&& $endDate == $latest['END_DATE']
				&& $responsibleID === (int)$latest['RESPONSIBLE_ID']
				&& $stageID === $latest['STAGE_ID']
				&& $currencyID === $latest['CURRENCY_ID']
				&& $total === (double)$latest['SUM_TOTAL']
				&& $sumSlots['UF_SUM_1'] === (double)$latest['UF_SUM_1']
				&& $sumSlots['UF_SUM_2'] === (double)$latest['UF_SUM_2']
				&& $sumSlots['UF_SUM_3'] === (double)$latest['UF_SUM_3']
				&& $sumSlots['UF_SUM_4'] === (double)$latest['UF_SUM_4']
				&& $sumSlots['UF_SUM_5'] === (double)$latest['UF_SUM_5']
			)
			{
				//Skip upsert if nothing changed.
				return;
			}

			if( $date->getTimestamp() !== $latest['CREATED_DATE']->getTimestamp()
				|| $startDate->getTimestamp() !== $latest['START_DATE']->getTimestamp()
				|| $endDate->getTimestamp() !== $latest['END_DATE']->getTimestamp()
				|| $responsibleID !== (int)$latest['RESPONSIBLE_ID']
			) {
				//Synchronize dates and responsible user.
				if(!$isFinalized)
				{
					//Deal is not finalized. Clear final item and synchronize process item.
					DealSumStatisticsTable::deleteByFilter(
						array(
							'OWNER_ID' => $ownerID,
							'SEMANTIC_ID' => PhaseSemantics::getFinalSemantis()
						)
					);

					DealSumStatisticsTable::synchronize(
						$ownerID,
						array(
							'CREATED_DATE' => $startDate,
							'START_DATE' => $startDate,
							'END_DATE' => $endDate,
							'RESPONSIBLE_ID' => $responsibleID
						),
						PhaseSemantics::getProcessSemantis()
					);
				}
				else
				{
					//Remove finalizing record(s) for avoid possible primary key conflict with "process" semantics.
					//We will insert new finalizing record at the end of this method.
					DealSumStatisticsTable::deleteByFilter(
						array(
							'OWNER_ID' => $ownerID,
							'SEMANTIC_ID' => PhaseSemantics::getFinalSemantis()
						)
					);

					if($startDate->getTimestamp() === $endDate->getTimestamp())
					{
						//Deal is finalized and start date is equal to end date. Clear process item and synchronize final item.
						DealSumStatisticsTable::deleteByFilter(
							array(
								'OWNER_ID' => $ownerID,
								'SEMANTIC_ID' => PhaseSemantics::getProcessSemantis()
							)
						);
					}
					else
					{
						//Deal is finalized and start date is not equal to end date. synchronize process and final items.
						DealSumStatisticsTable::synchronize(
							$ownerID,
							array(
								'CREATED_DATE' => $startDate,
								'START_DATE' => $startDate,
								'END_DATE' => $endDate,
								'RESPONSIBLE_ID' => $responsibleID
							),
							PhaseSemantics::getProcessSemantis()
						);
					}
				}
			}
			elseif($stageID !== $latest['STAGE_ID'] && !$isFinalized)
			{
				//Remove finalizing record(s)
				DealSumStatisticsTable::deleteByFilter(
					array(
						'OWNER_ID' => $ownerID,
						'SEMANTIC_ID' => PhaseSemantics::getFinalSemantis()
					)
				);
			}
		}
	}

	$data = array_merge(
		array(
			'OWNER_ID' => $ownerID,
			'CREATED_DATE' => $date,
			'START_DATE' => $startDate,
			'END_DATE' => $endDate,
			'PERIOD_YEAR' => $year,
			'PERIOD_QUARTER' => $quarter,
			'PERIOD_MONTH' => $month,
			'PERIOD_DAY' => $day,
			'RESPONSIBLE_ID' => $responsibleID,
			'CATEGORY_ID' => $categoryID,
			'STAGE_SEMANTIC_ID' => $semanticID,
			'STAGE_ID' => $stageID,
			'IS_LOST' => $isLost ? 'Y' : 'N',
			'CURRENCY_ID' => $accountingCurrencyID,
			'SUM_TOTAL' => $total
		),
		$sumSlots
	);
	DealSumStatisticsTable::upsert($data);
}