feat(treatment): select treatment behaviour by practice domain, not by if-branch
Everything that differs between specialties as data is already stored as data. What is left is behaviour — when a case opens, what happens once a session ends — so it becomes a TreatmentWorkflow resolved through a tagged-service registry. The booking path calls one collaborator and never names a specialty; adding dentistry is a new class, not an edit to confirmation. A clinic that has chosen no practice domain still gets working multi-session courses: DefaultTreatmentWorkflow answers for null and for any code without a dedicated implementation, keeping "unset means behave as today, not error". LaserTreatmentWorkflow is deliberately empty beyond claiming `beauty` — it is the seam where laser-specific behaviour will land without disturbing anyone else. Session due dates are anchored to the previous session's actual finish, so a patient who comes twenty days late shifts the rest of their course instead of getting the next session while it can still do nothing. Only the next session is recomputed; later ones keep their estimate because they are anchored to nothing yet. Attachment targets the first session without an appointment rather than the first open one: a patient booking again mid-course was otherwise matched to the session that already had a booking, and the second appointment went nowhere. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -47,6 +47,27 @@ class TreatmentSessionRepository extends ServiceEntityRepository
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* اولین جلسهای که هنوز نوبتی ندارد.
|
||||
*
|
||||
* جدا از {@see self::findNextOpen()} است چون آن جلسهٔ رزروشده را هم «باز» میداند:
|
||||
* بیماری که وسط دوره نوبت دوم میگیرد باید به جلسهٔ **بعدی** بچسبد، نه به جلسهای
|
||||
* که همین حالا نوبت دارد.
|
||||
*/
|
||||
public function findNextUnbooked(TreatmentCase $case): ?TreatmentSession
|
||||
{
|
||||
return $this->createQueryBuilder('s')
|
||||
->where('s.treatmentCase = :case')
|
||||
->andWhere('s.appointment IS NULL')
|
||||
->andWhere('s.status IN (:open)')
|
||||
->setParameter('case', $case)
|
||||
->setParameter('open', [TreatmentSession::STATUS_PLANNED, TreatmentSession::STATUS_NO_SHOW])
|
||||
->orderBy('s.sessionNumber', 'ASC')
|
||||
->setMaxResults(1)
|
||||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
|
||||
/** جلسهٔ انجامشدهٔ قبلی — لنگرِ محاسبهٔ سررسید جلسهٔ بعد. */
|
||||
public function findLastFinishedBefore(TreatmentCase $case, int $sessionNumber): ?TreatmentSession
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user