247 lines
8.9 KiB
PHP
247 lines
8.9 KiB
PHP
<?php
|
||
|
||
namespace App\Services;
|
||
|
||
use App\Models\MedicalHistory;
|
||
use App\Models\MigrationPatient;
|
||
use App\Models\MisMedicalHistory;
|
||
use Illuminate\Support\Facades\Schema;
|
||
|
||
class OutcomePatientService
|
||
{
|
||
// Базовый select по пациенту
|
||
private function patientSelect(): array
|
||
{
|
||
return [
|
||
'MedicalHistoryID',
|
||
'FAMILY',
|
||
'Name',
|
||
'OT',
|
||
'BD',
|
||
'DateRecipient',
|
||
'DateExtract',
|
||
'DateDeath',
|
||
'rf_EmerSignID',
|
||
'rf_kl_VisitResultID',
|
||
];
|
||
}
|
||
|
||
// Базовые relation для выбытия
|
||
private function outcomeRelations(): array
|
||
{
|
||
return [
|
||
'outcomeMigration' => function ($q) {
|
||
$q->select([
|
||
'stt_migrationpatient.MigrationPatientID',
|
||
'stt_migrationpatient.rf_MedicalHistoryID',
|
||
'stt_migrationpatient.DateOut',
|
||
'stt_migrationpatient.rf_DiagnosID',
|
||
'stt_migrationpatient.rf_kl_VisitResultID',
|
||
'stt_migrationpatient.rf_StationarBranchID',
|
||
])->with(['mainDiagnosis' => function ($diagnosisQuery) {
|
||
$diagnosisQuery->select([
|
||
'DiagnosID',
|
||
'rf_MKBID',
|
||
])->with(['mkb' => function ($mkbQuery) {
|
||
$mkbQuery->select([
|
||
'MKBID',
|
||
'DS',
|
||
'NAME',
|
||
]);
|
||
}]);
|
||
}]);
|
||
},
|
||
];
|
||
}
|
||
|
||
public function getOutcomePatients(
|
||
int $branchId,
|
||
DateRange $dateRange,
|
||
string $outcomeType = 'all',
|
||
bool $onlyIds = false
|
||
) {
|
||
if ($this->useMaterializedViews()) {
|
||
return $this->getOutcomePatientsFromMaterializedViews($branchId, $dateRange, $outcomeType, $onlyIds);
|
||
}
|
||
|
||
return match ($outcomeType) {
|
||
'deceased' => $this->getBranchDeceasedPatients($branchId, $dateRange, $onlyIds),
|
||
'transferred' => $this->getBranchTransferredPatients($branchId, $dateRange, $onlyIds),
|
||
'discharged' => $this->getBranchDischargedPatients($branchId, $dateRange, $onlyIds),
|
||
'without-transferred' => $this->getBranchOutcomePatientsWithoutTransferred($branchId, $dateRange, $onlyIds),
|
||
default => $this->getAllBranchOutcomePatients($branchId, $dateRange, $onlyIds),
|
||
};
|
||
}
|
||
|
||
// Общий фильтр периода
|
||
private function applyPeriod($query, string $column, DateRange $dateRange)
|
||
{
|
||
return $query
|
||
->where($column, '>=', $dateRange->startSql())
|
||
->where($column, '<', $dateRange->endSql());
|
||
}
|
||
|
||
// Форматирование результата
|
||
private function finalizePatientsQuery($query, bool $onlyIds = false)
|
||
{
|
||
if ($onlyIds) {
|
||
return $query->pluck('MedicalHistoryID');
|
||
}
|
||
|
||
return $query
|
||
->select($this->patientSelect())
|
||
->with($this->outcomeRelations())
|
||
->orderBy('DateRecipient', 'DESC')
|
||
->get();
|
||
}
|
||
|
||
// Умершие в отделении. Фильтруем по движению пациента, по дате смерти. Без DateExtract
|
||
public function getBranchDeceasedPatients(
|
||
int $branchId,
|
||
DateRange $dateRange,
|
||
bool $onlyIds = false
|
||
) {
|
||
$query = MisMedicalHistory::query()
|
||
->where('MedicalHistoryID', '<>', 0)
|
||
->whereHas('migrations', function ($q) use ($branchId) {
|
||
$q->where('rf_StationarBranchID', $branchId)
|
||
->whereIn('rf_kl_VisitResultID', [5, 6, 15, 16]);
|
||
});
|
||
|
||
$this->applyPeriod($query, 'DateDeath', $dateRange);
|
||
|
||
return $this->finalizePatientsQuery($query, $onlyIds);
|
||
}
|
||
|
||
// Переведенные из отделения
|
||
public function getBranchTransferredPatients(
|
||
int $branchId,
|
||
DateRange $dateRange,
|
||
bool $onlyIds = false
|
||
) {
|
||
$query = MisMedicalHistory::query()
|
||
->where('MedicalHistoryID', '<>', 0)
|
||
->whereHas('migrations', function ($q) use ($branchId) {
|
||
$q->where('rf_StationarBranchID', $branchId)
|
||
->whereIn('rf_kl_VisitResultID', [4, 14]);
|
||
});
|
||
|
||
$this->applyPeriod($query, 'DateExtract', $dateRange);
|
||
|
||
return $this->finalizePatientsQuery($query, $onlyIds);
|
||
}
|
||
|
||
// Выписанные из стационара, связанные с отделением
|
||
public function getBranchDischargedPatients(
|
||
int $branchId,
|
||
DateRange $dateRange,
|
||
bool $onlyIds = false
|
||
) {
|
||
$query = MisMedicalHistory::query()
|
||
->where('MedicalHistoryID', '<>', 0)
|
||
->whereHas('migrations', function ($q) use ($branchId) {
|
||
$q->where('rf_StationarBranchID', $branchId)
|
||
->whereIn('rf_kl_VisitResultID', [1, 11, 2, 12, 7, 18, 48]);
|
||
});
|
||
|
||
$this->applyPeriod($query, 'DateExtract', $dateRange);
|
||
|
||
return $this->finalizePatientsQuery($query, $onlyIds);
|
||
}
|
||
|
||
// Выбывшие без переведенных
|
||
public function getBranchOutcomePatientsWithoutTransferred(
|
||
int $branchId,
|
||
DateRange $dateRange,
|
||
bool $onlyIds = false
|
||
) {
|
||
$query = MisMedicalHistory::query()
|
||
->where('MedicalHistoryID', '<>', 0)
|
||
->whereHas('migrations', function ($q) use ($branchId) {
|
||
$q->where('rf_StationarBranchID', $branchId)
|
||
->whereNotIn('rf_kl_VisitResultID', [4, 14])
|
||
->where('rf_kl_VisitResultID', '<>', 0);
|
||
});
|
||
|
||
$this->applyPeriod($query, 'DateExtract', $dateRange);
|
||
|
||
return $this->finalizePatientsQuery($query, $onlyIds);
|
||
}
|
||
|
||
// Все выбывшие из отделения
|
||
public function getAllBranchOutcomePatients(
|
||
int $branchId,
|
||
DateRange $dateRange,
|
||
bool $onlyIds = false
|
||
) {
|
||
$query = MisMedicalHistory::query()
|
||
->where('MedicalHistoryID', '<>', 0)
|
||
->whereHas('migrations', function ($q) use ($branchId) {
|
||
$q->where('rf_StationarBranchID', $branchId)
|
||
->where('rf_kl_VisitResultID', '<>', 0);
|
||
});
|
||
|
||
$this->applyPeriod($query, 'DateExtract', $dateRange);
|
||
|
||
return $this->finalizePatientsQuery($query, $onlyIds);
|
||
}
|
||
|
||
private function getOutcomePatientsFromMaterializedViews(
|
||
int $branchId,
|
||
DateRange $dateRange,
|
||
string $outcomeType,
|
||
bool $onlyIds
|
||
) {
|
||
$migrationQuery = MigrationPatient::query()
|
||
->where('stationar_branch_id', $branchId);
|
||
|
||
$migrationQuery = match ($outcomeType) {
|
||
'deceased' => $migrationQuery->deceased($dateRange->startSql(), $dateRange->endSql()),
|
||
'transferred' => $migrationQuery->transferred($dateRange->startSql(), $dateRange->endSql()),
|
||
'discharged' => $migrationQuery->discharged($dateRange->startSql(), $dateRange->endSql()),
|
||
'without-transferred' => $migrationQuery->where(function ($query) use ($dateRange) {
|
||
$query->discharged($dateRange->startSql(), $dateRange->endSql())
|
||
->orWhere(fn ($orQuery) => $orQuery->deceased($dateRange->startSql(), $dateRange->endSql()));
|
||
}),
|
||
default => $migrationQuery->where(function ($query) use ($dateRange) {
|
||
$query->discharged($dateRange->startSql(), $dateRange->endSql())
|
||
->orWhere(fn ($orQuery) => $orQuery->deceased($dateRange->startSql(), $dateRange->endSql()))
|
||
->orWhere(fn ($orQuery) => $orQuery->transferred($dateRange->startSql(), $dateRange->endSql()));
|
||
}),
|
||
};
|
||
|
||
$historyIds = $migrationQuery
|
||
->distinct()
|
||
->pluck('medical_history_id')
|
||
->filter()
|
||
->values()
|
||
->all();
|
||
|
||
if (empty($historyIds)) {
|
||
return $onlyIds ? collect() : collect();
|
||
}
|
||
|
||
$query = MedicalHistory::query()
|
||
->whereIn('id', $historyIds)
|
||
->with([
|
||
'latestMigration' => fn ($builder) => $builder->where('stationar_branch_id', $branchId),
|
||
'migrations' => fn ($builder) => $builder
|
||
->where('stationar_branch_id', $branchId)
|
||
->orderByDesc('ingoing_date'),
|
||
'operations',
|
||
])
|
||
->orderByDesc('recipient_date');
|
||
|
||
if ($onlyIds) {
|
||
return $query->pluck('original_id');
|
||
}
|
||
|
||
return $query->get();
|
||
}
|
||
|
||
private function useMaterializedViews(): bool
|
||
{
|
||
return Schema::hasTable('mv_medicalhistory_summary') && Schema::hasTable('mv_migrationpatient_details');
|
||
}
|
||
}
|