* оптимизировал запросы выдачи пациентов, сохранения снапшотов

* доработал страницу отчета дежурного
* переделал "действия" над пациентом
* подключил виджеты на странице отчета дежурного
This commit is contained in:
brusnitsyn
2026-05-08 17:04:56 +09:00
parent 6cf1ffbb2b
commit 90e0d04dfd
17 changed files with 818 additions and 292 deletions

View File

@@ -0,0 +1,84 @@
<?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';
}
}