Обновлен стартовый экран
Переписаны запросы для статистики, отчетов Добавлена интеграция отчета сестры
This commit is contained in:
@@ -5,6 +5,8 @@ namespace App\Http\Controllers\Web;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Resources\MedicalHistoryResource;
|
||||
use App\Models\Department;
|
||||
use App\Models\DepartmentMetrikaDefault;
|
||||
use App\Models\ObservableMedicalHistory;
|
||||
use App\Models\ReportDuty;
|
||||
use App\Models\ReportNurse;
|
||||
use App\Services\DateRangeService;
|
||||
@@ -15,6 +17,7 @@ use App\Services\NurseMedicalHistoryService;
|
||||
use App\Services\NurseReportService;
|
||||
use App\Services\UnifiedMedicalHistoryService;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Inertia\Inertia;
|
||||
|
||||
@@ -37,65 +40,306 @@ class DutyReportController extends Controller
|
||||
public function index(Request $request)
|
||||
{
|
||||
$user = Auth::user();
|
||||
$search = $request->get('search');
|
||||
$selectedUserId = $request->query('userId') ? (int) $request->query('userId') : null;
|
||||
$departmentId = $request->query('departmentId', $user->department->department_id);
|
||||
$department = Department::where('department_id', $departmentId)->firstOrFail();
|
||||
$bedsInDepartment = DepartmentMetrikaDefault::where('rf_department_id', $departmentId)
|
||||
->where('rf_metrika_item_id', 1)->first()->value ?? 0;
|
||||
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
|
||||
|
||||
// Проверяем, есть ли отчет за этот период
|
||||
$isRangeOneDay = $this->dateRangeService->isRangeOneDay($dateRange->startDate, $dateRange->endDate);
|
||||
$isPastPeriod = $this->dateRangeService->isPastPeriod($dateRange);
|
||||
$existsReport = ReportDuty::where('rf_department_id', $departmentId)
|
||||
->where('period_end', '>', $dateRange->startSql())
|
||||
$isCurrentPeriod = !$isPastPeriod;
|
||||
|
||||
// Всегда загружаем отчеты за период
|
||||
$reportsDuty = ReportDuty::where('rf_department_id', $departmentId)
|
||||
->where('period_start', '>=', $dateRange->startSql())
|
||||
->where('period_end', '<=', $dateRange->endSql())
|
||||
->exists();
|
||||
->orderBy('period_end', 'desc')
|
||||
->with(['unwantedEvents', 'doctor'])
|
||||
->get();
|
||||
|
||||
$hasReport = $existsReport && $isPastPeriod;
|
||||
$reportsNurse = ReportNurse::where('rf_department_id', $departmentId)
|
||||
->where('period_start', '>=', $dateRange->startSql())
|
||||
->where('period_end', '<=', $dateRange->endSql())
|
||||
->orderBy('period_end', 'desc')
|
||||
->get();
|
||||
|
||||
$hasDutyReport = $reportsDuty->count() > 0;
|
||||
$hasNurseReport = $reportsNurse->count() > 0;
|
||||
|
||||
$reportDutyIds = $reportsDuty->pluck('id')->toArray();
|
||||
$reportNurseIds = $reportsNurse->pluck('id')->toArray();
|
||||
|
||||
// dd($reportsDuty, $dateRange->endSql());
|
||||
|
||||
// Получаем пациентов (источник зависит от периода)
|
||||
if ($isCurrentPeriod) {
|
||||
// Для текущего периода - пациенты из МИС
|
||||
$patients = $this->medicalHistoryService->getGroupedHistories(
|
||||
$dateRange,
|
||||
$department->rf_mis_department_id,
|
||||
$search
|
||||
);
|
||||
|
||||
// Если есть отчет, загружаем из него дополнительные данные
|
||||
if ($hasDutyReport) {
|
||||
// Получаем нежелательные события и наблюдения из отчета
|
||||
$reportData = $this->getReportAdditionalData($reportsDuty);
|
||||
|
||||
// Добавляем эти данные к пациентам
|
||||
$patients = $this->mergeReportData($patients, $reportData);
|
||||
}
|
||||
|
||||
$nursePatients = $hasNurseReport
|
||||
? $this->nurseMedicalHistoryService->getGroupedHistories(
|
||||
$dateRange,
|
||||
$department->rf_mis_department_id,
|
||||
$reportNurseIds
|
||||
)
|
||||
: [];
|
||||
|
||||
$currentPatients = $patients['meta']['counts']['in_department'];
|
||||
$loaded = $bedsInDepartment > 0
|
||||
? round(($currentPatients * 100) / $bedsInDepartment)
|
||||
: 0;
|
||||
|
||||
$latestReport = $reportsDuty->first();
|
||||
|
||||
if ($hasReport) {
|
||||
$inDepartmentHistories = $this->dutyMedicalHistoryService->getDepartmentHistories($dateRange, $department->rf_mis_department_id);
|
||||
$plannedHistories = collect([ 'data' => [] ]);
|
||||
$emergencyHistories = collect([ 'data' => [] ]);
|
||||
$recipientHistories = $this->dutyMedicalHistoryService->getRecipientHistories($dateRange, $department->rf_mis_department_id);
|
||||
$dischargedHistories = $this->dutyMedicalHistoryService->getDischargedHistories($dateRange, $department->rf_mis_department_id);
|
||||
$deceasedHistories = $this->dutyMedicalHistoryService->getDeceasedHistories($dateRange, $department->rf_mis_department_id);
|
||||
$transferredHistories = $this->dutyMedicalHistoryService->getTransferredHistories($dateRange, $department->rf_mis_department_id);
|
||||
$reanimationHistories = collect([ 'data' => [] ]);
|
||||
} else if ($this->dateRangeService->isPastPeriod($dateRange)) {
|
||||
$inDepartmentHistories = collect([ 'data' => [] ]);
|
||||
$plannedHistories = collect([ 'data' => [] ]);
|
||||
$emergencyHistories = collect([ 'data' => [] ]);
|
||||
$recipientHistories = collect([ 'data' => [] ]);
|
||||
$dischargedHistories = collect([ 'data' => [] ]);
|
||||
$deceasedHistories = collect([ 'data' => [] ]);
|
||||
$transferredHistories = collect([ 'data' => [] ]);
|
||||
$reanimationHistories = collect([ 'data' => [] ]);
|
||||
} else {
|
||||
$patients = $this->medicalHistoryService->getGroupedHistories($dateRange, $department->rf_mis_department_id);
|
||||
// Для прошедшего периода - данные из отчета
|
||||
$patients = $hasDutyReport
|
||||
? $this->dutyMedicalHistoryService->getGroupedHistories(
|
||||
$dateRange,
|
||||
$department->rf_mis_department_id,
|
||||
$reportDutyIds,
|
||||
$search
|
||||
)
|
||||
: $this->getEmptyPatientsData();
|
||||
|
||||
$nursePatients = $hasNurseReport
|
||||
? $this->nurseMedicalHistoryService->getGroupedHistories(
|
||||
$dateRange,
|
||||
$department->rf_mis_department_id,
|
||||
$reportNurseIds
|
||||
)
|
||||
: [];
|
||||
|
||||
$latestReport = $reportsDuty->first();
|
||||
|
||||
if ($latestReport && $hasDutyReport) {
|
||||
$currentPatients = $patients['meta']['counts']['in_department'];
|
||||
$loaded = $latestReport->getLoadedDepartmentAttribute($currentPatients);
|
||||
} else {
|
||||
$loaded = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return Inertia::render('Report/Index', [
|
||||
'department' => $department,
|
||||
'patients' => $patients,
|
||||
'departmentInfo' => [
|
||||
// TODO: Добавить вывод информации из шапки
|
||||
],
|
||||
'nursePatients' => $nursePatients,
|
||||
'latestReport' => $latestReport ?? null,
|
||||
'canSaveReport' => $isRangeOneDay && $user->currentRoleCan('report.create'),
|
||||
'canEditPastReport' => $user->currentRoleCan('report.edit.past'),
|
||||
'canSaveNurseReport' => $isRangeOneDay && $user->currentRoleCan('nurse.report.create'),
|
||||
'stats' => $this->prepareStats($patients, $nursePatients, $loaded, $bedsInDepartment),
|
||||
'dates' => [
|
||||
$dateRange->startDate->getTimestampMs(),
|
||||
$dateRange->endDate->getTimestampMs(),
|
||||
]
|
||||
],
|
||||
'selectedUserId' => $selectedUserId,
|
||||
'selectedDepartmentId' => (int) $departmentId,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохранение отчета от роли мед. сестра
|
||||
* Получает дополнительные данные из отчета (нежелательные события, наблюдения)
|
||||
*/
|
||||
private function getReportAdditionalData($reportsDuty): array
|
||||
{
|
||||
$unwantedEvents = [];
|
||||
$observations = [];
|
||||
|
||||
foreach ($reportsDuty as $report) {
|
||||
// Нежелательные события
|
||||
foreach ($report->unwantedEvents as $event) {
|
||||
$unwantedEvents[] = [
|
||||
...$event->toArray(),
|
||||
];
|
||||
}
|
||||
|
||||
// Наблюдения (если есть связь)
|
||||
if ($report->relationLoaded('observations') || $report->observations) {
|
||||
foreach ($report->observations as $observation) {
|
||||
$observations[] = [
|
||||
...$observation->toArray(),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'unwanted_events' => $unwantedEvents,
|
||||
'observations' => $observations
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Объединяет данные пациентов из МИС с данными из отчета
|
||||
*/
|
||||
private function mergeReportData(array $patients, array $reportData): array
|
||||
{
|
||||
// Группируем нежелательные события по отчетам
|
||||
// $eventsByPatient = [];
|
||||
// foreach ($reportData['unwanted_events'] as $event) {
|
||||
// $reportId = $event['report_duty_id'];
|
||||
// if (!isset($eventsByPatient[$reportId])) {
|
||||
// $eventsByPatient[$reportId] = [];
|
||||
// }
|
||||
// $eventsByPatient[$reportId][] = $event;
|
||||
// }
|
||||
|
||||
// Группируем наблюдения по пациентам
|
||||
$observationsByPatient = [];
|
||||
foreach ($reportData['observations'] as $observation) {
|
||||
$patientId = $observation['patient_id'];
|
||||
if (!isset($observationsByPatient[$patientId])) {
|
||||
$observationsByPatient[$patientId] = [];
|
||||
}
|
||||
$observationsByPatient[$patientId][] = $observation;
|
||||
}
|
||||
|
||||
// Добавляем данные из отчета к каждому пациенту
|
||||
foreach ($patients['data'] as &$patient) {
|
||||
$patientId = $patient['original_id'] ?? $patient['id'] ?? null;
|
||||
|
||||
// Может быть позже пригодится
|
||||
// if ($patientId && isset($eventsByPatient[$patientId])) {
|
||||
// $patient['unwanted_events'] = $eventsByPatient[$patientId];
|
||||
// } else {
|
||||
// $patient['unwanted_events'] = [];
|
||||
// }
|
||||
|
||||
if ($patientId && isset($observationsByPatient[$patientId])) {
|
||||
$patient['observations'] = $observationsByPatient[$patientId];
|
||||
} else {
|
||||
$patient['observations'] = [];
|
||||
}
|
||||
}
|
||||
|
||||
return $patients;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получает данные из сестринского отчета
|
||||
*/
|
||||
private function getNurseReportAdditionalData($reportsNurse): array
|
||||
{
|
||||
$nurseData = [];
|
||||
|
||||
foreach ($reportsNurse as $report) {
|
||||
// Загружаем необходимые данные из сестринского отчета
|
||||
// Например, наблюдения медсестер, процедуры и т.д.
|
||||
if ($report->relationLoaded('nurseObservations')) {
|
||||
$nurseData = array_merge($nurseData, $report->nurseObservations->toArray());
|
||||
}
|
||||
}
|
||||
|
||||
return $nurseData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает пустую структуру данных для пациентов
|
||||
*/
|
||||
private function getEmptyPatientsData(): array
|
||||
{
|
||||
return [
|
||||
'data' => [],
|
||||
'meta' => [
|
||||
'total' => 0,
|
||||
'sortBy' => 'ingoing_date',
|
||||
'sortOrder' => 'desc',
|
||||
'counts' => [
|
||||
'in_department' => 0,
|
||||
'recipient' => 0,
|
||||
'discharged' => 0,
|
||||
'deceased' => 0,
|
||||
'urgent' => 0,
|
||||
'planned' => 0,
|
||||
'reanimations' => 0,
|
||||
'surgical_planned' => 0,
|
||||
'surgical_urgent' => 0,
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Подготавливает статистику для отображения на фронтенде
|
||||
*/
|
||||
private function prepareStats(array $patients, array $nursePatients, int $loaded, ?int $bedsInDepartment): array
|
||||
{
|
||||
return [
|
||||
'nurse' => [
|
||||
'current' => empty($nursePatients) ? 0 : ($nursePatients['meta']['counts']['in_department'] ?? 0),
|
||||
'recipient' => empty($nursePatients) ? 0 : ($nursePatients['meta']['counts']['recipient'] ?? 0),
|
||||
'discharged' => empty($nursePatients) ? 0 : ($nursePatients['meta']['counts']['discharged'] ?? 0),
|
||||
],
|
||||
'duty' => [
|
||||
'beds' => $bedsInDepartment ?? 0,
|
||||
'loaded' => $loaded,
|
||||
'current' => $patients['meta']['counts']['in_department'] ?? 0,
|
||||
'recipient' => $patients['meta']['counts']['recipient'] ?? 0,
|
||||
'discharged' => ($patients['meta']['counts']['discharged'] ?? 0) + ($patients['meta']['counts']['deceased'] ?? 0),
|
||||
'deceased' => $patients['meta']['counts']['deceased'] ?? 0,
|
||||
'surgical_planned' => $patients['meta']['counts']['surgical_planned'] ?? 0,
|
||||
'surgical_urgent' => $patients['meta']['counts']['surgical_urgent'] ?? 0,
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохранение отчета
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
abort_if(!auth()->user()->currentRoleCan('report.create'), 403);
|
||||
|
||||
$user = auth()->user();
|
||||
$observables = $request->get('observables', []);
|
||||
$unwantedEvents = $request->get('unwanted_events', []);
|
||||
$selectedUserId = $request->get('userId') ? (int) $request->get('userId') : null;
|
||||
$selectedDepartmentId = $request->get('departmentId') ? (int) $request->get('departmentId') : null;
|
||||
$staff = (int) $request->get('staff', 0);
|
||||
|
||||
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
|
||||
$report = $this->dutyReportService->saveReport($dateRange);
|
||||
$this->dutyReportService->saveSnapshot($dateRange, $report);
|
||||
$report = $this->dutyReportService->saveReport($dateRange, null, $selectedUserId, $selectedDepartmentId);
|
||||
$stats = $this->dutyReportService->saveSnapshot($dateRange, $report, null, auth()->id());
|
||||
$this->dutyReportService->saveObservables($observables, $report);
|
||||
$this->dutyReportService->saveUnwantedEvents($unwantedEvents, $report);
|
||||
|
||||
$this->dutyReportService->saveMetrics($stats, $report, $staff);
|
||||
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
public function closeObservation(Request $request)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
|
||||
|
||||
$observable = $request->get('observable');
|
||||
$observableId = $observable['id'] ?? null;
|
||||
|
||||
if ($observableId === null) return response()->json('Observable not found', 404);
|
||||
|
||||
$observable = ObservableMedicalHistory::find($observableId);
|
||||
$observable->update([
|
||||
'observable_out' => $dateRange->endDate,
|
||||
'out_reason' => 'Закрыто пользователем'
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user