This commit is contained in:
brusnitsyn
2026-02-20 17:28:16 +09:00
parent 94e374c32b
commit 52a80ccd3b
41 changed files with 2555 additions and 206 deletions

View File

@@ -14,6 +14,12 @@ class MedicalHistorySnapshot extends Model
'patient_type',
];
/**
* Типы пациентов
*/
const PATIENT_TYPE_DISCHARGED = 'discharged'; // Выписанные
const PATIENT_TYPE_CURRENT = 'current'; // Текущие
public function report()
{
return $this->belongsTo(Report::class, 'rf_report_id');

41
app/Models/MisBed.php Normal file
View File

@@ -0,0 +1,41 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MisBed extends Model
{
protected $table = 'stt_Bed';
protected $primaryKey = 'BedID';
public $timestamps = false;
protected $fillable = [
'DateWorkB',
'DateWorkE',
'Flag',
'Num',
'rf_BedAssigmentID',
'rf_BedProfileID',
'rf_BedStatusID',
'rf_BedTypeID',
'rf_WardID',
'UGUID',
'x_Edition',
'x_Status',
'ShiftNum',
'rf_PreviousBedID'
];
protected $casts = [
'DateWorkB' => 'datetime',
'DateWorkE' => 'datetime',
'UGUID' => 'string',
'x_Status' => 'integer'
];
public function bedActions()
{
return $this->hasMany(MisBedAction::class, 'rf_BedID', 'BedID');
}
}

View File

@@ -0,0 +1,62 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MisBedAction extends Model
{
protected $table = 'stt_BedAction';
protected $primaryKey = 'BedActionID';
public $timestamps = false;
protected $fillable = [
'x_Edition',
'x_Status',
'Date',
'rf_ActionTypeID',
'Flag',
'rf_BedID',
'rf_MigrationPatientID',
'rf_LPUDoctorID',
'UGUID',
'rf_PatientID',
'rf_DocPRVDID',
'rf_MedStageID',
'rf_BedProfileID',
'SystemDate'
];
protected $casts = [
'Date' => 'datetime',
'SystemDate' => 'datetime',
'UGUID' => 'string',
'x_Status' => 'integer'
];
/**
* Типы действий с койками
*/
const ACTION_TYPE_OCCUPIED = 1; // Поступление
const ACTION_TYPE_FREE = 2; // Выписка
public function bed()
{
return $this->belongsTo(MisBed::class, 'rf_BedID', 'BedID');
}
/**
* Получить информацию о пребывании пациента на койке
*/
public static function getPatientStayPeriods($migrationPatientId)
{
$query = self::where('rf_MigrationPatientID', $migrationPatientId)
->whereIn('rf_ActionTypeID', [
self::ACTION_TYPE_OCCUPIED,
self::ACTION_TYPE_FREE
])
->orderBy('Date');
return $query->get();
}
}

View File

@@ -3,13 +3,14 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
class MisMedicalHistory extends Model
{
protected $table = 'stt_medicalhistory';
protected $primaryKey = 'MedicalHistoryID';
public $timestamps = false;
protected $fillable = [
'MedicalHistoryID',
@@ -21,9 +22,64 @@ class MisMedicalHistory extends Model
];
protected $casts = [
'DateRecipient' => 'datetime'
'DateRecipient' => 'datetime',
'DateExtract' => 'datetime'
];
/**
* Проверить, находится ли пациент еще в стационаре
*/
public function isStillInHospital(): bool
{
// Проверяем специальное значение даты
if ($this->DateExtract && $this->DateExtract->format('dmY') === '01012222') {
return true;
}
// Или проверяем по статусу
return $this->rf_kl_VisitStatusID === 0;
}
/**
* Получить реальную дату выписки (если пациент выписан)
*/
public function getActualDischargeDate(): ?Carbon
{
if (!$this->DateExtract) {
return null;
}
// Если это специальное значение - значит не выписан
if ($this->DateExtract->format('dmY') === '01012222') {
return null;
}
return $this->DateExtract;
}
/**
* Рассчитать койко-дни для данной истории болезни
*/
public function getBedDays(): int
{
if (!$this->DateRecipient) {
return 0;
}
$start = Carbon::parse($this->DateRecipient);
// Определяем дату окончания
if ($this->isStillInHospital()) {
// Пациент еще в стационаре
$end = Carbon::now();
} else {
// Пациент выписан
$end = Carbon::parse($this->DateExtract);
}
return $start->diffInDays($end);
}
public function observationPatient()
{
return $this->hasMany(ObservationPatient::class, 'rf_medicalhistory_id', 'MedicalHistoryID');

View File

@@ -3,9 +3,15 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Carbon;
class Report extends Model
{
/**
* ID метрики для среднего койко-дня
*/
const METRIC_BED_DAYS_ID = 18;
protected $primaryKey = 'report_id';
public $timestamps = false;
@@ -41,4 +47,70 @@ class Report extends Model
{
return $this->belongsTo(MisLpuDoctor::class, 'rf_lpudoctor_id');
}
/**
* Связь со снапшотами
*/
public function snapshots()
{
return $this->hasMany(MedicalHistorySnapshot::class, 'rf_report_id', 'report_id');
}
/**
* Получить выписанных пациентов из снапшотов
*/
public function getDischargedPatientsOnSnapshots()
{
return $this->snapshots()
->where('patient_type', MedicalHistorySnapshot::PATIENT_TYPE_DISCHARGED)
->distinct()
->with('medicalHistory')
->get();
}
/**
* Получить текущих пациентов из снапшотов
*/
public function getCurrentPatientsOnSnapshots()
{
return $this->snapshots()
->where('patient_type', MedicalHistorySnapshot::PATIENT_TYPE_CURRENT)
->with('medicalHistory')
->get();
}
/**
* Рассчитать и сохранить средний койко-день на основе снапшотов
*/
public function calculateAndSaveAverageBedDays()
{
$dischargedPatients = $this->getDischargedPatientsOnSnapshots();
if ($dischargedPatients->isEmpty()) {
$avgBedDays = 0;
} else {
$totalDays = 0;
foreach ($dischargedPatients as $snapshot) {
$history = $snapshot->medicalHistory;
if ($history && $history->DateRecipient && $history->DateExtract) {
$start = Carbon::parse($history->DateRecipient);
$end = Carbon::parse($history->DateExtract);
$days = $start->diffInDays($end);
$totalDays += $days;
}
}
$avgBedDays = round($totalDays / $dischargedPatients->count(), 1);
}
// Сохраняем результат как метрику
MetrikaResult::updateOrCreate([
'rf_report_id' => $this->report_id,
'rf_metrika_item_id' => self::METRIC_BED_DAYS_ID,
],
[
'value' => $avgBedDays,
]);
return $avgBedDays;
}
}