reportStorageService = $reportStorageService ?? app(ReportStorageService::class); $this->reportMetricsFinalizer = $reportMetricsFinalizer ?? app(ReportMetricsFinalizer::class); } private readonly ReportStorageService $reportStorageService; private readonly ReportMetricsFinalizer $reportMetricsFinalizer; public function save(ReportSnapshot $snapshot): SavedReportResult { $this->legacyAdapter->prepareMemoryForHeavySave(); $actor = $snapshot->actorUserId ? User::query()->find($snapshot->actorUserId) : null; if (! $actor) { throw new RuntimeException('Actor user was not found.'); } $report = DB::transaction(function () use ($snapshot, $actor) { $report = $this->reportStorageService->createOrUpdateReport($snapshot, $actor); $this->reportStorageService->saveMetrics($report, $snapshot); $this->reportStorageService->saveUnwantedEvents($report, $snapshot); $this->reportStorageService->saveObservationPatients($report, $snapshot); $this->legacyAdapter->createPatientSnapshots($report, $actor, $snapshot, $snapshot->autoFill); $this->legacyAdapter->syncCalculatedMetrics($report, $actor, $snapshot); return $report; }); DB::transaction(function () use ($report) { $this->reportMetricsFinalizer->finalize($report); $this->legacyAdapter->saveLethalMetricFromSnapshots($report); }); $this->legacyAdapter->clearCacheAfterReportCreation($actor, $report); $savedSnapshot = $this->findSnapshot((int) $report->report_id); if (! $savedSnapshot) { throw new RuntimeException('Saved report could not be reloaded for comparison.'); } return new SavedReportResult( reportId: (int) $report->report_id, snapshot: $savedSnapshot, ); } public function findSnapshot(int $reportId): ?ReportSnapshot { /** @var Report|null $report */ $report = Report::query() ->with(['metrikaResults', 'observationPatients', 'unwantedEvents']) ->find($reportId); if (! $report || ! $report->period_start || ! $report->period_end) { return null; } return new ReportSnapshot( departmentId: (int) $report->rf_department_id, userId: (int) ($report->rf_lpudoctor_id ?? $report->rf_user_id), actorUserId: (int) $report->rf_user_id, periodStart: new \DateTimeImmutable($report->period_start->format('Y-m-d H:i:s')), periodEnd: new \DateTimeImmutable($report->period_end->format('Y-m-d H:i:s')), status: (string) ($report->status ?? 'draft'), autoFill: false, metrics: $report->metrikaResults ->mapWithKeys(fn (MetrikaResult $metric) => [(int) $metric->rf_metrika_item_id => $metric->value]) ->all(), observationPatients: $report->observationPatients ->map(fn (ObservationPatient $patient) => [ 'medical_history_id' => $patient->rf_medicalhistory_id, 'department_patient_id' => $patient->rf_department_patient_id, 'comment' => $patient->comment, ])->values()->all(), unwantedEvents: $report->unwantedEvents ->map(fn (UnwantedEvent $event) => [ 'title' => $event->title, 'comment' => $event->comment, 'is_visible' => (bool) $event->is_visible, ])->values()->all(), reportId: (int) $report->report_id, createdAt: $report->created_at ? new \DateTimeImmutable($report->created_at->format('Y-m-d H:i:s')) : null, sentAt: $report->sent_at ? new \DateTimeImmutable($report->sent_at->format('Y-m-d H:i:s')) : null, ); } }