getBranchId($user->department->rf_mis_department_id); [$startDate, $endDate] = $this->parseDates($dates); $dateRange = $this->dateRangeService->getNormalizedDateRange($user, $startDate, $endDate); $isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin(); // Массив для хранения подсчитанных метрик $metrics = []; // 1. Плановые пациенты $planIds = $this->patientService->getPlanOrEmergencyPatients( 'plan', $isHeadOrAdmin, $branchId, $dateRange, false, true, true, $fillableAuto ); $this->createSnapshotsForType($report, 'plan', $planIds); $metrics[4] = $this->patientService->getPlanOrEmergencyPatients( 'plan', $isHeadOrAdmin, $branchId, $dateRange, true, $fillableAuto ); // metrika_item_3 - плановые // 2. Экстренные пациенты $emergencyIds = $this->patientService->getPlanOrEmergencyPatients( 'emergency', $isHeadOrAdmin, $branchId, $dateRange, false, true, true, $fillableAuto ); $this->createSnapshotsForType($report, 'emergency', $emergencyIds); $metrics[12] = $this->patientService->getPlanOrEmergencyPatients( 'emergency', $isHeadOrAdmin, $branchId, $dateRange, true, $fillableAuto );; // metrika_item_12 - экстренные // 3. Выписанные $dischargedIds = $this->patientService->getOutcomePatients( $branchId, $dateRange, 'discharged', true ); $this->createSnapshotsForType($report, 'discharged', $dischargedIds); $metrics[15] = count($dischargedIds); // metrika_item_15 - выписанные // 4. Переведенные $transferredIds = $this->patientService->getOutcomePatients( $branchId, $dateRange, 'transferred', true ); $this->createSnapshotsForType($report, 'transferred', $transferredIds); $metrics[13] = count($transferredIds); // metrika_item_13 - переведенные // 5. Умершие $deceasedIds = $this->patientService->getOutcomePatients( $branchId, $dateRange, 'deceased', true ); $this->createSnapshotsForType($report, 'deceased', $deceasedIds); // $metrics[9] = count($deceasedIds); // metrika_item_9 - умершие // 6. Поступившие (все новые поступления - плановые + экстренные) $recipientIds = $this->patientService->getPlanOrEmergencyPatients( null, $isHeadOrAdmin, $branchId, $dateRange, false, true, false // только поступившие сегодня ); $this->createSnapshotsForType($report, 'recipient', $recipientIds); // $metrics[3] = count($recipientIds); // metrika_item_3 - поступившие // 8. Плановые операции $planSurgeryCount = $this->patientService->getSurgicalPatients( 'plan', $branchId, $dateRange, true ); // $metrics[11] = $planSurgeryCount; // metrika_item_11 - плановые операции // 9. Экстренные операции $emergencySurgeryCount = $this->patientService->getSurgicalPatients( 'emergency', $branchId, $dateRange, true ); // $metrics[10] = $emergencySurgeryCount; // metrika_item_10 - экстренные операции // Сохраняем все метрики $this->saveMetrics($report, $metrics); } /** * Сохранить метрики в базу */ private function saveMetrics(Report $report, array $metrics): void { foreach ($metrics as $metrikaItemId => $value) { MetrikaResult::updateOrCreate( [ 'rf_report_id' => $report->report_id, 'rf_metrika_item_id' => $metrikaItemId, ], [ 'value' => $value, ] ); } } /** * Получить статистику из снапшотов */ public function getStatisticsFromSnapshots(array $reportIds): array { return [ 'plan' => $this->getCountFromSnapshots('plan', $reportIds), 'emergency' => $this->getCountFromSnapshots('emergency', $reportIds), 'outcome' => $this->getCountFromSnapshots('outcome', $reportIds), 'deceased' => $this->getCountFromSnapshots('deceased', $reportIds), 'discharged' => $this->getCountFromSnapshots('discharged', $reportIds), 'transferred' => $this->getCountFromSnapshots('transferred', $reportIds), 'recipient' => $this->getCountFromSnapshots('recipient', $reportIds), ]; } /** * Получить пациентов из снапшотов по типу */ public function getPatientsFromSnapshots( string $type, array $reportIds, ?int $branchId = null, bool $onlyIds = false ): Collection { // Для плановых и экстренных включаем уже лечащихся // $includeCurrent = in_array($type, ['plan', 'emergency']); $medicalHistoryIds = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds) ->where('patient_type', $type) ->pluck('rf_medicalhistory_id') ->unique() ->toArray(); if (empty($medicalHistoryIds)) { return collect(); } if ($onlyIds) { return collect($medicalHistoryIds); } return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds) ->when($type === 'plan', fn($q) => $q->plan()) ->when($type === 'emergency', fn($q) => $q->emergency()) ->orderBy('DateRecipient', 'DESC') ->get(); } /** * Получить количество пациентов из снапшотов */ private function getCountFromSnapshots(string $type, array $reportIds): int { $query = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds); if ($type === 'outcome') { $query->whereIn('patient_type', ['discharged', 'deceased']); } else { $query->where('patient_type', $type); } return $query->distinct('rf_medicalhistory_id') ->count('rf_medicalhistory_id'); } /** * Создать снапшоты для определенного типа пациентов */ private function createSnapshotsForType(Report $report, string $type, Collection $medicalHistoryIds): void { foreach ($medicalHistoryIds as $id) { MedicalHistorySnapshot::updateOrCreate( [ 'rf_report_id' => $report->report_id, 'rf_medicalhistory_id' => $id, 'patient_type' => $type ], [ 'rf_report_id' => $report->report_id, 'rf_medicalhistory_id' => $id, 'patient_type' => $type, ] ); } } /** * Получить ID отделения */ private function getBranchId(int $misDepartmentId): ?int { return MisStationarBranch::where('rf_DepartmentID', $misDepartmentId) ->value('StationarBranchID'); } /** * Разобрать даты */ private function parseDates(array $dates): array { return [ Carbon::createFromTimestampMs($dates[0])->setTimezone('Asia/Yakutsk'), Carbon::createFromTimestampMs($dates[1])->setTimezone('Asia/Yakutsk'), ]; } }