• Модуль: tasks
  • Путь к файлу: ~/bitrix/modules/tasks/lib/internals/counter/processor/efficiencyprocessor.php
  • Класс: BitrixTasksInternalsCounterProcessorEfficiencyProcessor
  • Вызов: EfficiencyProcessor::updateEfficiencyForUpdated
private function updateEfficiencyForUpdated(int $taskId): array
{
	if (
		!array_key_exists($taskId, $this->originData)
		|| !array_key_exists($taskId, $this->modifiedData)
	)
	{
		return [];
	}

	/** @var EventResource $oldTask */
	$oldTask = $this->originData[$taskId];
	/** @var EventResource $newTask */
	$newTask = $this->modifiedData[$taskId];

	if (
		!$oldTask
		|| !$newTask
	)
	{
		return [];
	}

	$oldStatus = $oldTask->getStatus();
	$newStatus = $newTask->getStatus();
	$statusChanged = $oldStatus !== $newStatus;

	/** @var DateTime $oldDeadline */
	$oldDeadline = $oldTask->getDeadline();
	/** @var DateTime $newDeadline */
	$newDeadline = $newTask->getDeadline();
	$deadlineChanged =
		(!$oldDeadline && $newDeadline)
		|| ($oldDeadline && !$newDeadline)
		|| ($oldDeadline && $newDeadline && $oldDeadline->isNotEqualTo($newDeadline))
	;
	$isViolation = ($deadlineChanged ? $newTask->isExpired() : $oldTask->isExpired());

	$oldGroupId = $oldTask->getGroupId();
	$newGroupId = $newTask->getGroupId();
	$groupChanged = $oldGroupId !== $newGroupId;
	$groupId = ($groupChanged ? $newGroupId : $oldGroupId);

	$oldMembers = $oldTask->getMembersAsArray();
	$newMembers = $newTask->getMembersAsArray();

	$oldResponsibleId = current($oldMembers[MemberTable::MEMBER_TYPE_RESPONSIBLE]);
	$newResponsibleId = current($newMembers[MemberTable::MEMBER_TYPE_RESPONSIBLE]);
	$responsibleChanged = $oldResponsibleId !== $newResponsibleId;

	$oldAccomplices = $oldMembers[MemberTable::MEMBER_TYPE_ACCOMPLICE];
	$newAccomplices = $newMembers[MemberTable::MEMBER_TYPE_ACCOMPLICE];
	$accomplicesIn = array_diff($newAccomplices, $oldAccomplices);
	$accomplicesOut = array_diff($oldAccomplices, $newAccomplices);
	$allAccomplices = array_unique(array_merge($oldAccomplices, $newAccomplices));
	$accomplicesChanged = $oldAccomplices !== $newAccomplices;

	$oldTaskData = [
		'ID' => $taskId,
		'TITLE' => $newTask->getTitle(),
		'DEADLINE' => $newTask->getDeadline(),
		'CREATED_BY' => current($oldMembers[MemberTable::MEMBER_TYPE_ORIGINATOR]),
	];
	$newTaskData = [
		'ID' => $taskId,
		'TITLE' => $newTask->getTitle(),
		'DEADLINE' => $newTask->getDeadline(),
		'CREATED_BY' => current($newMembers[MemberTable::MEMBER_TYPE_ORIGINATOR]),
	];

	$responsibleModified = false;
	$accomplicesModified = false;

	$canProceed = false;
	$statusesCompleted = [Status::DEFERRED, Status::COMPLETED, Status::SUPPOSEDLY_COMPLETED];
	$statusesInProgress = [Status::NEW, Status::PENDING, Status::IN_PROGRESS];

	$processedMembers = [];

	// TASK DEFERRED OR COMPLETED
	if ($statusChanged && in_array($newStatus, $statusesCompleted, true))
	{
		Effective::repair($taskId);
		$this->modifyEfficiencyForResponsible($oldResponsibleId, $oldTaskData, $oldGroupId, false);
		$processedMembers[$oldResponsibleId] = $oldResponsibleId;

		foreach ($oldAccomplices as $userId)
		{
			if ($userId !== $oldResponsibleId)
			{
				$this->modifyEfficiencyForAccomplice($userId, $oldTaskData, $oldGroupId, false);
				$processedMembers[$userId] = $userId;
			}
		}

		if ($responsibleChanged)
		{
			$this->modifyEfficiencyForResponsible($newResponsibleId, $newTaskData, $groupId, false);
			$processedMembers[$newResponsibleId] = $newResponsibleId;
		}
		if ($accomplicesChanged)
		{
			foreach ($accomplicesIn as $userId)
			{
				if ($userId !== $oldResponsibleId && $userId !== $newResponsibleId)
				{
					$this->modifyEfficiencyForAccomplice($userId, $newTaskData, $groupId, false);
					$processedMembers[$userId] = $userId;
				}
			}
		}

		return $processedMembers;
	}

	// TASK RESTARTED
	if (
		$statusChanged
		&& in_array($oldStatus, $statusesCompleted, true)
		&& in_array($newStatus, $statusesInProgress, true)
	)
	{
		if (!$responsibleChanged)
		{
			$this->modifyEfficiencyForResponsible($oldResponsibleId, $oldTaskData, $groupId, $isViolation);
			$processedMembers[$oldResponsibleId] = $oldResponsibleId;
			$responsibleModified = true;
		}
		if (!$accomplicesChanged)
		{
			foreach ($oldAccomplices as $userId)
			{
				if ($userId !== $oldResponsibleId && $userId !== $newResponsibleId)
				{
					$this->modifyEfficiencyForAccomplice($userId, $oldTaskData, $groupId, $isViolation);
					$processedMembers[$userId] = $userId;
				}
			}
			$accomplicesModified = true;
		}

		$canProceed = true;
	}

	if (!$canProceed && in_array($oldStatus, $statusesCompleted, true))
	{
		return $processedMembers;
	}

	// RESPONSIBLE CHANGED
	if ($responsibleChanged)
	{
		if (
			($activeViolations = Effective::checkActiveViolations($taskId, $oldResponsibleId))
			&& in_array($oldResponsibleId, $newAccomplices, true)
		)
		{
			EffectiveTable::update(
				$activeViolations[0]['ID'],
				['USER_TYPE' => MemberTable::MEMBER_TYPE_ACCOMPLICE, 'GROUP_ID' => $groupId]
			);
		}
		else
		{
			Effective::repair($taskId, $oldResponsibleId, MemberTable::MEMBER_TYPE_RESPONSIBLE);
		}

		$this->modifyEfficiencyForResponsible($oldResponsibleId, $oldTaskData, $oldGroupId, false);
		$processedMembers[$oldResponsibleId] = $oldResponsibleId;

		if ($activeViolations = Effective::checkActiveViolations($taskId, $newResponsibleId))
		{
			EffectiveTable::update(
				$activeViolations[0]['ID'],
				['USER_TYPE' => MemberTable::MEMBER_TYPE_RESPONSIBLE, 'GROUP_ID' => $groupId]
			);
			$this->modifyEfficiencyForResponsible($newResponsibleId, $newTaskData, $groupId, false);
			$processedMembers[$newResponsibleId] = $newResponsibleId;
		}
		else
		{
			$this->modifyEfficiencyForResponsible($newResponsibleId, $newTaskData, $groupId, $isViolation);
			$processedMembers[$newResponsibleId] = $newResponsibleId;
		}

		$responsibleModified = true;
	}

	// ACCOMPLICES CHANGED
	if ($accomplicesChanged)
	{
		foreach ($accomplicesOut as $userId)
		{
			if ($userId !== $oldResponsibleId && $userId !== $newResponsibleId)
			{
				Effective::repair($taskId, $userId, MemberTable::MEMBER_TYPE_ACCOMPLICE);
				$this->modifyEfficiencyForAccomplice($userId, $oldTaskData, $oldGroupId, false);
				$processedMembers[$userId] = $userId;
			}
		}
		foreach ($accomplicesIn as $userId)
		{
			if ($userId !== $oldResponsibleId && $userId !== $newResponsibleId)
			{
				$this->modifyEfficiencyForAccomplice($userId, $newTaskData, $groupId, $isViolation);
				$processedMembers[$userId] = $userId;
			}
		}
	}

	// DEADLINE CHANGED
	if ($deadlineChanged && !$isViolation)
	{
		Effective::repair($taskId);

		if (!$responsibleModified)
		{
			$this->modifyEfficiencyForResponsible($oldResponsibleId, $newTaskData, $groupId, false);
			$processedMembers[$oldResponsibleId] = $oldResponsibleId;
			$responsibleModified = true;
		}
		if (!$accomplicesModified)
		{
			$accomplices = ($accomplicesChanged ? array_diff($newAccomplices, $accomplicesIn) : $allAccomplices);
			foreach ($accomplices as $userId)
			{
				if ($userId !== $oldResponsibleId && $userId !== $newResponsibleId)
				{
					$this->modifyEfficiencyForAccomplice($userId, $newTaskData, $groupId, false);
					$processedMembers[$userId] = $userId;
				}
			}
			$accomplicesModified = true;
		}
	}

	// GROUP CHANGED
	if ($groupChanged)
	{
		if ($activeViolations = Effective::checkActiveViolations($taskId))
		{
			foreach ($activeViolations as $violation)
			{
				EffectiveTable::update($violation['ID'], ['GROUP_ID' => $newGroupId]);
			}

			if (!$responsibleModified)
			{
				$this->modifyEfficiencyForResponsible($oldResponsibleId, $newTaskData, $newGroupId, false);
				$processedMembers[$oldResponsibleId] = $oldResponsibleId;
			}
			if (!$accomplicesModified)
			{
				$accomplices = ($accomplicesChanged ? array_diff($newAccomplices, $accomplicesIn) : $allAccomplices);
				foreach ($accomplices as $userId)
				{
					if ($userId !== $oldResponsibleId && $userId !== $newResponsibleId)
					{
						$this->modifyEfficiencyForAccomplice($userId, $newTaskData, $newGroupId, false);
						$processedMembers[$userId] = $userId;
					}
				}
			}
		}
		else
		{
			if (!$responsibleModified)
			{
				$this->modifyEfficiencyForResponsible($oldResponsibleId, $newTaskData, $newGroupId, $isViolation);
				$processedMembers[$oldResponsibleId] = $oldResponsibleId;
			}
			if (!$accomplicesModified)
			{
				$accomplices = ($accomplicesChanged ? array_diff($newAccomplices, $accomplicesIn) : $allAccomplices);
				foreach ($accomplices as $userId)
				{
					if ($userId !== $oldResponsibleId && $userId !== $newResponsibleId)
					{
						$this->modifyEfficiencyForAccomplice($userId, $newTaskData, $newGroupId, $isViolation);
						$processedMembers[$userId] = $userId;
					}
				}
			}
		}
	}

	return $processedMembers;
}