• Модуль: timeman
  • Путь к файлу: ~/bitrix/modules/timeman/lib/service/worktime/violation/fixedscheduleviolationbuilder.php
  • Класс: BitrixTimemanServiceWorktimeViolationFixedScheduleViolationBuilder
  • Вызов: FixedScheduleViolationBuilder::buildPeriodTimeLackViolation
public function buildPeriodTimeLackViolation($params, $fromDateTime, $toDateTime)
{
	$result = new WorktimeViolationResult();
	$schedule = $params->getSchedule();
	$violationRules = $this->getViolationRules();
	if (!$violationRules->isPeriodWorkTimeLackControlEnabled())
	{
		return $result->addError(new Error('', WorktimeViolationResult::ERROR_CODE_VIOLATION_NOT_UNDER_CONTROL));
	}
	$shifts = $schedule->obtainShifts();
	if (empty($shifts))
	{
		return $result->addError(new Error('', WorktimeViolationResult::ERROR_CODE_SHIFT_NOT_FOUND));
	}

	$activeUsers = $this->findActiveUsers($schedule, $violationRules->getEntityCode());
	if ($activeUsers->count() === 0)
	{
		return $result->addError(new Error('', WorktimeViolationResult::ERROR_CODE_NO_USERS_ASSIGNED_TO_SCHEDULE));
	}


	$workDays = [];
	foreach ($shifts as $shift)
	{
		foreach (str_split($shift->getWorkDays()) as $workDay)
		{
			if (isset($workDays[$workDay]))
			{
				return $result->addError(new Error('', WorktimeViolationResult::ERROR_CODE_SHIFTS_DAYS_INTERSECT));
			}
			$workDays[$workDay] = $shift->getDuration() - $shift->getBreakDuration();
			if ($workDays[$workDay] < 0)
			{
				return $result->addError(new Error('', WorktimeViolationResult::ERROR_CODE_INVALID_SHIFT_DURATION));
			}
		}
	}

	$this->setAbsenceData($this->findAbsenceForPeriod($fromDateTime, $toDateTime, $activeUsers->getIdList()));

	$workedStatistics = $this->findRecordsForPeriod($fromDateTime, $toDateTime, $schedule, $activeUsers->getIdList());
	$workedStatistics = array_combine(array_column($workedStatistics, 'USER_ID'), $workedStatistics);

	$periodDates = $this->createPeriodDates($fromDateTime, $toDateTime);
	foreach ($activeUsers as $user)
	{
		$expectedSeconds = $this->calculateExpectedWorkedSecondsForPeriod(
			$periodDates,
			$workDays,
			$user->getId()
		);
		if ($expectedSeconds <= 0)
		{
			continue;
		}

		if (empty($workedStatistics[$user->getId()]['DURATION'])
			|| $expectedSeconds - (int)$workedStatistics[$user->getId()]['DURATION'] > $violationRules->getMaxWorkTimeLackForPeriod())
		{
			if (empty($workedStatistics[$user->getId()]))
			{
				$recordSeconds = 0;
				$violatedSeconds = $expectedSeconds;
			}
			else
			{
				$recordSeconds = $workedStatistics[$user->getId()]['DURATION'];
				$violatedSeconds = $expectedSeconds - (int)$workedStatistics[$user->getId()]['DURATION'] - $violationRules->getMaxWorkTimeLackForPeriod();
			}
			$result->addViolation(
				$this->createViolation(
					WorktimeViolation::TYPE_TIME_LACK_FOR_PERIOD,
					$recordSeconds,
					$violatedSeconds,
					$user->getId()
				)
			);
		}
	}

	return $result;
}