Модуль отчетов
This commit is contained in:
49
app/Services/Reports/BuiltIn/DutyDoctorReport.php
Normal file
49
app/Services/Reports/BuiltIn/DutyDoctorReport.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Reports\BuiltIn;
|
||||
|
||||
use App\Models\Department;
|
||||
use App\Services\DateRange;
|
||||
use App\Services\Reports\Contracts\ReportDefinition;
|
||||
use App\Services\Reports\ReportPayload;
|
||||
use App\Services\Reports\ReportSourceRegistry;
|
||||
|
||||
class DutyDoctorReport implements ReportDefinition
|
||||
{
|
||||
public function __construct(private readonly ReportSourceRegistry $sources) {}
|
||||
|
||||
public function code(): string
|
||||
{
|
||||
return 'duty';
|
||||
}
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return 'Отчёт дежурного врача';
|
||||
}
|
||||
|
||||
public function requiredPermissions(): array
|
||||
{
|
||||
return ['report.view'];
|
||||
}
|
||||
|
||||
public function build(Department $department, DateRange $dateRange): ReportPayload
|
||||
{
|
||||
$sections = [
|
||||
$this->sources->get('duty_metrics')->toSection($department, $dateRange),
|
||||
$this->sources->get('duty_patients')->toSection($department, $dateRange),
|
||||
$this->sources->get('unwanted_events')->toSection($department, $dateRange),
|
||||
$this->sources->get('observable_patients')->toSection($department, $dateRange),
|
||||
];
|
||||
|
||||
return new ReportPayload(
|
||||
title: $this->label(),
|
||||
meta: [
|
||||
'Отделение' => $department->name_full ?? $department->name_short,
|
||||
'Период' => $dateRange->start()->format('d.m.Y H:i').' — '.$dateRange->end()->format('d.m.Y H:i'),
|
||||
'Сформирован' => now('Asia/Yakutsk')->format('d.m.Y H:i'),
|
||||
],
|
||||
sections: $sections,
|
||||
);
|
||||
}
|
||||
}
|
||||
106
app/Services/Reports/BuiltIn/HeadNurseReport.php
Normal file
106
app/Services/Reports/BuiltIn/HeadNurseReport.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Reports\BuiltIn;
|
||||
|
||||
use App\Domain\Reports\ValueObjects\MetrikaConfig;
|
||||
use App\Models\Department;
|
||||
use App\Models\DepartmentMetrikaDefault;
|
||||
use App\Models\ReportNursePatient;
|
||||
use App\Services\Classification\PatientStatusClassifier;
|
||||
use App\Services\DateRange;
|
||||
use App\Services\Reports\Contracts\ReportDefinition;
|
||||
use App\Services\Reports\ReportPayload;
|
||||
use App\Services\Reports\ReportSection;
|
||||
use App\Services\Reports\ReportSourceRegistry;
|
||||
|
||||
class HeadNurseReport implements ReportDefinition
|
||||
{
|
||||
public function __construct(private readonly ReportSourceRegistry $sources) {}
|
||||
|
||||
public function code(): string
|
||||
{
|
||||
return 'nurse';
|
||||
}
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return 'Отчёт старшей медсестры';
|
||||
}
|
||||
|
||||
public function requiredPermissions(): array
|
||||
{
|
||||
return ['nurse.report.view'];
|
||||
}
|
||||
|
||||
public function build(Department $department, DateRange $dateRange): ReportPayload
|
||||
{
|
||||
$sections = [
|
||||
$this->buildMetricsSection($department, $dateRange),
|
||||
$this->sources->get('nurse_patients')->toSection($department, $dateRange, null, [], 'Журнал пациентов'),
|
||||
];
|
||||
|
||||
return new ReportPayload(
|
||||
title: $this->label(),
|
||||
meta: [
|
||||
'Отделение' => $department->name_full ?? $department->name_short,
|
||||
'Период' => $dateRange->start()->format('d.m.Y H:i').' — '.$dateRange->end()->format('d.m.Y H:i'),
|
||||
'Сформирован' => now('Asia/Yakutsk')->format('d.m.Y H:i'),
|
||||
],
|
||||
sections: $sections,
|
||||
);
|
||||
}
|
||||
|
||||
private function buildMetricsSection(Department $department, DateRange $dateRange): ReportSection
|
||||
{
|
||||
$reportIds = $this->sources->nurseReports($department, $dateRange)->pluck('id');
|
||||
|
||||
$counts = [
|
||||
'recipient' => 0,
|
||||
'discharged' => 0,
|
||||
'transferred' => 0,
|
||||
'deceased' => 0,
|
||||
'in_department' => 0,
|
||||
];
|
||||
|
||||
if ($reportIds->isNotEmpty()) {
|
||||
$patients = ReportNursePatient::whereIn('report_nurse_id', $reportIds)->with('migrations')->get();
|
||||
|
||||
foreach ($patients as $patient) {
|
||||
match (PatientStatusClassifier::classify($patient, $dateRange)) {
|
||||
PatientStatusClassifier::STATUS_RECIPIENT => $counts['recipient']++,
|
||||
PatientStatusClassifier::STATUS_DISCHARGED => $counts['discharged']++,
|
||||
PatientStatusClassifier::STATUS_TRANSFERRED => $counts['transferred']++,
|
||||
PatientStatusClassifier::STATUS_DECEASED => $counts['deceased']++,
|
||||
PatientStatusClassifier::STATUS_IN_DEPARTMENT => $counts['in_department']++,
|
||||
default => null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
$beds = (int) (DepartmentMetrikaDefault::where('rf_department_id', $department->department_id)
|
||||
->where('rf_metrika_item_id', MetrikaConfig::BEDS)
|
||||
->value('value') ?? 0);
|
||||
|
||||
$occupancy = $beds > 0 ? round($counts['in_department'] * 100 / $beds, 1) : 0;
|
||||
|
||||
$row = [
|
||||
'beds' => $beds,
|
||||
'recipient' => $counts['recipient'],
|
||||
'discharged' => $counts['discharged'],
|
||||
'transferred' => $counts['transferred'],
|
||||
'deceased' => $counts['deceased'],
|
||||
'in_department' => $counts['in_department'],
|
||||
'occupancy_percent' => $occupancy,
|
||||
];
|
||||
|
||||
return new ReportSection('Показатели', [
|
||||
'beds' => 'Коек',
|
||||
'recipient' => 'Поступило',
|
||||
'discharged' => 'Выписано',
|
||||
'transferred' => 'Переведено',
|
||||
'deceased' => 'Умерло',
|
||||
'in_department' => 'В отделении',
|
||||
'occupancy_percent' => 'Занятость, %',
|
||||
], [$row]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user