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:
@@ -5,6 +5,7 @@ namespace App\PracticeDomain\Controller;
|
||||
use App\PracticeDomain\Entity\PracticeDomain;
|
||||
use App\PracticeDomain\Repository\PracticeDomainRepository;
|
||||
use App\Shared\Constant\ErrorCodes;
|
||||
use App\Treatment\Workflow\TreatmentWorkflowRegistry;
|
||||
use App\Shared\Controller\BaseController;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use OpenApi\Attributes as OA;
|
||||
@@ -19,6 +20,7 @@ class PracticeDomainController extends BaseController
|
||||
{
|
||||
public function __construct(
|
||||
private readonly PracticeDomainRepository $domains,
|
||||
private readonly TreatmentWorkflowRegistry $workflows,
|
||||
private readonly EntityManagerInterface $em,
|
||||
) {}
|
||||
|
||||
@@ -34,7 +36,7 @@ class PracticeDomainController extends BaseController
|
||||
$includeInactive = $this->isGranted('ROLE_ADMIN');
|
||||
|
||||
return $this->success(array_map(
|
||||
static fn (PracticeDomain $d): array => $d->toArray(),
|
||||
fn (PracticeDomain $d): array => $d->toArray($this->workflows->hasDedicatedWorkflow($d->getCode())),
|
||||
$this->domains->findOrdered($includeInactive),
|
||||
));
|
||||
}
|
||||
@@ -73,7 +75,7 @@ class PracticeDomainController extends BaseController
|
||||
$this->em->persist($domain);
|
||||
$this->em->flush();
|
||||
|
||||
return $this->success($domain->toArray(), 201);
|
||||
return $this->success($domain->toArray($this->workflows->hasDedicatedWorkflow($domain->getCode())), 201);
|
||||
}
|
||||
|
||||
#[Route('/api/v1/practice-domain/{uuid}', name: 'practice_domain_update', methods: ['PATCH'])]
|
||||
@@ -108,6 +110,6 @@ class PracticeDomainController extends BaseController
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
return $this->success($domain->toArray());
|
||||
return $this->success($domain->toArray($this->workflows->hasDedicatedWorkflow($domain->getCode())));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user