Работа над журналом для ст. мед сестер
This commit is contained in:
@@ -0,0 +1,213 @@
|
||||
<?php
|
||||
|
||||
namespace App\Infrastructure\Reports\Services;
|
||||
|
||||
use App\Domain\Reports\ValueObjects\MetrikaConfig;
|
||||
use App\Models\Department;
|
||||
use App\Models\Report;
|
||||
use App\Models\User;
|
||||
use App\Services\DateRange;
|
||||
use App\Services\PatientService;
|
||||
use App\Services\SnapshotService;
|
||||
use App\Services\UnifiedPatientService;
|
||||
|
||||
/**
|
||||
* Сервис чтения сводной статистики отчёта.
|
||||
*
|
||||
* Инкапсулирует выбор источника данных: submitted-снапшоты для закрытых
|
||||
* отчётов или live-реплика для текущей рабочей формы.
|
||||
*/
|
||||
class ReportStatisticsReadService
|
||||
{
|
||||
public function __construct(
|
||||
private readonly UnifiedPatientService $unifiedPatientService,
|
||||
private readonly PatientService $patientService,
|
||||
private readonly SnapshotService $snapshotService,
|
||||
private readonly ReportReadContextResolver $contextResolver,
|
||||
private readonly CalculatedMetricsSynchronizer $calculatedMetricsSynchronizer,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Получить статистику для шапки отчёта.
|
||||
*/
|
||||
public function getReportStatistics(Department $department, User $user, DateRange $dateRange): array
|
||||
{
|
||||
$branchId = $this->contextResolver->resolveBranchId($department);
|
||||
|
||||
if (! $branchId) {
|
||||
return $this->emptyStatistics();
|
||||
}
|
||||
|
||||
if ($this->contextResolver->shouldUseSnapshots($department, $dateRange)) {
|
||||
return $this->getStatisticsFromSnapshots($department, $dateRange);
|
||||
}
|
||||
|
||||
return $this->getStatisticsFromReplica($department, $user, $dateRange, $branchId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить статистику из сохранённых снапшотов submitted-отчётов.
|
||||
*/
|
||||
private function getStatisticsFromSnapshots(Department $department, DateRange $dateRange): array
|
||||
{
|
||||
$reports = $this->contextResolver->getReportsForDateRange(
|
||||
$department->department_id,
|
||||
$dateRange
|
||||
);
|
||||
|
||||
$reportIds = $reports->pluck('report_id')->all();
|
||||
$lastReportId = $reportIds[0] ?? null;
|
||||
$recipientReportIds = $this->contextResolver->getRecipientReportIds($reportIds);
|
||||
|
||||
$snapshotStats = [
|
||||
'plan' => $this->getMetrikaResultCount(MetrikaConfig::PLAN, $reportIds),
|
||||
'emergency' => $this->getMetrikaResultCount(MetrikaConfig::EMERGENCY, $reportIds),
|
||||
'outcome' => $this->getMetrikaResultCount(MetrikaConfig::OUTCOME, $reportIds),
|
||||
'deceased' => $this->getMetrikaResultCount(MetrikaConfig::DECEASED, $reportIds),
|
||||
'current' => $this->getMetrikaResultCount(MetrikaConfig::CURRENT, $reportIds, false),
|
||||
'transferred' => $this->getMetrikaResultCount(MetrikaConfig::TRANSFERRED, $reportIds),
|
||||
'recipient' => $this->getMetrikaResultCount(MetrikaConfig::RECIPIENT, $reportIds),
|
||||
'beds' => $this->getMetrikaResultCount(MetrikaConfig::BEDS, $reportIds, false),
|
||||
'countStaff' => $lastReportId
|
||||
? $this->getMetrikaResultCount(MetrikaConfig::STAFF_COUNT, [$lastReportId], false)
|
||||
: 0,
|
||||
];
|
||||
|
||||
$recipientIds = $this->snapshotService
|
||||
->getPatientsFromSnapshots('recipient', $recipientReportIds)
|
||||
->pluck('id')
|
||||
->all();
|
||||
|
||||
$surgicalCount = [
|
||||
$this->getMetrikaResultCount(MetrikaConfig::EMERGENCY_SURGERY, $reportIds),
|
||||
$this->getMetrikaResultCount(MetrikaConfig::PLAN_SURGERY, $reportIds),
|
||||
];
|
||||
|
||||
return [
|
||||
'recipientCount' => $snapshotStats['recipient'] ?? 0,
|
||||
'extractCount' => $snapshotStats['outcome'] ?? 0,
|
||||
'currentCount' => $snapshotStats['current'] ?? 0,
|
||||
'deadCount' => $snapshotStats['deceased'] ?? 0,
|
||||
'countStaff' => $snapshotStats['countStaff'] ?? 0,
|
||||
'surgicalCount' => $surgicalCount,
|
||||
'recipientIds' => $recipientIds,
|
||||
'beds' => $snapshotStats['beds'] ?? 0,
|
||||
'percentDead' => $this->calculatePercentDead($snapshotStats['deceased'], $snapshotStats['outcome']),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить статистику из live-реплики МИС и manual-источников.
|
||||
*/
|
||||
private function getStatisticsFromReplica(
|
||||
Department $department,
|
||||
User $user,
|
||||
DateRange $dateRange,
|
||||
int $branchId
|
||||
): array {
|
||||
$planCount = $this->unifiedPatientService->getLivePatientCountByStatus($department, $user, 'plan', $dateRange, $branchId, true);
|
||||
$emergencyCount = $this->unifiedPatientService->getLivePatientCountByStatus($department, $user, 'emergency', $dateRange, $branchId, true);
|
||||
$currentCount = $this->unifiedPatientService->getLivePatientCountByStatus($department, $user, 'current', $dateRange, $branchId);
|
||||
$recipientCount = $this->unifiedPatientService->getLivePatientCountByStatus($department, $user, 'recipient', $dateRange, $branchId);
|
||||
$outcomeCount = $this->unifiedPatientService->getLivePatientCountByStatus($department, $user, 'outcome', $dateRange, $branchId);
|
||||
$deadCount = $this->unifiedPatientService->getLivePatientCountByStatus($department, $user, 'outcome-deceased', $dateRange, $branchId);
|
||||
|
||||
$misSurgicalCount = [
|
||||
$this->patientService->getSurgicalPatients('emergency', $branchId, $dateRange, true),
|
||||
$this->patientService->getSurgicalPatients('plan', $branchId, $dateRange, true),
|
||||
];
|
||||
$manualSurgicalCount = $this->calculatedMetricsSynchronizer->getManualSurgicalCounts($department, $dateRange);
|
||||
$surgicalCount = [
|
||||
($misSurgicalCount[0] ?? 0) + ($manualSurgicalCount[0] ?? 0),
|
||||
($misSurgicalCount[1] ?? 0) + ($manualSurgicalCount[1] ?? 0),
|
||||
];
|
||||
|
||||
$recipientIds = $this->unifiedPatientService
|
||||
->getRecipientIdsForReport($department, $user, $dateRange, $branchId);
|
||||
|
||||
return [
|
||||
'recipientCount' => $recipientCount,
|
||||
'extractCount' => $outcomeCount,
|
||||
'currentCount' => $currentCount,
|
||||
'deadCount' => $deadCount,
|
||||
'surgicalCount' => $surgicalCount,
|
||||
'recipientIds' => $recipientIds,
|
||||
'planCount' => $planCount,
|
||||
'emergencyCount' => $emergencyCount,
|
||||
'percentDead' => $this->calculatePercentDead($deadCount, $outcomeCount),
|
||||
'beds' => (int) ($department->metrikaDefault
|
||||
->where('rf_metrika_item_id', MetrikaConfig::BEDS)
|
||||
->first()
|
||||
?->value ?? 0),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить агрегированное значение метрики из набора отчётов.
|
||||
*
|
||||
* @param array<int, int> $reportIds
|
||||
*/
|
||||
private function getMetrikaResultCount(int $metrikaItemId, array $reportIds, bool $sum = true): int
|
||||
{
|
||||
if (empty($reportIds)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$reports = Report::query()
|
||||
->whereIn('report_id', $reportIds)
|
||||
->with('metrikaResults')
|
||||
->orderBy('created_at', 'DESC')
|
||||
->get();
|
||||
|
||||
if (! $sum) {
|
||||
foreach ($reports as $report) {
|
||||
$metric = $report->metrikaResults
|
||||
->firstWhere('rf_metrika_item_id', $metrikaItemId);
|
||||
|
||||
if ($metric) {
|
||||
return (int) $metric->value;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
|
||||
foreach ($reports as $report) {
|
||||
foreach ($report->metrikaResults as $metrikaResult) {
|
||||
if ((int) $metrikaResult->rf_metrika_item_id === $metrikaItemId) {
|
||||
$count += (int) $metrikaResult->value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
private function calculatePercentDead(int $deadCount, int $outcomeCount): float|int
|
||||
{
|
||||
if ($outcomeCount === 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return round(($deadCount / $outcomeCount) * 100, 2);
|
||||
}
|
||||
|
||||
private function emptyStatistics(): array
|
||||
{
|
||||
return [
|
||||
'recipientCount' => 0,
|
||||
'extractCount' => 0,
|
||||
'currentCount' => 0,
|
||||
'deadCount' => 0,
|
||||
'surgicalCount' => [0, 0],
|
||||
'recipientIds' => [],
|
||||
'planCount' => 0,
|
||||
'emergencyCount' => 0,
|
||||
'percentDead' => 0,
|
||||
'beds' => 0,
|
||||
'countStaff' => 0,
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user