Files
onboard/app/Infrastructure/Reports/Services/CalculatedMetricsSynchronizer.php

142 lines
6.3 KiB
PHP

<?php
namespace App\Infrastructure\Reports\Services;
use App\Domain\Reports\ValueObjects\MetrikaConfig;
use App\Models\Department;
use App\Models\DepartmentPatientOperation;
use App\Models\MedicalHistorySnapshot;
use App\Models\MisStationarBranch;
use App\Models\ObservationPatient;
use App\Models\Report;
use App\Models\UnwantedEvent;
use App\Models\User;
use App\Services\DateRange;
use App\Services\DateRangeService;
use App\Services\PatientService;
class CalculatedMetricsSynchronizer
{
public function __construct(
private readonly DateRangeService $dateRangeService,
private readonly PatientService $patientService,
private readonly ReportStorageService $reportStorageService,
) {}
/**
* @param array<string, mixed> $data
*/
public function sync(Report $report, User $user, array $data): void
{
if (! isset($data['dates'][0], $data['dates'][1])) {
return;
}
$department = Department::query()->where('department_id', $report->rf_department_id)->first();
if (! $department) {
return;
}
$dateRange = $this->dateRangeService->getNormalizedDateRange(
$user,
(string) $data['dates'][0],
(string) $data['dates'][1]
);
$branchId = $this->getBranchId($department->rf_mis_department_id);
$planCount = $this->countUniqueSnapshotsForTypes($report->report_id, ['plan']);
$emergencyCount = $this->countUniqueSnapshotsForTypes($report->report_id, ['emergency']);
$recipientCount = $this->countUniqueSnapshotsForTypes($report->report_id, ['recipient']);
$dischargedCount = $this->countUniqueSnapshotsForTypes($report->report_id, ['discharged']);
$transferredCount = $this->countUniqueSnapshotsForTypes($report->report_id, ['transferred']);
$deceasedCount = $this->countUniqueSnapshotsForTypes($report->report_id, ['deceased']);
$currentCount = $this->countUniqueSnapshotsForTypes($report->report_id, ['current']);
$outcomeCount = $dischargedCount + $deceasedCount;
$manualSurgicalCount = $this->getManualSurgicalCounts($department, $dateRange);
$misEmergencySurgery = $branchId
? $this->patientService->getSurgicalPatients('emergency', $branchId, $dateRange, true)
: 0;
$misPlanSurgery = $branchId
? $this->patientService->getSurgicalPatients('plan', $branchId, $dateRange, true)
: 0;
$observationCount = ObservationPatient::query()
->where('rf_department_id', $department->department_id)
->where('rf_report_id', $report->report_id)
->count();
$unwantedEventsCount = UnwantedEvent::query()
->where('rf_report_id', $report->report_id)
->count();
$this->reportStorageService->saveMetric($report, MetrikaConfig::RECIPIENT, $recipientCount);
$this->reportStorageService->saveMetric($report, MetrikaConfig::PLAN, $planCount);
$this->reportStorageService->saveMetric($report, MetrikaConfig::OUTCOME, $outcomeCount);
$this->reportStorageService->saveMetric($report, MetrikaConfig::CURRENT, $currentCount);
$this->reportStorageService->saveMetric($report, MetrikaConfig::DECEASED, $deceasedCount);
$this->reportStorageService->saveMetric($report, MetrikaConfig::EMERGENCY_SURGERY, $misEmergencySurgery + ($manualSurgicalCount[0] ?? 0));
$this->reportStorageService->saveMetric($report, MetrikaConfig::PLAN_SURGERY, $misPlanSurgery + ($manualSurgicalCount[1] ?? 0));
$this->reportStorageService->saveMetric($report, MetrikaConfig::EMERGENCY, $emergencyCount);
$this->reportStorageService->saveMetric($report, MetrikaConfig::TRANSFERRED, $transferredCount);
$this->reportStorageService->saveMetric($report, MetrikaConfig::OBSERVATION, $observationCount);
$this->reportStorageService->saveMetric($report, MetrikaConfig::DISCHARGED, $dischargedCount);
$this->reportStorageService->saveMetric($report, MetrikaConfig::UNWANTED_EVENTS, $unwantedEventsCount);
}
private function getBranchId(int $misDepartmentId): ?int
{
return MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
->value('StationarBranchID');
}
private function countUniqueSnapshotsForTypes(int $reportId, array $patientTypes): int
{
return MedicalHistorySnapshot::query()
->where('rf_report_id', $reportId)
->whereIn('patient_type', $patientTypes)
->get(['medical_history_snapshot_id', 'patient_uid', 'rf_medicalhistory_id'])
->map(function (MedicalHistorySnapshot $snapshot) {
return $snapshot->patient_uid
?: ($snapshot->rf_medicalhistory_id
? "mis:{$snapshot->rf_medicalhistory_id}"
: "snapshot:{$snapshot->medical_history_snapshot_id}");
})
->unique()
->count();
}
public function getManualSurgicalCounts(Department $department, DateRange $dateRange): array
{
$baseQuery = DepartmentPatientOperation::query()
->whereBetween('started_at', [$dateRange->startSql(), $dateRange->endSql()])
->whereHas('patient', function ($query) use ($department) {
$query->where('rf_department_id', $department->department_id)
->whereIn('source_type', ['manual', 'special']);
});
$emergencyCount = (clone $baseQuery)
->where(function ($query) {
$query->where('urgency', 'emergency')
->orWhere(function ($fallback) {
$fallback->whereNull('urgency')
->whereHas('patient', fn ($patientQuery) => $patientQuery->where('patient_kind', 'emergency'));
});
})
->count();
$planCount = (clone $baseQuery)
->where(function ($query) {
$query->where('urgency', 'plan')
->orWhere(function ($fallback) {
$fallback->whereNull('urgency')
->whereHas('patient', fn ($patientQuery) => $patientQuery->where('patient_kind', 'plan'));
});
})
->count();
return [$emergencyCount, $planCount];
}
}