first commit
This commit is contained in:
269
app/Support/MedicalReport/FormTemplateBuilderPage.php
Normal file
269
app/Support/MedicalReport/FormTemplateBuilderPage.php
Normal file
@@ -0,0 +1,269 @@
|
||||
<?php
|
||||
|
||||
namespace App\Support\MedicalReport;
|
||||
|
||||
use App\Models\Department;
|
||||
use App\Models\HospitalUnit;
|
||||
use App\Models\MedicalReport;
|
||||
use App\Models\MedicalReportFormTemplate;
|
||||
|
||||
class FormTemplateBuilderPage
|
||||
{
|
||||
public function __construct(
|
||||
private readonly TemplateWorkbook $templateWorkbook,
|
||||
private readonly StructuredTemplateRegistry $structuredTemplateRegistry,
|
||||
private readonly ReportInputTypeBlueprintFactory $reportInputTypeBlueprintFactory,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
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<string, mixed>|null $effectiveTemplate
|
||||
* @param array<int, array{id: int, name: string}>|null $fallbackDepartmentOptions
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
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<array{id: int, name: string}>
|
||||
*/
|
||||
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<array<string, mixed>> $configuredMetrics
|
||||
* @param list<array<string, mixed>> $fields
|
||||
* @return list<array{key: string, label: string, source_field: string, aggregation: string}>
|
||||
*/
|
||||
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<array{key: string, label: string, coordinate: string}>
|
||||
*/
|
||||
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<array{slug: string, name: string}>
|
||||
*/
|
||||
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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user