Работа над журналом для ст. мед сестер
This commit is contained in:
164
app/Infrastructure/Reports/Services/ReportSaveOrchestrator.php
Normal file
164
app/Infrastructure/Reports/Services/ReportSaveOrchestrator.php
Normal file
@@ -0,0 +1,164 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Reports\Services;
|
||||
|
||||
use App\Domain\Reports\Models\ReportSnapshot;
|
||||
use App\Domain\Reports\ValueObjects\MetrikaConfig;
|
||||
use App\Models\MedicalHistorySnapshot;
|
||||
use App\Models\MetrikaResult;
|
||||
use App\Models\Report;
|
||||
use App\Models\User;
|
||||
use App\Services\DateRangeService;
|
||||
use App\Services\SnapshotService;
|
||||
use DateTimeImmutable;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* Legacy-compatible save orchestration for report persistence.
|
||||
*
|
||||
* New architecture uses EloquentReportRepository directly; this service keeps
|
||||
* the old ReportService public API thin while the cutover is still gradual.
|
||||
*/
|
||||
class ReportSaveOrchestrator
|
||||
{
|
||||
public function __construct(
|
||||
private readonly DateRangeService $dateRangeService,
|
||||
private readonly SnapshotService $snapshotService,
|
||||
private readonly ReportStorageService $reportStorageService,
|
||||
private readonly CalculatedMetricsSynchronizer $calculatedMetricsSynchronizer,
|
||||
private readonly ReportMetricsFinalizer $reportMetricsFinalizer,
|
||||
private readonly ReportRuntimeService $reportRuntimeService,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function storeReport(array $data, User $user, bool $fillableAuto = false): Report
|
||||
{
|
||||
$this->reportRuntimeService->prepareForHeavySave();
|
||||
$snapshot = $this->buildSnapshot($data, $user, $fillableAuto);
|
||||
|
||||
$report = DB::transaction(function () use ($snapshot, $user, $data, $fillableAuto) {
|
||||
$report = $this->reportStorageService->createOrUpdateReport($snapshot, $user);
|
||||
$this->reportStorageService->saveMetrics($report, $snapshot);
|
||||
$this->reportStorageService->saveUnwantedEvents($report, $snapshot);
|
||||
$this->reportStorageService->saveObservationPatients($report, $snapshot);
|
||||
|
||||
$this->snapshotService->createPatientSnapshots(
|
||||
$report,
|
||||
$user,
|
||||
[
|
||||
$snapshot->periodStart->getTimestamp(),
|
||||
$snapshot->periodEnd->getTimestamp(),
|
||||
],
|
||||
$fillableAuto
|
||||
);
|
||||
|
||||
$this->syncCalculatedMetrics($report, $user, $data);
|
||||
|
||||
return $report;
|
||||
});
|
||||
|
||||
DB::transaction(function () use ($report) {
|
||||
$this->finalizeStoredReport($report);
|
||||
$this->saveLethalMetricFromSnapshots($report);
|
||||
});
|
||||
|
||||
$this->reportRuntimeService->clearCacheAfterReportCreation($user, $report);
|
||||
|
||||
return $report;
|
||||
}
|
||||
|
||||
public function syncCalculatedMetrics(Report $report, User $user, array $data): void
|
||||
{
|
||||
$this->calculatedMetricsSynchronizer->sync($report, $user, $data);
|
||||
}
|
||||
|
||||
public function finalizeStoredReport(Report $report): void
|
||||
{
|
||||
$this->reportMetricsFinalizer->finalize($report);
|
||||
}
|
||||
|
||||
public function saveLethalMetricFromSnapshots(Report $report): void
|
||||
{
|
||||
$snapshots = MedicalHistorySnapshot::query()
|
||||
->where('rf_report_id', $report->report_id)
|
||||
->whereIn('patient_type', ['discharged', 'deceased'])
|
||||
->with('medicalHistory')
|
||||
->get();
|
||||
|
||||
if ($snapshots->isNotEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
MetrikaResult::query()->updateOrCreate(
|
||||
[
|
||||
'rf_report_id' => $report->report_id,
|
||||
'rf_metrika_item_id' => MetrikaConfig::AVERAGE_BED_DAYS,
|
||||
],
|
||||
['value' => 0]
|
||||
);
|
||||
|
||||
\Log::info("No discharged patients in report {$report->report_id}, saved 0");
|
||||
}
|
||||
|
||||
private function buildSnapshot(array $data, User $user, bool $fillableAuto): ReportSnapshot
|
||||
{
|
||||
$dateRange = $this->dateRangeService->getNormalizedDateRange(
|
||||
$user,
|
||||
(string) ($data['dates'][0] ?? null),
|
||||
(string) ($data['dates'][1] ?? null)
|
||||
);
|
||||
|
||||
$rangeEndAt = $dateRange->endSql();
|
||||
$createdAt = $data['created_at'] ?? $rangeEndAt;
|
||||
$sentAt = $data['sent_at'] ?? $rangeEndAt;
|
||||
|
||||
return new ReportSnapshot(
|
||||
departmentId: (int) $data['departmentId'],
|
||||
userId: (int) $data['userId'],
|
||||
actorUserId: (int) $user->id,
|
||||
periodStart: new DateTimeImmutable($dateRange->startSql()),
|
||||
periodEnd: new DateTimeImmutable($dateRange->endSql()),
|
||||
status: (string) ($data['status'] ?? 'draft'),
|
||||
autoFill: $fillableAuto,
|
||||
metrics: MetrikaConfig::normalizeMetrics((array) ($data['metrics'] ?? [])),
|
||||
observationPatients: $this->normalizeObservationPatients((array) ($data['observationPatients'] ?? [])),
|
||||
unwantedEvents: $this->normalizeUnwantedEvents((array) ($data['unwantedEvents'] ?? [])),
|
||||
reportId: isset($data['reportId']) && $data['reportId'] ? (int) $data['reportId'] : null,
|
||||
createdAt: new DateTimeImmutable((string) $createdAt),
|
||||
sentAt: new DateTimeImmutable((string) $sentAt),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $patients
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function normalizeObservationPatients(array $patients): array
|
||||
{
|
||||
return array_values(array_map(static function (array $patient): array {
|
||||
return [
|
||||
'medical_history_id' => $patient['medical_history_id'] ?? $patient['id'] ?? null,
|
||||
'department_patient_id' => $patient['department_patient_id'] ?? null,
|
||||
'comment' => $patient['comment'] ?? null,
|
||||
];
|
||||
}, $patients));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, array<string, mixed>> $events
|
||||
* @return array<int, array<string, mixed>>
|
||||
*/
|
||||
private function normalizeUnwantedEvents(array $events): array
|
||||
{
|
||||
return array_values(array_map(static function (array $event): array {
|
||||
return [
|
||||
'unwanted_event_id' => $event['unwanted_event_id'] ?? null,
|
||||
'title' => $event['title'] ?? '',
|
||||
'comment' => $event['comment'] ?? '',
|
||||
'is_visible' => (bool) ($event['is_visible'] ?? true),
|
||||
];
|
||||
}, $events));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user