createReplacement(); $dto = ReplacementDto::fromDomain($replacement); self::assertSame((string) $replacement->id, $dto->id); self::assertSame(self::REPLACED_TEACHER_ID, $dto->replacedTeacherId); self::assertSame(self::REPLACEMENT_TEACHER_ID, $dto->replacementTeacherId); self::assertEquals(new DateTimeImmutable('2026-03-01'), $dto->startDate); self::assertEquals(new DateTimeImmutable('2026-03-31'), $dto->endDate); self::assertSame(ReplacementStatus::ACTIVE->value, $dto->status); self::assertSame('Congé maladie', $dto->reason); } #[Test] public function fromDomainPreservesAllClassSubjectPairs(): void { $replacement = $this->createReplacementWithMultipleClasses(); $dto = ReplacementDto::fromDomain($replacement); self::assertCount(2, $dto->classes); self::assertSame(self::CLASS_ID, $dto->classes[0]['classId']); self::assertSame(self::SUBJECT_ID, $dto->classes[0]['subjectId']); self::assertSame('550e8400-e29b-41d4-a716-446655440021', $dto->classes[1]['classId']); self::assertSame('550e8400-e29b-41d4-a716-446655440031', $dto->classes[1]['subjectId']); } #[Test] public function fromDomainPreservesNullReason(): void { $replacement = TeacherReplacement::designer( tenantId: TenantId::fromString(self::TENANT_ID), replacedTeacherId: UserId::fromString(self::REPLACED_TEACHER_ID), replacementTeacherId: UserId::fromString(self::REPLACEMENT_TEACHER_ID), startDate: new DateTimeImmutable('2026-03-01'), endDate: new DateTimeImmutable('2026-03-31'), classes: [ new ClassSubjectPair( ClassId::fromString(self::CLASS_ID), SubjectId::fromString(self::SUBJECT_ID), ), ], reason: null, createdBy: UserId::fromString(self::CREATED_BY_ID), now: new DateTimeImmutable('2026-02-15 10:00:00'), ); $dto = ReplacementDto::fromDomain($replacement); self::assertNull($dto->reason); } private function createReplacement(): TeacherReplacement { return TeacherReplacement::designer( tenantId: TenantId::fromString(self::TENANT_ID), replacedTeacherId: UserId::fromString(self::REPLACED_TEACHER_ID), replacementTeacherId: UserId::fromString(self::REPLACEMENT_TEACHER_ID), startDate: new DateTimeImmutable('2026-03-01'), endDate: new DateTimeImmutable('2026-03-31'), classes: [ new ClassSubjectPair( ClassId::fromString(self::CLASS_ID), SubjectId::fromString(self::SUBJECT_ID), ), ], reason: 'Congé maladie', createdBy: UserId::fromString(self::CREATED_BY_ID), now: new DateTimeImmutable('2026-02-15 10:00:00'), ); } private function createReplacementWithMultipleClasses(): TeacherReplacement { return TeacherReplacement::designer( tenantId: TenantId::fromString(self::TENANT_ID), replacedTeacherId: UserId::fromString(self::REPLACED_TEACHER_ID), replacementTeacherId: UserId::fromString(self::REPLACEMENT_TEACHER_ID), startDate: new DateTimeImmutable('2026-03-01'), endDate: new DateTimeImmutable('2026-03-31'), classes: [ new ClassSubjectPair( ClassId::fromString(self::CLASS_ID), SubjectId::fromString(self::SUBJECT_ID), ), new ClassSubjectPair( ClassId::fromString('550e8400-e29b-41d4-a716-446655440021'), SubjectId::fromString('550e8400-e29b-41d4-a716-446655440031'), ), ], reason: 'Congé maladie', createdBy: UserId::fromString(self::CREATED_BY_ID), now: new DateTimeImmutable('2026-02-15 10:00:00'), ); } }