fix(treatment): make the staff panel a queue instead of an assignment list
findTodayForStaff filtered on appointments.staff, and no booking path ever sets that column. The result was a staff panel that was empty for every operator, in every tenant, no matter how much work the day held. Today's sessions now reach an operator three ways: the session they already claimed (performedBy), the appointment a secretary pre-assigned to them, or unclaimed work whose protocol names them. A protocol with no staff list means everyone may perform it — the same "no rows is not a restriction" rule ResourceServiceOffering already uses. The query is also tenant-scoped, which the old one was not: it relied on appointments.staff being a same-tenant row rather than saying so. Verified against the dev database: the operator behind 09128726723 now gets both of today's sessions on "لیزر توتال", which the old query returned none of. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -88,16 +88,53 @@ class TreatmentSessionRepository extends ServiceEntityRepository
|
||||
/**
|
||||
* جلسات امروزِ یک پرسنل — از روی نوبتِ متصل، نه از روی سررسید تخمینی.
|
||||
*
|
||||
* صف است، نه فهرستِ اختصاصیافته. سه چیز اینجا میآید:
|
||||
* - جلسهای که همین پرسنل برداشته (`performedBy`)،
|
||||
* - نوبتی که منشی از قبل به او داده (`appointment.staff`)،
|
||||
* - و جلسهٔ بیصاحبی که پروتکلش او را مجاز میداند.
|
||||
*
|
||||
* فیلترِ قبلی فقط شرط دوم را داشت، و چون هیچ مسیرِ نوبتدهی اپراتور را ست
|
||||
* نمیکند، پنل پرسنل همیشه خالی بود.
|
||||
*
|
||||
* پروتکلِ بدون فهرست پرسنل یعنی «همه مجازند» — همان قاعدهٔ
|
||||
* `ResourceServiceOffering` که نبودِ رکورد را محدودیت حساب نمیکند.
|
||||
*
|
||||
* @return TreatmentSession[]
|
||||
*/
|
||||
public function findTodayForStaff(ClinicStaff $staff, int $dayStart, int $dayEnd): array
|
||||
{
|
||||
$allowsThisStaff = <<<'DQL'
|
||||
EXISTS (
|
||||
SELECT 1 FROM App\Treatment\Entity\TreatmentProtocolStaff ps
|
||||
JOIN ps.protocol p
|
||||
WHERE p.serviceItem = c.serviceItem AND p.active = true AND ps.staff = :staff
|
||||
)
|
||||
DQL;
|
||||
|
||||
$namesAnyStaff = <<<'DQL'
|
||||
EXISTS (
|
||||
SELECT 1 FROM App\Treatment\Entity\TreatmentProtocolStaff ps2
|
||||
JOIN ps2.protocol p2
|
||||
WHERE p2.serviceItem = c.serviceItem AND p2.active = true
|
||||
)
|
||||
DQL;
|
||||
|
||||
return $this->createQueryBuilder('s')
|
||||
->join('s.appointment', 'a')
|
||||
->where('a.staff = :staff')
|
||||
->andWhere('a.slotStart >= :from')
|
||||
->join('s.treatmentCase', 'c')
|
||||
->where('a.slotStart >= :from')
|
||||
->andWhere('a.slotStart <= :to')
|
||||
// محیط، وگرنه پرسنلِ یک کلینیک جلسات کلینیک دیگر را میبیند.
|
||||
->andWhere('s.entityType = :type')
|
||||
->andWhere('s.entityId = :id')
|
||||
->andWhere(sprintf(
|
||||
's.performedBy = :staff OR a.staff = :staff OR (s.performedBy IS NULL AND a.staff IS NULL AND (%s OR NOT %s))',
|
||||
$allowsThisStaff,
|
||||
$namesAnyStaff,
|
||||
))
|
||||
->setParameter('staff', $staff)
|
||||
->setParameter('type', $staff->getEntityType())
|
||||
->setParameter('id', $staff->getEntityId())
|
||||
->setParameter('from', $dayStart)
|
||||
->setParameter('to', $dayEnd)
|
||||
->orderBy('a.slotStart', 'ASC')
|
||||
|
||||
Reference in New Issue
Block a user