patients); $startDate = Carbon::parse($this->dateRange[0]); $endDate = Carbon::parse($this->dateRange[1]); return [ 'title' => sprintf('%s «%s»', $this->reportName, $this->department->name_full ?? $this->department->name_short), 'day' => $startDate->format('d'), 'month' => $startDate->locale('ru')->getTranslatedMonthName('Do MMMM'), 'year' => $endDate->format('Y'), 'planned' => $this->urgencyGroup($patients, 'planned'), 'urgent' => $this->urgencyGroup($patients, 'urgent'), 'inDepartment' => $patients->where('period_flags.current_at_end', true)->count(), 'plannedOperations' => $this->operationsGroup($patients, [6]), 'urgentOperations' => $this->operationsGroup($patients, [4, 5]), 'reanimation' => $this->flagGroup($patients, 'in_reanimation'), 'observables' => $this->observableGroup($patients), 'deceased' => $this->flagGroup($patients, 'period_flags.deceased'), ]; } private function urgencyGroup(Collection $patients, string $flag): array { // Поступившие именно в этот отчётный период (сутки), а не все, кто вообще сейчас в отделении $filtered = $patients ->where('period_flags.recipient', true) ->where("period_flags.{$flag}", true) ->values(); return [ 'count' => $filtered->count(), 'patients' => $filtered->map(fn (array $p) => $this->presentPatient($p))->all(), ]; } private function operationsGroup(Collection $patients, array $urgentStatuses): array { // latest_migration.operations уже ограничены периодом (start_date в рамках суток), // в отличие от верхнеуровневого operations, у которого нижняя граница не задана $filtered = $patients->filter(function (array $p) use ($urgentStatuses) { return collect(data_get($p, 'latest_migration.operations', [])) ->whereIn('urgent_status', $urgentStatuses) ->isNotEmpty(); })->values(); return [ 'count' => $filtered->count(), 'patients' => $filtered->map(fn (array $p) => $this->presentPatient($p, withDiagnosis: false))->all(), ]; } private function flagGroup(Collection $patients, string $flag): array { $filtered = $patients->where($flag, true)->values(); return [ 'count' => $filtered->count(), 'patients' => $filtered->map(fn (array $p) => $this->presentPatient($p))->all(), ]; } private function presentPatient(array $patient, bool $withDiagnosis = true): array { $age = ! empty($patient['birth_date']) ? (int) Carbon::parse($patient['birth_date'])->diffInYears(Carbon::parse($this->dateRange[1])) : null; return [ 'full_name' => $patient['full_name'], 'age' => $age !== null ? "{$age} ".$this->pluralizeAge($age) : '', 'diagnosis' => $withDiagnosis ? (data_get($patient, 'latest_migration.diagnosis_name') ?? '') : null, 'migration_id' => (data_get($patient, 'latest_migration.original_id') ?? ''), 'observable_reason' => (data_get($patient, 'observable.observable_reason') ?? '') ]; } private function observableGroup(Collection $patients): array { // Поступившие именно в этот отчётный период (сутки), а не все, кто вообще сейчас в отделении $filtered = $patients ->where('in_observable', true) ->values(); return [ 'count' => $filtered->count(), 'patients' => $filtered->map(fn (array $p) => $this->presentPatient($p))->all(), ]; } private function pluralizeAge(int $age): string { $mod100 = $age % 100; $mod10 = $age % 10; if ($mod100 >= 11 && $mod100 <= 14) { return 'лет'; } return match ($mod10) { 1 => 'год', 2, 3, 4 => 'года', default => 'лет', }; } }