'string', ]; protected $fillable = [ 'fam', // Фамилия 'im', // Имя 'ot', // Отчество 'mpostdate', // Д. пост. (mpostdate) 'menddate', // Д. вып. (menddate) 'narhiv', // № в архиве 'datearhiv', // Д. архив 'snils', // Год нахождения в стационаре 'enp', // ЕНП 'nkarta', // № карты 'dr', // ДР ]; public function getFullNameAttribute() { return "$this->fam $this->im $this->ot"; } public function archiveHistory() { return $this->hasMany(ArchiveHistory::class, 'foxpro_history_id', 'keykarta'); } public function archiveInfo() { return $this->hasOne(ArchiveInfo::class, 'foxpro_history_id', 'keykarta'); } /** * Проверяет, можно ли выдать эту карту */ public function canBeIssued(): bool { // Проверяем, есть ли открытые выдачи $hasOpenIssue = $this->archiveHistory() ->whereNotNull('issue_at') ->whereNull('return_at') ->where('has_lost', false) ->exists(); $hasNotBadStatus = $this->archiveInfo() ->whereNotNull('status_id') ->whereNot('status_id', 1) ->whereNot('status_id', 3) ->whereNot('status_id', 4) ->exists(); return ($hasOpenIssue !== true && $hasNotBadStatus === true); } /** * Получает текущую открытую выдачу (если есть) */ public function getCurrentIssue(): ?ArchiveHistory { return $this->archiveHistory() ->whereNotNull('issue_at') ->whereNull('return_at') ->where('has_lost', false) ->latest('issue_at') ->first(); } public function scopeSearch($query, $searchText) { return $query->where(function($q) use ($searchText) { if (is_numeric($searchText)) { $q->where('medcardnum', 'ILIKE', "$searchText"); } else { // Ищем в объединенном ФИО и в отдельных полях $searchPattern = "%{$searchText}%"; $q->where(function($subQ) use ($searchPattern) { // Поиск в объединенной строке $subQ->whereRaw("CONCAT(family, ' ', name, ' ', COALESCE(ot, '')) ILIKE ?", [$searchPattern]) // И дополнительно в отдельных полях для точности ->orWhere('family', 'ILIKE', $searchPattern) ->orWhere('name', 'ILIKE', $searchPattern) ->orWhere('ot', 'ILIKE', $searchPattern); }); } }); } }