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 = $this->getHistoricalCurrentMedicalHistoryIds($branchId, $dateRange); } 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) ->select([ 'MedicalHistoryID', 'FAMILY', 'Name', 'OT', 'BD', 'DateRecipient', 'DateExtract', 'rf_EmerSignID', 'rf_kl_VisitResultID', ]) ->with([ 'surgicalOperations' => function ($q) { $q->select([ 'SurgicalOperationID', 'rf_MedicalHistoryID', 'rf_kl_ServiceMedicalID', 'Date', ])->with(['serviceMedical' => function ($serviceQuery) { $serviceQuery->select([ 'ServiceMedicalID', 'ServiceMedicalCode', 'ServiceMedicalName', ]); }]); }, 'outcomeMigration' => function ($q) { $q->select([ 'MigrationPatientID', 'rf_MedicalHistoryID', 'DateOut', 'rf_DiagnosID', ])->with(['mainDiagnosis' => function ($diagnosisQuery) { $diagnosisQuery->select([ 'DiagnosID', 'rf_MKBID', ])->with(['mkb' => function ($mkbQuery) { $mkbQuery->select([ 'MKBID', 'DS', 'NAME', ]); }]); }]); }, 'migrations' => function ($q) use ($branchId) { $q->where('rf_StationarBranchID', $branchId) ->select([ 'MigrationPatientID', 'rf_MedicalHistoryID', 'rf_DiagnosID', 'DateIngoing', 'rf_StationarBranchID', ]) ->orderByDesc('DateIngoing') ->with(['mainDiagnosis' => function ($diagnosisQuery) { $diagnosisQuery->select([ 'DiagnosID', 'rf_MKBID', 'rf_MigrationPatientID', ])->with(['mkb' => function ($mkbQuery) { $mkbQuery->select([ 'MKBID', 'DS', 'NAME', ]); }]); }]); }, ]) ->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) { // Добавляем флаг "поступил сегодня" $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, bool $fillableAuto = false ) { // Поступившие сегодня $recipientIds = $this->buildRecipientQuery(null, $isHeadOrAdmin, $branchId, $dateRange, $fillableAuto) ->pluck('rf_MedicalHistoryID') ->toArray(); // Уже находящиеся на лечении if ($fillableAuto) { $currentIds = $this->getHistoricalCurrentMedicalHistoryIds($branchId, $dateRange); } else { $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) ->select([ 'MedicalHistoryID', 'FAMILY', 'Name', 'OT', 'BD', 'DateRecipient', 'DateExtract', 'rf_EmerSignID', 'rf_kl_VisitResultID', ]) ->with([ 'surgicalOperations' => function ($q) { $q->select([ 'SurgicalOperationID', 'rf_MedicalHistoryID', 'rf_kl_ServiceMedicalID', 'Date', ])->with(['serviceMedical' => function ($serviceQuery) { $serviceQuery->select([ 'ServiceMedicalID', 'ServiceMedicalCode', 'ServiceMedicalName', ]); }]); }, 'outcomeMigration' => function ($q) { $q->select([ 'MigrationPatientID', 'rf_MedicalHistoryID', 'DateOut', 'rf_DiagnosID', ])->with(['mainDiagnosis' => function ($diagnosisQuery) { $diagnosisQuery->select([ 'DiagnosID', 'rf_MKBID', ])->with(['mkb' => function ($mkbQuery) { $mkbQuery->select([ 'MKBID', 'DS', 'NAME', ]); }]); }]); }, 'migrations' => function ($q) use ($branchId) { $q->where('rf_StationarBranchID', $branchId) ->select([ 'MigrationPatientID', 'rf_MedicalHistoryID', 'rf_DiagnosID', 'DateIngoing', 'rf_StationarBranchID', ]) ->orderByDesc('DateIngoing') ->with(['mainDiagnosis' => function ($diagnosisQuery) { $diagnosisQuery->select([ 'DiagnosID', 'rf_MKBID', 'rf_MigrationPatientID', ])->with(['mkb' => function ($mkbQuery) { $mkbQuery->select([ 'MKBID', 'DS', 'NAME', ]); }]); }]); }, ]) ->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 { // Загрузка отношений, необходимых для FormattedPatientResource $query->with([ 'outcomeMigration.mainDiagnosis.mkb', // mkb через диагноз ]); $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 ) { $query = MisMedicalHistory::query() ->where('MedicalHistoryID', '<>', 0) ->whereHas('migrations', function ($migrationQuery) use ($branchId, $outcomeType) { $migrationQuery->where('rf_StationarBranchID', $branchId); if ($outcomeType === 'deceased') { $migrationQuery->whereIn('rf_kl_VisitResultID', [5, 6, 15, 16]); } elseif ($outcomeType === 'transferred') { $migrationQuery->whereIn('rf_kl_VisitResultID', [4, 14]); } elseif ($outcomeType === 'discharged') { $migrationQuery->whereIn('rf_kl_VisitResultID', [1, 11, 2, 12, 7, 18, 48]); } elseif ($outcomeType === 'without-transferred') { $migrationQuery->whereNotIn('rf_kl_VisitResultID', [4, 14]) ->where('rf_kl_VisitResultID', '<>', 0); } }); if ($dateRange->isOneDay) { $query->where('DateExtract', '>', $dateRange->startSql()) ->where('DateExtract', '<=', $dateRange->endSql()); } else { $startAt = $dateRange->startSql(); $endDate = $dateRange->end()->toDateString(); $query->where('DateExtract', '>', $startAt) ->whereDate('DateExtract', '<=', $endDate); } if ($onlyIds) { return $query->pluck('MedicalHistoryID'); } return $query ->select([ 'MedicalHistoryID', 'FAMILY', 'Name', 'OT', 'BD', 'DateRecipient', 'DateExtract', 'rf_EmerSignID', 'rf_kl_VisitResultID', ]) ->with([ 'outcomeMigration' => function ($q) { $q->select([ 'MigrationPatientID', 'rf_MedicalHistoryID', 'DateOut', 'rf_DiagnosID', ])->with(['mainDiagnosis' => function ($diagnosisQuery) { $diagnosisQuery->select([ 'DiagnosID', 'rf_MKBID', ])->with(['mkb' => function ($mkbQuery) { $mkbQuery->select([ 'MKBID', 'DS', 'NAME', ]); }]); }]); }, ]) ->orderBy('DateRecipient', 'DESC') ->get() ->map(fn ($patient) => $this->addOutcomeInfo($patient)); } /** * Получить пациентов, находящихся в реанимации на конец периода */ public function getReanimationPatients( int $branchId, DateRange $dateRange, bool $onlyIds = false ) { $medicalHistoryIds = MisReanimation::query() ->join('stt_migrationpatient as mp', 'mp.MigrationPatientID', '=', 'stt_reanimation.rf_MigrationPatientID') ->where('stt_reanimation.rf_StationarBranchID', $branchId) ->where('mp.rf_StationarBranchID', $branchId) ->where('mp.rf_MedicalHistoryID', '<>', 0) ->where('stt_reanimation.DateIn', '<=', $dateRange->endSql()) ->where(function ($query) use ($dateRange) { $query->where('stt_reanimation.DateOut', '>=', $dateRange->endSql()) ->orWhereNull('stt_reanimation.DateOut') ->orWhereDate('stt_reanimation.DateOut', '1900-01-01') ->orWhereDate('stt_reanimation.DateOut', '2222-01-01'); }) ->distinct() ->pluck('mp.rf_MedicalHistoryID') ->toArray(); if (empty($medicalHistoryIds)) { return collect(); } if ($onlyIds) { return collect($medicalHistoryIds); } return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds) ->select([ 'MedicalHistoryID', 'FAMILY', 'Name', 'OT', 'BD', 'DateRecipient', 'DateExtract', 'rf_EmerSignID', 'rf_kl_VisitResultID', ]) ->with([ 'surgicalOperations' => function ($q) { $q->select([ 'SurgicalOperationID', 'rf_MedicalHistoryID', 'rf_kl_ServiceMedicalID', 'Date', ])->with(['serviceMedical' => function ($serviceQuery) { $serviceQuery->select([ 'ServiceMedicalID', 'ServiceMedicalCode', 'ServiceMedicalName', ]); }]); }, 'outcomeMigration' => function ($q) { $q->select([ 'MigrationPatientID', 'rf_MedicalHistoryID', 'DateOut', 'rf_DiagnosID', ])->with(['mainDiagnosis' => function ($diagnosisQuery) { $diagnosisQuery->select([ 'DiagnosID', 'rf_MKBID', ])->with(['mkb' => function ($mkbQuery) { $mkbQuery->select([ 'MKBID', 'DS', 'NAME', ]); }]); }]); }, ]) ->orderBy('DateRecipient', 'DESC') ->get(); } /** * Получить пациентов с операциями */ public function getSurgicalPatients( string $type, int $branchId, DateRange $dateRange, bool $countOnly = false ) { $query = MisSurgicalOperation::where('rf_StationarBranchID', $branchId) ->completed() ->where('Date', '>=', $dateRange->startSql()) ->where('Date', '<=', $dateRange->endSql()); // ->whereBetween('Date', [$dateRange->startSql(), $dateRange->endSql()]); if ($type === 'plan') { $query->where('rf_TypeSurgOperationInTimeID', 6); } else { $query->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) ->where('DateIngoing', '>=', $dateRange->startSql()) ->where('DateIngoing', '<=', $dateRange->endSql()); // ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]); } else { $query = MisMigrationPatient::currentlyInTreatment($branchId) ->where('DateIngoing', '>=', $dateRange->startSql()) ->where('DateIngoing', '<=', $dateRange->endSql()); // ->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 ) { $startAt = $dateRange->start()->copy()->subDay()->format('Y-m-d H:i:s'); $endAt = $dateRange->end()->copy()->addDay()->format('Y-m-d H:i:s'); if ($dateRange->isOneDay) { $startAt = $dateRange->startSql(); $endAt = $dateRange->endSql(); } $query = DB::table('stt_medicalhistory as mh') ->selectRaw('mh."MedicalHistoryID" as "rf_MedicalHistoryID"') ->where('mh.MedicalHistoryID', '<>', 0); $query->whereExists(function ($subQuery) use ($branchId, $startAt, $endAt) { $subQuery->select(DB::raw(1)) ->from('stt_migrationpatient as mp') ->whereColumn('mp.rf_MedicalHistoryID', 'mh.MedicalHistoryID') ->where('mp.rf_StationarBranchID', $branchId) ->where('mp.DateIngoing', '>', $startAt) ->where('mp.DateIngoing', '<=', $endAt); }); if ($type === 'plan') { $query->where('mh.rf_EmerSignID', 1); } elseif ($type === 'emergency') { $query->whereIn('mh.rf_EmerSignID', [2, 4]); } return $query->distinct(); } private function getHistoricalCurrentMedicalHistoryIds(int $branchId, DateRange $dateRange): array { // Исторический срез по основной таблице миграций: // для каждой истории болезни берём последнюю миграцию в отделении // на момент конца периода и проверяем, что пациент числился в отделении. $latestRows = DB::table('stt_migrationpatient') ->select('rf_MedicalHistoryID', DB::raw('MAX("MigrationPatientID") as max_migration_patient_id')) ->where('rf_StationarBranchID', $branchId) ->where('rf_MedicalHistoryID', '<>', 0) ->where('DateIngoing', '<=', $dateRange->endSql()) ->groupBy('rf_MedicalHistoryID'); return DB::table('stt_migrationpatient as mp') ->joinSub($latestRows, 'latest', function ($join) { $join->on('mp.rf_MedicalHistoryID', '=', 'latest.rf_MedicalHistoryID') ->on('mp.MigrationPatientID', '=', 'latest.max_migration_patient_id'); }) ->join('stt_medicalhistory as mh', 'mh.MedicalHistoryID', '=', 'mp.rf_MedicalHistoryID') ->where('mp.rf_StationarBranchID', $branchId) ->where('mh.DateRecipient', '<=', $dateRange->endSql()) ->where('mp.DateOut', '>=', $dateRange->endSql()) ->where(function ($query) use ($dateRange) { $query->where('mh.DateExtract', '>', $dateRange->endSql()) ->orWhereDate('mh.DateExtract', '1900-01-01'); }) ->distinct() ->pluck('mp.rf_MedicalHistoryID') ->toArray(); } /** * Добавить информацию об исходе пациенту */ 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 { return $this->getPlanOrEmergencyPatients( $type, $isHeadOrAdmin, $branchId, $dateRange, true, false, true ); } /** * Получить название типа исхода */ 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 . ')' }; } }