114 lines
4.7 KiB
PHP
114 lines
4.7 KiB
PHP
<?php
|
|
|
|
namespace App\Infrastructure\Reports\Repositories;
|
|
|
|
use App\Domain\Reports\Contracts\ReportRepository;
|
|
use App\Domain\Reports\Models\ReportSnapshot;
|
|
use App\Domain\Reports\Models\SavedReportResult;
|
|
use App\Infrastructure\Reports\Adapters\LegacyReportServiceAdapter;
|
|
use App\Models\MetrikaResult;
|
|
use App\Models\ObservationPatient;
|
|
use App\Models\Report;
|
|
use App\Models\UnwantedEvent;
|
|
use App\Infrastructure\Reports\Services\ReportMetricsFinalizer;
|
|
use App\Infrastructure\Reports\Services\ReportStorageService;
|
|
use App\Models\User;
|
|
use Illuminate\Support\Facades\DB;
|
|
use RuntimeException;
|
|
|
|
class EloquentReportRepository implements ReportRepository
|
|
{
|
|
public function __construct(
|
|
private readonly LegacyReportServiceAdapter $legacyAdapter,
|
|
?ReportStorageService $reportStorageService = null,
|
|
?ReportMetricsFinalizer $reportMetricsFinalizer = null,
|
|
) {
|
|
$this->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,
|
|
);
|
|
}
|
|
|
|
}
|