fix auto-stop when starting timesheet with tags (#2067)

This commit is contained in:
Kevin Papst
2020-10-27 18:35:22 +01:00
committed by GitHub
parent 8c39b4197e
commit 61c0cbc887
3 changed files with 55 additions and 33 deletions

View File

@@ -120,6 +120,22 @@ class TimesheetRepository extends EntityRepository
}
}
public function begin()
{
$this->getEntityManager()->beginTransaction();
}
public function commit()
{
$this->getEntityManager()->flush();
$this->getEntityManager()->commit();
}
public function rollback()
{
$this->getEntityManager()->rollback();
}
/**
* @param Timesheet $timesheet
* @throws \Doctrine\ORM\ORMException

View File

@@ -145,18 +145,25 @@ final class TimesheetService
throw new AccessDeniedException('You are not allowed to start this timesheet record');
}
$this->validateTimesheet($timesheet);
$this->repository->begin();
try {
$this->stopActiveEntries($timesheet);
} catch (ValidationFailedException $vex) {
// could happen for timesheets that were started in the future (end before begin)
throw new ValidationFailedException($vex->getViolations(), 'Cannot stop running timesheet');
}
$this->validateTimesheet($timesheet);
$this->dispatcher->dispatch(new TimesheetCreatePreEvent($timesheet));
$this->repository->save($timesheet);
$this->dispatcher->dispatch(new TimesheetCreatePostEvent($timesheet));
$this->dispatcher->dispatch(new TimesheetCreatePreEvent($timesheet));
$this->repository->save($timesheet);
$this->dispatcher->dispatch(new TimesheetCreatePostEvent($timesheet));
try {
$this->stopActiveEntries($timesheet);
} catch (ValidationFailedException $vex) {
// could happen for timesheets that were started in the future (end before begin)
throw new ValidationFailedException($vex->getViolations(), 'Cannot stop running timesheet');
}
$this->repository->commit();
} catch (\Exception $ex) {
$this->repository->rollback();
throw $ex;
}
return $timesheet;
}
@@ -170,6 +177,7 @@ final class TimesheetService
*/
public function updateTimesheet(Timesheet $timesheet): Timesheet
{
// FIXME stop active entries upon update
// there is at least one edge case which leads to a problem:
// if you do not allow overlapping entries, you cannot restart a timesheet by removing the
// end date if another timesheet is running, because the check for existing timesheets will always trigger
@@ -187,7 +195,7 @@ final class TimesheetService
}
/**
* Does NOT validate the given timesheet!
* Does NOT validate the given timesheets!
*
* @param array $timesheets
* @return array
@@ -256,7 +264,9 @@ final class TimesheetService
}
/**
* Stops all active records for the current user, besides the given $timesheet.
* Stops active records if more than allowed are running for the timesheet user.
*
* The given $timesheet will be ignored and not stopped (assuming it is the latest one that was re-started).
*
* @param Timesheet $timesheet
* @return int
@@ -265,28 +275,22 @@ final class TimesheetService
*/
private function stopActiveEntries(Timesheet $timesheet): int
{
$user = $timesheet->getUser();
$hardLimit = $this->configuration->getActiveEntriesHardLimit();
$activeEntries = $this->repository->getActiveEntries($user);
$activeEntries = $this->repository->getActiveEntries($timesheet->getUser());
if (empty($activeEntries)) {
return 0;
}
$activeEntries = array_reverse($activeEntries);
$needsStop = \count($activeEntries) - $hardLimit;
$counter = 0;
// reduce limit by one:
// this method is only called when a new entry is started
// -> all entries, including the new one must not exceed the $limit
$limit = $hardLimit - 1;
if (\count($activeEntries) > $limit) {
$i = 1;
foreach ($activeEntries as $activeEntry) {
if ($i > $limit && $timesheet->getId() !== $activeEntry->getId()) {
if ($hardLimit > 1) {
throw new ValidationException('timesheet.start.exceeded_limit');
}
$this->stopTimesheet($activeEntry);
$counter++;
}
$i++;
foreach ($activeEntries as $activeEntry) {
if ($timesheet->getId() !== $activeEntry->getId() && $needsStop > 0) {
$this->stopTimesheet($activeEntry);
$needsStop--;
$counter++;
}
}

View File

@@ -128,12 +128,14 @@ class TimesheetServiceTest extends TestCase
$timesheet2->expects($this->once())->method('setBegin');
$timesheet2->expects($this->once())->method('setEnd');
$newTimesheet = new Timesheet();
$repository = $this->createMock(TimesheetRepository::class);
$repository->method('getActiveEntries')->willReturn([$timesheet1, $timesheet2]);
$repository->method('getActiveEntries')->willReturn([$newTimesheet, $timesheet1, $timesheet2]);
$sut = $this->getSut($authorizationChecker, null, null, $repository);
$sut->saveNewTimesheet(new Timesheet());
$sut->saveNewTimesheet($newTimesheet);
}
public function testCannotRestartedPersistedTimesheet()