202 lines
7.9 KiB
PHP
202 lines
7.9 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers\Web;
|
||
|
||
use App\Application\Reports\ReportSavePathService;
|
||
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,
|
||
protected ReportSavePathService $reportSavePathService,
|
||
) {}
|
||
|
||
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->reportSavePathService->saveManual(Auth::user(), $validated);
|
||
|
||
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;
|
||
});
|
||
}
|
||
}
|