142 lines
6.3 KiB
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];
|
|
}
|
|
}
|