Files
ladill-care/app/Http/Controllers/Care/VisitWorkflowController.php
T
isaaccladandCursor 3ee59a0956
Deploy Ladill Care / deploy (push) Failing after 1m9s
Activate Care workflows across check-in and financial clearance.
Enforce service-queue gates, cashier settlements, and clinical stage progression so patient journeys cannot bypass configured payment or authorization rules.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-17 21:13:06 +00:00

82 lines
2.8 KiB
PHP

<?php
namespace App\Http\Controllers\Care;
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Http\Controllers\Controller;
use App\Models\Visit;
use App\Models\VisitStageAdvance;
use App\Services\Care\AuditLogger;
use App\Services\Care\CareFeatures;
use App\Services\Care\OrganizationResolver;
use App\Services\Care\Workflow\WorkflowEngine;
use App\Services\Care\Workflow\WorkflowQueueReleaseService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class VisitWorkflowController extends Controller
{
use ScopesToAccount;
public function __construct(
protected CareFeatures $features,
protected WorkflowEngine $workflows,
protected WorkflowQueueReleaseService $queueRelease,
) {}
public function advance(Request $request, Visit $visit): RedirectResponse
{
$this->authorizeAbility($request, 'appointments.manage');
$this->authorizeVisit($request, $visit);
$organization = $this->organization($request);
abort_unless($this->features->enabled($organization, CareFeatures::WORKFLOW_ENGINE), 404);
$validated = $request->validate([
'to_code' => ['nullable', 'string', 'max:100'],
]);
if (! $this->workflows->canManuallyAdvance($visit)) {
return back()->with('error', 'Complete this clinical service from its own workspace before advancing the visit.');
}
try {
$advance = $this->workflows->advance($visit, $validated['to_code'] ?? null);
} catch (\DomainException $e) {
return back()->with('error', $e->getMessage());
}
if ($advance === null) {
return back()->with('info', 'This visit has no next workflow stage.');
}
AuditLogger::record(
$this->ownerRef($request),
'visit.workflow_advanced',
$visit->organization_id,
$this->ownerRef($request),
VisitStageAdvance::class,
$advance->id,
['stage_code' => $advance->stage_code, 'status' => $advance->status],
);
$this->queueRelease->releaseCurrent($organization, $visit);
$message = $advance->isBlocked()
? "Visit moved to {$advance->stage?->name}; financial clearance is required before service."
: "Visit moved to {$advance->stage?->name}.";
return back()->with($advance->isBlocked() ? 'warning' : 'success', $message);
}
protected function authorizeVisit(Request $request, Visit $visit): void
{
$this->authorizeOwner($request, $visit);
abort_unless($visit->organization_id === $this->organization($request)->id, 404);
$branchId = app(OrganizationResolver::class)->branchScope($this->member($request));
if ($branchId !== null && $visit->branch_id !== $branchId) {
abort(404);
}
}
}