Профиль хирургии

This commit is contained in:
brusnitsyn
2026-03-25 17:37:32 +09:00
parent 52a80ccd3b
commit f566ab96df
75 changed files with 3841 additions and 1009 deletions

View File

@@ -0,0 +1,47 @@
<?php
// app/Services/MetricCalculators/AverageBedDaysCalculator.php
namespace App\Services\MetricCalculators;
use App\Services\Base\BaseMetricService;
use App\Contracts\MetricCalculatorInterface;
use Illuminate\Support\Facades\DB;
class AverageBedDaysCalculator extends BaseMetricService implements MetricCalculatorInterface
{
public function getMetricId(): int
{
return 18;
}
public function calculate(array $departmentIds, string $startDate, string $endDate): array
{
if (empty($departmentIds)) {
return [];
}
$results = DB::table('reports as r')
->join('metrika_results as mr', 'r.report_id', '=', 'mr.rf_report_id')
->whereIn('r.rf_department_id', $departmentIds)
->where('mr.rf_metrika_item_id', 18)
// ->whereBetween('r.created_at', [$startDate, $endDate])
->where('r.sent_at', '>', $startDate)
->where('r.sent_at', '<=', $endDate)
->select(
'r.rf_department_id',
DB::raw('AVG(CAST(mr.value AS DECIMAL)) as avg_value')
)
->groupBy('r.rf_department_id')
->get()
->keyBy('rf_department_id');
$averages = [];
foreach ($departmentIds as $deptId) {
$averages[$deptId] = isset($results[$deptId])
? round((float)$results[$deptId]->avg_value, 1)
: 0;
}
return $averages;
}
}

View File

@@ -0,0 +1,58 @@
<?php
// app/Services/MetricCalculators/LethalityCalculator.php
namespace App\Services\MetricCalculators;
use App\Services\Base\BaseMetricService;
use App\Contracts\MetricCalculatorInterface;
use Illuminate\Support\Facades\DB;
class LethalityCalculator extends BaseMetricService implements MetricCalculatorInterface
{
public function getMetricId(): int
{
return 19;
}
public function calculate(array $departmentIds, string $startDate, string $endDate): array
{
if (empty($departmentIds)) {
return [];
}
$results = DB::table('reports as r')
->join('metrika_results as mr', 'r.report_id', '=', 'mr.rf_report_id')
->whereIn('r.rf_department_id', $departmentIds)
->whereIn('mr.rf_metrika_item_id', [7, 9])
// ->whereBetween('r.created_at', [$startDate, $endDate])
->where('r.sent_at', '>', $startDate)
->where('r.sent_at', '<=', $endDate)
->select(
'r.rf_department_id',
'mr.rf_metrika_item_id',
DB::raw('SUM(CAST(mr.value AS INTEGER)) as total')
)
->groupBy('r.rf_department_id', 'mr.rf_metrika_item_id')
->get()
->groupBy('rf_department_id');
$lethality = [];
foreach ($departmentIds as $deptId) {
$deceased = 0;
$discharged = 0;
if (isset($results[$deptId])) {
foreach ($results[$deptId] as $item) {
if ($item->rf_metrika_item_id == 9) $deceased = (int)$item->total;
else $discharged = (int)$item->total;
}
}
$lethality[$deptId] = ($discharged > 0 && $deceased > 0)
? round(($deceased / $discharged) * 100, 1)
: 0;
}
return $lethality;
}
}

View File

@@ -0,0 +1,99 @@
<?php
// app/Services/MetricCalculators/PreoperativeDaysCalculator.php
namespace App\Services\MetricCalculators;
use App\Services\Base\BaseMetricService;
use App\Contracts\MetricCalculatorInterface;
use App\Models\MedicalHistorySnapshot;
use App\Models\Report;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
class PreoperativeDaysCalculator extends BaseMetricService implements MetricCalculatorInterface
{
public function getMetricId(): int
{
return 21;
}
public function calculate(array $departmentIds, string $startDate, string $endDate): array
{
if (empty($departmentIds)) {
return [];
}
// Получаем отчеты за период
$reports = Report::whereIn('rf_department_id', $departmentIds)
->where('sent_at', '>', $startDate)
->where('sent_at', '<=', $endDate)
// ->whereBetween('created_at', [$startDate, $endDate])
->get(['report_id', 'rf_department_id'])
->keyBy('report_id');
if ($reports->isEmpty()) {
return array_fill_keys($departmentIds, 0);
}
$reportIds = $reports->keys()->toArray();
// Получаем пациентов из снапшотов
$snapshots = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
->whereIn('patient_type', ['discharged', 'deceased'])
->get(['rf_report_id', 'rf_medicalhistory_id']);
if ($snapshots->isEmpty()) {
return array_fill_keys($departmentIds, 0);
}
$historyIds = $snapshots->pluck('rf_medicalhistory_id')->unique()->toArray();
// Получаем первые операции и первые поступления одним запросом
$operations = DB::table('stt_surgicaloperation as so')
->join('stt_migrationpatient as mp', 'so.rf_MedicalHistoryID', '=', 'mp.rf_MedicalHistoryID')
->whereIn('so.rf_MedicalHistoryID', $historyIds)
->whereNotNull('so.Date')
->whereNotNull('mp.DateIngoing')
->select(
'so.rf_MedicalHistoryID',
DB::raw('MIN(so."Date") as first_operation'),
DB::raw('MIN(mp."DateIngoing") as first_admission')
)
->groupBy('so.rf_MedicalHistoryID')
->get()
->keyBy('rf_MedicalHistoryID');
// Группируем по отделениям
$results = [];
foreach ($snapshots as $snapshot) {
$deptId = $reports[$snapshot->rf_report_id]->rf_department_id;
$historyId = $snapshot->rf_medicalhistory_id;
if (!isset($operations[$historyId])) {
continue;
}
$op = $operations[$historyId];
$days = Carbon::parse($op->first_admission)
->diffInDays(Carbon::parse($op->first_operation));
if ($days >= 0) {
if (!isset($results[$deptId])) {
$results[$deptId] = ['total' => 0, 'count' => 0];
}
$results[$deptId]['total'] += $days;
$results[$deptId]['count']++;
}
}
// Усредняем по отделениям
$preoperative = [];
foreach ($departmentIds as $deptId) {
$preoperative[$deptId] = isset($results[$deptId]) && $results[$deptId]['count'] > 0
? round($results[$deptId]['total'] / $results[$deptId]['count'], 1)
: 0;
}
return $preoperative;
}
}