can($appointment, $user, self::ACTION_VIEW); } /** مجوز تغییر نوبت: ویرایش، جابه‌جایی، رزرو، جایگزینی و تغییر وضعیت. */ public function canManage(Appointment $appointment, User $user): bool { return $this->can($appointment, $user, self::ACTION_UPDATE_STATUS); } public function canCancel(Appointment $appointment, User $user): bool { return $this->can($appointment, $user, self::ACTION_CANCEL); } public function can(Appointment $appointment, User $user, string $action): bool { if ($user->hasRole('ROLE_ADMIN')) { return true; } if ($appointment->getDoctor()->getUser()->getId() === $user->getId()) { return true; } // بیمار نوبت خودش را می‌بیند و لغو می‌کند، ولی جابه‌جا/ویرایش نمی‌کند. if ($appointment->getUser()->getId() === $user->getId()) { return $action === self::ACTION_VIEW || $action === self::ACTION_CANCEL; } $clinic = $appointment->getClinic(); if ($clinic !== null && $this->clinicPermissions->can($user, $clinic, self::RESOURCE, $action)) { return true; } return $this->secretaryCan($appointment, $user, $action); } /** * کلینیکی که این کاربر در آن اجازهٔ دیدن نوبت‌های این پزشک را دارد، یا null. * برای لیست‌هایی که باید به یک محیط محدود شوند (نه تک‌نوبت). */ public function viewableClinicFor(User $user, \App\Doctor\Entity\Doctor $doctor): ?\App\Clinic\Entity\Clinic { $dbUuid = $this->contextRepo->findByUser($user)?->getDbUuid(); $clinic = $dbUuid !== null ? $this->clinicRepo->findByUuid($dbUuid) : null; if ($clinic === null) { $clinic = $this->clinicRepo->findByUser($user); } if ($clinic === null || !$clinic->hasDoctor($doctor)) { return null; } return $this->clinicPermissions->can($user, $clinic, self::RESOURCE, self::ACTION_VIEW) ? $clinic : null; } /** * منشی در محیط فعالِ خودش. در محیط کلینیک، نوبت باید هم متعلق به همان کلینیک * باشد و هم پزشکش جزو پزشکان تخصیص‌یافته به این منشی — عضویت در کلینیک به‌تنهایی * یعنی منشیِ یک پزشک بتواند نوبت پزشک دیگری را دست‌کاری کند. */ private function secretaryCan(Appointment $appointment, User $user, string $action): bool { $dbUuid = $this->contextRepo->findByUser($user)?->getDbUuid(); if ($dbUuid === null) { return false; } $clinic = $this->clinicRepo->findByUuid($dbUuid); if ($clinic !== null) { if ($appointment->getClinic()?->getId() !== $clinic->getId()) { return false; } $relation = $this->secretaryRepo->findActiveClinicRow($user, $clinic, $appointment->getDoctor()); return $relation !== null && $this->secretaryPermissions->can($relation, self::RESOURCE, $action); } $doctor = $this->doctorRepo->findByUuid($dbUuid); if ($doctor === null || $doctor->getId() !== $appointment->getDoctor()->getId()) { return false; } $relation = $this->secretaryRepo->findActiveBySecretaryForDoctor($user, $doctor); return $relation !== null && $this->secretaryPermissions->can($relation, self::RESOURCE, $action); } }