feat: apply season task deadlines to all open checklist entries
This commit is contained in:
1 parent
3fe510e64e
commit
300bb2058f
5 files changed
+81
-1
No files matched your search
@@ -46,6 +46,9 @@ class TaskDeadlineController extends AbstractController
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) {
|
||||
$applyToAll = true === $form->get('applyToAll')->getData();
|
||||
$appliedCount = $applyToAll ? ($seasonAssignment?->applyDeadlinesToOpenTasks($task) ?? 0) : 0;
|
||||
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->logger->info('Change season assignment task deadlines', [
|
||||
@@ -54,9 +57,13 @@ class TaskDeadlineController extends AbstractController
|
||||
'task' => $task->getTaskKey(),
|
||||
'deadline_override_1' => $task->getDeadlineOverride1()?->format('Y-m-d'),
|
||||
'deadline_override_2' => $task->getDeadlineOverride2()?->format('Y-m-d'),
|
||||
'apply_to_all' => $applyToAll,
|
||||
'applied_count' => $appliedCount,
|
||||
]);
|
||||
|
||||
$this->addFlash('success', 'Die Fristen wurden gespeichert');
|
||||
$this->addFlash('success', $applyToAll
|
||||
? 'Die Fristen wurden für alle offenen Einträge gespeichert'
|
||||
: 'Die Fristen wurden gespeichert');
|
||||
|
||||
return new HxRedirectResponse($returnUrl);
|
||||
}
|
||||
|
||||
@@ -208,6 +208,30 @@ class SeasonAssignment implements BlameableEntityInterface, TimestampableEntityI
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies both deadline overrides of $source onto every other entry that is not ticked off,
|
||||
* empty ones included - an empty override resets the entry to its computed deadline. Entries
|
||||
* already done keep theirs: their deadline is history by then.
|
||||
*
|
||||
* @return int the number of entries changed, $source not counted
|
||||
*/
|
||||
public function applyDeadlinesToOpenTasks(SeasonAssignmentTask $source): int
|
||||
{
|
||||
$count = 0;
|
||||
|
||||
foreach ($this->tasks as $task) {
|
||||
if ($task === $source || $task->isDone()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$task->setDeadlineOverride1($source->getDeadlineOverride1());
|
||||
$task->setDeadlineOverride2($source->getDeadlineOverride2());
|
||||
++$count;
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection<int, Upload>
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Form;
|
||||
|
||||
use App\Entity\SeasonAssignmentTask;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
@@ -27,6 +28,13 @@ class SeasonTaskDeadlineType extends AbstractType
|
||||
'required' => false,
|
||||
'help' => 'Ohne Angabe gilt Frist 1.',
|
||||
])
|
||||
// unmapped: the controller copies the entered deadlines onto the other entries
|
||||
->add('applyToAll', CheckboxType::class, [
|
||||
'label' => 'auf alle Fristen anwenden',
|
||||
'required' => false,
|
||||
'mapped' => false,
|
||||
'help' => 'Gilt für alle noch nicht erledigten Einträge. Leere Felder setzen deren Fristen auf den berechneten Wert zurück.',
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
</p>
|
||||
{{ form_row(form.deadlineOverride1) }}
|
||||
{{ form_row(form.deadlineOverride2) }}
|
||||
{{ form_row(form.applyToAll) }}
|
||||
</div>
|
||||
<button type="submit" class="btn">
|
||||
Speichern
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace App\Tests\Entity;
|
||||
|
||||
use App\Entity\JobProfile;
|
||||
use App\Entity\SeasonAssignment;
|
||||
use App\Entity\SeasonAssignmentTask;
|
||||
use App\Entity\Teamer;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -100,4 +101,43 @@ class SeasonAssignmentTest extends TestCase
|
||||
$this->assertSame('2027-04-30', $seasonAssignment->getDateTo()->format('Y-m-d'));
|
||||
$this->assertSame('AGR', $seasonAssignment->getHotelCode());
|
||||
}
|
||||
|
||||
public function testApplyingDeadlinesCopiesBothOverridesOntoOpenEntriesOnly(): void
|
||||
{
|
||||
$seasonAssignment = new SeasonAssignment();
|
||||
$source = (new SeasonAssignmentTask())
|
||||
->setDeadlineOverride1(new \DateTimeImmutable('2026-11-15'))
|
||||
->setDeadlineOverride2(new \DateTimeImmutable('2026-11-30'));
|
||||
$open = new SeasonAssignmentTask();
|
||||
$done = (new SeasonAssignmentTask())
|
||||
->setDone(true)
|
||||
->setDeadlineOverride1(new \DateTimeImmutable('2026-10-01'));
|
||||
$seasonAssignment->addTask($source)->addTask($open)->addTask($done);
|
||||
|
||||
$this->assertSame(1, $seasonAssignment->applyDeadlinesToOpenTasks($source));
|
||||
|
||||
$this->assertSame('2026-11-15', $open->getDeadlineOverride1()?->format('Y-m-d'));
|
||||
$this->assertSame('2026-11-30', $open->getDeadlineOverride2()?->format('Y-m-d'));
|
||||
$this->assertSame('2026-10-01', $done->getDeadlineOverride1()?->format('Y-m-d'));
|
||||
$this->assertNull($done->getDeadlineOverride2());
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty fields are applied as well: that is how the office resets every entry to its
|
||||
* computed deadline in one go.
|
||||
*/
|
||||
public function testApplyingEmptyDeadlinesResetsTheOverrides(): void
|
||||
{
|
||||
$seasonAssignment = new SeasonAssignment();
|
||||
$source = new SeasonAssignmentTask();
|
||||
$other = (new SeasonAssignmentTask())
|
||||
->setDeadlineOverride1(new \DateTimeImmutable('2026-11-15'))
|
||||
->setDeadlineOverride2(new \DateTimeImmutable('2026-11-30'));
|
||||
$seasonAssignment->addTask($source)->addTask($other);
|
||||
|
||||
$seasonAssignment->applyDeadlinesToOpenTasks($source);
|
||||
|
||||
$this->assertNull($other->getDeadlineOverride1());
|
||||
$this->assertNull($other->getDeadlineOverride2());
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user