Issue cashier booth tickets when financial gates block service.
Deploy Ladill Care / deploy (push) Successful in 41s

Pay-before-service holds now create a billing queue ticket (via an open bill) so cashiers can Call next / Serve; clearance completes the ticket and releases the clinical line as before.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-18 19:29:29 +00:00
co-authored by Cursor
parent c3219a1bf1
commit 131ccd6edb
9 changed files with 405 additions and 23 deletions
+31 -2
View File
@@ -174,6 +174,7 @@ class WorkflowEngine
$this->gate->obligationFor($visit, $advance->stage);
$satisfied = $this->gate->isSatisfied($visit, $advance->stage);
$becameBlocked = false;
if ($advance->isBlocked() && $satisfied) {
$advance->forceFill([
@@ -187,9 +188,17 @@ class WorkflowEngine
'blocked_reason' => $this->gate->blockedReason($visit, $advance->stage),
'cleared_at' => null,
])->save();
$becameBlocked = true;
}
return $advance->fresh();
$fresh = $advance->fresh();
// Only enqueue when the gate newly blocks — not on every refresh — so
// CareQueueBridge::issueForBill → canRelease → refreshGate cannot recurse.
if ($becameBlocked && $fresh?->blocked_reason === 'awaiting_payment') {
$this->enqueueCashierBooth($visit);
}
return $fresh;
}
protected function enterStage(Visit $visit, FacilityWorkflow $workflow, WorkflowStage $stage): VisitStageAdvance
@@ -198,7 +207,7 @@ class WorkflowEngine
$satisfied = $this->gate->isSatisfied($visit, $stage);
return VisitStageAdvance::create([
$advance = VisitStageAdvance::create([
'owner_ref' => $visit->owner_ref,
'visit_id' => $visit->id,
'workflow_id' => $workflow->id,
@@ -209,6 +218,26 @@ class WorkflowEngine
'entered_at' => now(),
'cleared_at' => $satisfied ? now() : null,
]);
if ($advance->isBlocked() && $advance->blocked_reason === 'awaiting_payment') {
$this->enqueueCashierBooth($visit);
}
return $advance;
}
/**
* Resolve lazily to avoid a constructor cycle with WorkflowQueueReleaseService.
*/
protected function enqueueCashierBooth(Visit $visit): void
{
$organization = $visit->organization
?? \App\Models\Organization::query()->find($visit->organization_id);
if ($organization === null) {
return;
}
app(WorkflowQueueReleaseService::class)->enqueueCashier($organization, $visit);
}
protected function resolveTarget(Visit $visit, ?string $toCode, ?FacilityWorkflow $workflow = null): ?WorkflowStage