Release 2.32 (#5411)

* bump packages
* dynamic invoice options
* make sure that invoice previews can be detected
* support for mpdf associated files
* do not include any future times in work contract calculation
* re-add username column in Excel spreadsheet
* deactivate internal rate editing
* show if plugin update exists
* shorten name to Kimai only, without Time-Tracking
* remove check for existing id in work contract
* fix metafield already defined in search
* helper methods to unlock months
* new translation
* send event on unlock month
This commit is contained in:
Kevin Papst
2025-04-06 09:53:48 +02:00
committed by GitHub
parent 2a75cd6230
commit 2e6b700b43
58 changed files with 749 additions and 437 deletions

View File

@@ -13,6 +13,7 @@ use App\Entity\User;
use App\Entity\WorkingTime;
use App\Event\WorkingTimeApproveMonthEvent;
use App\Event\WorkingTimeQueryStatsEvent;
use App\Event\WorkingTimeUnlockMonthEvent;
use App\Event\WorkingTimeYearEvent;
use App\Event\WorkingTimeYearSummaryEvent;
use App\Repository\TimesheetRepository;
@@ -155,12 +156,14 @@ final class WorkingTimeService
$dayDate = $day->getDay();
$result = new WorkingTime($user, $dayDate);
if (($firstDay === null || $firstDay <= $dayDate) && ($lastDay === null || $lastDay >= $dayDate)) {
$result->setExpectedTime($calculator->getWorkHoursForDay($dayDate));
}
if ($dayDate <= $until) {
if (($firstDay === null || $firstDay <= $dayDate) && ($lastDay === null || $lastDay >= $dayDate)) {
$result->setExpectedTime($calculator->getWorkHoursForDay($dayDate));
}
if (\array_key_exists($key, $stats)) {
$result->setActualTime($stats[$key]);
if (\array_key_exists($key, $stats)) {
$result->setActualTime($stats[$key]);
}
}
$day->setWorkingTime($result);
@@ -181,6 +184,7 @@ final class WorkingTimeService
return $year->getMonth($monthDate);
}
// deprecated 3.0 remove $user, fetch from $month->getUser() instead
public function approveMonth(User $user, Month $month, \DateTimeInterface $approvalDate, User $approvedBy): void
{
foreach ($month->getDays() as $day) {
@@ -189,10 +193,6 @@ final class WorkingTimeService
continue;
}
if ($workingTime->getId() !== null) {
continue;
}
if ($month->isLocked() || $workingTime->isApproved()) {
continue;
}
@@ -205,15 +205,38 @@ final class WorkingTimeService
$this->workingTimeRepository->persistScheduledWorkingTimes();
// $user = $month->getUser();
$user->setPreferenceValue(self::LATEST_APPROVAL_PREF, $this->workingTimeRepository->getLatestApprovalDate($user)?->format(self::LATEST_APPROVAL_FORMAT));
$this->userRepository->saveUser($user);
$this->eventDispatcher->dispatch(new WorkingTimeApproveMonthEvent($user, $month, $approvalDate, $approvedBy));
$this->eventDispatcher->dispatch(new WorkingTimeApproveMonthEvent($month, $approvedBy));
}
public function unlockMonth(Month $month, User $unlockedBy): void
{
foreach ($month->getDays() as $day) {
$workingTime = $day->getWorkingTime();
if ($workingTime === null || $workingTime->getId() === null) {
continue;
}
if (!$workingTime->isApproved()) {
continue;
}
$this->workingTimeRepository->scheduleWorkingTimeDelete($workingTime);
}
$this->workingTimeRepository->persistScheduledWorkingTimes();
$user = $month->getUser();
$user->setPreferenceValue(self::LATEST_APPROVAL_PREF, $this->workingTimeRepository->getLatestApprovalDate($user)?->format(self::LATEST_APPROVAL_FORMAT));
$this->userRepository->saveUser($user);
$this->eventDispatcher->dispatch(new WorkingTimeUnlockMonthEvent($month, $unlockedBy));
}
/**
* @param \DateTimeInterface $year
* @param User $user
* @return array<string, int>
*/
private function getYearStatistics(\DateTimeInterface $year, User $user): array