Files
onboard/app/Exports/DutyReportExport.php

119 lines
4.4 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\Exports;
use App\Models\Department;
use App\Models\User;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;
class DutyReportExport
{
private const RU_MONTHS = [
1 => 'январь', 2 => 'февраль', 3 => 'март', 4 => 'апрель',
5 => 'май', 6 => 'июнь', 7 => 'июль', 8 => 'август',
9 => 'сентябрь', 10 => 'октябрь', 11 => 'ноябрь', 12 => 'декабрь',
];
public function __construct(
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'),
];
}
private function urgencyGroup(Collection $patients, string $flag): array
{
// Поступившие именно в этот отчётный период (сутки), а не все, кто вообще сейчас в отделении
$filtered = $patients
->where('period_flags.recipient', true)
->where("period_flags.{$flag}", true)
->values();
return [
'count' => $filtered->count(),
'patients' => $filtered->map(fn (array $p) => $this->presentPatient($p))->all(),
];
}
private function operationsGroup(Collection $patients, array $urgentStatuses): array
{
// latest_migration.operations уже ограничены периодом (start_date в рамках суток),
// в отличие от верхнеуровневого operations, у которого нижняя граница не задана
$filtered = $patients->filter(function (array $p) use ($urgentStatuses) {
return collect(data_get($p, 'latest_migration.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'])
? (int) 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 => 'лет',
};
}
}