markBooked($appointment); $appointment->setCourseSession($session); $this->em->flush(); } /** * لغو نوبت: همان جلسه به `planned` برمی‌گردد و بقیهٔ دوره دست‌نخورده می‌ماند. * * @return bool `false` یعنی این نوبت اصلاً جزو دوره‌ای نبود */ public function unlink(Appointment $appointment): bool { $session = $this->sessions->findForAppointment($appointment); if ($session === null) { return false; } $session->unbook(); $appointment->setCourseSession(null); $this->em->flush(); return true; } /** * جلسه انجام شد. دوره وقتی کامل می‌شود که **همهٔ** جلساتش تمام شده باشند — * نه وقتی آخرین جلسه رزرو شد. */ public function complete(Appointment $appointment, ?int $at = null): bool { $session = $this->sessions->findForAppointment($appointment); if ($session === null) { return false; } $session->markCompleted($at); $course = $session->getCourse(); if ($course->completedCount() >= $course->getSessionCount()) { $course->complete($at); } $this->em->flush(); return true; } public function courseOf(Appointment $appointment): ?TreatmentCourse { return $this->sessions->findForAppointment($appointment)?->getCourse(); } }