Files
onboard/app/Services/Classification/PatientStatusClassifier.php
brusnitsyn 90e0d04dfd * оптимизировал запросы выдачи пациентов, сохранения снапшотов
* доработал страницу отчета дежурного
* переделал "действия" над пациентом
* подключил виджеты на странице отчета дежурного
2026-05-08 17:04:56 +09:00

85 lines
3.0 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Services\Classification;
use App\Models\MedicalHistory;
use App\Models\UnifiedMedicalHistory;
use App\Services\DateRange;
use Illuminate\Support\Carbon;
class PatientStatusClassifier
{
public const STATUS_IN_DEPARTMENT = 'in_department';
public const STATUS_RECIPIENT = 'recipient';
public const STATUS_DISCHARGED = 'discharged';
public const STATUS_TRANSFERRED = 'transferred';
public const STATUS_DECEASED = 'deceased';
public const URGENCY_URGENT = 'urgent'; // urgency_id = 1
public const URGENCY_PLANNED = 'planned'; // urgency_id = 2
public const URGENCY_UNKNOWN = 'unknown';
/**
* Определяет срочность пациента.
*/
public static function classifyUrgency(?int $urgencyId): string
{
return match ($urgencyId) {
1 => self::URGENCY_URGENT,
2 => self::URGENCY_PLANNED,
default => self::URGENCY_UNKNOWN,
};
}
/**
* Определяет поступил ли пациент в диапазоне.
*/
public static function classifyAdmitted(Carbon|string|null $ingoingDate): bool
{
if (is_null($ingoingDate)) {return false;}
$ingoingLocal = Carbon::parse($ingoingDate);
$now = Carbon::now();
// Окно смены: вчера 09:00 → сегодня 09:00
$shiftStart = $now->copy()->subDay()->setTime(9, 0);
$shiftEnd = $now->copy()->setTime(9, 0);
return $ingoingLocal->between($shiftStart, $shiftEnd);
}
/**
* Определяет статус пациента на основе "сырых" полей из БД.
* Логика изолирована и может быть легко протестирована.
*/
public static function classify(UnifiedMedicalHistory|MedicalHistory $history, DateRange $dateRange): string
{
// 1. Смерть — приоритет №1 (не зависит от дат)
if (!empty($history->death_date)) {
return self::STATUS_DECEASED;
}
// 2. Если есть дата выбытия
if (!empty($history->extract_date)) {
// Переведён (коды 3, 4)
if (in_array($history->visit_result_id, [3, 4], true)) {
return self::STATUS_TRANSFERRED;
}
// Выписан домой/иное (исключаем коды 3-6)
if (in_array($history->visit_result_id, [1], true)) {
return self::STATUS_DISCHARGED;
}
}
// 3. Поступившие
if ($history->latestMigration?->getAdmittedInCurrentAttribute()) {
return self::STATUS_RECIPIENT;
}
// 4. В отделении
if (empty($history->latestMigration?->out_date) && $history->latestMigration?->ingoing_date < $dateRange->startDate) {
return self::STATUS_IN_DEPARTMENT;
}
return 'unknown';
}
}