*/ public function pageData(MedicalReport $medicalReport, ?string $selectedDepartmentKey = null): array { $departments = $this->templateWorkbook->departments(); $selectedDepartmentKey ??= $departments[0]['key'] ?? null; $selectedDepartment = $selectedDepartmentKey === null ? null : collect($departments)->firstWhere('key', $selectedDepartmentKey); $selectedHospitalUnitId = $selectedDepartment['id'] ?? null; $databaseTemplateKeys = MedicalReportFormTemplate::query() ->with('hospitalUnit:id,slug') ->get() ->map(fn (MedicalReportFormTemplate $template): ?string => $template->hospitalUnit?->slug ?: $template->department_key) ->filter() ->values() ->all(); $databaseTemplate = $selectedDepartmentKey === null ? null : MedicalReportFormTemplate::query() ->where(function ($query) use ($selectedHospitalUnitId, $selectedDepartmentKey): void { if ($selectedHospitalUnitId !== null) { $query->where('hospital_unit_id', $selectedHospitalUnitId) ->orWhere('department_key', $selectedDepartmentKey); return; } $query->where('department_key', $selectedDepartmentKey); }) ->first(); $effectiveTemplate = $selectedDepartmentKey === null ? null : $this->structuredTemplateRegistry->templateForDepartment($selectedDepartmentKey); $blueprintTemplate = $selectedDepartment === null ? null : $this->reportInputTypeBlueprintFactory->templateForDepartment($selectedDepartment); $builderStarterTemplate = $selectedDepartment === null ? null : ($databaseTemplate !== null ? $effectiveTemplate : ($blueprintTemplate ?? $effectiveTemplate)); $starterSource = $databaseTemplate !== null ? 'database' : ($blueprintTemplate !== null ? 'blueprint' : 'source'); return [ 'report' => [ 'id' => $medicalReport->id, 'name' => $medicalReport->name, 'year' => $medicalReport->year, 'updated_at' => $medicalReport->updated_at?->toIso8601String(), ], 'selectedDepartment' => $selectedDepartmentKey, 'departments' => array_map(function (array $department) use ($databaseTemplateKeys): array { return [ ...$department, 'has_builder_template' => in_array($department['key'], $databaseTemplateKeys, true), ]; }, $departments), 'builder' => $selectedDepartment === null ? null : [ 'department' => [ 'key' => $selectedDepartment['key'], 'name' => $selectedDepartment['name'], 'profile_name' => $selectedDepartment['profile_name'] ?? null, 'report_input_type' => $selectedDepartment['report_input_type'] ?? null, 'report_input_type_label' => $selectedDepartment['report_input_type_label'] ?? null, 'sources' => $selectedDepartment['sources'] ?? [], ], 'template' => $this->builderTemplate( $selectedDepartment['key'], $selectedDepartment['name'], $builderStarterTemplate, $effectiveTemplate['department_options'] ?? null, ), 'uses_database_template' => $databaseTemplate !== null, 'starter_source' => $starterSource, ], ]; } /** * @param array|null $effectiveTemplate * @param array|null $fallbackDepartmentOptions * @return array */ private function builderTemplate( string $departmentKey, string $departmentName, ?array $effectiveTemplate, ?array $fallbackDepartmentOptions = null, ): array { $sections = collect($effectiveTemplate['sections'] ?? []) ->map(function (array $section): array { return [ 'key' => (string) $section['key'], 'title' => (string) $section['title'], 'economist_label' => (string) ($section['economist_label'] ?? ''), 'fields' => array_values($section['fields'] ?? []), 'export_metrics' => $this->exportMetrics( $section['export_metrics'] ?? [], $section['fields'] ?? [], ), 'default_entries' => array_values($section['default_entries'] ?? [$section['empty_entry'] ?? []]), ]; }) ->values() ->all(); if ($sections === [] && $effectiveTemplate !== null) { $sections = [[ 'key' => 'main', 'title' => 'Основной блок', 'economist_label' => $departmentName.' / Основной блок', 'fields' => array_values($effectiveTemplate['fields'] ?? []), 'export_metrics' => $this->exportMetrics( $effectiveTemplate['export_metrics'] ?? [], $effectiveTemplate['fields'] ?? [], ), 'default_entries' => array_values($effectiveTemplate['default_entries'] ?? [$effectiveTemplate['empty_entry'] ?? []]), ]]; } if ($sections === []) { $sections = [[ 'key' => 'main', 'title' => 'Основной блок', 'economist_label' => $departmentName.' / Основной блок', 'fields' => [ ['key' => 'name', 'label' => 'Показатель', 'type' => 'text'], ['key' => 'value', 'label' => 'Значение', 'type' => 'number'], ], 'export_metrics' => [ [ 'key' => 'value_total', 'label' => 'Значение', 'source_field' => 'value', 'aggregation' => 'sum', ], ], 'default_entries' => [ ['name' => '', 'value' => '0'], ], ]]; } return [ 'department' => $departmentKey, 'name' => (string) ($effectiveTemplate['title'] ?? $departmentName), 'description' => (string) ($effectiveTemplate['description'] ?? ''), 'department_options' => $effectiveTemplate['department_options'] ?? $fallbackDepartmentOptions ?? $this->departmentOptions(), 'analysis_columns' => $this->analysisColumns(), 'analysis_units' => $this->analysisUnits(), 'schema' => [ 'title' => (string) ($effectiveTemplate['title'] ?? $departmentName), 'description' => (string) ($effectiveTemplate['description'] ?? ''), 'sections' => $sections, ], ]; } /** * @return list */ private function departmentOptions(): array { return Department::query() ->where('is_active', true) ->orderBy('name') ->get(['id', 'name']) ->map(fn (Department $department): array => [ 'id' => $department->id, 'name' => $department->name, ]) ->all(); } /** * @param list> $configuredMetrics * @param list> $fields * @return list */ private function exportMetrics(array $configuredMetrics, array $fields): array { if ($configuredMetrics !== []) { return collect($configuredMetrics) ->map(fn (array $metric): array => [ 'key' => (string) ($metric['key'] ?? ''), 'label' => (string) ($metric['label'] ?? ''), 'source_field' => (string) ($metric['source_field'] ?? ''), 'aggregation' => (string) ($metric['aggregation'] ?? 'sum'), 'analysis_column' => ($metric['analysis_column'] ?? null) !== null ? (string) $metric['analysis_column'] : null, 'row_mode' => ($metric['row_mode'] ?? null) !== null ? (string) $metric['row_mode'] : null, 'target_unit_slug' => ($metric['target_unit_slug'] ?? null) !== null ? (string) $metric['target_unit_slug'] : null, ]) ->all(); } $hasDepartmentSelect = collect($fields) ->contains(fn (array $field): bool => ($field['type'] ?? null) === 'department-select'); return collect($fields) ->filter(fn (array $field): bool => ($field['type'] ?? 'text') === 'number') ->map(fn (array $field): array => [ 'key' => (string) $field['key'].'_total', 'label' => (string) $field['label'], 'source_field' => (string) $field['key'], 'aggregation' => 'sum', 'analysis_column' => null, 'row_mode' => $hasDepartmentSelect ? 'entry_department' : 'fixed_unit', 'target_unit_slug' => null, ]) ->values() ->all(); } /** * @return list */ private function analysisColumns(): array { return collect(config('medical-report.economist_analysis_columns', [])) ->filter(fn (mixed $column): bool => is_array($column)) ->map(fn (array $column): array => [ 'key' => (string) ($column['key'] ?? ''), 'label' => (string) ($column['label'] ?? ''), 'coordinate' => (string) ($column['coordinate'] ?? ''), ]) ->filter(fn (array $column): bool => $column['key'] !== '' && $column['label'] !== '') ->values() ->all(); } /** * @return list */ private function analysisUnits(): array { return HospitalUnit::query() ->where('is_active', true) ->orderBy('name') ->get(['slug', 'name']) ->map(fn (HospitalUnit $hospitalUnit): array => [ 'slug' => $hospitalUnit->slug, 'name' => $hospitalUnit->name, ]) ->all(); } }