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

* доработал страницу отчета дежурного
* переделал "действия" над пациентом
* подключил виджеты на странице отчета дежурного
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

@@ -5,10 +5,67 @@ namespace App\Services;
use App\Models\MedicalHistory;
use App\Models\MigrationPatient;
use App\Models\UnifiedMedicalHistory;
use App\Services\Classification\PatientStatusClassifier;
use Illuminate\Support\Carbon;
class UnifiedMedicalHistoryService
{
public function getGroupedHistories(DateRange $dateRange, int $departmentId): array
{
// 1. Один запрос: получаем "сырые" данные (без вычисляемых статусов)
$all = UnifiedMedicalHistory::with([
'latestMigration' => fn($q) => $q->where(function ($q) use ($dateRange) {
// Вариант А: Пациент уже лежит (текущий)
$q->whereNull('out_date')
->whereNotNull('medical_history_id')
->where('ingoing_date', '<', $dateRange->startSql());
})
->orWhere(function ($q) use ($dateRange) {
$q->where('ingoing_date', '<=', $dateRange->endSql())
->where('ingoing_date', '>', $dateRange->startSql());
})
])
->whereNull('extract_date')
->get()
// Фильтр по отделению в памяти (быстро для <1000 записей)
->filter(fn($h) => $h->latestMigration?->department_id === $departmentId);
// 2. Добавляем вычисляемые поля и превращаем в плоский массив
$prepared = $all->map(function (UnifiedMedicalHistory $h) use ($dateRange) {
return [
// Все исходные поля модели (автоматически через toArray)
...$h->toArray(),
// + вычисляемые мета-поля для фронтенда
'patient_status' => PatientStatusClassifier::classify($h, $dateRange),
'patient_urgency' => PatientStatusClassifier::classifyUrgency($h->urgency_id),
'admitted_today' => PatientStatusClassifier::classifyAdmitted($h->latestMigration?->ingoing_date),
];
});
// 3. Сортировка
$sortBy = 'recipient_date';
$sortOrder = 'desc';
$sorted = $prepared->sortBy($sortBy, SORT_REGULAR, $sortOrder === 'desc')->values();
// 4. Возвращаем плоский массив + метаданные для фронтенда
return [
'data' => $sorted->toArray(),
'meta' => [
'total' => $sorted->count(),
'sortBy' => $sortBy,
'sortOrder' => $sortOrder,
// Статистика для фильтров/бейджей (опционально)
'counts' => [
'in_department' => $sorted->where('patient_status', 'in_department')->count(),
'discharged' => $sorted->where('patient_status', 'discharged')->count(),
'urgent' => $sorted->where('patient_urgency', 'urgent')->count(),
'planned' => $sorted->where('patient_urgency', 'planned')->count(),
]
]
];
}
public function getHistories(DateRange $dateRange, int $departmentId)
{
$query = UnifiedMedicalHistory::query();
@@ -49,12 +106,10 @@ class UnifiedMedicalHistoryService
public function getDepartmentHistories(DateRange $dateRange, int $departmentId)
{
return UnifiedMedicalHistory::query()
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
->whereHas('latestMigration', function ($q) use ($departmentId, $dateRange) {
$q->department($departmentId)->current($dateRange);
})
->with(['latestMigration' => function ($q) use ($departmentId, $dateRange) {
$q->department($departmentId)->current($dateRange); // подгружаем только отфильтрованные движения
}])
->with(['latestMigration'])
->get()
// Сортировка по дате поступления в отделение (поле дочерней таблицы)
->sortByDesc(fn ($mh) => $mh->latestMigration->ingoing_date ?? $mh->recipient_date)
@@ -71,48 +126,40 @@ class UnifiedMedicalHistoryService
$now = Carbon::now();
return UnifiedMedicalHistory::query()
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
->whereHas('latestMigration', function ($q) use ($departmentId, $dateRange) {
$q->department($departmentId)->admitted($dateRange->startSql(), $dateRange->endSql());
})
->with(['latestMigration' => function ($q) use ($departmentId) {
$q->department($departmentId);
}])
->with(['latestMigration'])
->get();
}
public function getDischargedHistories(DateRange $dateRange, int $departmentId)
{
return UnifiedMedicalHistory::query()
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
->whereHas('latestMigration', function ($q) use ($departmentId, $dateRange) {
$q->department($departmentId)->discharged($dateRange->startSql(), $dateRange->endSql());
})
->with(['latestMigration' => function ($q) use ($departmentId) {
$q->department($departmentId);
}])
->with(['latestMigration'])
->get();
}
public function getDeceasedHistories(DateRange $dateRange, int $departmentId)
{
return UnifiedMedicalHistory::query()
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
->whereHas('latestMigration', function ($q) use ($departmentId, $dateRange) {
$q->department($departmentId)->deceased($dateRange->startSql(), $dateRange->endSql());
})
->with(['latestMigration' => function ($q) use ($departmentId) {
$q->department($departmentId);
}])
->with(['latestMigration'])
->get();
}
public function getTransferredHistories(DateRange $dateRange, int $departmentId)
{
return UnifiedMedicalHistory::query()
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
->whereHas('latestMigration', function ($q) use ($departmentId, $dateRange) {
$q->department($departmentId)->transferred($dateRange->startSql(), $dateRange->endSql());
})
->with(['latestMigration' => function ($q) use ($departmentId) {
$q->department($departmentId);
}])
->with(['latestMigration'])
->get();
}
}