* доработал страницу отчета дежурного * переделал "действия" над пациентом * подключил виджеты на странице отчета дежурного
238 lines
11 KiB
PHP
238 lines
11 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Models\MedicalHistory;
|
||
use App\Models\MigrationPatient;
|
||
use App\Services\Classification\PatientStatusClassifier;
|
||
use Illuminate\Support\Carbon;
|
||
|
||
class MedicalHistoryService
|
||
{
|
||
public function getGroupedHistories(DateRange $dateRange, int $departmentId): array
|
||
{
|
||
$startYear = Carbon::now()->startOfYear()->format('Y-m-d');
|
||
|
||
// 1. Один запрос: получаем "сырые" данные (без вычисляемых статусов)
|
||
$all = MedicalHistory::query()->whereHas('latestMigration', function ($q) use ($departmentId, $dateRange, $startYear) {
|
||
$q->where('department_id', $departmentId)
|
||
// пребывание пересекается с отчётным периодом
|
||
->where('ingoing_date', '<=', $dateRange->endSql())
|
||
->where('ingoing_date', '>=', $startYear)
|
||
->where(function ($sub) use ($dateRange) {
|
||
$sub->whereNull('out_date')
|
||
->orWhere('out_date', '>=', $dateRange->startSql())
|
||
->where('out_date', '<=', $dateRange->endSql());
|
||
});
|
||
})->with(['latestMigration' => function ($q) use ($departmentId) {
|
||
$q->where('department_id', $departmentId);
|
||
}, 'latestMigration.operations', 'latestMigration.reanimations'])->get();
|
||
|
||
|
||
// 2. Добавляем вычисляемые поля и превращаем в плоский массив
|
||
$prepared = $all->map(function (MedicalHistory $h) use ($dateRange) {
|
||
$patientStatus = PatientStatusClassifier::classify($h, $dateRange);
|
||
$patientUrgency = null;
|
||
if (!in_array($patientStatus, [
|
||
PatientStatusClassifier::STATUS_DECEASED,
|
||
PatientStatusClassifier::STATUS_DISCHARGED,
|
||
PatientStatusClassifier::STATUS_TRANSFERRED
|
||
])) $patientUrgency = PatientStatusClassifier::classifyUrgency($h->urgency_id);
|
||
return [
|
||
// Все исходные поля модели (автоматически через toArray)
|
||
...$h->toArray(),
|
||
|
||
// + вычисляемые мета-поля для фронтенда
|
||
'patient_status' => $patientStatus,
|
||
'patient_urgency' => $patientUrgency,
|
||
'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 = MedicalHistory::query();
|
||
|
||
$query->where('recipient_date', '>=', $dateRange->startSql())
|
||
->where('recipient_date', '<', $dateRange->endSql())
|
||
// 1. Оставляем только тех пациентов, у которых БЫЛО движение в этом отделении
|
||
->whereHas('latestMigration', fn($q) => $q->where('department_id', $departmentId))
|
||
|
||
// 2. Загружаем ТОЛЬКО последнее движение в этом отделении (не все миграции)
|
||
->with(['latestMigration' => fn($q) => $q->where('department_id', $departmentId)]);
|
||
|
||
$result = $query->paginate();
|
||
|
||
return $result;
|
||
}
|
||
|
||
public function getUrgencyHistory(DateRange $dateRange, int $departmentId, int $urgencyId)
|
||
{
|
||
$query = MedicalHistory::query();
|
||
|
||
$query->where('recipient_date', '>=', $dateRange->startSql())
|
||
->where('recipient_date', '<', $dateRange->endSql())
|
||
->urgency($urgencyId)
|
||
->whereHas('migrations', function ($m) use ($departmentId) {
|
||
$m->where('department_id', $departmentId);
|
||
})
|
||
->with([
|
||
'migrations' => fn ($m) => $m->where('department_id', $departmentId),
|
||
'migrations.operations'
|
||
]);
|
||
|
||
$result = $query->paginate();
|
||
|
||
return $result;
|
||
}
|
||
|
||
public function getDepartmentHistories(DateRange $dateRange, int $departmentId)
|
||
{
|
||
return MedicalHistory::query()
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->currentOrAdmitted($dateRange);
|
||
})
|
||
->with(['latestMigration' => function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->currentOrAdmitted($dateRange)->latest('ingoing_date'); // подгружаем только отфильтрованные движения
|
||
}, 'latestMigration.operations'])
|
||
->get()
|
||
// Сортировка по дате поступления в отделение (поле дочерней таблицы)
|
||
->sortByDesc(fn ($mh) => $mh->latestMigration->ingoing_date ?? $mh->recipient_date)
|
||
->values();
|
||
}
|
||
|
||
public function getPlannedHistories(DateRange $dateRange, int $departmentId)
|
||
{
|
||
return MedicalHistory::query()
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->currentOrAdmitted($dateRange);
|
||
})
|
||
->with(['latestMigration' => function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->currentOrAdmitted($dateRange)
|
||
->latest('ingoing_date'); // подгружаем только отфильтрованные движения
|
||
}, 'latestMigration.operations'])
|
||
->urgency(1)
|
||
->get()
|
||
// Сортировка по дате поступления в отделение (поле дочерней таблицы)
|
||
->sortByDesc(fn ($mh) => $mh->latestMigration->ingoing_date ?? $mh->recipient_date)
|
||
->values();
|
||
}
|
||
|
||
public function getEmergencyHistories(DateRange $dateRange, int $departmentId)
|
||
{
|
||
return MedicalHistory::query()
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->currentOrAdmitted($dateRange);
|
||
})
|
||
->with(['latestMigration' => function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->currentOrAdmitted($dateRange)->latest('ingoing_date'); // подгружаем только отфильтрованные движения
|
||
}, 'latestMigration.operations'])
|
||
->urgency(2)
|
||
->get()
|
||
// Сортировка по дате поступления в отделение (поле дочерней таблицы)
|
||
->sortByDesc(fn ($mh) => $mh->latestMigration->ingoing_date ?? $mh->recipient_date)
|
||
->values();
|
||
}
|
||
|
||
/**
|
||
* Получить карты поступившие сегодня
|
||
* @param DateRange $dateRange
|
||
* @param int $departmentId
|
||
*/
|
||
public function getRecipientHistories(DateRange $dateRange, int $departmentId)
|
||
{
|
||
$now = Carbon::now();
|
||
|
||
return MedicalHistory::query()
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->admitted($dateRange->startSql(), $dateRange->endSql());
|
||
})
|
||
->with(['latestMigration' => function ($q) use ($departmentId) {
|
||
$q->department($departmentId);
|
||
}, 'latestMigration.operations'])
|
||
->get();
|
||
}
|
||
|
||
public function getDischargedHistories(DateRange $dateRange, int $departmentId)
|
||
{
|
||
return MedicalHistory::query()
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->discharged($dateRange->startSql(), $dateRange->endSql());
|
||
})
|
||
->with(['latestMigration' => function ($q) use ($departmentId) {
|
||
$q->department($departmentId);
|
||
}, 'latestMigration.operations'])
|
||
->get();
|
||
}
|
||
|
||
public function getDeceasedHistories(DateRange $dateRange, int $departmentId)
|
||
{
|
||
return MedicalHistory::query()
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->deceased($dateRange->startSql(), $dateRange->endSql());
|
||
})
|
||
->with(['latestMigration' => function ($q) use ($departmentId) {
|
||
$q->department($departmentId);
|
||
}, 'latestMigration.operations'])
|
||
->get();
|
||
}
|
||
|
||
public function getTransferredHistories(DateRange $dateRange, int $departmentId)
|
||
{
|
||
return MedicalHistory::query()
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->transferred($dateRange->startSql(), $dateRange->endSql());
|
||
})
|
||
->with(['latestMigration' => function ($q) use ($departmentId) {
|
||
$q->department($departmentId);
|
||
}, 'latestMigration.operations'])
|
||
->get();
|
||
}
|
||
|
||
public function getReanimationHistories(DateRange $dateRange, int $departmentId)
|
||
{
|
||
return MedicalHistory::query()
|
||
->whereHas('migrations', function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->currentOrAdmitted($dateRange);
|
||
})
|
||
->whereHas('latestMigration.reanimations', function ($q) use ($dateRange) {
|
||
$q->currentOrAdmitted($dateRange);
|
||
})
|
||
->with(
|
||
[
|
||
'latestMigration' => function ($q) use ($departmentId, $dateRange) {
|
||
$q->department($departmentId)->currentOrAdmitted($dateRange)->latest('ingoing_date'); // подгружаем только отфильтрованные движения
|
||
},
|
||
'latestMigration.operations',
|
||
'latestMigration.reanimations'
|
||
])
|
||
->get()
|
||
// Сортировка по дате поступления в отделение (поле дочерней таблицы)
|
||
->sortByDesc(fn ($mh) => $mh->latestMigration->ingoing_date ?? $mh->recipient_date)
|
||
->values();
|
||
}
|
||
}
|