From 7ef20061f0773d85232b20d171bd06dfe2526f1b Mon Sep 17 00:00:00 2001 From: Brusnitsyn Date: Mon, 6 Jul 2026 07:37:53 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9E=D1=82=D1=87=D0=B5=D1=82=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B2=D1=80=D0=B0=D1=87=D0=B0=20=D0=B4=D0=B5=D0=B6?= =?UTF-8?q?=D1=83=D1=80=D0=BD=D0=BE=D0=B3=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Exports/DutyReportExport.php | 118 ++++++++++++++---- .../Controllers/Web/DutyReportController.php | 36 ++++-- resources/views/reports/duty.blade.php | 59 +++++++++ 3 files changed, 179 insertions(+), 34 deletions(-) create mode 100644 resources/views/reports/duty.blade.php diff --git a/app/Exports/DutyReportExport.php b/app/Exports/DutyReportExport.php index 35ea494..87b3425 100644 --- a/app/Exports/DutyReportExport.php +++ b/app/Exports/DutyReportExport.php @@ -4,38 +4,110 @@ namespace App\Exports; use App\Models\Department; use App\Models\User; -use Maatwebsite\Excel\Concerns\FromArray; -use Maatwebsite\Excel\Concerns\WithTitle; +use Illuminate\Support\Carbon; +use Illuminate\Support\Collection; -class DutyReportExport implements FromArray, WithTitle +class DutyReportExport { - protected array $data; - protected array $dateRange; - protected User $user; - protected Department $department; - protected string $reportName; + private const RU_MONTHS = [ + 1 => 'январь', 2 => 'февраль', 3 => 'март', 4 => 'апрель', + 5 => 'май', 6 => 'июнь', 7 => 'июль', 8 => 'август', + 9 => 'сентябрь', 10 => 'октябрь', 11 => 'ноябрь', 12 => 'декабрь', + ]; public function __construct( - array $data, - array $dateRange, - User $user, - Department $department, - string $reportName = 'Статистика по отделениям', - ) { - $this->data = $data; - $this->dateRange = $dateRange; - $this->user = $user; - $this->department = $department; - $this->reportName = $reportName; + protected array $patients, + protected array $dateRange, + protected User $user, + protected Department $department, + protected string $reportName = 'Отчёт дежурного врача по приёмному покою и отделению', + ) {} + + /** + * Данные для Blade-шаблона PDF-отчёта. + */ + public function toViewData(): array + { + $patients = collect($this->patients); + $endDate = Carbon::parse($this->dateRange[1]); + + return [ + 'title' => sprintf('%s «%s»', $this->reportName, $this->department->name_full ?? $this->department->name_short), + 'day' => $endDate->format('d'), + 'month' => self::RU_MONTHS[(int) $endDate->format('n')], + 'year' => $endDate->format('Y'), + 'planned' => $this->urgencyGroup($patients, 'planned'), + 'urgent' => $this->urgencyGroup($patients, 'urgent'), + 'inDepartment' => $patients->where('period_flags.current_at_end', true)->count(), + 'plannedOperations' => $this->operationsGroup($patients, [6]), + 'urgentOperations' => $this->operationsGroup($patients, [4, 5]), + 'reanimation' => $this->flagGroup($patients, 'in_reanimation'), + 'observableCount' => $patients->where('in_observable', true)->count(), + 'deceased' => $this->flagGroup($patients, 'period_flags.deceased'), + ]; } - public function array(): array + private function urgencyGroup(Collection $patients, string $flag): array { - // TODO: Implement array() method. + $filtered = $patients + ->where('period_flags.current_at_end', true) + ->where("period_flags.{$flag}", true) + ->values(); + + return [ + 'count' => $filtered->count(), + 'patients' => $filtered->map(fn (array $p) => $this->presentPatient($p))->all(), + ]; } - public function title(): string + private function operationsGroup(Collection $patients, array $urgentStatuses): array { - return $this->sheetTitle; + $filtered = $patients->filter(function (array $p) use ($urgentStatuses) { + return collect($p['operations'] ?? [])->whereIn('urgent_status', $urgentStatuses)->isNotEmpty(); + })->values(); + + return [ + 'count' => $filtered->count(), + 'patients' => $filtered->map(fn (array $p) => $this->presentPatient($p, withDiagnosis: false))->all(), + ]; + } + + private function flagGroup(Collection $patients, string $flag): array + { + $filtered = $patients->where($flag, true)->values(); + + return [ + 'count' => $filtered->count(), + 'patients' => $filtered->map(fn (array $p) => $this->presentPatient($p))->all(), + ]; + } + + private function presentPatient(array $patient, bool $withDiagnosis = true): array + { + $age = ! empty($patient['birth_date']) + ? Carbon::parse($patient['birth_date'])->diffInYears(Carbon::parse($this->dateRange[1])) + : null; + + return [ + 'full_name' => $patient['full_name'], + 'age' => $age !== null ? "{$age} ".$this->pluralizeAge($age) : '', + 'diagnosis' => $withDiagnosis ? (data_get($patient, 'latest_migration.diagnosis_name') ?? '') : null, + ]; + } + + private function pluralizeAge(int $age): string + { + $mod100 = $age % 100; + $mod10 = $age % 10; + + if ($mod100 >= 11 && $mod100 <= 14) { + return 'лет'; + } + + return match ($mod10) { + 1 => 'год', + 2, 3, 4 => 'года', + default => 'лет', + }; } } diff --git a/app/Http/Controllers/Web/DutyReportController.php b/app/Http/Controllers/Web/DutyReportController.php index 6510383..6b4c3a9 100644 --- a/app/Http/Controllers/Web/DutyReportController.php +++ b/app/Http/Controllers/Web/DutyReportController.php @@ -16,13 +16,12 @@ use App\Services\DutyReportService; use App\Services\MedicalHistoryService; use App\Services\NurseMedicalHistoryService; use App\Services\NurseReportService; -use App\Services\StatisticsService; use App\Services\UnifiedMedicalHistoryService; +use Barryvdh\DomPDF\Facade\Pdf; use Illuminate\Http\Request; use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Auth; use Inertia\Inertia; -use Maatwebsite\Excel\Facades\Excel; class DutyReportController extends Controller { @@ -32,7 +31,6 @@ class DutyReportController extends Controller protected DutyMedicalHistoryService $dutyMedicalHistoryService, protected DutyReportService $dutyReportService, protected NurseMedicalHistoryService $nurseMedicalHistoryService, - protected StatisticsService $statisticsService ) {} @@ -362,22 +360,38 @@ class DutyReportController extends Controller } /** - * Формирование отчета дежурного в Excel + * Формирование отчета дежурного врача в PDF */ public function generateReport(Request $request) { $user = $request->user(); - $queryStartDate = $request->query('startAt'); - $queryEndDate = $request->query('endAt'); $queryDepartmentId = $request->query('departmentId', $user->department->department_id); + $department = Department::findOrFail($queryDepartmentId); - [$startDate, $endDate] = $this->dateRangeService->getStatisticsDateRange($user, $queryStartDate, $queryEndDate); - $isRangeOneDay = $this->dateRangeService->isRangeOneDay($startDate, $endDate); - $department = Department::find($queryDepartmentId); + $dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user); - $finalData = $this->statisticsService->getStatisticsDataForDepartment($department->department_id, $startDate, $endDate, $isRangeOneDay); + $reportDutyIds = ReportDuty::where('rf_department_id', $department->department_id) + ->where('period_start', '>=', $dateRange->startSql()) + ->where('period_end', '<=', $dateRange->endSql()) + ->pluck('id') + ->toArray(); - return Excel::download(new DutyReportExport($finalData['data'], [$startDate, $endDate], $user, $department), 'statistics.xlsx'); + $patients = $this->dutyMedicalHistoryService->getGroupedHistories( + $dateRange, + $department->rf_mis_department_id, + $reportDutyIds + ); + + $export = new DutyReportExport( + $patients['data'], + [$dateRange->startDateRaw, $dateRange->endDateRaw], + $user, + $department + ); + + return Pdf::loadView('reports.duty', $export->toViewData()) + ->setPaper('a4') + ->download('duty-report.pdf'); } } diff --git a/resources/views/reports/duty.blade.php b/resources/views/reports/duty.blade.php new file mode 100644 index 0000000..ab1341e --- /dev/null +++ b/resources/views/reports/duty.blade.php @@ -0,0 +1,59 @@ + + + + + {{ $title }} + + + +

{{ $title }}

+

За «{{ $day }}» {{ $month }} {{ $year }} год.

+ +

Плановые: {{ $planned['count'] }}

+ @foreach ($planned['patients'] as $i => $p) +

{{ $i + 1 }}-{{ $p['full_name'] }} {{ $p['age'] }}.@if ($p['diagnosis']) Д/З: {{ $p['diagnosis'] }}.@endif

+ @endforeach + +

Экстренные: {{ $urgent['count'] }}

+ @foreach ($urgent['patients'] as $i => $p) +

{{ $i + 1 }}-{{ $p['full_name'] }} {{ $p['age'] }}.@if ($p['diagnosis']) Д/З: {{ $p['diagnosis'] }}.@endif

+ @endforeach + +

В отделении состоит: {{ $inDepartment }}

+ +

ПЛАНОВЫХ ОПЕРАЦИЙ: {{ $plannedOperations['count'] }}

+ @foreach ($plannedOperations['patients'] as $p) +

{{ $p['full_name'] }} {{ $p['age'] }}.

+ @endforeach + +

Экстренных операций: {{ $urgentOperations['count'] }}

+ @foreach ($urgentOperations['patients'] as $p) +

{{ $p['full_name'] }} {{ $p['age'] }}.

+ @endforeach + +

Реанимация: {{ $reanimation['count'] }}

+ @foreach ($reanimation['patients'] as $i => $p) +

{{ $i + 1 }}. {{ $p['full_name'] }} {{ $p['age'] }}.@if ($p['diagnosis']) {{ $p['diagnosis'] }}.@endif

+ @endforeach + +

Под наблюдением: {{ $observableCount }}

+ +

Летальные исходы: {{ $deceased['count'] > 0 ? '' : 'не было.' }}

+ @foreach ($deceased['patients'] as $i => $p) +

{{ $i + 1 }}. {{ $p['full_name'] }} {{ $p['age'] }}.@if ($p['diagnosis']) {{ $p['diagnosis'] }}.@endif

+ @endforeach + +
+

Дежурный врач ПДО: _____________

+

Дежурный врач отделения: _____________

+
+ +