Files
onboard/app/Services/PatientMigrationService.php
2026-04-21 10:08:14 +09:00

179 lines
7.2 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Services;
use App\Data\UnifiedPatientData;
use App\Models\MisMigrationPatient;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
class PatientMigrationService
{
private const ACTIVE_DATE_OUT = '2222-01-01 00:00:00';
const DEAD_VISIT_RESULT_IDS = [5, 6, 15, 16];
const TRANSFER_VISIT_RESULT_IDS = [2, 3, 4, 12, 13, 14, 35];
const OUTCOME_VISIT_RESULT_IDS = [1, 11];
public function __construct(
protected StationarBranchService $branchService
) { }
/**
* Получить всех пациентов в отделении за период
*/
public function getMigrationsInBranch(int $branchId, string $startAt, string $endAt): Collection
{
return $this->getMigrationsCached(
branchId: $branchId,
startAt: $startAt,
endAt: $endAt,
cacheTag: 'migrations_in_branch',
dateFilter: fn($q) => $q->where('DateOut', '>', $startAt)->where('DateOut', '<=', $endAt),
);
}
/**
* Получить текущих пациентов в отделении (активные)
*/
public function getMigrationsInBranchCurrent(int $branchId, string $startAt, string $endAt): Collection
{
return $this->getMigrationsCached(
branchId: $branchId,
startAt: $startAt,
endAt: $endAt,
cacheTag: 'migrations_in_branch_current',
dateFilter: fn($q) => $q->where('DateOut', self::ACTIVE_DATE_OUT),
);
}
/**
* Получить текущих пациентов в отделении (активные)
*/
public function getMigrationsInBranchDead(int $branchId, string $startAt, string $endAt): Collection
{
return $this->getMigrationsCached(
branchId: $branchId,
startAt: $startAt,
endAt: $endAt,
cacheTag: 'migrations_in_branch_dead',
dateFilter: fn($q) => $q->where('DateOut', '>', $startAt)->where('DateOut', '<=', $endAt),
additionalFilters: [
[
'key' => 'visit_result:dead',
'apply' => fn($q) => $q->whereIn('rf_kl_VisitResultID', self::DEAD_VISIT_RESULT_IDS)
]
]
);
}
public function getMigrationsInBranchTransfer(int $branchId, string $startAt, string $endAt): Collection
{
return $this->getMigrationsCached(
branchId: $branchId,
startAt: $startAt,
endAt: $endAt,
cacheTag: 'migrations_in_branch_transfer',
dateFilter: fn($q) => $q->where('DateOut', '>', $startAt)->where('DateOut', '<=', $endAt),
additionalFilters: [
[
'key' => 'visit_result:transfer',
'apply' => fn($q) => $q->whereIn('rf_kl_VisitResultID', self::TRANSFER_VISIT_RESULT_IDS)
]
]
);
}
public function getMigrationsInBranchOutcome(int $branchId, string $startAt, string $endAt): Collection
{
return $this->getMigrationsCached(
branchId: $branchId,
startAt: $startAt,
endAt: $endAt,
cacheTag: 'migrations_in_branch_outcome',
dateFilter: fn($q) => $q->where('DateOut', '>', $startAt)->where('DateOut', '<=', $endAt),
additionalFilters: [
[
'key' => 'visit_result:outcome',
'apply' => fn($q) => $q->whereIn('rf_kl_VisitResultID', self::OUTCOME_VISIT_RESULT_IDS)
]
]
);
}
/**
* Базовый метод с кешированием и общей логикой
*/
protected function getMigrationsCached(
int $branchId,
string $startAt,
string $endAt,
string $cacheTag,
\Closure $dateFilter,
array $additionalFilters = []
): Collection {
// Исключения
if (in_array($branchId, [0], true)) {
return collect();
}
// Нормализованный ключ кеша
$filterKeys = array_column($additionalFilters, 'key');
$filterHash = substr(md5(implode('|', $filterKeys)), 0, 6);
$dateHash = substr(md5($startAt . '_' . $endAt), 0, 8);
$cacheKey = "{$cacheTag}_{$branchId}_{$dateHash}_f{$filterHash}";
return Cache::tags([$cacheTag, "migrations_branch_{$branchId}"])
->remember($cacheKey, now()->addHours(6), function () use ($branchId, $startAt, $endAt, $dateFilter, $additionalFilters) {
return $this->buildBaseQuery($branchId, $startAt, $endAt)
->tap($dateFilter)
->tap(function ($q) use ($additionalFilters) {
foreach ($additionalFilters as $filter) {
if (isset($filter['apply']) && $filter['apply'] instanceof \Closure) {
$filter['apply']($q);
}
}
})
->get()
->each(function ($result) {
return UnifiedPatientData::fromMisMigrationPatient($result);
});
});
}
/**
* Строит базовый запрос с общими условиями и связями
*/
protected function buildBaseQuery(int $branchId, string $startAt, string $endAt): Builder
{
return MisMigrationPatient::query()
->select([
'MigrationPatientID', 'DateIngoing', 'DateOut', 'BedDays', 'rf_MedicalHistoryID',
'rf_StationarBranchID', 'rf_DiagnosID', 'rf_kl_ProfitTypeID', 'rf_kl_StatCureResultID',
'rf_kl_VisitResultID', 'rf_BedProfileID', 'rf_kl_BedProfileID'
])
->where('rf_StationarBranchID', $branchId)
// Жадная загрузка с ограничениями
->with([
'medicalHistory' => fn($q) => $q->select('MedicalHistoryID', 'FAMILY', 'Name', 'OT', 'BD'),
'medicalHistory.operationPurpose' => fn($q) => $q
->where('rf_StationarBranchID', $branchId)
->select('OperationPurposeID', 'rf_MedicalHistoryID', 'Date', 'rf_OperationStatusID',
'CancelDate', 'rf_StationarBranchID', 'PhysicalExam', 'Description', 'Indications', 'EpicrisDate',
'rf_SurgicalOperationID'
),
'medicalHistory.operationPurpose.surgicalOperation' => fn($q) => $q
->select('SurgicalOperationID', 'DataEnd', 'Date', 'Num', 'rf_kl_ServiceMedicalID',
'rf_MedicalHistoryID', 'rf_StationarBranchID', 'Description', 'rf_OperationResultID'
),
'diagnosis' => fn($q) => $q
->where('rf_DiagnosTypeID', 3)
->select('DiagnosID', 'Date', 'rf_DiagnosTypeID', 'rf_MedicalHistoryID', 'rf_MKBID',
'rf_MigrationPatientID', 'Description'
),
'diagnosis.mkb' => fn($q) => $q->select(['MKBID', 'DS', 'NAME']),
]);
}
}