$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, bool $onlyIds = false, bool $markRecipients = false, ?array $recipientReportIds = null ): Collection { $snapshots = MedicalHistorySnapshot::query() ->whereIn('rf_report_id', $reportIds) ->where('patient_type', $type) ->get() ->unique(fn (MedicalHistorySnapshot $snapshot) => $this->snapshotIdentity($snapshot)) ->values(); if ($snapshots->isEmpty()) { return collect(); } $recipientIds = []; if ($markRecipients) { $recipientReportIds ??= $reportIds; $recipientIds = MedicalHistorySnapshot::query() ->whereIn('rf_report_id', $recipientReportIds) ->where('patient_type', 'recipient') ->get() ->map(fn (MedicalHistorySnapshot $snapshot) => UnifiedPatientData::fromSnapshot($snapshot)->id) ->unique() ->values() ->all(); } $operationsByHistoryId = $this->getOperationsByMedicalHistoryId($snapshots); $operationsByDepartmentPatientId = $this->getOperationsByDepartmentPatientId($snapshots); $patients = $snapshots->map(function (MedicalHistorySnapshot $snapshot) use ($recipientIds, $operationsByHistoryId, $operationsByDepartmentPatientId) { $patientId = $snapshot->rf_department_patient_id ? "manual:{$snapshot->rf_department_patient_id}" : ($snapshot->patient_uid ?: "mis:{$snapshot->rf_medicalhistory_id}"); $misOperations = $snapshot->rf_medicalhistory_id ? ($operationsByHistoryId[$snapshot->rf_medicalhistory_id] ?? []) : []; $manualOperations = $snapshot->rf_department_patient_id ? ($operationsByDepartmentPatientId[$snapshot->rf_department_patient_id] ?? []) : []; $operations = collect($misOperations) ->merge($manualOperations) ->unique(fn (array $operation) => ($operation['code'] ?? '').'|'.($operation['name'] ?? '')) ->values() ->all(); return UnifiedPatientData::fromSnapshot( $snapshot, in_array($patientId, $recipientIds, true), $operations ); })->sortByDesc(fn (UnifiedPatientData $patient) => $patient->admittedAt ?? '')->values(); return $onlyIds ? $patients->pluck('id') : $patients; } public function getPatientsFromOneDayCurrentSnapshots( string $type, array $reportIds, bool $onlyIds = false, ?array $recipientReportIds = null ): Collection { $snapshots = MedicalHistorySnapshot::query() ->whereIn('rf_report_id', $reportIds) ->where('patient_type', 'current') ->get(); if ($snapshots->isEmpty()) { return $this->getPatientsFromSnapshots( $type, $reportIds, $onlyIds, true, $recipientReportIds ); } $recipientReportIds ??= $reportIds; $recipientIds = MedicalHistorySnapshot::query() ->whereIn('rf_report_id', $recipientReportIds) ->where('patient_type', 'recipient') ->get() ->map(fn (MedicalHistorySnapshot $snapshot) => UnifiedPatientData::fromSnapshot($snapshot)->id) ->unique() ->values() ->all(); $operationsByHistoryId = $this->getOperationsByMedicalHistoryId($snapshots); $operationsByDepartmentPatientId = $this->getOperationsByDepartmentPatientId($snapshots); $patients = $snapshots ->filter(fn (MedicalHistorySnapshot $snapshot) => $snapshot->patient_kind === $type) ->unique(fn (MedicalHistorySnapshot $snapshot) => $this->snapshotIdentity($snapshot)) ->map(function (MedicalHistorySnapshot $snapshot) use ($recipientIds, $operationsByHistoryId, $operationsByDepartmentPatientId) { $misOperations = $snapshot->rf_medicalhistory_id ? ($operationsByHistoryId[$snapshot->rf_medicalhistory_id] ?? []) : []; $manualOperations = $snapshot->rf_department_patient_id ? ($operationsByDepartmentPatientId[$snapshot->rf_department_patient_id] ?? []) : []; $operations = collect($misOperations) ->merge($manualOperations) ->unique(fn (array $operation) => ($operation['code'] ?? '').'|'.($operation['name'] ?? '')) ->values() ->all(); $patient = UnifiedPatientData::fromSnapshot( $snapshot, false, $operations ); $patient->isRecipientToday = in_array($patient->id, $recipientIds, true); return $patient; }) ->sortByDesc(fn (UnifiedPatientData $patient) => $patient->admittedAt ?? '') ->values(); return $onlyIds ? $patients->pluck('id') : $patients; } 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->get() ->map(fn (MedicalHistorySnapshot $snapshot) => $this->snapshotIdentity($snapshot)) ->unique() ->count(); } private function snapshotIdentity(MedicalHistorySnapshot $snapshot): string { return $snapshot->patient_uid ?: ($snapshot->rf_medicalhistory_id ? "mis:{$snapshot->rf_medicalhistory_id}" : "snapshot:{$snapshot->medical_history_snapshot_id}"); } private function getOperationsByMedicalHistoryId(Collection $snapshots): array { $historyIds = $snapshots->pluck('rf_medicalhistory_id')->filter()->unique()->values(); if ($historyIds->isEmpty()) { return []; } return MedicalHistory::query() ->whereIn('id', $historyIds) ->with(['operations']) ->get() ->mapWithKeys(function (MedicalHistory $history) { return [ $history->original_id => $history->operations->map(fn ($operation) => [ 'code' => $operation->service_medical_code ?? null, 'name' => $operation->service_medical_name ?? null, ])->values()->all(), ]; }) ->all(); } private function getOperationsByDepartmentPatientId(Collection $snapshots): array { $departmentPatientIds = $snapshots->pluck('rf_department_patient_id')->filter()->unique()->values(); if ($departmentPatientIds->isEmpty()) { return []; } return DepartmentPatientOperation::query() ->whereIn('rf_department_patient_id', $departmentPatientIds) ->with('serviceMedical') ->get() ->groupBy('rf_department_patient_id') ->map(fn (Collection $operations) => $operations->map(fn (DepartmentPatientOperation $operation) => [ 'code' => $operation->serviceMedical?->ServiceMedicalCode ?? $operation->service_code, 'name' => $operation->serviceMedical?->ServiceMedicalName ?? $operation->service_name, ])->values()->all()) ->all(); } }