saveBedDaysMetrics($report); $this->savePreoperativeMetrics($report); $this->saveDepartmentLoadMetric($report); } private function saveBedDaysMetrics(Report $report): void { $result = $this->bedDaysCalculator->calculate($this->buildStayIntervals($report)); $this->reportStorageService->saveMetric($report, MetrikaConfig::TOTAL_BED_DAYS, $result->total); $this->reportStorageService->saveMetric($report, MetrikaConfig::AVERAGE_BED_DAYS, $result->average); } private function savePreoperativeMetrics(Report $report): void { $result = $this->preoperativeDaysCalculator->calculate($this->buildOperationIntervals($report)); $this->reportStorageService->saveMetric($report, MetrikaConfig::TOTAL_PREOPERATIVE_DAYS, $result->total); $this->reportStorageService->saveMetric($report, MetrikaConfig::PREOPERATIVE_PATIENT_COUNT, $result->count); $this->reportStorageService->saveMetric($report, MetrikaConfig::PREOPERATIVE_AVERAGE_DAYS, $result->average); } private function saveDepartmentLoadMetric(Report $report): void { $currentCount = (float) ($report->metrikaResults()->where('rf_metrika_item_id', MetrikaConfig::CURRENT)->value('value') ?? 0); $bedsCount = (float) ($report->metrikaResults()->where('rf_metrika_item_id', MetrikaConfig::BEDS)->value('value') ?? 0); $this->reportStorageService->saveMetric( $report, MetrikaConfig::DEPARTMENT_LOADED, $this->departmentLoadCalculator->calculate($currentCount, $bedsCount), ); } /** * @return array */ private function buildStayIntervals(Report $report): array { $snapshots = MedicalHistorySnapshot::query() ->where('rf_report_id', $report->report_id) ->whereIn('patient_type', ['discharged', 'deceased']) ->with('medicalHistory') ->get(); $intervals = []; foreach ($snapshots as $snapshot) { $history = $snapshot->medicalHistory; if (! $history) { continue; } $startRaw = $history->DateRecipientHS ?? $history->DateRecipient ?? null; $endRaw = null; if ($snapshot->patient_type === 'deceased') { if ($this->isRealDate($history->DateDeath)) { $endRaw = $history->DateDeath; } elseif ($this->isRealDate($history->DateExtract)) { $endRaw = $history->DateExtract; } } elseif ($this->isRealDate($history->DateExtract)) { $endRaw = $history->DateExtract; } if (! $startRaw || ! $endRaw) { continue; } $intervals[] = new StayInterval( startAt: new DateTimeImmutable((string) $startRaw), endAt: new DateTimeImmutable((string) $endRaw), ); } return $intervals; } private function isRealDate(mixed $value): bool { if (! $value) { return false; } $date = $value instanceof DateTimeInterface ? $value->format('Y-m-d') : (new DateTimeImmutable((string) $value))->format('Y-m-d'); return ! in_array($date, ['1900-01-01', '2222-01-01'], true); } /** * @return array */ private function buildOperationIntervals(Report $report): array { $patientIds = MedicalHistorySnapshot::query() ->where('rf_report_id', $report->report_id) ->whereIn('patient_type', ['discharged', 'deceased']) ->pluck('rf_medicalhistory_id') ->unique() ->values(); if ($patientIds->isEmpty()) { return []; } $rows = DB::table('stt_medicalhistory as mh') ->join('stt_surgicaloperation as so', 'so.rf_MedicalHistoryID', '=', 'mh.MedicalHistoryID') ->whereIn('mh.MedicalHistoryID', $patientIds) ->whereNotNull('so.Date') ->select( 'mh.MedicalHistoryID', DB::raw('MIN(so."Date") as first_operation'), 'mh.DateRecipientHS', 'mh.DateRecipient' ) ->groupBy('mh.MedicalHistoryID', 'mh.DateRecipientHS', 'mh.DateRecipient') ->get(); $intervals = []; foreach ($rows as $row) { $startRaw = $row->DateRecipientHS ?? $row->DateRecipient ?? null; $operationRaw = $row->first_operation ?? null; if (! $startRaw || ! $operationRaw) { continue; } $intervals[] = new OperationInterval( admittedAt: new DateTimeImmutable((string) $startRaw), operationAt: new DateTimeImmutable((string) $operationRaw), ); } return $intervals; } }