getOutcomePatients($branchId, $startDate, $endDate, $outcomeType, $countOnly, $onlyIds); } // Обрабатываем обычные типы $method = 'get' . ucfirst($type) . 'Patients'; if (method_exists($this, $method)) { return $this->$method($isHeadOrAdmin, $branchId, $startDate, $endDate, $countOnly, $onlyIds); } throw new \InvalidArgumentException("Unknown patient type: {$type}"); } public function getPlanPatients( ?bool $isHeadOrAdmin, ?int $branchId, ?string $startDate, ?string $endDate, bool $countOnly, bool $onlyIds ): Collection|int|array { return $this->getAdmissionPatients('plan', $isHeadOrAdmin, $branchId, $startDate, $endDate, $countOnly, $onlyIds); } public function getEmergencyPatients( ?bool $isHeadOrAdmin, ?int $branchId, ?string $startDate, ?string $endDate, bool $countOnly, bool $onlyIds ): Collection|int|array { return $this->getAdmissionPatients('emergency', $isHeadOrAdmin, $branchId, $startDate, $endDate, $countOnly, $onlyIds); } private function getAdmissionPatients( string $admissionType, ?bool $isHeadOrAdmin, ?int $branchId, ?string $startDate, ?string $endDate, bool $countOnly, bool $onlyIds ): Collection|int|array { $query = $this->getBasePatientsQuery($isHeadOrAdmin, $branchId, $startDate, $endDate); if ($admissionType === 'plan') { $query->plan(); } else { $query->emergency(); } return $this->executeQuery($query, $countOnly, $onlyIds); } private function getBasePatientsQuery( ?bool $isHeadOrAdmin, ?int $branchId, ?string $startDate, ?string $endDate ) { $migrationPatient = new MisMigrationPatient(); if ($isHeadOrAdmin) { $medicalHistoryIds = $migrationPatient->newQuery() ->whereInDepartment($branchId) ->whereBetween('DateIngoing', [$startDate, $endDate]) ->pluck('rf_MedicalHistoryID') ->toArray(); } else { $medicalHistoryIds = $migrationPatient->newQuery() ->currentlyInTreatment($branchId) ->whereBetween('DateIngoing', [$startDate, $endDate]) ->pluck('rf_MedicalHistoryID') ->toArray(); } if (empty($medicalHistoryIds)) { return MisMedicalHistory::whereRaw('1=0'); // Пустой запрос } return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds) ->with(['surgicalOperations' => function ($query) use ($startDate, $endDate) { $query->whereBetween('Date', [$startDate, $endDate]); }]) ->orderBy('DateRecipient', 'DESC'); } private function executeQuery($query, bool $countOnly, bool $onlyIds): Collection|int|array { if ($onlyIds) { return $query->pluck('MedicalHistoryID')->toArray(); } if ($countOnly) { return $query->count(); } return $query->get(); } public function getObservationPatients(int $departmentId): Collection { return ObservationPatient::where('rf_department_id', $departmentId) ->with(['medicalHistory']) ->get() ->map(function ($observation) { $patient = $observation->medicalHistory; $patient->observation_comment = $observation->comment; return $patient; }); } public function getOutcomePatients(int $branchId, string $startDate, string $endDate, string $outcomeType, $countOnly = false, $onlyIds = false): Collection|int { return match($outcomeType) { 'discharged' => $this->getDischargedOutcomePatients($branchId, $startDate, $endDate, $countOnly, $onlyIds), 'transferred' => $this->getTransferredOutcomePatients($branchId, $startDate, $endDate, $countOnly, $onlyIds), 'deceased' => $this->getDeceasedOutcomePatients($branchId, $startDate, $endDate, $countOnly, $onlyIds), default => throw new \InvalidArgumentException("Неизвестный тип исхода: {$outcomeType}") }; } /** * Получить всех выбывших пациентов */ public function getAllOutcomePatients( int $branchId, string $startDate, string $endDate, bool $countOnly = false ): Collection|int { $migrationPatient = new MisMigrationPatient(); // Получаем миграции выбывших пациентов за период $migrations = $migrationPatient->newQuery() ->outcomePatients($branchId, $startDate, $endDate) ->select('rf_MedicalHistoryID', 'rf_kl_VisitResultID', 'DateOut') ->get() ->groupBy('rf_MedicalHistoryID'); if ($migrations->isEmpty()) { return $countOnly ? 0 : collect(); } $medicalHistoryIds = $migrations->keys()->toArray(); $query = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds) ->with(['surgicalOperations']) ->orderBy('DateRecipient', 'DESC'); if ($countOnly) { return $query->count(); } $patients = $query->get(); return $this->addOutcomeInfoToPatients($patients, $migrations); } /** * Получить миграции выбывших пациентов */ private function getOutcomeMigrations(int $branchId, string $startDate, string $endDate): Collection { $migrationPatient = new MisMigrationPatient(); return $migrationPatient->newQuery() ->outcomePatients($branchId, $startDate, $endDate) ->select('rf_MedicalHistoryID', 'rf_kl_VisitResultID', 'DateOut') ->get() ->groupBy('rf_MedicalHistoryID'); } /** * Добавить информацию о выбытии к пациентам */ private function addOutcomeInfoToPatients(Collection $patients, Collection $migrations): Collection { return $patients->map(function ($patient) use ($migrations) { $patientMigrations = $migrations->get($patient->MedicalHistoryID, collect()); if ($patientMigrations->isNotEmpty()) { $latestMigration = $patientMigrations->sortByDesc('DateOut')->first(); $patient->outcome_type = $this->getOutcomeTypeName($latestMigration->rf_kl_VisitResultID); $patient->outcome_date = $latestMigration->DateOut; $patient->visit_result_id = $latestMigration->rf_kl_VisitResultID; } return $patient; }); } /** * Получить понятное название типа выбытия */ 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 . ')' }; } /** * Получить выписанных пациентов */ public function getDischargedOutcomePatients( int $branchId, string $startDate, string $endDate, bool $countOnly = false, bool $onlyIds = false ): Collection|array|int { return $this->getSpecificOutcomePatients('discharged', $branchId, $startDate, $endDate, $onlyIds, $countOnly); } /** * Получить переведенных пациентов */ public function getTransferredOutcomePatients( int $branchId, string $startDate, string $endDate, bool $countOnly = false, bool $onlyIds = false ): Collection|array|int { return $this->getSpecificOutcomePatients('transferred', $branchId, $startDate, $endDate, $onlyIds, $countOnly); } /** * Получить умерших пациентов */ public function getDeceasedOutcomePatients( int $branchId, string $startDate, string $endDate, bool $countOnly = false, bool $onlyIds = false ): Collection|int|array { return $this->getSpecificOutcomePatients('deceased', $branchId, $startDate, $endDate, $onlyIds, $countOnly); } /** * Общий метод для получения пациентов с определенным типом выбытия */ private function getSpecificOutcomePatients( string $type, int $branchId, string $startDate, string $endDate, bool $onlyIds = false, bool $countOnly = false ): Collection|int|array { $migrationPatient = new MisMigrationPatient(); switch ($type) { case 'discharged': $query = $migrationPatient->newQuery()->discharged($branchId, $startDate, $endDate); break; case 'transferred': $query = $migrationPatient->newQuery()->transferred($branchId, $startDate, $endDate); break; case 'deceased': $query = $migrationPatient->newQuery()->deceasedOutcome($branchId, $startDate, $endDate); break; default: throw new \InvalidArgumentException("Неизвестный тип выбытия: {$type}"); } $medicalHistoryIds = $query->pluck('rf_MedicalHistoryID')->unique()->toArray(); if (empty($medicalHistoryIds)) { if ($countOnly) return 0; if ($onlyIds) return []; return collect(); } if ($onlyIds) { return $medicalHistoryIds; } $patients = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds) ->with(['surgicalOperations']) ->orderBy('DateRecipient', 'DESC'); if ($countOnly) { return $patients->count(); } return $patients->get(); } /** * Получить пациентов, находящихся на лечении */ public function getCurrentPatients( int $branchId, bool $countOnly = false, bool $onlyIds = false ): Collection|int|array { $migrationPatient = new MisMigrationPatient(); $medicalHistoryIds = $migrationPatient->newQuery() ->currentlyInTreatment($branchId) ->pluck('rf_MedicalHistoryID') ->unique() ->toArray(); if (empty($medicalHistoryIds)) { if ($countOnly) return 0; if ($onlyIds) return []; return collect(); } if ($onlyIds) { return $medicalHistoryIds; } $query = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds) ->currentlyHospitalized() ->with(['surgicalOperations']) ->orderBy('DateRecipient', 'DESC'); if ($countOnly) { return $query->count(); } return $query->get(); } /** * Получить пациентов с операциями */ public function getSurgicalPatients( string $status, bool $isHeadOrAdmin, int $branchId, string $startDate, string $endDate, bool $countOnly = false ): Collection|int { $query = MisSurgicalOperation::where('rf_StationarBranchID', $branchId) ->whereBetween('Date', [$startDate, $endDate]) ->orderBy('Date', 'DESC'); if ($status === 'plan') { $query->where('rf_TypeSurgOperationInTimeID', 6); } else { $query->whereIn('rf_TypeSurgOperationInTimeID', [4, 5]); } if ($countOnly) { return $query->count(); } return $query->get(); } /** * Получить пациентов (плановых или экстренных), которые были в отделении в течение периода */ public function getPatientsInDepartmentDuringPeriod( ?string $patientType, // 'plan', 'emergency', null (все) ?bool $isHeadOrAdmin, ?int $branchId, ?string $startDate, ?string $endDate, bool $countOnly = false, bool $onlyIds = false, bool $today = false ): Collection|int|array { // Используем скоуп inDepartment из модели MisMedicalHistory $query = MisMedicalHistory::query() ->whereHas('migrations', function ($q) use ($branchId, $startDate, $endDate) { $q->where('rf_StationarBranchID', $branchId) ->where('rf_MedicalHistoryID', '<>', 0) ->where(function ($subQ) use ($startDate, $endDate) { // Пациент находился в отделении в течение периода // 1. Поступил в течение периода $subQ->whereBetween('DateIngoing', [$startDate, $endDate]) // 2. Или выбыл в течение периода ->orWhereBetween('DateOut', [$startDate, $endDate]) // 3. Или находился в отделении в течение всего периода ->orWhere(function ($innerQ) use ($startDate, $endDate) { $innerQ->where('DateIngoing', '<=', $startDate) ->where(function ($deepQ) use ($endDate) { $deepQ->where('DateOut', '>=', $endDate) ->orWhereNull('DateOut') ->orWhere('DateOut', '1900-01-01'); }); }); }); }) ->with(['surgicalOperations' => function ($query) use ($startDate, $endDate) { $query->whereBetween('Date', [$startDate, $endDate]); }]) ->orderBy('DateRecipient', 'DESC'); // Фильтруем по типу (план/экстренность) if ($patientType === 'plan') { $query->plan(); } elseif ($patientType === 'emergency') { $query->emergency(); } // Для врача добавляем условие "все еще в отделении" if (!$isHeadOrAdmin && !$today) { $query->currentlyHospitalized(); } if ($onlyIds) { return $query->select('MedicalHistoryID') ->pluck('MedicalHistoryID')->values(); } if ($countOnly) { return $query->count(); } return $query->get(); } }