targetHourGateway = $targetHourGateway; $this->targetHourService = $targetHourService; $this->holidayGateway = $holidayGateway; $this->groupGateway = $groupGateway; $this->settingGateway = $settingGateway; $this->targetHourWrapper = $targetHourWrapper; $this->historyService = $historyService; } /** * @param int $addressId * @param DateTimeImmutable $fromDate * @param DateTimeImmutable $tillDate * @param string $statusOldType * @param string $statusWishType * * @return array */ private function findPossibleDays( int $addressId, DateTimeImmutable $fromDate, DateTimeImmutable $tillDate, string $statusOldType, string $statusWishType ): array { $evaluatedDays = []; while ($fromDate <= $tillDate) { $dayInfo = $this->targetHourGateway->findDayInfo($addressId, $fromDate); $dayType = $dayInfo->getType(); $workminutes = (int)$dayInfo->getWorkMinutes(); if ($workminutes < 0) { $workminutes = 0; } $isWorkDay = $workminutes != 0; //allowed are: //- days with no type //- days of the same type like the old //- rejected days which can be reclaimed if ( empty($dayType) || $dayType === $statusOldType || $dayType === self::SICKREJECT || $dayType === self::VACATIONREJECT ) { if ($this->isAddableDay($fromDate, $isWorkDay)) { $evaluatedDays[] = [ 'date' => $fromDate, 'type' => $this->getPossibleDayType($statusOldType, $statusWishType), 'workminutes' => $workminutes, 'vacationminutes' => $dayInfo->getVacationMinutes(), ]; } } $fromDate = $fromDate->modify('1 day'); } return $evaluatedDays; } /** * @param DateTimeInterface $date * @param bool $isWorkDay * * @return bool */ private function isAddableDay(DateTimeInterface $date, bool $isWorkDay): bool { $year = (int)$date->format('Y'); $holidays = $this->holidayGateway->findHolidayDataByYear($year); $isHoliday = $this->isHoliday($date, $holidays); if (!$isHoliday && $isWorkDay) { return true; } return false; } /** * @param string $statusOldType * @param string $statusWishType * * @return string */ private function getPossibleDayType(string $statusOldType, string $statusWishType): string { $isStatusAcceptedRemove = false; $isStatusRequestedRemove = false; if ( strstr($statusOldType, TimeManagementModule::VACATIONREQUEST) !== false || strstr($statusOldType, TimeManagementModule::SICKREQUEST) !== false ) { $isStatusRequestedRemove = true; } if ( strstr($statusOldType, TimeManagementModule::VACATION) !== false || strstr($statusOldType, TimeManagementModule::SICK) !== false || strstr($statusOldType, TimeManagementModule::ABSENT_DAY) !== false || strstr($statusOldType, TimeManagementModule::UNPAID) !== false ) { $isStatusAcceptedRemove = true; } $type = self::VACATIONREQUEST; if ($statusWishType === self::SICK) { $type = self::SICKREQUEST; } if ($isStatusRequestedRemove) { $type = self::NONE; } elseif ($isStatusAcceptedRemove) { $type = self::VACATIONREMOVE; if ($statusOldType === self::SICK) { $type = self::SICKREMOVE; } } return $type; } /** * @param DateTimeInterface $date * @param array $holidays * * @return bool */ private function isHoliday(DateTimeInterface $date, array $holidays): bool { /** @var HolidayData $holiday */ foreach ($holidays as $holiday) { if ($holiday->getDate()->getTimestamp() === $date->getTimestamp()) { return true; } } return false; } /** * @param int $addressId * @param bool $hasSuperPrivileges * * @return array */ public function findGroupsByAddressId(int $addressId, bool $hasSuperPrivileges): array { if ($hasSuperPrivileges) { return $this->groupGateway->findAllActiveGroupsWithMembers(); } return $this->groupGateway->findGroupsByAddressId($addressId); } /** * @param string $requestToken * * @throws InvalidRequestTokenException * @throws InvalidDateFormatException * * @return RequestInfoData */ public function getRequestInfoByToken(string $requestToken): RequestInfoData { return $this->targetHourGateway->getRequestInfoByToken($requestToken); } /** * @param $year * * @return array|HolidayData[] */ public function findHolidayDataByYear($year): array { return $this->holidayGateway->findHolidayDataByYear($year); } /** * @param int $addressId * @param int $year * @param bool $isAnonymised * @param int $groupId * * @throws InvalidDateFormatException * * @return array|CalendarData[] */ public function getCalendarData( int $addressId, int $year, bool $isAnonymised, int $groupId = 0 ): array { if ($isAnonymised) { if (empty($groupId)) { $calendarData = $this->targetHourGateway->findAnonymisedVacationCalendarDataByYearAndAddressId( $year, $addressId ); } else { $calendarData = $this->targetHourGateway->findAnonymisedVacationCalendarDataByYearAndAddressIdAndGroupId( $year, $addressId, $groupId ); } } else { $calendarData = $this->targetHourGateway->findAllVacationCalendarDataByYear($year); } return $calendarData; } /** * @param int $addressId * * @throws InvalidQueryException * * @return WorkDayData */ public function getWorkingDaysForAddress(int $addressId): WorkDayData { return $this->settingGateway->getWorkingDaysForAddress($addressId); } /** * @param int $addressId * @param DateTimeInterface $date * * @return DayInfoData */ public function getDayInfo(int $addressId, DateTimeInterface $date): DayInfoData { return $this->targetHourGateway->findDayInfo($addressId, $date); } /** * @param int $addressId * * @return float */ public function getAmountRequestedVacation(int $addressId): float { return $this->targetHourGateway->findAmountRequestedVacation($addressId); } /** * @param string $dayType * @param bool $isReject * * @return string */ private function evaluateNextDayType(string $dayType, bool $isReject): string { $isVacation = strstr($dayType, self::VACATIONREMOVE) !== false || strstr($dayType, self::VACATIONREQUEST) !== false; $isRemove = strstr($dayType, self::VACATIONREMOVE) !== false || strstr($dayType, self::SICKREMOVE) !== false; if ($isRemove) { if ($isReject) { if ($isVacation) { $type = self::VACATION; } else { $type = self::SICK; } } else { $type = self::NONE; } } else { if ($isReject) { if ($isVacation) { $type = self::VACATIONREJECT; } else { $type = self::SICKREJECT; } } else { if ($isVacation) { $type = self::VACATION; } else { $type = self::SICK; } } } return $type; } /** * @param int $addressId * @param DateTimeImmutable $from * @param DateTimeImmutable $till * @param bool $halfDay * @param string $comment * @param string $statusOldType * @param string $statusWishType * * @return string */ public function changeDays( int $addressId, DateTimeImmutable $from, DateTimeImmutable $till, bool $halfDay, string $comment, string $statusOldType, string $statusWishType ): string { if ($from > $till) { $till = $from; } $possibleDays = $this->findPossibleDays( $addressId, $from, $till, $statusOldType, $statusWishType ); if (empty($possibleDays)) { return ''; } $date = new DateTimeImmutable(); $requestToken = (string)$date->getTimestamp(); $this->historyService->saveActivity( $addressId, 0, $statusOldType, $possibleDays[0]['type'], $requestToken, $from, $till, $comment ); foreach ($possibleDays as $day) { $time = $day['vacationminutes'] / 60; if ($halfDay) { $workminutes = $day['workminutes']; if ($workminutes > 0) { $time = $workminutes / (2 * 60); } } $this->changeDayType( $addressId, $day['date'], $day['type'], $comment, (string)$time, $requestToken ); } if($day['type'] === self::NONE){ return ''; } else{ return $requestToken; } } /** * @param int $addressId * @param DateTimeInterface $date * @param string $type * @param string $comment * @param string $time * @param string $requestToken */ public function changeDayType( int $addressId, DateTimeInterface $date, string $type, string $comment, string $time, string $requestToken = '' ): void { $this->clearDayType($addressId, $date, $type); if ($type !== self::NONE) { $this->targetHourWrapper->handleType($addressId, $date, $type, true, $time, $requestToken); } else { if (!empty($requestToken)) { $this->targetHourService->updateVacationRequestToken($addressId, $date, $requestToken); } } if (!empty($comment)) { $this->targetHourWrapper->saveComment($addressId, $date, $comment); } $this->targetHourWrapper->recalculate($addressId, $date); } /** * @param int $addressId * @param DateTimeInterface $date * @param string $type */ private function clearDayType(int $addressId, DateTimeInterface $date, string $type): void { $types = [ TimeManagementModule::UNPAID, TimeManagementModule::ABSENT_DAY, TimeManagementModule::VACATION, TimeManagementModule::VACATIONREQUEST, TimeManagementModule::VACATIONREJECT, TimeManagementModule::VACATIONREMOVE, TimeManagementModule::SICK, TimeManagementModule::SICKREQUEST, TimeManagementModule::SICKREMOVE, TimeManagementModule::SICKREJECT, ]; if ($type != TimeManagementModule::NONE) { unset($types[$type]); } $this->targetHourWrapper->handleType($addressId, $date, implode('', $types), false); } /** * @param int $employeeAddressId * @param int $supervisorAddressId * @param bool $isReject * @param string $internalComment * @param string $requestToken * * @throws InvalidDateFormatException * @throws InvalidRequestTokenException */ public function handleRequestedDays( int $employeeAddressId, int $supervisorAddressId, bool $isReject, string $internalComment, string $requestToken ): void { $requestedDays = $this->targetHourGateway->getRequestedDaysByToken($requestToken); if (!empty($requestedDays)) { $from = $requestedDays[0]['date']; $till = $requestedDays[count($requestedDays) - 1]['date']; $oldType = $requestedDays[0]['type']; $newType = $this->evaluateNextDayType($oldType, $isReject); $this->historyService->saveActivity( 0, $supervisorAddressId, $oldType, $newType, $requestToken, $from, $till, $internalComment ); $date = new DateTimeImmutable(); $requestToken = (string)$date->getTimestamp(); foreach ($requestedDays as $requestedDay) { $this->targetHourService->updateTargetHourType( $employeeAddressId, $requestedDay['date'], $requestedDay['type'], $newType ); $this->targetHourService->updateVacationRequestToken( $employeeAddressId, $requestedDay['date'], $requestToken ); $this->targetHourWrapper->recalculate($employeeAddressId,$requestedDay['date']); } } if (!empty($internalComment)) { $this->targetHourService->saveInternalComment($requestToken, $internalComment); } } /** * @param int $daysTillDeletion * @param int $addressId * * @throws InvalidDateFormatException */ public function removeRejectedAfterXDays(int $daysTillDeletion, int $addressId): void { $rejectedDays = $this->targetHourGateway->findRejectedDays($daysTillDeletion, $addressId); if (!empty($rejectedDays)) { foreach ($rejectedDays as $day) { $this->clearDayType($addressId, $day['date'], TimeManagementModule::NONE); } } } /** * @param int $addressId * @param int $groupId * * @return bool */ public function checkAddressHasGroup(int $addressId, int $groupId): bool { return $this->groupGateway->isAddressInGroup($addressId, $groupId); } /** * @param string $type * * @return string */ public function mapTypeToLanguage(string $type): string { $mapping = [ self::NONE => 'Kein Status', self::VACATION => 'Urlaub', self::VACATIONREQUEST => 'Urlaubsantrag', self::VACATIONREJECT => 'Urlaub ablehnen', self::VACATIONREMOVE => 'Urlaub entfernen', self::SICK => 'Krank', self::SICKREQUEST => 'Krankheitsantrag', self::SICKREMOVE => 'Krankheit entfernen', self::SICKREJECT => 'Krankheit ablehnen', self::UNPAID => 'Unbezahlter Urlaub', self::ABSENT_DAY => 'Fehltag', ]; return $mapping[$type]; } /** * @param int $employeeAddressId * @param int $groupId * * @throws SupervisorNotFoundException * * @return int[] */ public function getSupervisorAddressIds(int $employeeAddressId, int $groupId): array { return $this->groupGateway->getSupervisorAddressIds($employeeAddressId, $groupId); } }