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(); } }