Improve weekly hours form (#5528)

This commit is contained in:
Kevin Papst
2025-06-06 15:20:00 +02:00
committed by GitHub
parent 2f2ebd6293
commit c8b4e4eabb
7 changed files with 119 additions and 82 deletions

View File

@@ -20,6 +20,7 @@ use App\Repository\TimesheetRepository;
use App\Timesheet\FavoriteRecordService;
use App\Timesheet\TimesheetService;
use App\Utils\PageSetup;
use App\WorkingTime\WorkingTimeService;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
@@ -38,6 +39,7 @@ final class QuickEntryController extends AbstractController
private readonly TimesheetRepository $repository,
private readonly FavoriteRecordService $favoriteRecordService,
private readonly EventDispatcherInterface $dispatcher,
private readonly WorkingTimeService $workingTimeService,
)
{
}
@@ -114,37 +116,46 @@ final class QuickEntryController extends AbstractController
ksort($rows);
// attach recent activities
$amount = $this->configuration->getQuickEntriesRecentAmount();
if ($amount > 0) {
$takeOverWeeks = $this->configuration->find('quick_entry.recent_activity_weeks');
$startFrom = null;
if ($takeOverWeeks !== null && \intval($takeOverWeeks) > 0) {
$startFrom = clone $startWeek;
$startFrom->modify(\sprintf('-%s weeks', $takeOverWeeks));
}
// this should also check via lock service
$locked = $this->workingTimeService->isApproved($user, $endWeek);
$favorites = $this->favoriteRecordService->favoriteEntries($user, $amount);
foreach ($favorites as $favorite) {
$timesheet = $favorite->getTimesheet();
if ($startFrom !== null && !$favorite->isFavorite() && $startFrom > $timesheet->getBegin()) {
continue;
if (!$locked) {
// attach recent activities
$amount = $this->configuration->getQuickEntriesRecentAmount();
if ($amount > 0) {
$takeOverWeeks = $this->configuration->find('quick_entry.recent_activity_weeks');
$startFrom = null;
if ($takeOverWeeks !== null && \intval($takeOverWeeks) > 0) {
$startFrom = clone $startWeek;
$startFrom->modify(\sprintf('-%s weeks', $takeOverWeeks));
}
$id = $timesheet->getProject()->getId() . '_' . $timesheet->getActivity()->getId();
if (\array_key_exists($id, $rows)) {
continue;
$favorites = $this->favoriteRecordService->favoriteEntries($user, $amount);
foreach ($favorites as $favorite) {
$timesheet = $favorite->getTimesheet();
if ($startFrom !== null && !$favorite->isFavorite() && $startFrom > $timesheet->getBegin()) {
continue;
}
$id = $timesheet->getProject()->getId() . '_' . $timesheet->getActivity()->getId();
if (\array_key_exists($id, $rows)) {
continue;
}
// edge case: a project that starts and ends between the start and end date allows to select it from the dropdown,
// but it is better to hide a row than displaying already ended projects
if ($timesheet->getProject() !== null && (!$timesheet->getProject()->isVisibleAtDate($startWeek) && !$timesheet->getProject()->isVisibleAtDate($endWeek))) {
continue;
}
// make sure no invisible entries are included
if (!$this->isGranted('start', $timesheet)) {
continue;
}
$rows[$id] = [
'days' => $week,
'project' => $timesheet->getProject(),
'activity' => $timesheet->getActivity()
];
}
// there is an edge case possible with a project that starts and ends between the start and end date
// user could still select it from the dropdown, but it is better to hide a row than displaying already ended projects
if ($timesheet->getProject() !== null && (!$timesheet->getProject()->isVisibleAtDate($startWeek) && !$timesheet->getProject()->isVisibleAtDate($endWeek))) {
continue;
}
$rows[$id] = [
'days' => $week,
'project' => $timesheet->getProject(),
'activity' => $timesheet->getActivity()
];
}
}
@@ -165,6 +176,7 @@ final class QuickEntryController extends AbstractController
if (!\array_key_exists('entry', $day)) {
// fill all rows and columns to make sure we do not have missing records
$tmp = $this->timesheetService->createNewTimesheet($user);
$tmp->setDuration(null);
$tmp->setProject($row['project']);
$tmp->setActivity($row['activity']);
$newTime = \DateTime::createFromInterface($day['day']);
@@ -185,6 +197,7 @@ final class QuickEntryController extends AbstractController
$empty->markAsPrototype();
foreach ($week as $dayId => $day) {
$tmp = $this->timesheetService->createNewTimesheet($user);
$tmp->setDuration(null);
$newTime = \DateTime::createFromInterface($day['day']);
$newTime = $newTime->setTime($defaultHour, $defaultMinute, 0, 0);
$tmp->setBegin($newTime);
@@ -194,18 +207,20 @@ final class QuickEntryController extends AbstractController
// add empty rows for simpler starting
$minRows = \intval($this->configuration->find('quick_entry.minimum_rows'));
if ($formModel->countRows() < $minRows) {
if (!$locked && $formModel->countRows() < $minRows) {
$newRows = $minRows - $formModel->countRows();
for ($a = 0; $a < $newRows; $a++) {
$model = $formModel->addRow($user);
foreach ($week as $dayId => $day) {
$tmp = $this->timesheetService->createNewTimesheet($user);
$tmp->setDuration(null);
$newTime = \DateTime::createFromInterface($day['day']);
$newTime = $newTime->setTime($defaultHour, $defaultMinute, 0, 0);
$tmp->setBegin($newTime);
$this->timesheetService->prepareNewTimesheet($tmp);
$model->addTimesheet($tmp);
}
$model->setMetaFields($metaFields);
}
}
@@ -229,12 +244,14 @@ final class QuickEntryController extends AbstractController
foreach ($tmpModel->getTimesheets() as $timesheet) {
if ($timesheet->getId() !== null) {
$duration = $timesheet->getDuration(false);
// previously running timesheets were deleted, which was wrong
// so now we distinguish between running timesheets and null duration
// running timesheets also have a empty duration.
// we distinguish them from temporary ones, to make sure they will not be deleted
if ($timesheet->isRunning()) {
$saveTimesheets[] = $timesheet;
} elseif ($duration === null) {
$deleteTimesheets[] = $timesheet;
if ($this->isGranted('delete', $timesheet)) {
$deleteTimesheets[] = $timesheet;
}
} else {
$saveTimesheets[] = $timesheet;
}
@@ -248,14 +265,22 @@ final class QuickEntryController extends AbstractController
try {
$saved = false;
if (\count($deleteTimesheets) > 0 && $this->isGranted('delete_own_timesheet')) {
if (\count($deleteTimesheets) > 0) {
$this->timesheetService->deleteMultipleTimesheets($deleteTimesheets);
$saved = true;
}
if (\count($saveTimesheets) > 0) {
$this->timesheetService->updateMultipleTimesheets($saveTimesheets);
$saved = true;
$saveMe = [];
foreach ($saveTimesheets as $timesheet) {
if ($timesheet->getId() === null || $this->isGranted('edit', $timesheet)) {
$saveMe[] = $timesheet;
}
}
if (\count($saveMe) > 0) {
$this->timesheetService->updateMultipleTimesheets($saveMe);
$saved = true;
}
}
if ($saved) {
@@ -278,6 +303,7 @@ final class QuickEntryController extends AbstractController
'days' => $week,
'form' => $form->createView(),
'metaColumns' => $metaFields,
'locked' => $locked,
]);
}
}