Merge::onRunning

  1. Bitrix24 API (v. 23.675.0)
  2. crm
  3. Merge
  4. onRunning
  • Модуль: crm
  • Путь к файлу: ~/bitrix/modules/crm/lib/agent/duplicate/background/merge.php
  • Класс: Bitrix\Crm\Agent\Duplicate\Background\Merge
  • Вызов: Merge::onRunning
protected function onRunning(array $progressData): bool
{
	if (!$this->checkStepInterval($progressData))
	{
		return false;
	}

	$typeIds = $this->getTypeIds($progressData['TYPES']);
	if(empty($typeIds))
	{
		return $this->setError($progressData, static::ERR_INDEX_TYPES);
	}

	if (!DuplicateIndexType::checkScopeValue($progressData['SCOPE']))
	{
		return $this->setError($progressData, static::ERR_SCOPE);
	}

	$entityTypeId = $this->getEntityTypeId();
	$scope = $progressData['SCOPE'];
	$userId = $this->getUserId();
	$enablePermissionCheck = !Container::getInstance()->getUserPermissions($userId)->isAdmin();

	$timeToMerge = (int)floor(static::STEP_TTL * static::STEP_INDEX_RATIO);
	$startTime = time();
	$endTime = $startTime;
	$isFinal = false;
	$needNotify = false;
	$notifyPercentage = 0;
	while (!$isFinal && $endTime - $startTime <= $timeToMerge)
	{

		$list = new DuplicateList(
			DuplicateIndexType::joinType($typeIds),
			$this->getEntityTypeId(),
			$userId,
			$enablePermissionCheck
		);
		$list->setScope($scope);
		$list->setStatusIDs([DuplicateStatus::PENDING]);

		$list->setSortTypeID(
			$entityTypeId === CCrmOwnerType::Company
				? DuplicateIndexType::ORGANIZATION
				: DuplicateIndexType::PERSON
		);
		$list->setSortOrder(SORT_ASC);

		$items = $list->getRootItems(0, 1);
		if(empty($items))
		{
			$isFinal = true;

			$list->setStatusIDs([]);
			$progressData['TOTAL_ITEMS'] = $list->getRootItemCount();
			$progressData['TOTAL_ENTITIES'] = DuplicateList::getTotalEntityCount(
				$userId,
				$entityTypeId,
				$typeIds,
				$scope
			);
			$progressData['STATUS'] = static::STATUS_FINISHED;
			$progressData['TIMESTAMP_FINISH'] = time();
			$progressData['TIMESTAMP'] = time();

			if ($this->isNeedFullNotification($progressData))
			{
				$notifyPercentage = static::PERCENT_FULL;
				$needNotify = true;
			}

			$this->setAgentResult(false);
		}
		else
		{
			$item = $items[0];

			$rootEntityId = $item->getRootEntityID();
			$criterion = $item->getCriterion();
			$entityIds = $criterion->getEntityIDs(
				$entityTypeId,
				$rootEntityId,
				$userId,
				$enablePermissionCheck,
				['limit' => 50]
			);
			$entityIds = array_unique($entityIds);

			if(empty($entityIds))
			{
				//Skip Junk item
				DuplicateIndexTable::deleteByFilter(
					array(
						'USER_ID' => $userId,
						'ENTITY_TYPE_ID' => $entityTypeId,
						'TYPE_ID' => $criterion->getIndexTypeID(),
						'MATCH_HASH' => $criterion->getMatchHash()
					)
				);
			}
			else
			{
				$isEntityMergerException = false;
				$merger = EntityMerger::create($entityTypeId, $userId, $enablePermissionCheck);
				$merger->setConflictResolutionMode(ConflictResolutionMode::ASK_USER);
				try
				{
					$merger->mergeBatch($entityIds, $rootEntityId, $criterion);
				}
				catch(EntityMergerException $e)
				{
					$isEntityMergerException = true;
					if($e->getCode() === EntityMergerException::CONFLICT_OCCURRED)
					{
						DuplicateIndexBuilder::setStatusID(
							$userId,
							$entityTypeId,
							$criterion->getIndexTypeID(),
							$criterion->getMatchHash(),
							$scope,
							DuplicateStatus::CONFLICT
						);
						$progressData['CONFLICTED_ITEMS']++;
					}
					else
					{
						DuplicateIndexBuilder::setStatusID(
							$userId,
							$entityTypeId,
							$criterion->getIndexTypeID(),
							$criterion->getMatchHash(),
							$scope,
							DuplicateStatus::ERROR
						);
					}
				}
				catch(Exception $e)
				{
					return $this->setError(
						$progressData,
						static::ERR_MERGE_UNHANDLED_EXCEPTION,
						['MESSAGE' => $e->getMessage()]
					);
				}

				$progressData['PROCESSED_ITEMS']++;
				// Recognize the need for progress notifications by 50% and 90%.
				if ($progressData['TIMESTAMP_START'] > 0 && $progressData['TOTAL_ITEMS'] > 0)
				{
					$percentage = (int)floor(
						static::PERCENT_FULL * $progressData['PROCESSED_ITEMS'] / $progressData['FOUND_ITEMS']
					);
					if (
						$percentage >= static::PERCENT_HALF
						&& $percentage < static::PERCENT_ALMOST
						&& $progressData['TIMESTAMP_HALF'] === 0
					)
					{
						$progressData['TIMESTAMP_HALF'] = time();
						if ($this->isNeedHalfNotification($progressData))
						{
							$notifyPercentage = static::PERCENT_HALF;
							$needNotify = true;
						}
					}
					else if ($percentage >= static::PERCENT_ALMOST && $progressData['TIMESTAMP_ALMOST'] === 0)
					{
						$progressData['TIMESTAMP_ALMOST'] = time();
						if ($this->isNeedAlmostNotification($progressData))
						{
							$notifyPercentage = static::PERCENT_ALMOST;
							$needNotify = true;
						}
					}
				}

				if (!$isEntityMergerException)
				{
					$progressData['MERGED_ITEMS']++;
				}
			}
		}

		$currentProgressData = $this->getProgressData();
		if (
			isset($currentProgressData['TIMESTAMP'])
			&& isset($currentProgressData['NEXT_STATUS'])
			&& $currentProgressData['TIMESTAMP'] >= $progressData['TIMESTAMP']
			&& $currentProgressData['NEXT_STATUS'] !== static::STATUS_UNDEFINED
			&& $currentProgressData['NEXT_STATUS'] !== $progressData['NEXT_STATUS']
		)
		{
			$progressData['NEXT_STATUS'] = $currentProgressData['NEXT_STATUS'];
		}

		$this->setProgressData($progressData);

		$endTime = time();
	}

	// Progress notification, if needed.
	if ($needNotify)
	{
		$this->notifyPercentage($notifyPercentage);
	}

	return false;
}

Добавить комментарий