feat: all-season assignments

This commit is contained in:
Björn Fromme authored and Björn Fromme committed 2026-09-26 12:13:16 +02:00
1 parent 675cec1b69
commit cf876ed224
119 files changed
+6194 -294

No files matched your search

@@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
namespace App\Tests\Repository;
use App\Entity\SeasonAssignmentTask;
use App\Repository\SeasonAssignmentTaskRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
/**
* The reminders are only as good as the set of rows they start from, so the conditions are
* compiled and pinned here - the suite has no fixtures.
*
* Note what is deliberately absent: the deadlines. They are a relative offset off the
* assignment's first day, and month arithmetic is not invertible day by day, so they are
* resolved in PHP rather than reproduced in DQL.
*/
class SeasonAssignmentTaskRepositoryTest extends KernelTestCase
{
public function testOpenTasksExcludeDoneOnesAndDeletedRecords(): void
{
$dql = $this->createOpenQueryBuilder()->getQuery()->getDQL();
$this->assertStringContainsString('task.done = :done', $dql);
$this->assertStringContainsString('season_assignment.deletedAt IS NULL', $dql);
$this->assertStringContainsString('teamer.deletedAt IS NULL', $dql);
// the period is the assignment's own, so there is no destination left to join
$this->assertStringNotContainsString('destination', $dql);
}
/**
* An inner join, not a left one: an assignment the office has laid out but not staffed yet
* has nobody to remind and nobody who could be late.
*/
public function testAnUnstaffedAssignmentIsLeftOut(): void
{
$dql = $this->createOpenQueryBuilder()->getQuery()->getDQL();
$this->assertStringContainsString('INNER JOIN season_assignment.teamer teamer', $dql);
$this->assertStringNotContainsString('LEFT JOIN', $dql);
}
public function testTheSeasonWindowIsOptional(): void
{
$unscoped = $this->createOpenQueryBuilder()->getQuery()->getDQL();
$scoped = $this
->createOpenQueryBuilder(new \DateTimeImmutable('2026-11-01'), new \DateTimeImmutable('2027-04-01'))
->getQuery()
->getDQL()
;
$this->assertStringNotContainsString('windowStart', $unscoped);
$this->assertStringContainsString('season_assignment.dateFrom >= :windowStart', $scoped);
$this->assertStringContainsString('season_assignment.dateFrom <= :windowEnd', $scoped);
}
private function createOpenQueryBuilder(
?\DateTimeImmutable $windowStart = null,
?\DateTimeImmutable $windowEnd = null,
): QueryBuilder {
/** @var EntityManagerInterface $entityManager */
$entityManager = static::getContainer()->get(EntityManagerInterface::class);
/** @var SeasonAssignmentTaskRepository $repository */
$repository = $entityManager->getRepository(SeasonAssignmentTask::class);
return $repository->createOpenQueryBuilder($windowStart, $windowEnd);
}
}