Redesign Care patient-flow board and remove Queue from nurses.
Deploy Ladill Care / deploy (push) Successful in 39s
Deploy Ladill Care / deploy (push) Successful in 39s
Shared queue-board is now a Waiting/Called/In care/Done stage board with prominent tickets and Call next; nurses lose queue.manage and canAccessPatientQueue so /queue and queue nav are gated while specialty workspaces stay available. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -176,7 +176,8 @@ class ConsultationController extends Controller
|
||||
$queueIntegration = ['enabled' => false];
|
||||
$queueBranchId = null;
|
||||
$queueBridge = app(CareQueueBridge::class);
|
||||
if ($permissions->handlesFloorCare($member) && $queueBridge->isEnabled($organization)) {
|
||||
$canAccessPatientQueue = $permissions->canAccessPatientQueue($member);
|
||||
if ($canAccessPatientQueue && $queueBridge->isEnabled($organization)) {
|
||||
$queueBranchId = app(BranchContext::class)->resolve($request, $organization, $member)
|
||||
?: (int) ($consultation->practitioner?->branch_id
|
||||
?: $consultation->visit?->branch_id
|
||||
@@ -207,6 +208,7 @@ class ConsultationController extends Controller
|
||||
'consultationAssessments' => $consultationAssessments,
|
||||
'startableTemplates' => $startableTemplates,
|
||||
'assessmentStatuses' => config('care.assessment_statuses'),
|
||||
'canAccessPatientQueue' => $canAccessPatientQueue,
|
||||
'universalTemplate' => $universalTemplate,
|
||||
'universalAssessment' => $universalAssessment,
|
||||
'canCaptureUniversal' => $canCaptureUniversal,
|
||||
|
||||
@@ -41,7 +41,9 @@ class DashboardController extends Controller
|
||||
$canBills = $this->permissions->can($member, 'bills.view');
|
||||
$canFinance = $this->permissions->can($member, 'reports.finance.view');
|
||||
$canConsult = $this->permissions->can($member, 'consultations.manage');
|
||||
$showPatientQueue = $this->permissions->can($member, 'appointments.view') && ! $canBranches;
|
||||
$showPatientQueue = $this->permissions->canAccessPatientQueue($member)
|
||||
&& $this->permissions->can($member, 'appointments.view')
|
||||
&& ! $canBranches;
|
||||
|
||||
$branchQuery = Branch::owned($owner)->where('organization_id', $organization->id);
|
||||
$this->scopeToBranch($request, $branchQuery);
|
||||
|
||||
@@ -32,7 +32,7 @@ class QueueController extends Controller
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$this->authorizeAbility($request, 'appointments.view');
|
||||
abort_unless(app(CarePermissions::class)->handlesFloorCare($this->member($request)), 403);
|
||||
abort_unless(app(CarePermissions::class)->canAccessPatientQueue($this->member($request)), 403);
|
||||
$organization = $this->organization($request);
|
||||
$member = $this->member($request);
|
||||
$owner = $this->ownerRef($request);
|
||||
@@ -126,6 +126,24 @@ class QueueController extends Controller
|
||||
$todayQuery->where('branch_id', $branchId);
|
||||
}
|
||||
|
||||
$doneQuery = Appointment::owned($owner)
|
||||
->where('organization_id', $organization->id)
|
||||
->where('status', Appointment::STATUS_COMPLETED)
|
||||
->whereDate('completed_at', today());
|
||||
if ($lockToPractitioner) {
|
||||
$doneQuery->whereIn('practitioner_id', $practitionerScope ?: [0]);
|
||||
} elseif ($branchId) {
|
||||
$doneQuery->where('branch_id', $branchId);
|
||||
}
|
||||
if ($practitionerId && ! $lockToPractitioner) {
|
||||
$doneQuery->where('practitioner_id', $practitionerId);
|
||||
}
|
||||
$done = $doneQuery
|
||||
->with(['patient', 'practitioner'])
|
||||
->orderByDesc('completed_at')
|
||||
->limit(20)
|
||||
->get();
|
||||
|
||||
$heroStats = [
|
||||
'waiting' => $queue->count(),
|
||||
'in_consultation' => $inConsultation->count(),
|
||||
@@ -149,6 +167,7 @@ class QueueController extends Controller
|
||||
'practitionerId' => $practitionerId,
|
||||
'queue' => $queue,
|
||||
'inConsultation' => $inConsultation,
|
||||
'done' => $done,
|
||||
'canManageQueue' => $canManageQueue,
|
||||
'canConsult' => $canConsult,
|
||||
'heroStats' => $heroStats,
|
||||
@@ -160,7 +179,7 @@ class QueueController extends Controller
|
||||
|
||||
public function callNext(Request $request, CareQueueSessionAdvance $advance): RedirectResponse
|
||||
{
|
||||
abort_unless(app(CarePermissions::class)->handlesFloorCare($this->member($request)), 403);
|
||||
abort_unless(app(CarePermissions::class)->canAccessPatientQueue($this->member($request)), 403);
|
||||
$this->authorizeAbility($request, 'appointments.view');
|
||||
$organization = $this->organization($request);
|
||||
abort_unless($this->queueBridge->isEnabled($organization), 404);
|
||||
|
||||
@@ -39,8 +39,12 @@ class SpecialtyModuleController extends Controller
|
||||
403,
|
||||
);
|
||||
|
||||
// Specialty patient flow lives on Queue; clinical depth opens from Queue Start.
|
||||
return redirect()->route('care.queue.index');
|
||||
// Specialty patient flow lives on Queue; nurses stay on the specialty workspace.
|
||||
if (app(\App\Services\Care\CarePermissions::class)->canAccessPatientQueue($this->member($request))) {
|
||||
return redirect()->route('care.queue.index');
|
||||
}
|
||||
|
||||
return redirect()->route('care.specialty.workspace', $module);
|
||||
}
|
||||
|
||||
public function visits(
|
||||
@@ -57,7 +61,11 @@ class SpecialtyModuleController extends Controller
|
||||
403,
|
||||
);
|
||||
|
||||
return redirect()->route('care.queue.index');
|
||||
if (app(\App\Services\Care\CarePermissions::class)->canAccessPatientQueue($this->member($request))) {
|
||||
return redirect()->route('care.queue.index');
|
||||
}
|
||||
|
||||
return redirect()->route('care.specialty.workspace', $module);
|
||||
}
|
||||
|
||||
public function history(
|
||||
@@ -543,7 +551,14 @@ class SpecialtyModuleController extends Controller
|
||||
);
|
||||
|
||||
return redirect()
|
||||
->route('care.queue.index')
|
||||
->route(
|
||||
app(\App\Services\Care\CarePermissions::class)->canAccessPatientQueue($member)
|
||||
? 'care.queue.index'
|
||||
: 'care.specialty.workspace',
|
||||
app(\App\Services\Care\CarePermissions::class)->canAccessPatientQueue($member)
|
||||
? []
|
||||
: ['module' => $module],
|
||||
)
|
||||
->with('success', 'Referred '.$patient->fullName().' to '.($definition['label'] ?? $module).'.');
|
||||
}
|
||||
|
||||
@@ -650,6 +665,7 @@ class SpecialtyModuleController extends Controller
|
||||
|| $permissions->can($member, 'consultations.manage')
|
||||
);
|
||||
$canManageQueue = $permissions->can($member, 'appointments.manage') && $canManageSpecialty;
|
||||
$canAccessPatientQueue = $permissions->canAccessPatientQueue($member);
|
||||
$canBookAppointments = $permissions->can($member, 'appointments.manage');
|
||||
$canViewPatients = $permissions->can($member, 'patients.view');
|
||||
$canViewAppointments = $permissions->can($member, 'appointments.view');
|
||||
@@ -657,6 +673,22 @@ class SpecialtyModuleController extends Controller
|
||||
? (string) (\App\Models\Branch::owned($owner)->whereKey($branchId)->value('name') ?? '')
|
||||
: '';
|
||||
|
||||
$done = Appointment::owned($owner)
|
||||
->where('organization_id', $organization->id)
|
||||
->where('status', Appointment::STATUS_COMPLETED)
|
||||
->whereDate('completed_at', today())
|
||||
->when($departmentIds !== [], fn ($q) => $q->whereIn('department_id', $departmentIds))
|
||||
->when($departmentIds === [], fn ($q) => $q->whereRaw('1 = 0'))
|
||||
->when($kpiBranch, fn ($q) => $q->where('branch_id', $kpiBranch))
|
||||
->when(
|
||||
$practitionerScope !== null,
|
||||
fn ($q) => $q->whereIn('practitioner_id', $practitionerScope ?: [0]),
|
||||
)
|
||||
->with(['patient', 'practitioner'])
|
||||
->orderByDesc('completed_at')
|
||||
->limit(20)
|
||||
->get();
|
||||
|
||||
$workspaceVisit = null;
|
||||
$patientHeader = null;
|
||||
$timeline = [];
|
||||
@@ -843,6 +875,7 @@ class SpecialtyModuleController extends Controller
|
||||
'waiting' => $waiting,
|
||||
'queue' => $waiting,
|
||||
'inConsultation' => $inConsultation,
|
||||
'done' => $done,
|
||||
'openVisits' => $openVisits,
|
||||
'visitHistory' => $visitHistory,
|
||||
'kpis' => $kpis,
|
||||
@@ -900,6 +933,7 @@ class SpecialtyModuleController extends Controller
|
||||
'canManageClinical' => $canManageClinical,
|
||||
'canManageVitals' => $canManageVitals,
|
||||
'canManageQueue' => $canManageQueue,
|
||||
'canAccessPatientQueue' => $canAccessPatientQueue,
|
||||
'canBookAppointments' => $canBookAppointments,
|
||||
'canViewPatients' => $canViewPatients,
|
||||
'canViewAppointments' => $canViewAppointments,
|
||||
|
||||
@@ -34,7 +34,7 @@ class CarePermissions
|
||||
],
|
||||
'nurse' => [
|
||||
'dashboard.view', 'patients.view', 'appointments.view',
|
||||
'consultations.view', 'vitals.manage', 'queue.manage',
|
||||
'consultations.view', 'vitals.manage',
|
||||
'service_queues.console',
|
||||
'assessments.view', 'assessments.capture',
|
||||
],
|
||||
@@ -109,4 +109,17 @@ class CarePermissions
|
||||
'cashier',
|
||||
], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dedicated patient-flow board (GP / specialty Queue homes).
|
||||
* Nurses keep specialty workspaces and vitals — not the call-next board.
|
||||
*/
|
||||
public function canAccessPatientQueue(?Member $member): bool
|
||||
{
|
||||
if (! $this->handlesFloorCare($member)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $member->role !== 'nurse';
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user