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']), ]); } }