Files
ladill-care/app/Services/Care/Emergency/EmergencyVitalsService.php
T
isaaccladandCursor 7989ab9184
Deploy Ladill Care / deploy (push) Successful in 34s
Ship full Emergency specialty suite on the shared shell.
Add ED visit stages, triage-driven routing, vitals, observation, disposition, reports, and print summary so Emergency matches Dentistry’s operational depth without a parallel EHR.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-18 17:48:57 +00:00

116 lines
3.2 KiB
PHP

<?php
namespace App\Services\Care\Emergency;
use App\Models\Appointment;
use App\Models\Consultation;
use App\Models\Organization;
use App\Models\Visit;
use App\Models\VitalSign;
use App\Services\Care\ConsultationService;
use Illuminate\Support\Collection;
class EmergencyVitalsService
{
public function __construct(
protected ConsultationService $consultations,
) {}
/**
* @return Collection<int, VitalSign>
*/
public function forVisit(Visit $visit): Collection
{
$consultationIds = Consultation::owned($visit->owner_ref)
->where('visit_id', $visit->id)
->pluck('id');
if ($consultationIds->isEmpty()) {
return collect();
}
return VitalSign::owned($visit->owner_ref)
->whereIn('consultation_id', $consultationIds)
->orderByDesc('recorded_at')
->orderByDesc('id')
->get();
}
public function latestForVisit(Visit $visit): ?VitalSign
{
return $this->forVisit($visit)->first();
}
/**
* @param array<string, mixed> $vitals
*/
public function record(
Organization $organization,
Visit $visit,
string $ownerRef,
array $vitals,
?string $actorRef = null,
): VitalSign {
$consultation = $this->ensureConsultation($visit, $ownerRef, $actorRef);
$saved = $this->consultations->saveVitals(
$consultation,
$ownerRef,
$vitals,
$actorRef,
);
if (! $saved) {
throw new \InvalidArgumentException('Enter at least one vital sign value.');
}
return $saved;
}
protected function ensureConsultation(Visit $visit, string $ownerRef, ?string $actorRef): Consultation
{
$existing = Consultation::owned($ownerRef)
->where('visit_id', $visit->id)
->where('status', '!=', Consultation::STATUS_COMPLETED)
->orderByDesc('id')
->first();
if ($existing) {
return $existing;
}
$completed = Consultation::owned($ownerRef)
->where('visit_id', $visit->id)
->orderByDesc('id')
->first();
if ($completed) {
return $completed;
}
$visit->loadMissing('appointment', 'patient');
$appointment = $visit->appointment;
if (! $appointment instanceof Appointment) {
$appointment = Appointment::query()->where('visit_id', $visit->id)->first();
}
if ($appointment) {
try {
return $this->consultations->startFromAppointment($appointment, $ownerRef, $actorRef);
} catch (\InvalidArgumentException) {
// Fall through to draft consultation.
}
}
return Consultation::create([
'owner_ref' => $ownerRef,
'visit_id' => $visit->id,
'appointment_id' => $appointment?->id,
'practitioner_id' => $appointment?->practitioner_id,
'patient_id' => $visit->patient_id,
'status' => Consultation::STATUS_DRAFT,
'started_at' => now(),
]);
}
}