startDate->copy()->startOfYear()->format('Y-m-d'); $periodMigrationFilter = function ($q) use ($departmentId, $dateRange, $startYear) { $q->where('department_id', $departmentId) ->where('ingoing_date', '<=', $dateRange->endSql()) ->where(function ($sub) use ($dateRange, $startYear) { $sub->whereNull('out_date') ->where('ingoing_date', '>', $startYear); $sub->orWhere(function ($sub2) use ($dateRange, $startYear) { $sub2->whereNotNull('out_date') ->where('out_date', '>', $dateRange->startSql()) ->where('out_date', '>', $startYear); }); }); }; $departmentMigrationFilter = function ($q) use ($departmentId) { $q->where('department_id', $departmentId) ->orderByDesc('ingoing_date'); }; // 1. Один запрос: получаем "сырые" данные (без вычисляемых статусов) $all = ReportNursePatient::query() ->when($reportIds, function ($query, $reportIds) { return $query->whereIn('report_nurse_id', $reportIds); }) ->whereHas('migrations', $periodMigrationFilter) ->with([ 'latestMigration' => $periodMigrationFilter, 'migrations' => $departmentMigrationFilter, 'operations' => function ($q) use ($departmentId, $dateRange) { $q->where('department_id', $departmentId) ->where('start_date', '>=', $dateRange->startSql()) ->where('start_date', '<', $dateRange->endSql()) // Только операции пока пациент реально лежал в отделении ->whereExists(function ($sub) use ($departmentId) { $sub->select(\DB::raw(1)) ->from('mv_migrationpatient_details') ->where('department_id', $departmentId) ->whereColumn('medical_history_id', 'mv_surgical_operations.medical_history_id') ->whereColumn('ingoing_date', '<=', 'mv_surgical_operations.start_date') ->where(function ($q2) { $q2->whereNull('out_date') ->orWhereColumn('out_date', '>=', 'mv_surgical_operations.start_date'); }); }); } ]) ->selectRaw('DISTINCT ON (original_id) report_nurse_patients.*') ->orderBy('original_id') ->orderBy('report_nurse_id', 'desc') ->get(); // 2. Добавляем вычисляемые поля и превращаем в плоский массив $prepared = $all->map(function (ReportNursePatient $h) use ($dateRange) { $patientStatus = PatientStatusClassifier::classify($h, $dateRange); $patientUrgency = null; $patientReanimation = 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, 'in_reanimation' => $patientReanimation, 'admitted_today' => PatientStatusClassifier::classifyAdmitted($h->latestMigration?->ingoing_date, $dateRange), ]; }); // 3. Сортировка $sortBy = 'recipient_date'; $sortOrder = 'desc'; $sorted = $prepared->sortBy($sortBy, SORT_REGULAR, $sortOrder === 'desc')->values(); // 4. Возвращаем плоский массив + метаданные для фронтенда $countInDepartment = $sorted->where('patient_status', 'in_department')->count(); $countRecipient = $sorted->where('patient_status', 'recipient')->count(); $countDischarged = $sorted->where('patient_status', 'discharged')->count(); $countDeceased = $sorted->where('patient_status', 'deceased')->count(); $countUrgent = $sorted->where('patient_urgency', 'urgent')->count(); $countPlanned = $sorted->where('patient_urgency', 'planned')->count(); $countReanimations = $sorted->where('in_reanimation', true)->count(); // 4. Возвращаем плоский массив + метаданные для фронтенда return [ 'data' => $sorted->toArray(), 'meta' => [ 'total' => $sorted->count(), 'sortBy' => $sortBy, 'sortOrder' => $sortOrder, 'counts' => [ 'in_department' => $countInDepartment + $countRecipient, 'recipient' => $countRecipient, 'discharged' => $countDischarged + $countDeceased, 'deceased' => $countDeceased, 'urgent' => $countUrgent, 'planned' => $countPlanned, 'reanimations' => $countReanimations, ] ] ]; } public function getHistories(DateRange $dateRange, int $departmentId) { $query = ReportNursePatient::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 = ReportNursePatient::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 ReportNursePatient::query() ->whereHas('migrations', function ($q) use ($departmentId, $dateRange) { $q->department($departmentId)->current($dateRange); }) ->with(['latestMigration' => function ($q) use ($departmentId, $dateRange) { $q->department($departmentId)->current($dateRange); // подгружаем только отфильтрованные движения }]) ->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 ReportNursePatient::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); }]) ->get(); } public function getDischargedHistories(DateRange $dateRange, int $departmentId) { return ReportNursePatient::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); }]) ->get(); } public function getDeceasedHistories(DateRange $dateRange, int $departmentId) { return ReportNursePatient::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); }]) ->get(); } public function getTransferredHistories(DateRange $dateRange, int $departmentId) { return ReportNursePatient::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); }]) ->get(); } }