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); } /** * What the propagate action may still rewrite: an entry that is not ticked off, on an * assignment that has not ended. A finished entry keeps the document it handed out. */ public function testPropagationSkipsTickedEntriesAndEndedAssignments(): void { /** @var EntityManagerInterface $entityManager */ $entityManager = static::getContainer()->get(EntityManagerInterface::class); /** @var SeasonAssignmentTaskRepository $repository */ $repository = $entityManager->getRepository(SeasonAssignmentTask::class); $dql = $repository ->createOpenForTaskQueryBuilder('contract', new \DateTimeImmutable('2026-11-01')) ->getQuery() ->getDQL() ; $this->assertStringContainsString('task.taskKey = :taskKey', $dql); $this->assertStringContainsString('task.done = :done', $dql); $this->assertStringContainsString('season_assignment.dateTo >= :today', $dql); $this->assertStringContainsString('season_assignment.deletedAt IS NULL', $dql); } 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); } }