*/ private array $affectationResults = []; protected function setUp(): void { $this->tenantId = TenantId::generate(); $this->classId = ClassId::generate(); $this->subjectId = SubjectId::generate(); $this->replacementRepository = new InMemoryTeacherReplacementRepository(); $this->now = new DateTimeImmutable('2026-04-14 10:00:00'); } #[Test] public function itReturnsTrueWhenTeacherIsAffected(): void { $teacherId = UserId::generate(); $this->setTeacherAffecte($teacherId); $checker = $this->createChecker(); $evaluation = $this->createEvaluation(); self::assertTrue($checker->peutSaisirNotes($teacherId, $evaluation, $this->tenantId, $this->now)); } #[Test] public function itReturnsFalseWhenTeacherIsNotAffectedAndNoReplacement(): void { $teacherId = UserId::generate(); $checker = $this->createChecker(); $evaluation = $this->createEvaluation(); self::assertFalse($checker->peutSaisirNotes($teacherId, $evaluation, $this->tenantId, $this->now)); } #[Test] public function itReturnsTrueWhenTeacherHasActiveReplacement(): void { $replacementTeacherId = UserId::generate(); $this->createActiveReplacement($replacementTeacherId); $checker = $this->createChecker(); $evaluation = $this->createEvaluation(); self::assertTrue($checker->peutSaisirNotes($replacementTeacherId, $evaluation, $this->tenantId, $this->now)); } #[Test] public function itReturnsFalseWhenReplacementIsExpired(): void { $replacementTeacherId = UserId::generate(); $this->createExpiredReplacement($replacementTeacherId); $checker = $this->createChecker(); $evaluation = $this->createEvaluation(); self::assertFalse($checker->peutSaisirNotes($replacementTeacherId, $evaluation, $this->tenantId, $this->now)); } #[Test] public function itReturnsTrueWhenBothAffectedAndActiveReplacement(): void { $teacherId = UserId::generate(); $this->setTeacherAffecte($teacherId); $this->createActiveReplacement($teacherId); $checker = $this->createChecker(); $evaluation = $this->createEvaluation(); self::assertTrue($checker->peutSaisirNotes($teacherId, $evaluation, $this->tenantId, $this->now)); } #[Test] public function itReturnsFalseWhenReplacementIsOnDifferentClassSubject(): void { $replacementTeacherId = UserId::generate(); $otherClassId = ClassId::generate(); $otherSubjectId = SubjectId::generate(); $replacement = TeacherReplacement::designer( tenantId: $this->tenantId, replacedTeacherId: UserId::generate(), replacementTeacherId: $replacementTeacherId, startDate: $this->now->modify('-1 day'), endDate: $this->now->modify('+7 days'), classes: [new ClassSubjectPair($otherClassId, $otherSubjectId)], reason: 'Maladie', createdBy: UserId::generate(), now: $this->now->modify('-1 day'), ); $this->replacementRepository->save($replacement); $checker = $this->createChecker(); $evaluation = $this->createEvaluation(); self::assertFalse($checker->peutSaisirNotes($replacementTeacherId, $evaluation, $this->tenantId, $this->now)); } #[Test] public function itReturnsFalseWhenReplacementStartsInTheFuture(): void { $replacementTeacherId = UserId::generate(); $futureStart = $this->now->modify('+1 day'); $replacement = TeacherReplacement::designer( tenantId: $this->tenantId, replacedTeacherId: UserId::generate(), replacementTeacherId: $replacementTeacherId, startDate: $futureStart, endDate: $this->now->modify('+14 days'), classes: [new ClassSubjectPair($this->classId, $this->subjectId)], reason: 'Congé prévu', createdBy: UserId::generate(), now: $this->now, ); $this->replacementRepository->save($replacement); $checker = $this->createChecker(); $evaluation = $this->createEvaluation(); self::assertFalse($checker->peutSaisirNotes($replacementTeacherId, $evaluation, $this->tenantId, $this->now)); } #[Test] public function itShortCircuitsOnAffectationWithoutCheckingReplacement(): void { $teacherId = UserId::generate(); $this->setTeacherAffecte($teacherId); // No replacement seeded — if it tries to check replacement for an // assigned teacher, the result should still be true (short-circuit) $checker = $this->createChecker(); $evaluation = $this->createEvaluation(); self::assertTrue($checker->peutSaisirNotes($teacherId, $evaluation, $this->tenantId, $this->now)); } private function setTeacherAffecte(UserId $teacherId): void { $this->affectationResults[(string) $teacherId] = true; } private function createChecker(): AutorisationSaisieNotesChecker { $test = $this; $affectationChecker = new class($test) implements EnseignantAffectationChecker { public function __construct(private readonly AutorisationSaisieNotesCheckerTest $test) { } public function estAffecte( UserId $teacherId, ClassId $classId, SubjectId $subjectId, TenantId $tenantId, ): bool { return $this->test->isTeacherAffecte((string) $teacherId); } }; return new AutorisationSaisieNotesChecker( $affectationChecker, $this->replacementRepository, ); } public function isTeacherAffecte(string $teacherId): bool { return $this->affectationResults[$teacherId] ?? false; } private function createEvaluation(): Evaluation { return Evaluation::creer( tenantId: $this->tenantId, classId: $this->classId, subjectId: $this->subjectId, teacherId: UserId::generate(), title: 'Contrôle de maths', description: null, evaluationDate: $this->now, gradeScale: new GradeScale(20), coefficient: new Coefficient(1.0), now: $this->now, ); } private function createActiveReplacement(UserId $replacementTeacherId): void { $replacement = TeacherReplacement::designer( tenantId: $this->tenantId, replacedTeacherId: UserId::generate(), replacementTeacherId: $replacementTeacherId, startDate: $this->now->modify('-1 day'), endDate: $this->now->modify('+7 days'), classes: [new ClassSubjectPair($this->classId, $this->subjectId)], reason: 'Maladie', createdBy: UserId::generate(), now: $this->now->modify('-1 day'), ); $this->replacementRepository->save($replacement); } private function createExpiredReplacement(UserId $replacementTeacherId): void { $replacement = TeacherReplacement::designer( tenantId: $this->tenantId, replacedTeacherId: UserId::generate(), replacementTeacherId: $replacementTeacherId, startDate: $this->now->modify('-14 days'), endDate: $this->now->modify('-1 day'), classes: [new ClassSubjectPair($this->classId, $this->subjectId)], reason: 'Maladie', createdBy: UserId::generate(), now: $this->now->modify('-14 days'), ); $this->replacementRepository->save($replacement); } }