Gate specialty modules by staff role with view and refer levels.
Deploy Ladill Care / deploy (push) Successful in 37s
Deploy Ladill Care / deploy (push) Successful in 37s
Give nurses, lab techs, pharmacists, and GPs broad access to day-to-day modules, keep restricted specialties for specialists (with support nurses), and let GPs view results or refer without full clinical edit. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -104,6 +104,7 @@ class SpecialtyModuleController extends Controller
|
||||
$organization = $this->organization($request);
|
||||
$member = $this->member($request);
|
||||
abort_unless($modules->memberCanAccess($organization, $member, $module), 403);
|
||||
abort_unless($modules->memberCanManage($organization, $member, $module), 403);
|
||||
abort_unless($visit->organization_id === $organization->id, 404);
|
||||
|
||||
$validated = $request->validate([
|
||||
@@ -142,6 +143,7 @@ class SpecialtyModuleController extends Controller
|
||||
$organization = $this->organization($request);
|
||||
$member = $this->member($request);
|
||||
abort_unless($modules->memberCanAccess($organization, $member, $module), 403);
|
||||
abort_unless($modules->memberCanManage($organization, $member, $module), 403);
|
||||
abort_unless($visit->organization_id === $organization->id, 404);
|
||||
$this->authorizeBranch($request, (int) $visit->branch_id);
|
||||
|
||||
@@ -256,6 +258,7 @@ class SpecialtyModuleController extends Controller
|
||||
$organization = $this->organization($request);
|
||||
$member = $this->member($request);
|
||||
abort_unless($modules->memberCanAccess($organization, $member, $module), 403);
|
||||
abort_unless($modules->memberCanManage($organization, $member, $module), 403);
|
||||
abort_unless($visit->organization_id === $organization->id, 404);
|
||||
|
||||
$tab = (string) $request->input('tab', '');
|
||||
@@ -345,6 +348,7 @@ class SpecialtyModuleController extends Controller
|
||||
$organization = $this->organization($request);
|
||||
$member = $this->member($request);
|
||||
abort_unless($modules->memberCanAccess($organization, $member, $module), 403);
|
||||
abort_unless($modules->memberCanManage($organization, $member, $module), 403);
|
||||
abort_unless($visit->organization_id === $organization->id, 404);
|
||||
abort_unless($visit->patient_id, 422);
|
||||
|
||||
@@ -388,6 +392,7 @@ class SpecialtyModuleController extends Controller
|
||||
$member = $this->member($request);
|
||||
$owner = $this->ownerRef($request);
|
||||
abort_unless($modules->memberCanAccess($organization, $member, $module), 403);
|
||||
abort_unless($modules->memberCanManage($organization, $member, $module), 403);
|
||||
abort_unless($queueBridge->isEnabled($organization), 404);
|
||||
|
||||
$resolver = app(OrganizationResolver::class);
|
||||
@@ -473,6 +478,74 @@ class SpecialtyModuleController extends Controller
|
||||
return back()->with('success', 'Called '.$ticket['ticket_number'].' — '.$name.'.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Refer a patient into this specialty queue (walk-in) without full clinical edit access.
|
||||
*/
|
||||
public function refer(
|
||||
Request $request,
|
||||
string $module,
|
||||
SpecialtyModuleService $modules,
|
||||
AppointmentService $appointments,
|
||||
): RedirectResponse {
|
||||
$definition = $modules->definition($module);
|
||||
abort_unless($definition, 404);
|
||||
|
||||
$organization = $this->organization($request);
|
||||
$member = $this->member($request);
|
||||
abort_unless($modules->memberCanRefer($organization, $member, $module), 403);
|
||||
|
||||
$owner = $this->ownerRef($request);
|
||||
$branchScope = app(OrganizationResolver::class)->branchScope($member);
|
||||
|
||||
$validated = $request->validate([
|
||||
'patient_id' => ['required', 'integer', 'exists:care_patients,id'],
|
||||
'branch_id' => ['nullable', 'integer', 'exists:care_branches,id'],
|
||||
'reason' => ['nullable', 'string', 'max:500'],
|
||||
'notes' => ['nullable', 'string', 'max:2000'],
|
||||
]);
|
||||
|
||||
$branchId = (int) ($validated['branch_id'] ?? $branchScope ?? 0);
|
||||
abort_unless($branchId > 0, 422);
|
||||
$this->authorizeBranch($request, $branchId);
|
||||
|
||||
$department = Department::owned($owner)
|
||||
->where('type', $definition['department_type'] ?? 'general')
|
||||
->where('branch_id', $branchId)
|
||||
->where('is_active', true)
|
||||
->orderBy('id')
|
||||
->first();
|
||||
|
||||
if (! $department) {
|
||||
return back()->with('error', 'No active '.($definition['label'] ?? $module).' department at this branch.');
|
||||
}
|
||||
|
||||
$patient = \App\Models\Patient::owned($owner)
|
||||
->where('organization_id', $organization->id)
|
||||
->findOrFail((int) $validated['patient_id']);
|
||||
|
||||
$appointment = $appointments->walkIn($organization, $owner, [
|
||||
'patient_id' => $patient->id,
|
||||
'branch_id' => $branchId,
|
||||
'department_id' => $department->id,
|
||||
'reason' => $validated['reason'] ?? ('Referral to '.($definition['label'] ?? $module)),
|
||||
'notes' => $validated['notes'] ?? null,
|
||||
], $owner);
|
||||
|
||||
\App\Services\Care\AuditLogger::record(
|
||||
$owner,
|
||||
'specialty.referral',
|
||||
$organization->id,
|
||||
$owner,
|
||||
Appointment::class,
|
||||
$appointment->id,
|
||||
['module' => $module, 'department_id' => $department->id],
|
||||
);
|
||||
|
||||
return redirect()
|
||||
->route('care.queue.index')
|
||||
->with('success', 'Referred '.$patient->fullName().' to '.($definition['label'] ?? $module).'.');
|
||||
}
|
||||
|
||||
protected function renderShell(
|
||||
Request $request,
|
||||
string $module,
|
||||
@@ -489,6 +562,10 @@ class SpecialtyModuleController extends Controller
|
||||
$member = $this->member($request);
|
||||
abort_unless($modules->memberCanAccess($organization, $member, $module), 403);
|
||||
|
||||
$canManageSpecialty = $modules->memberCanManage($organization, $member, $module);
|
||||
$canReferSpecialty = $modules->memberCanRefer($organization, $member, $module);
|
||||
$specialtyAccessLevel = $modules->memberAccessLevel($organization, $member, $module);
|
||||
|
||||
$owner = $this->ownerRef($request);
|
||||
$resolver = app(OrganizationResolver::class);
|
||||
$branchScope = $resolver->branchScope($member);
|
||||
@@ -559,8 +636,8 @@ class SpecialtyModuleController extends Controller
|
||||
$services = $shell->provisionedServices($organization, $module);
|
||||
|
||||
$permissions = app(\App\Services\Care\CarePermissions::class);
|
||||
$canConsult = $permissions->can($member, 'consultations.manage');
|
||||
$canManageQueue = $permissions->can($member, 'appointments.manage');
|
||||
$canConsult = $permissions->can($member, 'consultations.manage') && $canManageSpecialty;
|
||||
$canManageQueue = $permissions->can($member, 'appointments.manage') && $canManageSpecialty;
|
||||
$branchLabel = $branchId
|
||||
? (string) (\App\Models\Branch::owned($owner)->whereKey($branchId)->value('name') ?? '')
|
||||
: '';
|
||||
@@ -803,6 +880,9 @@ class SpecialtyModuleController extends Controller
|
||||
'lockToPractitioner' => $practitionerScope !== null,
|
||||
'canConsult' => $canConsult,
|
||||
'canManageQueue' => $canManageQueue,
|
||||
'canManageSpecialty' => $canManageSpecialty,
|
||||
'canReferSpecialty' => $canReferSpecialty,
|
||||
'specialtyAccessLevel' => $specialtyAccessLevel,
|
||||
'queueIntegration' => $branchId
|
||||
? $queueBridge->listMeta($organization, $module, $branchId)
|
||||
: ['enabled' => false],
|
||||
|
||||
Reference in New Issue
Block a user