*/ class ResourceServiceOfferingRepository extends ServiceEntityRepository { public function __construct(ManagerRegistry $registry) { parent::__construct($registry, ResourceServiceOffering::class); } public function findOneFor(ClinicResource $resource, ServiceItem $item): ?ResourceServiceOffering { return $this->findOneBy(['resource' => $resource, 'serviceItem' => $item]); } /** @return ResourceServiceOffering[] سرویس‌های یک منبع، برای تب پنل */ public function findForResource(ClinicResource $resource): array { return $this->createQueryBuilder('o') ->join('o.serviceItem', 'i') ->addSelect('i') ->where('o.resource = :resource') ->setParameter('resource', $resource) ->orderBy('i.name', 'ASC') ->getQuery() ->getResult(); } /** * آیا برای این سرویس **اصلاً** رابطه‌ای تعریف شده؟ * * پایهٔ سازگاری عقب‌روِ {@see ClinicResourceRepository::findEligible()}: محیطی که هنوز * رابطه‌ها را پر نکرده نباید یک‌شبه بدون وقت آزاد شود، پس فیلتر فقط وقتی اعمال * می‌شود که کلینیک دست‌کم یک ردیف برای آن سرویس ساخته باشد. */ public function hasAnyFor(ServiceItem $item, ?ResourceType $type = null): bool { $qb = $this->createQueryBuilder('o') ->select('1') ->where('o.serviceItem = :item') ->setParameter('item', $item) ->setMaxResults(1); /** * محدود به نوعِ منبع، وقتی نوع داده شده. * * «کدام منبع این سرویس را می‌دهد» دربارهٔ نقشِ انجام‌دهنده است، نه دربارهٔ اتاق و * پشتیبان‌ها. بدون این قید، ثبت رابطه برای دستگاه‌ها باعث می‌شد اتاقِ همان * برنامه ناگهان «واجد شرایط نباشد» و کل برنامه بشکند. */ if ($type !== null) { $qb->join('o.resource', 'r')->andWhere('r.type = :type')->setParameter('type', $type); } return (bool) $qb->getQuery()->getOneOrNullResult(); } /** @return int[] شناسهٔ منابعی که این سرویس را فعال ارائه می‌دهند */ /** * کدام‌یک از این منابع دست‌کم یک سرویسِ فعال ارائه می‌دهند — یعنی «قابل رزرو»اند. * * عکسِ `activeResourceIdsFor()`: آن از سرویس به منبع می‌رود، این از منبع به سرویس. * تایم‌لاین نوبت‌ها با همین فیلتر می‌کند تا دستگاهی که هنوز به هیچ سرویسی وصل نشده، * ردیفِ همیشه‌خالی نسازد. * * @param int[] $resourceIds * @return int[] */ public function bookableResourceIds(array $resourceIds): array { if ($resourceIds === []) { return []; } $rows = $this->createQueryBuilder('o') ->select('DISTINCT IDENTITY(o.resource) AS resource_id') ->where('o.resource IN (:ids)') ->andWhere('o.active = true') ->setParameter('ids', $resourceIds) ->getQuery() ->getArrayResult(); return array_map(static fn (array $r): int => (int) $r['resource_id'], $rows); } public function activeResourceIdsFor(ServiceItem $item, ?ResourceType $type = null): array { $qb = $this->createQueryBuilder('o') ->select('IDENTITY(o.resource) AS resource_id') ->where('o.serviceItem = :item') ->andWhere('o.active = true') ->setParameter('item', $item); if ($type !== null) { $qb->join('o.resource', 'r')->andWhere('r.type = :type')->setParameter('type', $type); } $rows = $qb->getQuery()->getArrayResult(); return array_map(static fn (array $row): int => (int) $row['resource_id'], $rows); } public function deleteForResource(ClinicResource $resource): int { return (int) $this->createQueryBuilder('o') ->delete() ->where('o.resource = :resource') ->setParameter('resource', $resource) ->getQuery() ->execute(); } }