Files
ladill-care/app/Http/Controllers/Care/CareUnitController.php
T
isaaccladandCursor 82a2b1a9a7
Deploy Ladill Care / deploy (push) Successful in 48s
Restrict care unit and department setup to admins.
Nurses keep Nursing Services for clinical work but can no longer browse or create structural units and departments.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-20 11:33:38 +00:00

233 lines
8.7 KiB
PHP

<?php
namespace App\Http\Controllers\Care;
use App\Http\Controllers\Controller;
use App\Http\Controllers\Care\Concerns\ScopesToAccount;
use App\Models\CareUnit;
use App\Models\Department;
use App\Models\Visit;
use App\Services\Care\AuditLogger;
use App\Services\Care\CarePermissions;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Validation\Rule;
use Illuminate\View\View;
class CareUnitController extends Controller
{
use ScopesToAccount;
public function index(Request $request): View
{
$this->authorizeAbility($request, 'admin.departments.view');
$organization = $this->organization($request);
$owner = $this->ownerRef($request);
$member = $this->member($request);
$permissions = app(CarePermissions::class);
$units = CareUnit::owned($owner)
->where('organization_id', $organization->id)
->with(['department.branch'])
->orderBy('sort_order')
->orderBy('name')
->get();
$heroStats = [
'total' => $units->count(),
'inpatient' => $units->where('kind', 'inpatient')->count(),
'float' => $units->where('kind', 'float_pool')->count(),
'active' => $units->where('is_active', true)->count(),
];
return view('care.admin.care-units.index', [
'units' => $units,
'organization' => $organization,
'kinds' => config('care.care_unit_kinds'),
'heroStats' => $heroStats,
'canManage' => $permissions->can($member, 'admin.departments.manage'),
]);
}
public function create(Request $request): View
{
$this->authorizeAbility($request, 'admin.departments.manage');
$organization = $this->organization($request);
$owner = $this->ownerRef($request);
$departments = Department::owned($owner)
->whereHas('branch', fn ($q) => $q->where('organization_id', $organization->id))
->with('branch')
->where('is_active', true)
->orderBy('name')
->get();
return view('care.admin.care-units.create', [
'organization' => $organization,
'departments' => $departments,
'kinds' => config('care.care_unit_kinds'),
'selectedDepartmentId' => $request->integer('department_id') ?: null,
]);
}
public function store(Request $request): RedirectResponse
{
$this->authorizeAbility($request, 'admin.departments.manage');
$organization = $this->organization($request);
$owner = $this->ownerRef($request);
$validated = $request->validate([
'department_id' => ['required', 'integer', 'exists:care_departments,id'],
'name' => ['required', 'string', 'max:255'],
'code' => ['nullable', 'string', 'max:50'],
'kind' => ['required', 'string', Rule::in(array_keys(config('care.care_unit_kinds')))],
]);
$department = Department::owned($owner)->with('branch')->findOrFail($validated['department_id']);
abort_unless((int) $department->branch?->organization_id === (int) $organization->id, 404);
$unit = CareUnit::create([
'owner_ref' => $owner,
'organization_id' => $organization->id,
'department_id' => $department->id,
'name' => $validated['name'],
'code' => $validated['code'] ?? null,
'kind' => $validated['kind'],
'is_active' => true,
]);
AuditLogger::record($owner, 'care_unit.created', $organization->id, $owner, CareUnit::class, $unit->id);
return redirect()->route('care.care-units.show', $unit)->with('success', 'Care unit created.');
}
public function show(Request $request, CareUnit $careUnit): View
{
$this->authorizeCareUnitView($request);
$this->authorizeOwner($request, $careUnit);
$organization = $this->organization($request);
abort_unless((int) $careUnit->organization_id === (int) $organization->id, 404);
$careUnit->load(['department.branch', 'beds']);
$placedVisits = Visit::owned($this->ownerRef($request))
->where('organization_id', $organization->id)
->where('care_unit_id', $careUnit->id)
->whereIn('status', [Visit::STATUS_OPEN, Visit::STATUS_IN_PROGRESS])
->with(['patient', 'bed'])
->orderBy('placed_at')
->get();
$placeableVisits = Visit::owned($this->ownerRef($request))
->where('organization_id', $organization->id)
->where('branch_id', $careUnit->department?->branch_id)
->whereIn('status', [Visit::STATUS_OPEN, Visit::STATUS_IN_PROGRESS])
->where(function ($q) use ($careUnit) {
$q->whereNull('care_unit_id')
->orWhere('care_unit_id', '!=', $careUnit->id);
})
->with(['patient', 'careUnit'])
->orderByDesc('checked_in_at')
->limit(50)
->get();
$availableBeds = $careUnit->beds
->where('is_active', true)
->whereIn('status', ['available', 'reserved'])
->values();
$canPlace = app(CarePermissions::class)->can($this->member($request), 'inpatient.placement.manage');
return view('care.admin.care-units.show', [
'unit' => $careUnit,
'kinds' => config('care.care_unit_kinds'),
'bedStatuses' => config('care.bed_statuses'),
'placedVisits' => $placedVisits,
'placeableVisits' => $placeableVisits,
'availableBeds' => $availableBeds,
'canPlace' => $canPlace,
]);
}
protected function authorizeCareUnitView(Request $request): void
{
$permissions = app(CarePermissions::class);
$member = $this->member($request);
abort_unless(
$permissions->can($member, 'admin.departments.view')
|| $permissions->can($member, 'inpatient.placement.view'),
403,
);
}
public function edit(Request $request, CareUnit $careUnit): View
{
$this->authorizeAbility($request, 'admin.departments.manage');
$this->authorizeOwner($request, $careUnit);
$organization = $this->organization($request);
$owner = $this->ownerRef($request);
$departments = Department::owned($owner)
->whereHas('branch', fn ($q) => $q->where('organization_id', $organization->id))
->with('branch')
->orderBy('name')
->get();
return view('care.admin.care-units.edit', [
'unit' => $careUnit,
'departments' => $departments,
'kinds' => config('care.care_unit_kinds'),
]);
}
public function update(Request $request, CareUnit $careUnit): RedirectResponse
{
$this->authorizeAbility($request, 'admin.departments.manage');
$this->authorizeOwner($request, $careUnit);
$organization = $this->organization($request);
$owner = $this->ownerRef($request);
$validated = $request->validate([
'department_id' => ['required', 'integer', 'exists:care_departments,id'],
'name' => ['required', 'string', 'max:255'],
'code' => ['nullable', 'string', 'max:50'],
'kind' => ['required', 'string', Rule::in(array_keys(config('care.care_unit_kinds')))],
'is_active' => ['boolean'],
]);
$department = Department::owned($owner)->with('branch')->findOrFail($validated['department_id']);
abort_unless((int) $department->branch?->organization_id === (int) $organization->id, 404);
$careUnit->update([
'department_id' => $department->id,
'name' => $validated['name'],
'code' => $validated['code'] ?? null,
'kind' => $validated['kind'],
'is_active' => $request->boolean('is_active', true),
]);
AuditLogger::record($owner, 'care_unit.updated', $organization->id, $owner, CareUnit::class, $careUnit->id);
return redirect()->route('care.care-units.show', $careUnit)->with('success', 'Care unit updated.');
}
public function destroy(Request $request, CareUnit $careUnit): RedirectResponse
{
$this->authorizeAbility($request, 'admin.departments.manage');
$this->authorizeOwner($request, $careUnit);
$careUnit->delete();
AuditLogger::record(
$this->ownerRef($request),
'care_unit.deleted',
$careUnit->organization_id,
$this->ownerRef($request),
CareUnit::class,
$careUnit->id,
);
return redirect()->route('care.care-units.index')->with('success', 'Care unit removed.');
}
}