• Модуль: timeman
  • Путь к файлу: ~/bitrix/modules/timeman/lib/absence.php
  • Класс: BitrixTimemanAbsence
  • Вызов: Absence::getMonthReport
static function getMonthReport($userId, $year, $month, $workdayHours = self::DEFAULT_WORKDAY_HOURS, $idleMinutes = null)
{
	$userId = intval($userId);
	if ($userId <= 0)
		return false;

	$year = intval($year);
	$year = $year > 3000 || $year < 1900? date('Y'): $year;

	$month = intval($month);
	$month = $month > 12 || $month < 1? date('n'): $month;

	$idleMinutes = !is_null($idleMinutes)? intval($idleMinutes): self::getMinimumIdleForReport();
	$idleMinutes = $idleMinutes > 0? $idleMinutes: 0;

	$workdayHours = intval($workdayHours);
	$workdayHours = $workdayHours > 0? $workdayHours: 1;
	$workdayHoursInSeconds = $workdayHours*60*60;

	$dateStart = new BitrixMainTypeDateTime($year.'-'.str_pad($month, 2, '0', STR_PAD_LEFT).'-01 00:00:00', 'Y-m-d H:i:s');
	$dateFinish = new BitrixMainTypeDateTime(($year+($month==12? 1: 0)).'-'.str_pad(($month==12? 1: $month+1), 2, '0', STR_PAD_LEFT).'-01 00:00:00', 'Y-m-d H:i:s');
	$dateFinish->add('-1 SECONDS');

	$workDays = Array();

	$orm = BitrixTimemanModelAbsenceTable::getList(Array(
		'select' => Array(
				'ID', 'USER_ID', 'TYPE', 'DATE_START', 'DATE_FINISH', 'DURATION', 'ACTIVE', 'ENTRY_ID', 'REPORT_TYPE', 'REPORT_TEXT', 'SYSTEM_TEXT', 'SOURCE_START', 'SOURCE_FINISH', 'IP_START', 'IP_FINISH',
				'ENTRIES_DATE_START' => 'ENTRIES.DATE_START',
				'ENTRIES_DATE_FINISH' => 'ENTRIES.DATE_FINISH',
				'ENTRIES_TIME_LEAKS' => 'ENTRIES.TIME_LEAKS',
				'ENTRIES_DURATION' => 'ENTRIES.DURATION',
		),
		'filter' => Array(
			'=USER_ID' => $userId,
			'>=DATE_START' => $dateStart,
			'<=DATE_START' => $dateFinish
		),
		'runtime' => Array(
			new BitrixMainEntityReferenceField(
				'ENTRIES',
				'BitrixTimemanModelEntriesTable',
				array(
					"=ref.ID" => "this.ENTRY_ID",
				),
				array("join_type"=>"left")
			)
		)
	));
	while ($entry = $orm->fetch())
	{
		$entry['ACTIVE'] = $entry['ACTIVE'] !== 'N';
		$entry['DURATION'] = (int)$entry['DURATION'];

		if (
			$entry['ENTRIES_DURATION'] == 0
			&& $entry['ENTRIES_DATE_START'] instanceof BitrixMainTypeDateTime
			&& $entry['ENTRIES_DATE_FINISH'] instanceof BitrixMainTypeDateTime
		)
		{
			$entry['ENTRIES_DURATION'] = $entry['ENTRIES_DATE_FINISH']->getTimestamp() - $entry['ENTRIES_DATE_START']->getTimestamp() - (int)$entry['ENTRIES_TIME_LEAKS'];
		}

		$index = $entry['DATE_START'] instanceof BitrixMainTypeDateTime? $entry['DATE_START']->format('Ymd'): time();

		$duration = $entry['DURATION'];

		if ($entry['ENTRIES_DATE_FINISH'] instanceof BitrixMainTypeDateTime)
		{
			$entry['ENTRIES_DAY_COMPLETE'] = true;
		}
		else
		{
			$entry['ENTRIES_DAY_COMPLETE'] = false;
			$entry['ENTRIES_DATE_FINISH'] = new BitrixMainTypeDateTime();
			$entry['ENTRIES_DURATION'] = $entry['ENTRIES_DATE_FINISH']->getTimestamp() - $entry['ENTRIES_DATE_START']->getTimestamp();
		}

		if (!$entry['DATE_FINISH'] && $entry['ENTRIES_DATE_FINISH'] instanceof BitrixMainTypeDateTime)
		{
			$entry['DATE_FINISH'] = $entry['ENTRIES_DATE_FINISH'];
			$duration = $entry['DURATION'] = $entry['DATE_FINISH']->getTimestamp() - $entry['DATE_START']->getTimestamp();
		}

		if ($entry['ENTRIES_DATE_FINISH'] instanceof BitrixMainTypeDateTime)
		{
			if (
				$entry['DATE_START'] instanceof BitrixMainTypeDateTime
				&& $entry['DATE_START']->getTimestamp() > $entry['ENTRIES_DATE_FINISH']->getTimeStamp()
			)
			{
				continue;
			}
			else if (
				$entry['DATE_FINISH'] instanceof BitrixMainTypeDateTime
				&& $entry['DATE_FINISH']->getTimestamp() > $entry['ENTRIES_DATE_FINISH']->getTimeStamp()
			)
			{
				$entry['DATE_FINISH'] = $entry['ENTRIES_DATE_FINISH'];

				$duration = $entry['DURATION'] = $entry['DATE_FINISH']->getTimestamp() - $entry['DATE_START']->getTimestamp();
			}
		}

		$workDays[$index]['INDEX'] = $index;
		$workDays[$index]['DAY_TITLE'] = $entry['DATE_START'] instanceof BitrixMainTypeDateTime? $entry['DATE_START']->format(BitrixMainTypeDate::getFormat()): '';
		$workDays[$index]['WORKDAY_DATE_START'] = $entry['ENTRIES_DATE_START'] instanceof BitrixMainTypeDateTime? $entry['ENTRIES_DATE_START']: null;
		$workDays[$index]['WORKDAY_DATE_FINISH'] = $entry['ENTRIES_DATE_FINISH'] instanceof BitrixMainTypeDateTime? $entry['ENTRIES_DATE_FINISH']: null;
		$workDays[$index]['WORKDAY_COMPLETE'] = $entry['ENTRIES_DAY_COMPLETE'];
		$workDays[$index]['WORKDAY_TIME_LEAKS_USER'] = (int)$entry['ENTRIES_TIME_LEAKS'];
		$workDays[$index]['WORKDAY_TIME_LEAKS_FINAL'] = 0;
		$workDays[$index]['WORKDAY_DURATION'] = (int)$entry['ENTRIES_DURATION'];
		$workDays[$index]['WORKDAY_DURATION_FINAL'] = 0;
		$workDays[$index]['WORKDAY_DURATION_CONFIG'] = $workdayHoursInSeconds;

		if (!isset($workDays[$index]['REPORTS']))
		{
			$workDays[$index]['REPORTS'] = [];
			$workDays[$index]['WORKDAY_TIME_LEAKS_REAL'] = 0;
		}

		$duration = (int)$duration;

		$entry['DATE_START'] = $entry['DATE_START'] instanceof BitrixMainTypeDateTime? $entry['DATE_START']: null;
		$entry['DATE_FINISH'] = $entry['DATE_FINISH'] instanceof BitrixMainTypeDateTime? $entry['DATE_FINISH']: null;

		if (
			$entry['SOURCE_START'] == self::SOURCE_TM_EVENT
			|| $entry['SOURCE_START'] == self::SOURCE_DESKTOP_OFFLINE_AGENT
			|| $entry['SOURCE_START'] == self::SOURCE_DESKTOP_ONLINE_EVENT
			|| $entry['SOURCE_START'] == self::SOURCE_DESKTOP_START_EVENT && !BitrixTimemanCommon::isNetworkRange($entry['IP_START'])
		)
		{
			// ok
		}
		else if (
			$entry['DATE_FINISH'] && !$duration
			|| $duration && $duration <= $idleMinutes*60
		)
		{
			continue;
		}

		$entry['IP_START_NETWORK'] = false;
		if ($entry['IP_START'])
		{
			if ($result = BitrixTimemanCommon::isNetworkRange($entry['IP_START']))
			{
				$entry['IP_START_NETWORK'] = $result;
			}
		}

		$entry['IP_FINISH_NETWORK'] = false;
		if ($entry['IP_FINISH'])
		{
			if ($result = BitrixTimemanCommon::isNetworkRange($entry['IP_FINISH']))
			{
				$entry['IP_FINISH_NETWORK'] = $result;
			}
		}


		if ($entry['REPORT_TYPE'] != self::REPORT_TYPE_WORK)
		{
			$workDays[$index]['WORKDAY_TIME_LEAKS_REAL'] += $duration;
		}
		else
		{
			$workDays[$index]['WORKDAY_TIME_LEAKS_REAL'] += 0;
		}

		if ($workDays[$index]['WORKDAY_DATE_START'])
		{
//				$workdayHours
			if (!$workDays[$index]['WORKDAY_COMPLETE'] && $entry['ENTRIES_DURATION'] > 0)
			{
				$workDays[$index]['WORKDAY_DURATION'] = $workDays[$index]['WORKDAY_DURATION'] - $workDays[$index]['WORKDAY_TIME_LEAKS_USER'];
			}
			if ($workDays[$index]['WORKDAY_DATE_FINISH'] && $entry['ENTRIES_DURATION'] > 0)
			{
				if ($workDays[$index]['WORKDAY_DURATION'] > $workdayHoursInSeconds)
				{
					$workDays[$index]['WORKDAY_TIME_LEAKS_FINAL'] = $workDays[$index]['WORKDAY_DURATION'] - $workdayHoursInSeconds - $workDays[$index]['WORKDAY_TIME_LEAKS_REAL'];
					$workDays[$index]['WORKDAY_TIME_LEAKS_FINAL'] = $workDays[$index]['WORKDAY_TIME_LEAKS_FINAL'] * -1;
				}
				else
				{
					$workDays[$index]['WORKDAY_TIME_LEAKS_FINAL'] = $workdayHoursInSeconds - $workDays[$index]['WORKDAY_DURATION'] + $workDays[$index]['WORKDAY_TIME_LEAKS_REAL'];
				}

				if ($workDays[$index]['WORKDAY_TIME_LEAKS_FINAL'] > $workdayHoursInSeconds)
				{
					$workDays[$index]['WORKDAY_TIME_LEAKS_FINAL'] = $workdayHoursInSeconds;
				}
			}
		}

		if ($entry['ENTRIES_DURATION'] > 0)
		{
			$workDays[$index]['WORKDAY_DURATION_FINAL'] = $workdayHoursInSeconds-$workDays[$index]['WORKDAY_TIME_LEAKS_FINAL'];
		}

		unset($entry['ENTRIES_DATE_FINISH']);
		unset($entry['ENTRIES_DATE_START']);
		unset($entry['ENTRIES_DAY_COMPLETE']);
		unset($entry['ENTRIES_DURATION']);
		unset($entry['ENTRIES_TIME_LEAKS']);

		$workDays[$index]['REPORTS'][] = $entry;
	}

	if (!empty($workDays))
	{
		foreach ($workDays as $key => $row)
		{
			BitrixMainTypeCollection::sortByColumn(
				$workDays[$key]['REPORTS'],
				array('ID' => SORT_ASC)
			);
		}
		BitrixMainTypeCollection::sortByColumn(
			$workDays,
			array('INDEX' => SORT_ASC)
		);
	}

	return Array(
		'REPORT' => Array(
			'MONTH_TITLE' => Loc::getMessage('MONTH_'.$month),
			'DATE_START' => $dateStart,
			'DATE_FINISH' => $dateFinish,
			'DAYS' => $workDays,
		),
		'USER' => self::getUserData($userId)
	);
}