feat(migrations): add clinic_id context to weekly_schedules, date_overrides, and holidays
- Introduced clinic_id to weekly_schedules, date_overrides, and holidays to differentiate between personal and clinic schedules. - Updated unique constraints and indexes to accommodate the new clinic context. feat(command): create AssignScheduleClinicCommand to move schedules - Added a command to move a doctor's personal weekly schedule into a clinic context. - Implemented checks to ensure sessions align with the target clinic. feat(context): implement EntityContext and EntityContextResolver - Created EntityContext to represent the effective working environment of a request (doctor or clinic). - Developed EntityContextResolver to determine the execution context based on user roles and active contexts. test: add ServiceModeContextTest for appointment scheduling - Implemented tests to ensure service booking respects clinic and personal contexts. - Verified that financial data is omitted in clinic contexts in InvitedDoctorDashboardScopeTest.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
namespace App\Appointment\Repository;
|
||||
|
||||
use App\Appointment\Entity\DateOverride;
|
||||
use App\Clinic\Entity\Clinic;
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
@@ -19,10 +20,32 @@ class DateOverrideRepository extends ServiceEntityRepository
|
||||
return $this->findOneBy(['uuid' => $uuid]);
|
||||
}
|
||||
|
||||
/**
|
||||
* استثناهای یک context. برخلاف تعطیلی، هیچ اجتماعی در کار نیست: استثنای کلینیک
|
||||
* فقط در همان کلینیک دیده میشود و استثنای شخصی فقط در مطب شخصی.
|
||||
*
|
||||
* @return DateOverride[]
|
||||
*/
|
||||
public function findByDoctorAndClinic(Doctor $doctor, ?Clinic $clinic): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('o')
|
||||
->where('o.doctor = :doctor')
|
||||
->setParameter('doctor', $doctor)
|
||||
->orderBy('o.date', 'ASC');
|
||||
|
||||
if ($clinic === null) {
|
||||
$qb->andWhere('o.clinic IS NULL');
|
||||
} else {
|
||||
$qb->andWhere('o.clinic = :clinic')->setParameter('clinic', $clinic);
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/** @return DateOverride[] */
|
||||
public function findByDoctor(Doctor $doctor): array
|
||||
{
|
||||
return $this->findBy(['doctor' => $doctor], ['date' => 'ASC']);
|
||||
return $this->findByDoctorAndClinic($doctor, null);
|
||||
}
|
||||
|
||||
public function save(DateOverride $entity, bool $flush = true): void
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Appointment\Repository;
|
||||
|
||||
use App\Appointment\Entity\Holiday;
|
||||
use App\Clinic\Entity\Clinic;
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
@@ -30,19 +31,48 @@ class HolidayRepository extends ServiceEntityRepository
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/** @return Holiday[] */
|
||||
public function findActiveByDoctor(Doctor $doctor, int $from, int $to): array
|
||||
/**
|
||||
* تعطیلیهای دیدهشده در یک context: اجتماع تعطیلیهای سراسری پزشک با
|
||||
* تعطیلیهای مخصوص همان کلینیک. $clinic === null یعنی مطب شخصی، که فقط
|
||||
* تعطیلی سراسری میبیند.
|
||||
*
|
||||
* @return Holiday[]
|
||||
*/
|
||||
public function findAllByDoctorInContext(Doctor $doctor, ?Clinic $clinic): array
|
||||
{
|
||||
return $this->createQueryBuilder('h')
|
||||
$qb = $this->createQueryBuilder('h')
|
||||
->where('h.doctor = :doctor')
|
||||
->setParameter('doctor', $doctor)
|
||||
->orderBy('h.startDate', 'DESC');
|
||||
|
||||
if ($clinic === null) {
|
||||
$qb->andWhere('h.clinic IS NULL');
|
||||
} else {
|
||||
$qb->andWhere('h.clinic IS NULL OR h.clinic = :clinic')->setParameter('clinic', $clinic);
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/** @return Holiday[] */
|
||||
public function findActiveByDoctor(Doctor $doctor, int $from, int $to, ?Clinic $clinic = null): array
|
||||
{
|
||||
$qb = $this->createQueryBuilder('h')
|
||||
->where('h.doctor = :doctor')
|
||||
->andWhere('h.active = true')
|
||||
->andWhere('h.startDate <= :to')
|
||||
->andWhere('h.endDate >= :from')
|
||||
->setParameter('doctor', $doctor)
|
||||
->setParameter('from', $from)
|
||||
->setParameter('to', $to)
|
||||
->getQuery()
|
||||
->getResult();
|
||||
->setParameter('to', $to);
|
||||
|
||||
if ($clinic === null) {
|
||||
$qb->andWhere('h.clinic IS NULL');
|
||||
} else {
|
||||
$qb->andWhere('h.clinic IS NULL OR h.clinic = :clinic')->setParameter('clinic', $clinic);
|
||||
}
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
public function save(Holiday $entity, bool $flush = true): void
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Appointment\Repository;
|
||||
|
||||
use App\Appointment\Entity\WeeklySchedule;
|
||||
use App\Clinic\Entity\Clinic;
|
||||
use App\Doctor\Entity\Doctor;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
@@ -14,9 +15,45 @@ class WeeklyScheduleRepository extends ServiceEntityRepository
|
||||
parent::__construct($registry, WeeklySchedule::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* برنامهٔ یک context مشخص. $clinic === null یعنی مطب شخصی.
|
||||
*
|
||||
* چون MySQL در unique index مقادیر NULL را متمایز میشمارد، یکتایی رکورد شخصی
|
||||
* را همین متد تضمین میکند: قبل از ساخت برنامهٔ جدید همیشه صدا زده میشود.
|
||||
*/
|
||||
public function findByDoctorAndClinic(Doctor $doctor, ?Clinic $clinic): ?WeeklySchedule
|
||||
{
|
||||
$qb = $this->createQueryBuilder('ws')
|
||||
->where('ws.doctor = :doctor')
|
||||
->setParameter('doctor', $doctor);
|
||||
|
||||
if ($clinic === null) {
|
||||
$qb->andWhere('ws.clinic IS NULL');
|
||||
} else {
|
||||
$qb->andWhere('ws.clinic = :clinic')->setParameter('clinic', $clinic);
|
||||
}
|
||||
|
||||
return $qb->setMaxResults(1)->getQuery()->getOneOrNullResult();
|
||||
}
|
||||
|
||||
/** همهٔ برنامههای پزشک در همهٔ contextها (شخصی + هر کلینیک). @return WeeklySchedule[] */
|
||||
public function findAllByDoctor(Doctor $doctor): array
|
||||
{
|
||||
return $this->createQueryBuilder('ws')
|
||||
->where('ws.doctor = :doctor')
|
||||
->setParameter('doctor', $doctor)
|
||||
->orderBy('ws.clinic', 'ASC')
|
||||
->getQuery()
|
||||
->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated برنامهٔ context شخصی را برمیگرداند. برای کد جدید از
|
||||
* findByDoctorAndClinic() استفاده کن تا context صریح باشد.
|
||||
*/
|
||||
public function findByDoctor(Doctor $doctor): ?WeeklySchedule
|
||||
{
|
||||
return $this->findOneBy(['doctor' => $doctor]);
|
||||
return $this->findByDoctorAndClinic($doctor, null);
|
||||
}
|
||||
|
||||
/** @param Doctor[] $doctors @return WeeklySchedule[] */
|
||||
|
||||
Reference in New Issue
Block a user