reportRegistry->availableFor($user); abort_if(empty($available), 403); $department = $this->resolveDepartment($request, $user); $dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user); // Без явного типа в запросе показываем только список отчётов — без предпросмотра. $type = $request->query('type'); $definition = $type ? $this->reportRegistry->find($type, $user) : null; $payload = $definition?->build($department, $dateRange); return Inertia::render('Reports/Index', [ 'reportTypes' => array_map(fn (ReportDefinition $d) => [ 'code' => $d->code(), 'label' => $d->label(), 'audience' => $this->audienceLabel($d->requiredPermissions()), ], $available), 'departments' => collect($user->availableDepartments())->map(fn (Department $d) => [ 'id' => $d->department_id, 'name' => $d->name_full ?? $d->name_short, ])->values()->all(), 'selectedType' => $definition?->code(), 'selectedDepartmentId' => $department->department_id, 'isHeadOrAdmin' => $user->isSeniorStaff(), 'date' => [ $dateRange->start()->getTimestampMs(), $dateRange->end()->getTimestampMs(), ], 'payload' => $payload ? [ 'title' => $payload->title, 'meta' => $payload->meta, 'sections' => array_map(fn ($section) => [ 'title' => $section->title, 'columns' => $section->columns, 'rows' => $section->rows, ], $payload->sections), ] : null, ]); } public function exportExcel(Request $request) { [$definition, $department, $dateRange] = $this->resolveExportContext($request); $payload = $definition->build($department, $dateRange); return Excel::download(new ReportExcelExport($payload), $this->fileName($definition, 'xlsx')); } public function exportPdf(Request $request) { [$definition, $department, $dateRange] = $this->resolveExportContext($request); $payload = $definition->build($department, $dateRange); return ReportPdfExport::render($payload)->download($this->fileName($definition, 'pdf')); } /** * @return array{0: ReportDefinition, 1: Department, 2: \App\Services\DateRange} */ private function resolveExportContext(Request $request): array { $user = Auth::user(); $type = $request->query('type'); $definition = $type ? $this->reportRegistry->find($type, $user) : null; abort_if($definition === null, 403); $department = $this->resolveDepartment($request, $user); $dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user); return [$definition, $department, $dateRange]; } private function resolveDepartment(Request $request, User $user): Department { $departmentId = $request->query('departmentId'); $available = collect($user->availableDepartments()); if ($departmentId && $available->contains(fn (Department $d) => (int) $d->department_id === (int) $departmentId)) { return $available->first(fn (Department $d) => (int) $d->department_id === (int) $departmentId); } return $user->department ?? $available->first(); } /** * @param array $permissions */ private function audienceLabel(array $permissions): string { if (empty($permissions)) { return 'Доступен всем'; } $labels = [ 'report.view' => 'Дежурный врач', 'nurse.report.view' => 'Старшая медсестра', ]; return implode(' · ', array_map(fn ($p) => $labels[$p] ?? $p, $permissions)); } private function fileName(ReportDefinition $definition, string $extension): string { $slug = str_replace([' ', ':', '/', '\\'], '_', $definition->label()); return sprintf('%s_%s.%s', $slug, now('Asia/Yakutsk')->format('Ymd_His'), $extension); } }