>|null */ private ?array $departments = null; /** * @return list> */ public function departments(): array { if ($this->departments !== null) { return $this->departments; } $directory = config('medical-report.source_directory'); if (! is_string($directory) || $directory === '' || ! is_dir($directory)) { return $this->departments = []; } /** @var array> $sourcesByCanonicalName */ $sourcesByCanonicalName = []; foreach (File::files($directory) as $file) { $sourceName = $file->getFilenameWithoutExtension(); $canonicalName = $this->canonicalName($sourceName); $sourcesByCanonicalName[$canonicalName] ??= []; $sourcesByCanonicalName[$canonicalName][] = [ 'name' => $file->getFilename(), 'path' => $file->getPathname(), 'extension' => strtolower($file->getExtension()), 'canonical_name' => $canonicalName, ]; } $reportingUnitSources = config('medical-report.reporting_unit_sources', []); $departments = []; $databaseReportingUnits = HospitalUnit::query() ->with('profile:id,name,sort_order') ->where('is_reporting_unit', true) ->where('is_active', true) ->get() ->sortBy([ fn (HospitalUnit $unit): int => $unit->profile?->sort_order ?? PHP_INT_MAX, fn (HospitalUnit $unit): string => $unit->name, ]) ->values(); $profileNamesByUnit = collect(config('medical-report.finance_profiles', [])) ->flatMap(function (array $profile): array { return collect($profile['units'] ?? []) ->filter(fn (mixed $unit): bool => is_string($unit) && trim($unit) !== '') ->mapWithKeys(fn (string $unit): array => [$unit => $profile['name']]) ->all(); }) ->all(); if ($databaseReportingUnits->isNotEmpty()) { foreach ($databaseReportingUnits as $unit) { $mappedSourceNames = $reportingUnitSources[$unit->name] ?? [$unit->name]; $sources = collect($mappedSourceNames) ->filter(fn (mixed $sourceName): bool => is_string($sourceName) && trim($sourceName) !== '') ->flatMap(fn (string $sourceName): array => $sourcesByCanonicalName[$sourceName] ?? []) ->sortBy(fn (array $source): int => match ($source['extension']) { 'xlsx' => 0, 'pdf' => 1, default => 2, }) ->values() ->all(); if ($sources === []) { continue; } $departments[] = [ 'id' => $unit->id, 'key' => $unit->slug, 'name' => $unit->name, 'profile_name' => $unit->profile?->name, 'report_input_type' => $unit->report_input_type, 'report_input_type_label' => $this->reportInputTypeLabel($unit->report_input_type), 'template_name' => $sources[0]['canonical_name'] ?? $unit->name, 'sources' => array_map(fn (array $source): array => [ 'name' => $source['name'], 'path' => $source['path'], 'extension' => $source['extension'], ], $sources), ]; } return $this->departments = $departments; } foreach (config('medical-report.reporting_units', []) as $unitName) { if (! is_string($unitName) || trim($unitName) === '') { continue; } $mappedSourceNames = $reportingUnitSources[$unitName] ?? [$unitName]; $sources = collect($mappedSourceNames) ->filter(fn (mixed $sourceName): bool => is_string($sourceName) && trim($sourceName) !== '') ->flatMap(fn (string $sourceName): array => $sourcesByCanonicalName[$sourceName] ?? []) ->sortBy(fn (array $source): int => match ($source['extension']) { 'xlsx' => 0, 'pdf' => 1, default => 2, }) ->values() ->all(); if ($sources === []) { continue; } $departments[] = [ 'key' => Str::slug(Str::ascii($unitName)), 'name' => $unitName, 'profile_name' => $profileNamesByUnit[$unitName] ?? null, 'report_input_type' => config('medical-report.reporting_unit_input_types.'.$unitName), 'report_input_type_label' => $this->reportInputTypeLabel( config('medical-report.reporting_unit_input_types.'.$unitName) ), 'template_name' => $sources[0]['canonical_name'] ?? $unitName, 'sources' => array_map(fn (array $source): array => [ 'name' => $source['name'], 'path' => $source['path'], 'extension' => $source['extension'], ], $sources), ]; } return $this->departments = $departments; } public function canonicalName(string $sourceName): string { $aliases = config('medical-report.aliases', []); if (is_array($aliases) && isset($aliases[$sourceName]) && is_string($aliases[$sourceName])) { return $aliases[$sourceName]; } return Str::of($sourceName) ->replaceMatches('/\s+/', ' ') ->trim() ->toString(); } private function reportInputTypeLabel(?string $reportInputType): ?string { if ($reportInputType === null || $reportInputType === '') { return null; } $label = config('medical-report.report_input_type_labels.'.$reportInputType); return is_string($label) && $label !== '' ? $label : $reportInputType; } }