Files
onboard/app/Http/Controllers/Web/ReportController.php
2026-05-06 22:32:11 +09:00

200 lines
7.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
namespace App\Http\Controllers\Web;
use App\Exports\ReportPageExport;
use App\Http\Controllers\Controller;
use App\Http\Resources\Mis\FormattedPatientResource;
use App\Models\Department;
use App\Services\DateRangeService;
use App\Services\ReportPageService;
use App\Services\ReportService;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Inertia\Inertia;
use Maatwebsite\Excel\Facades\Excel;
class ReportController extends Controller
{
public function __construct(
protected ReportPageService $reportPageService,
protected ReportService $reportService,
protected DateRangeService $dateRangeService,
) {}
public function index(Request $request)
{
$user = Auth::user();
$departmentId = $request->query('departmentId', $user->department->department_id);
$department = Department::where('department_id', $departmentId)->firstOrFail();
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
return Inertia::render('Report/Index', $this->reportPageService->build($department, $user, $dateRange));
}
public function store(Request $request)
{
$validated = $request->validate([
'metrics' => 'required|array',
'observationPatients' => 'nullable|array',
'departmentId' => 'required|integer',
'unwantedEvents' => 'nullable|array',
'dates' => 'required|array',
'userId' => 'required|integer',
'reportId' => 'nullable|integer',
'status' => 'nullable|in:draft,submitted',
]);
$this->reportService->storeReport($validated, Auth::user());
return redirect()->route('start');
}
public function export(Request $request)
{
$user = Auth::user();
$departmentId = $request->query('departmentId', $user->department->department_id);
$department = Department::where('department_id', $departmentId)->firstOrFail();
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
$statistics = $this->reportService->getReportStatistics($department, $user, $dateRange);
$counts = $this->reportService->getPatientsCountsMap($department, $user, $dateRange);
$statusGroups = [
'МИС' => [
'mis-plan' => 'Планово',
'mis-emergency' => 'Экстренно',
'mis-observation' => 'На контроле',
'mis-reanimation' => 'Реанимация',
'mis-outcome-discharged' => 'Выписанные',
'mis-outcome-deceased' => 'Умершие',
'mis-outcome-transferred' => 'Переведенные',
],
'Спец. контингент' => [
'special-plan' => 'Планово',
'special-emergency' => 'Экстренно',
'special-observation' => 'На контроле',
'special-outcome-discharged' => 'Выписанные',
'special-outcome-deceased' => 'Умершие',
'special-outcome-transferred' => 'Переведенные',
],
];
$summaryRows = [
['Показатель', 'Значение'],
['Отделение', $department->name_full],
['Период', $dateRange->startSql().' - '.$dateRange->endSql()],
['Сформирован', now('Asia/Yakutsk')->format('Y-m-d H:i:s')],
['Коек', $statistics['beds'] ?? 0],
['Поступило', $statistics['recipientCount'] ?? 0],
['Выбыло', $statistics['extractCount'] ?? 0],
['Состоит', $statistics['currentCount'] ?? 0],
['Умерло', $statistics['deadCount'] ?? 0],
['% смертности', $statistics['percentDead'] ?? 0],
['% загруженности', $statistics['percentLoadedBeds'] ?? 0],
[''],
['Раздел / Статус', 'Количество'],
];
foreach ($statusGroups as $groupLabel => $groupStatuses) {
$summaryRows[] = [$groupLabel, ''];
foreach ($groupStatuses as $status => $label) {
$summaryRows[] = [$label, $counts[$status] ?? 0];
}
}
$patientRows = [[
'Раздел',
'Статус',
'ФИО',
'Возраст',
'Дата рождения',
'Дата поступления',
'Код диагноза',
'Диагноз',
'Операции',
'Состояние (реанимация)',
'Период закрыт (реанимация)',
]];
foreach ($statusGroups as $groupLabel => $groupStatuses) {
$patientRows[] = [$groupLabel, '', '', '', '', '', '', '', '', '', ''];
foreach ($groupStatuses as $status => $label) {
$patients = collect($this->reportService->getPatientsByStatus(
$department,
$user,
$status,
$dateRange
));
if ($status === 'mis-reanimation') {
$this->attachReanimationIndicators($patients, (int) $department->department_id);
}
$resolvedPatients = FormattedPatientResource::collection($patients)->resolve();
foreach ($resolvedPatients as $patient) {
$operations = collect($patient['operations'] ?? [])
->map(fn ($operation) => $operation['code'] ?? $operation['name'] ?? null)
->filter()
->implode(', ');
$patientRows[] = [
$groupLabel,
$label,
$patient['fullname'] ?? '',
$patient['age'] ?? '',
$patient['birth_date'] ?? '',
$patient['admitted_at'] ?? '',
$patient['mkb']['ds'] ?? '',
$patient['mkb']['name'] ?? '',
$operations,
$patient['reanimation_indicator'] ?? '',
isset($patient['reanimation_is_complete']) && $patient['reanimation_is_complete'] ? 'Да' : 'Нет',
];
}
}
}
$fileName = sprintf(
'report_%d_%s.xlsx',
$department->department_id,
now('Asia/Yakutsk')->format('Ymd_His')
);
return Excel::download(new ReportPageExport($summaryRows, $patientRows), $fileName);
}
private function attachReanimationIndicators(Collection $patients, int $departmentId): void
{
if ($patients->isEmpty()) {
return;
}
$medicalHistoryIds = $patients
->map(fn ($patient) => (int) ($patient->medicalHistoryId ?? $patient->MedicalHistoryID ?? 0))
->filter()
->unique()
->values()
->all();
if (empty($medicalHistoryIds)) {
return;
}
$latestIndicators = $this->reportService->getLatestReanimationIndicators($departmentId, $medicalHistoryIds);
$patients->transform(function ($patient) use ($latestIndicators) {
$medicalHistoryId = (int) ($patient->medicalHistoryId ?? $patient->MedicalHistoryID ?? 0);
$indicator = $medicalHistoryId ? $latestIndicators->get($medicalHistoryId) : null;
$patient->reanimation_indicator = $indicator?->indicator;
$patient->reanimation_comment = $indicator?->comment;
return $patient;
});
}
}