buildRecipientQuery($type, $isHeadOrAdmin, $branchId, $dateRange, $fillableAuto); if ($fillableAuto) $recipientIds = $recipientQuery->distinct()->pluck('rf_MedicalHistoryID')->toArray(); else $recipientIds = $recipientQuery->pluck('rf_MedicalHistoryID')->toArray(); // Если нужно добавить уже находящихся в отделении if ($includeCurrent) { if ($fillableAuto) { $currentIds = LifeMisMigrationPatient::currentlyInTreatment($branchId, $dateRange) ->distinct() ->pluck('rf_MedicalHistoryID') ->toArray(); } else { $currentIds = MisMigrationPatient::currentlyInTreatment($branchId) ->pluck('rf_MedicalHistoryID') ->toArray(); } $medicalHistoryIds = array_unique(array_merge($recipientIds, $currentIds)); } else { $medicalHistoryIds = $recipientIds; } if (empty($medicalHistoryIds)) { if ($countOnly) return 0; if ($onlyIds) return collect(); return collect(); } // Получаем истории $query = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds) ->with([ 'surgicalOperations' => function ($q) use ($dateRange) { $q->whereBetween('Date', [$dateRange->startSql(), $dateRange->endSql()]); }, 'migrations' => function ($q) use ($branchId) { $q->where('rf_StationarBranchID', $branchId) ->take(1) // берем только одну последнюю ->with(['diagnosis' => function ($q) { $q->where('rf_DiagnosTypeID', 3) ->take(1) ->with('mkb'); }]); } ]) ->orderBy('DateRecipient', 'DESC'); // Фильтруем по типу (план/экстренные) if ($type === 'plan') { $query->plan(); } elseif ($type === 'emergency') { $query->emergency(); } if ($countOnly) { return $query->count(); } if ($onlyIds) { return $query->pluck('MedicalHistoryID'); } return $query->get()->map(function ($patient) use ($recipientIds, $branchId) { // Добавляем флаг "поступил сегодня" $patient->is_recipient_today = in_array($patient->MedicalHistoryID, $recipientIds); return $patient; }); } /** * Получить всех пациентов в отделении (поступившие сегодня + уже лечащиеся) */ public function getAllPatientsInDepartment( bool $isHeadOrAdmin, int $branchId, DateRange $dateRange, bool $countOnly = false, bool $onlyIds = false ) { // Поступившие сегодня $recipientIds = $this->buildRecipientQuery(null, $isHeadOrAdmin, $branchId, $dateRange) ->pluck('rf_MedicalHistoryID') ->toArray(); // Уже находящиеся на лечении $currentIds = MisMigrationPatient::currentlyInTreatment($branchId) ->pluck('rf_MedicalHistoryID') ->toArray(); // Объединяем и убираем дубли $allIds = array_unique(array_merge($recipientIds, $currentIds)); if (empty($allIds)) { if ($countOnly) return 0; return collect(); } if ($countOnly) { return count($allIds); } if ($onlyIds) { return collect($allIds); } return MisMedicalHistory::whereIn('MedicalHistoryID', $allIds) ->with(['surgicalOperations' => function ($q) use ($dateRange) { $q->whereBetween('Date', [$dateRange->startSql(), $dateRange->endSql()]); }]) ->orderBy('DateRecipient', 'DESC') ->get() ->map(function ($patient) use ($recipientIds) { $patient->is_recipient_today = in_array($patient->MedicalHistoryID, $recipientIds); return $patient; }); } /** * Получить пациентов под наблюдением */ public function getObservationPatients(int $departmentId, bool $onlyIds = false) { $query = MisMedicalHistory::whereHas('observationPatient', function ($q) use ($departmentId) { $q->where('rf_department_id', $departmentId); }); if (!$onlyIds) { $query->with(['observationPatient' => function ($query) use ($departmentId) { $query->where('rf_department_id', $departmentId) ->select(['rf_medicalhistory_id', 'observation_patient_id', 'comment']); }]) ->orderBy('DateRecipient', 'DESC'); } if ($onlyIds) $patients = $query->pluck('MedicalHistoryID'); else $patients = $query->get(); return $patients->map(function ($patient) { $patient->comment = $patient->observationPatient ->pluck('comment') ->filter() ->implode('; '); return $patient; }); } /** * Получить выбывших пациентов */ public function getOutcomePatients( int $branchId, DateRange $dateRange, string $outcomeType = 'all', bool $onlyIds = false ) { $methodMap = [ 'discharged' => 'outcomeDischarged', 'transferred' => 'outcomeTransferred', 'without-transferred' => 'outcomeWithoutTransferred', 'deceased' => 'deceasedOutcome', 'all' => 'outcomePatients', ]; $method = $methodMap[$outcomeType] ?? 'outcomePatients'; $medicalHistoryIds = MisMigrationPatient::{$method}($branchId, $dateRange) ->pluck('rf_MedicalHistoryID') ->unique() ->toArray(); if (empty($medicalHistoryIds)) { return collect(); } if ($onlyIds) return collect($medicalHistoryIds); return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds) ->with(['surgicalOperations']) ->orderBy('DateRecipient', 'DESC') ->get() ->map(function ($patient) { return $this->addOutcomeInfo($patient); }); } /** * Получить пациентов с операциями */ public function getSurgicalPatients( string $type, int $branchId, DateRange $dateRange, bool $countOnly = false ) { $query = MisMedicalHistory::whereHas('surgicalOperations', function ($q) use ($type, $branchId, $dateRange) { $q->where('rf_StationarBranchID', $branchId) ->whereBetween('Date', [$dateRange->startSql(), $dateRange->endSql()]); if ($type === 'plan') { $q->where('rf_TypeSurgOperationInTimeID', 6); } else { $q->whereIn('rf_TypeSurgOperationInTimeID', [4, 5]); } }); if ($countOnly) { return $query->count(); } return $query->get(); } /** * Получить текущих пациентов */ public function getCurrentPatients(int $branchId, bool $countOnly = false) { $medicalHistoryIds = MisMigrationPatient::currentlyInTreatment($branchId) ->pluck('rf_MedicalHistoryID') ->unique() ->toArray(); if (empty($medicalHistoryIds)) { return $countOnly ? 0 : collect(); } $query = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds) ->currentlyHospitalized() ->with(['surgicalOperations']) ->orderBy('DateRecipient', 'DESC'); if ($countOnly) { return $query->count(); } return $query->get(); } /** * Собрать базовый запрос для пациентов */ private function buildPatientQuery( ?string $type, bool $isHeadOrAdmin, int $branchId, DateRange $dateRange ) { if ($isHeadOrAdmin) { $query = MisMigrationPatient::whereInDepartment($branchId) ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]); } else { $query = MisMigrationPatient::currentlyInTreatment($branchId) ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]); } $medicalHistoryIds = $query->pluck('rf_MedicalHistoryID')->toArray(); if (empty($medicalHistoryIds)) { return MisMedicalHistory::whereRaw('1 = 0'); } $query = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds); if ($type === 'plan') { $query->plan(); } elseif ($type === 'emergency') { $query->emergency(); } if (!$isHeadOrAdmin && !in_array($type, ['discharged', 'transferred', 'deceased'])) { $query->currentlyHospitalized(); } return $query; } /** * Построить запрос для поступивших пациентов */ private function buildRecipientQuery( ?string $type, bool $isHeadOrAdmin, int $branchId, DateRange $dateRange, bool $fillableAuto = false ) { // Разная логика для заведующего и врача if ($isHeadOrAdmin) { // Заведующий: все поступившие за период if ($fillableAuto) { $query = LifeMisMigrationPatient::whereInDepartment($branchId) ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]); } else { $query = MisMigrationPatient::whereInDepartment($branchId) ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]); } } else { // Врач: только поступившие за сутки if ($fillableAuto) { $query = LifeMisMigrationPatient::whereInDepartment($branchId) ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]); } else { $query = MisMigrationPatient::whereInDepartment($branchId) ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]); }; } return $query; } /** * Добавить информацию об исходе пациенту */ private function addOutcomeInfo(MisMedicalHistory $patient) { $latestMigration = $patient->migrations ->whereNotNull('DateOut') ->where('DateOut', '<>', '1900-01-01') ->sortByDesc('DateOut') ->first(); if ($latestMigration) { $patient->outcome_type = $this->getOutcomeTypeName($latestMigration->rf_kl_VisitResultID); $patient->outcome_date = $latestMigration->DateOut; $patient->visit_result_id = $latestMigration->rf_kl_VisitResultID; } return $patient; } /** * Получить количество пациентов по типу с учетом уже находящихся в отделении */ public function getPatientsCountWithCurrent( ?string $type, bool $isHeadOrAdmin, int $branchId, DateRange $dateRange ): int { // Поступившие сегодня указанного типа $recipientCount = $this->buildRecipientQuery($type, $isHeadOrAdmin, $branchId, $dateRange) ->count(); // Если нужны плановые/экстренные среди уже лечащихся $currentCount = 0; if ($type === 'plan' || $type === 'emergency') { $currentIds = MisMigrationPatient::currentlyInTreatment($branchId) ->pluck('rf_MedicalHistoryID') ->toArray(); if (!empty($currentIds)) { $currentCount = MisMedicalHistory::whereIn('MedicalHistoryID', $currentIds) ->when($type === 'plan', fn($q) => $q->plan()) ->when($type === 'emergency', fn($q) => $q->emergency()) ->count(); } } return $currentCount; } /** * Получить название типа исхода */ private function getOutcomeTypeName(int $visitResultId): string { return match($visitResultId) { 1, 7, 8, 9, 10, 11, 48, 49, 124 => 'Выписка', 2, 3, 4, 12, 13, 14 => 'Перевод', 5, 6, 15, 16 => 'Умер', default => 'Другое (' . $visitResultId . ')' }; } }