Files
ladill-care/app/Services/Care/NursingAssessmentService.php
T
isaaccladandCursor 9eb6c21828
Deploy Ladill Care / deploy (push) Successful in 55s
Add nursing assessment packs, ward board, and nurse performance KPIs.
Seeds NEWS2/Braden/Morse/pain packs with visit vitals and a unit dashboard for MAR, assessments, notes, and handover activity.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-20 10:32:52 +00:00

110 lines
3.4 KiB
PHP

<?php
namespace App\Services\Care;
use App\Models\Assessment;
use App\Models\AssessmentTemplate;
use App\Models\CareUnit;
use App\Models\Visit;
use App\Models\VisitVital;
use Illuminate\Support\Collection;
class NursingAssessmentService
{
/** @var list<string> */
public const NURSING_PACK_CODES = ['news2', 'braden', 'morse', 'pain_nrs'];
/**
* @return Collection<int, AssessmentTemplate>
*/
public function nursingTemplates(): Collection
{
return AssessmentTemplate::query()
->whereNull('organization_id')
->where('is_current', true)
->where('is_active', true)
->whereIn('code', self::NURSING_PACK_CODES)
->orderBy('name')
->get();
}
/**
* Board rows for placed patients: latest nursing assessments + latest vitals.
*
* @return list<array<string, mixed>>
*/
public function unitBoard(CareUnit $unit, string $ownerRef): array
{
$templates = $this->nursingTemplates();
$visits = Visit::owned($ownerRef)
->where('care_unit_id', $unit->id)
->whereIn('status', [Visit::STATUS_OPEN, Visit::STATUS_IN_PROGRESS])
->with(['patient', 'bed'])
->orderBy('placed_at')
->get();
$rows = [];
foreach ($visits as $visit) {
$latestByCode = Assessment::owned($ownerRef)
->where('visit_id', $visit->id)
->whereIn('status', [Assessment::STATUS_DRAFT, Assessment::STATUS_COMPLETED])
->whereHas('template', fn ($q) => $q->whereIn('code', $templates->pluck('code')->all()))
->with(['template', 'score'])
->orderByDesc('id')
->get()
->unique(fn (Assessment $a) => $a->template?->code)
->keyBy(fn (Assessment $a) => $a->template?->code);
$latestVitals = VisitVital::owned($ownerRef)
->where('visit_id', $visit->id)
->orderByDesc('recorded_at')
->first();
$rows[] = [
'visit' => $visit,
'patient' => $visit->patient,
'bed' => $visit->bed,
'assessments' => $latestByCode,
'vitals' => $latestVitals,
];
}
return $rows;
}
public function recordVisitVitals(
Visit $visit,
string $ownerRef,
?string $actorRef,
array $data,
): VisitVital {
$vital = VisitVital::create([
'owner_ref' => $ownerRef,
'organization_id' => $visit->organization_id,
'visit_id' => $visit->id,
'patient_id' => $visit->patient_id,
'care_unit_id' => $visit->care_unit_id,
'bp_systolic' => $data['bp_systolic'] ?? null,
'bp_diastolic' => $data['bp_diastolic'] ?? null,
'pulse' => $data['pulse'] ?? null,
'temperature' => $data['temperature'] ?? null,
'spo2' => $data['spo2'] ?? null,
'respiratory_rate' => $data['respiratory_rate'] ?? null,
'notes' => $data['notes'] ?? null,
'recorded_by' => $actorRef,
'recorded_at' => now(),
]);
AuditLogger::record(
$ownerRef,
'visit_vitals.recorded',
$visit->organization_id,
$actorRef,
VisitVital::class,
$vital->id,
);
return $vital;
}
}