diff --git a/app/Console/Commands/FillReportsFromDate.php b/app/Console/Commands/FillReportsFromDate.php
new file mode 100644
index 0000000..65f43ae
--- /dev/null
+++ b/app/Console/Commands/FillReportsFromDate.php
@@ -0,0 +1,98 @@
+option('date') ?? Carbon::now()->subDays(7)->format('Y-m-d');
+ $endDate = $this->option('end-date') ?? Carbon::now()->format('Y-m-d');
+ $departmentId = $this->option('department');
+ $userId = $this->option('user');
+ $force = $this->option('force');
+
+ $this->info("Заполнение отчетов с {$startDate} по {$endDate}");
+
+ // Получаем отделения
+ $departments = $departmentId
+ ? Department::where('department_id', $departmentId)->get()
+ : Department::all();
+
+ if ($departments->isEmpty()) {
+ $this->error('Отделения не найдены');
+ return 1;
+ }
+
+ $totalReports = 0;
+ $totalErrors = 0;
+
+ foreach ($departments as $department) {
+ $this->info("Обработка отделения: {$department->name}");
+
+ // Получаем пользователей отделения
+ $users = $userId
+ ? User::where('id', $userId)->where('rf_department_id', $department->department_id)->get()
+ : $this->getDepartmentUsers($department);
+
+ if ($users->isEmpty()) {
+ $this->warn("В отделении {$department->name} нет пользователей");
+ continue;
+ }
+
+ foreach ($users as $user) {
+ try {
+ $created = $this->autoReportService->fillReportsForUser(
+ $user,
+ $startDate,
+ $endDate,
+ $force
+ );
+
+ $totalReports += $created;
+ $this->info("Для пользователя {$user->name} создано {$created} отчетов");
+ } catch (\Exception $e) {
+ $totalErrors++;
+ $this->error("Ошибка для пользователя {$user->name}: {$e->getMessage()}");
+ }
+ }
+ }
+
+ $this->info("Готово! Создано отчетов: {$totalReports}, ошибок: {$totalErrors}");
+
+ return 0;
+ }
+
+ private function getDepartmentUsers(Department $department)
+ {
+ // Получаем пользователей, которые могут создавать отчеты
+ return User::where('rf_department_id', $department->department_id)
+ ->where(function ($query) {
+ $query->where('role', 'doctor')
+ ->orWhere('role', 'head_of_department');
+ })
+ ->where('is_active', true)
+ ->get();
+ }
+}
diff --git a/app/Http/Controllers/Api/ReportController.php b/app/Http/Controllers/Api/ReportController.php
index 880ab69..3e4993b 100644
--- a/app/Http/Controllers/Api/ReportController.php
+++ b/app/Http/Controllers/Api/ReportController.php
@@ -185,12 +185,12 @@ class ReportController extends Controller
}
}
- $isRangeOneDay = $this->dateService->isRangeOneDay($startDate, $endDate);
+ $isRangeOneDay = $this->dateRangeService->isRangeOneDay($startDate, $endDate);
$date = $isHeadOrAdmin ? [
- $this->dateService->parseDate($isRangeOneDay ? $endDate : $startDate)->getTimestampMs(),
- $this->dateService->parseDate($endDate)->getTimestampMs()
- ] : $this->dateService->parseDate($endDate)->getTimestampMs();
+ $this->dateRangeService->parseDate($isRangeOneDay ? $endDate : $startDate)->getTimestampMs(),
+ $this->dateRangeService->parseDate($endDate)->getTimestampMs()
+ ] : $this->dateRangeService->parseDate($endDate)->getTimestampMs();
return response()->json([
'department' => [
@@ -285,72 +285,6 @@ class ReportController extends Controller
return $count;
}
- /**
- * Получить количество пациентов из снапшотов
- */
- private function getCountFromSnapshots(string $type, array $reportIds)
- {
- return match($type) {
- 'plan' => MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->where('patient_type', 'plan')
- ->distinct('rf_medicalhistory_id')
- ->count('rf_medicalhistory_id'),
- 'emergency' => MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->where('patient_type', 'emergency')
- ->distinct('rf_medicalhistory_id')
- ->count('rf_medicalhistory_id'),
- 'outcome' => MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->whereIn('patient_type', ['discharged', 'transferred', 'deceased'])
- ->distinct('rf_medicalhistory_id')
- ->count('rf_medicalhistory_id'),
- 'deceased' => MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->where('patient_type', 'deceased')
- ->distinct('rf_medicalhistory_id')
- ->count('rf_medicalhistory_id'),
- 'discharged' => MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->where('patient_type', 'discharged')
- ->distinct('rf_medicalhistory_id')
- ->count('rf_medicalhistory_id'),
- 'transferred' => MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->where('patient_type', 'transferred')
- ->distinct('rf_medicalhistory_id')
- ->count('rf_medicalhistory_id'),
- 'recipient' => MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->where('patient_type', 'recipient')
- ->distinct('rf_medicalhistory_id')
- ->count('rf_medicalhistory_id'),
- default => 0
- };
- }
-
- /**
- * Получить ID пациентов на лечении из снапшотов
- */
- private function getCurrentPatientsFromSnapshots(array $reportIds, $branchId)
- {
- // Получаем ID всех пациентов из снапшотов за период
- $allSnapshotPatientIds = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->pluck('rf_medicalhistory_id')
- ->unique()
- ->toArray();
-
- if (empty($allSnapshotPatientIds)) {
- return 0;
- }
-
- // Получаем ID выбывших пациентов
- $outcomePatientIds = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->whereIn('patient_type', ['discharged', 'transferred', 'deceased'])
- ->pluck('rf_medicalhistory_id')
- ->unique()
- ->toArray();
-
- // Текущие пациенты = все пациенты - выбывшие
- $currentPatientIds = array_diff($allSnapshotPatientIds, $outcomePatientIds);
-
- return count($currentPatientIds);
- }
-
/**
* Получить ID поступивших пациентов из снапшотов
*/
@@ -365,33 +299,6 @@ class ReportController extends Controller
return $recipientIds;
}
-// /**
-// * Получить отчеты по промежутку дат (оптимизированная версия)
-// */
-// private function getReportsForDateRange($departmentId, $startDate, $endDate)
-// {
-// $start = Carbon::parse($startDate);
-// $end = Carbon::parse($endDate);
-//
-// // Если промежуток большой, ограничиваем количество отчетов
-// $daysDiff = $start->diffInDays($end);
-//
-// if ($daysDiff > 30) {
-// // Для больших промежутков берем только последние отчеты
-// return Report::where('rf_department_id', $departmentId)
-// ->whereBetween('created_at', [$start, $end])
-// ->orderBy('created_at', 'DESC')
-// ->take(30) // Ограничиваем количеством
-// ->get()
-// ->reverse(); // Возвращаем в правильном порядке
-// }
-//
-// return Report::where('rf_department_id', $departmentId)
-// ->whereBetween('created_at', [$start, $end])
-// ->orderBy('created_at', 'ASC')
-// ->get();
-// }
-
public function store(Request $request)
{
$user = Auth::user();
@@ -408,7 +315,8 @@ class ReportController extends Controller
'observationPatients' => 'nullable',
'departmentId' => 'required|integer',
'unwantedEvents' => 'nullable|array',
- 'dates' => 'required|array',
+ 'startAt' => 'required|integer',
+ 'endAt' => 'required|integer',
'userId' => 'required|integer',
'reportId' => 'nullable'
]);
@@ -417,7 +325,7 @@ class ReportController extends Controller
$unwantedEvents = $data['unwantedEvents'];
// Определяем даты в зависимости от роли
- [$startDate, $endDate] = $this->getDateRangeForRole($user, $data['dates'][0], $data['dates'][1]);
+ $dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
$metriks = [];
foreach ($metrics as $key => $value) {
@@ -429,6 +337,57 @@ class ReportController extends Controller
$metriks[] = $metrika;
}
+ // 1. Плановые
+ $planIds = $this->reportService->getPatientsByStatus(
+ $user,
+ 'plan',
+ $dateRange,
+ true,
+ true,
+ );
+ $planCount = $this->reportService->getPatientsCountByStatus($user, 'plan', $dateRange);
+ // 2. Экстренные
+ $emergencyIds = $this->reportService->getPatientsByStatus(
+ $user,
+ 'emergency',
+ $dateRange,
+ true,
+ true,
+ );
+ $emergencyCount = $this->reportService->getPatientsCountByStatus($user, 'emergency', $dateRange);
+ // 3. Выписанные
+ $dischargedIds = $this->reportService->getPatientsByStatus(
+ $user,
+ 'outcome',
+ $dateRange,
+ true,
+ true
+ );
+ // 4. Переведенные
+ $transferredIds = $this->reportService->getPatientsByStatus(
+ $user,
+ 'outcome-transferred',
+ $dateRange,
+ true,
+ true
+ );
+ // 5. Умершие
+ $deceasedIds = $this->reportService->getPatientsByStatus(
+ $user,
+ 'outcome-deceased',
+ $dateRange,
+ true,
+ true
+ );
+ // 6. Поступившие
+ $recipientIds = $this->reportService->getPatientsByStatus(
+ $user,
+ 'recipient',
+ $dateRange,
+ true,
+ true
+ );
+
\DB::beginTransaction();
if (isset($data['reportId']) && $data['reportId']) {
@@ -483,6 +442,17 @@ class ReportController extends Controller
$unwantedEvent->delete();
}
}
+ MetrikaResult::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 16
+ ],
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 16,
+ 'value' => count($unwantedEvents),
+ ]
+ );
foreach ($metriks as $metrika) {
MetrikaResult::updateOrCreate(
@@ -519,11 +489,21 @@ class ReportController extends Controller
$observationPatient->delete();
}
}
+ MetrikaResult::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 14
+ ],
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 14,
+ 'value' => count($observationPatients),
+ ]
+ );
// Сохраняем снимок для каждого типа пациентов
-
- // 1. Плановые
- $planIds = $this->getPlanOrEmergencyPatients('plan', false, $branchId, $startDate, $endDate, false, false, true);
+ // Планово
+ //$this->getPlanOrEmergencyPatients('plan', false, $branchId, $dateRange->startSql(), $dateRange->endSql(), false, false, true);
foreach ($planIds as $id) {
MedicalHistorySnapshot::create([
'rf_report_id' => $report->report_id,
@@ -531,9 +511,20 @@ class ReportController extends Controller
'patient_type' => 'plan'
]);
}
+ MetrikaResult::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 4
+ ],
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 4,
+ 'value' => $planCount,
+ ]
+ );
- // 2. Экстренные
- $emergencyIds = $this->getPlanOrEmergencyPatients('emergency', false, $branchId, $startDate, $endDate, false, false, true);
+ //$this->getPlanOrEmergencyPatients('emergency', false, $branchId, $startDate, $endDate, false, false, true);
+ // Экстренно
foreach ($emergencyIds as $id) {
MedicalHistorySnapshot::create([
'rf_report_id' => $report->report_id,
@@ -541,9 +532,19 @@ class ReportController extends Controller
'patient_type' => 'emergency'
]);
}
+ MetrikaResult::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 12
+ ],
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 12,
+ 'value' => $emergencyCount,
+ ]
+ );
- // 3. Выписанные
- $dischargedIds = $this->getDischargedPatients($branchId, $startDate, $endDate, true);
+ //$this->getDischargedPatients($branchId, $startDate, $endDate, true);
foreach ($dischargedIds as $id) {
MedicalHistorySnapshot::create([
'rf_report_id' => $report->report_id,
@@ -551,9 +552,19 @@ class ReportController extends Controller
'patient_type' => 'discharged'
]);
}
+ MetrikaResult::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 15,
+ ],
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 15,
+ 'value' => count($dischargedIds),
+ ]
+ );
- // 4. Переведенные
- $transferredIds = $this->getTransferredPatients($branchId, $startDate, $endDate, true);
+ //$this->getTransferredPatients($branchId, $startDate, $endDate, true);
foreach ($transferredIds as $id) {
MedicalHistorySnapshot::create([
'rf_report_id' => $report->report_id,
@@ -561,9 +572,19 @@ class ReportController extends Controller
'patient_type' => 'transferred'
]);
}
+ MetrikaResult::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 13,
+ ],
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 13,
+ 'value' => count($transferredIds),
+ ]
+ );
- // 5. Умершие
- $deceasedIds = $this->getDeceasedOutcomePatients($branchId, $startDate, $endDate, false, true);
+ //$this->getDeceasedOutcomePatients($branchId, $startDate, $endDate, false, true);
foreach ($deceasedIds as $id) {
MedicalHistorySnapshot::create([
'rf_report_id' => $report->report_id,
@@ -571,19 +592,29 @@ class ReportController extends Controller
'patient_type' => 'deceased'
]);
}
-
- // 5. Поступившие
- $recipientIds = $this->getPlanOrEmergencyPatients(
- null,
- $isHeadOrAdmin,
- $branchId,
- $startDate,
- $endDate,
- false,
- true,
- true,
- today: true
+ MetrikaResult::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 9,
+ ],
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 9,
+ 'value' => count($deceasedIds),
+ ]
);
+
+// $recipientIds = $this->getPlanOrEmergencyPatients(
+// null,
+// $isHeadOrAdmin,
+// $branchId,
+// $startDate,
+// $endDate,
+// false,
+// true,
+// true,
+// today: true
+// );
foreach ($recipientIds as $id) {
MedicalHistorySnapshot::create([
'rf_report_id' => $report->report_id,
@@ -591,8 +622,19 @@ class ReportController extends Controller
'patient_type' => 'recipient'
]);
}
+ MetrikaResult::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 3,
+ ],
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 3,
+ 'value' => count($recipientIds),
+ ]
+ );
- // 6. Находящиеся на лечении
+ // 7. Находящиеся на лечении
// $currentIds = $this->getCurrentPatients($branchId, false, true);
// foreach ($currentIds as $id) {
// MedicalHistorySnapshot::create([
@@ -651,59 +693,6 @@ class ReportController extends Controller
return response()->json($count);
}
- /**
- * Определить диапазон дат в зависимости от роли
- */
- private function getDateRangeForRole($user, $startAt = null, $endAt = null): array
- {
- // Функция для парсинга даты
- $parseDate = function($dateInput) {
- if (is_numeric($dateInput)) {
- return Carbon::createFromTimestampMs($dateInput)
- ->setTimezone('Asia/Yakutsk');
- }
- return Carbon::parse($dateInput, 'Asia/Yakutsk');
- };
-
- // Если переданы обе даты (и заведующий, и врач могут выбрать даты)
- if ($startAt && $endAt) {
- $startDate = $parseDate($startAt);
- $endDate = $parseDate($endAt);
-
- if ($startDate->isSameDay($endDate)) {
- // Сдвигаем начало на день назад для всех ролей при выборе одного дня
- // И всегда для врача
- $startDate = $startDate->copy()->addDays(-1)->setTime(6, 0)->format('Y-m-d H:i:s');
- $endDate = $endDate->setTime(6, 0)->format('Y-m-d H:i:s');
- } else {
- // Для диапазона оставляем как есть (только для заведующих)
- $startDate = $startDate->setTime(6, 0)->format('Y-m-d H:i:s');
- $endDate = $endDate->setTime(6, 0)->format('Y-m-d H:i:s');
- }
- }
- // Если даты не переданы - логика по умолчанию в зависимости от роли
- else {
- // Для заведующего или администратора - сутки
- if ($user->isHeadOfDepartment() || $user->isAdmin()) {
- $startDate = Carbon::now('Asia/Yakutsk')
- ->subDay()
- ->setTime(6, 0)
- ->format('Y-m-d H:i:s');
-
- $endDate = Carbon::now('Asia/Yakutsk')
- ->setTime(6, 0)
- ->format('Y-m-d H:i:s');
- }
- // Для врача - только сутки (вчера 06:00 - сегодня 06:00)
- else {
- $startDate = Carbon::now('Asia/Yakutsk')->subDay()->setTime(6, 0)->format('Y-m-d H:i:s');
- $endDate = Carbon::now('Asia/Yakutsk')->setTime(6, 0)->format('Y-m-d H:i:s');
- }
- }
-
- return [$startDate, $endDate];
- }
-
/**
* Получить пациентов (плановых или экстренных)
*/
@@ -784,61 +773,6 @@ class ReportController extends Controller
}
}
- /**
- * Получить пациентов под наблюдением
- */
- private function getObservationPatients(
- $userDepartmentId
- ) {
- $observationPatients = ObservationPatient::where('rf_department_id', $userDepartmentId)
- ->select(['rf_medicalhistory_id', 'observation_patient_id'])
- ->get()
- ->groupBy('rf_medicalhistory_id');
-
- $medicalHistoryIds = $observationPatients->keys()->toArray();
-
- if (empty($medicalHistoryIds)) {
- return collect();
- }
-
- $patients = MisMedicalHistory::whereHas('observationPatient', function ($q) use ($userDepartmentId) {
- $q->where('rf_department_id', $userDepartmentId);
- })
- ->with(['observationPatient' => function($query) use ($userDepartmentId) {
- $query->where('rf_department_id', $userDepartmentId)
- ->select(['rf_medicalhistory_id', 'observation_patient_id', 'comment']);
- }])
- ->orderBy('DateRecipient', 'DESC')
- ->get();
-
- // Добавляем комментарии
- $patients = $patients->map(function ($patient) {
- // Объединяем все комментарии
- $patient->comment = $patient->observationPatient
- ->pluck('comment')
- ->filter()
- ->implode('; ');
-
- return $patient;
- });
-
- return $patients;
- }
-
- /**
- * Получить выбывших пациентов
- */
- private function getOutcomePatients(
- $misDepartmentId,
- $startDate,
- $endDate
- ) {
- // Здесь оставляем оригинальный запрос, т.к. он специфичен для умерших
- return MisMedicalHistory::deceased()
- ->inDepartment($misDepartmentId, $startDate, $endDate)
- ->get();
- }
-
/**
* Получить всех выбывших пациентов
*/
@@ -896,54 +830,6 @@ class ReportController extends Controller
};
}
- /**
- * Получить выписанных пациентов
- */
- private function getDischargedPatients($branchId, $startDate, $endDate, bool $onlyIds = false)
- {
- $medicalHistoryIds = MisMigrationPatient::discharged($branchId, $startDate, $endDate)
- ->pluck('rf_MedicalHistoryID')
- ->unique()
- ->toArray();
-
- if (empty($medicalHistoryIds)) {
- return collect();
- }
-
- if ($onlyIds) {
- return $medicalHistoryIds;
- }
-
- return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
- ->with(['surgicalOperations'])
- ->orderBy('DateRecipient', 'DESC')
- ->get();
- }
-
- /**
- * Получить переведенных пациентов
- */
- private function getTransferredPatients($branchId, $startDate, $endDate, bool $onlyIds = false)
- {
- $medicalHistoryIds = MisMigrationPatient::transferred($branchId, $startDate, $endDate)
- ->pluck('rf_MedicalHistoryID')
- ->unique()
- ->toArray();
-
- if (empty($medicalHistoryIds)) {
- return collect();
- }
-
- if ($onlyIds) {
- return $medicalHistoryIds;
- }
-
- return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
- ->with(['surgicalOperations'])
- ->orderBy('DateRecipient', 'DESC')
- ->get();
- }
-
/**
* Получить умерших пациентов (исход)
*/
@@ -1050,8 +936,12 @@ class ReportController extends Controller
$departmentId = $user->department->rf_mis_department_id;
$users = MisLpuDoctor::select(['LPUDoctorID', 'FAM_V', 'IM_V', 'OT_V'])
+ ->whereHas('prvds', function ($query) use ($departmentId) {
+ $query->where('rf_DepartmentID', $departmentId)
+ ->whereDate('D_END', '2222-01-01 00:00:00.000000');
+ })
->active()
- ->inMyDepartment()
+ ->whereNotIn('LPUDoctorID', [0, 1])
->get();
return response()->json([
@@ -1075,184 +965,4 @@ class ReportController extends Controller
->orderBy('created_at', 'ASC')
->get();
}
-
- /**
- * Получить плановых/экстренных пациентов из снапшотов через реплику
- */
- private function getPatientsFromSnapshotsUsingReplica(string $status, array $reportIds, $branchId, $startDate, $endDate)
- {
- // Получаем ID пациентов из снапшотов
- $patientType = $status === 'plan' ? 'plan' : 'emergency';
-
- $medicalHistoryIds = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->where('patient_type', $patientType)
- ->pluck('rf_medicalhistory_id')
- ->unique()
- ->toArray();
-
- if (empty($medicalHistoryIds)) {
- return collect();
- }
-
- // Используем существующие скоупы для получения данных из реплики
- $query = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
- ->with(['surgicalOperations' => function ($query) use ($startDate, $endDate) {
- $query->whereBetween('Date', [$startDate, $endDate]);
- }])
- ->orderBy('DateRecipient', 'DESC');
-
- // Применяем те же фильтры
- if ($status === 'plan') {
- $query->plan();
- } else {
- $query->emergency();
- }
-
- return $query->get();
- }
-
- /**
- * Получить пациентов под наблюдением из снапшотов через реплику
- */
- private function getObservationPatientsFromSnapshotsUsingReplica($userDepartmentId, array $reportIds)
- {
- // Получаем ID пациентов из снапшотов наблюдения
- $medicalHistoryIds = ObservationPatient::whereIn('rf_report_id', $reportIds)
- ->pluck('rf_medicalhistory_id')
- ->unique()
- ->toArray();
-
- if (empty($medicalHistoryIds)) {
- return collect();
- }
-
- // Используем существующий метод с фильтрацией по ID из снапшотов
- $patients = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
- ->whereHas('observationPatient', function ($q) use ($userDepartmentId) {
- $q->where('rf_department_id', $userDepartmentId);
- })
- ->with(['observationPatient' => function($query) use ($userDepartmentId) {
- $query->where('rf_department_id', $userDepartmentId)
- ->select(['rf_medicalhistory_id', 'observation_patient_id', 'comment']);
- }])
- ->orderBy('DateRecipient', 'DESC')
- ->get();
-
- // Добавляем комментарии
- $patients = $patients->map(function ($patient) {
- $patient->comment = $patient->observationPatient
- ->pluck('comment')
- ->filter()
- ->implode('; ');
- return $patient;
- });
-
- return $patients;
- }
-
- /**
- * Получить пациентов с исходом из снапшотов через реплику
- */
- private function getOutcomePatientsFromSnapshotsUsingReplica(string $outcomeType, array $reportIds, $branchId, $startDate, $endDate)
- {
- // Получаем ID пациентов из снапшотов исходов
- $medicalHistoryIds = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
- ->where('patient_type', $outcomeType)
- ->pluck('rf_medicalhistory_id')
- ->unique()
- ->toArray();
-
- if (empty($medicalHistoryIds)) {
- return collect();
- }
-
- // Используем соответствующий метод для получения данных из реплики
- return match($outcomeType) {
- 'discharged' => $this->getDischargedPatientsByIds($medicalHistoryIds, $branchId),
- 'transferred' => $this->getTransferredPatientsByIds($medicalHistoryIds, $branchId),
- 'deceased' => $this->getDeceasedPatientsByIds($medicalHistoryIds, $branchId),
- default => collect()
- };
- }
-
- /**
- * Получить выписанных пациентов по ID из снапшотов
- */
- private function getDischargedPatientsByIds(array $medicalHistoryIds, $branchId)
- {
- return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
- ->with(['surgicalOperations'])
- ->orderBy('DateRecipient', 'DESC')
- ->get()
- ->map(function ($patient) use ($branchId) {
- // Получаем информацию о выписке
- $migration = $patient->migrations
- ->where('rf_kl_VisitResultID', 'in', [1, 7, 8, 9, 10, 11, 48, 49, 124])
- ->whereNotNull('DateOut')
- ->sortByDesc('DateOut')
- ->first();
-
- if ($migration) {
- $patient->outcome_type = $this->getOutcomeTypeName($migration->rf_kl_VisitResultID);
- $patient->outcome_date = $migration->DateOut;
- $patient->visit_result_id = $migration->rf_kl_VisitResultID;
- }
-
- return $patient;
- });
- }
-
- /**
- * Получить переведенных пациентов по ID из снапшотов
- */
- private function getTransferredPatientsByIds(array $medicalHistoryIds, $branchId)
- {
- return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
- ->with(['surgicalOperations'])
- ->orderBy('DateRecipient', 'DESC')
- ->get()
- ->map(function ($patient) use ($branchId) {
- // Получаем информацию о переводе
- $migration = $patient->migrations
- ->where('rf_kl_VisitResultID', 'in', [2, 3, 4, 12, 13, 14])
- ->whereNotNull('DateOut')
- ->sortByDesc('DateOut')
- ->first();
-
- if ($migration) {
- $patient->outcome_type = $this->getOutcomeTypeName($migration->rf_kl_VisitResultID);
- $patient->outcome_date = $migration->DateOut;
- $patient->visit_result_id = $migration->rf_kl_VisitResultID;
- }
-
- return $patient;
- });
- }
-
- /**
- * Получить умерших пациентов по ID из снапшотов
- */
- private function getDeceasedPatientsByIds(array $medicalHistoryIds, $branchId)
- {
- return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
- ->with(['surgicalOperations'])
- ->orderBy('DateRecipient', 'DESC')
- ->get()
- ->map(function ($patient) use ($branchId) {
- // Получаем информацию о смерти
- $migration = $patient->migrations
- ->where('rf_kl_VisitResultID', 'in', [5, 6, 15, 16])
- ->whereNotNull('DateOut')
- ->sortByDesc('DateOut')
- ->first();
-
- if ($migration) {
- $patient->outcome_type = $this->getOutcomeTypeName($migration->rf_kl_VisitResultID);
- $patient->outcome_date = $migration->DateOut;
- $patient->visit_result_id = $migration->rf_kl_VisitResultID;
- }
-
- return $patient;
- });
- }
}
diff --git a/app/Http/Controllers/Web/ReportController.php b/app/Http/Controllers/Web/ReportController.php
index 5fda37a..f5d8607 100644
--- a/app/Http/Controllers/Web/ReportController.php
+++ b/app/Http/Controllers/Web/ReportController.php
@@ -68,12 +68,9 @@ class ReportController extends Controller
'reportId' => 'nullable|integer'
]);
- $report = $this->reportService->storeReport($validated, Auth::user());
+ $report = $this->reportService->storeReport($validated, Auth::user(), false);
- return response()->json([
- 'message' => 'success',
- 'report_id' => $report->report_id
- ]);
+ return redirect()->route('start');
}
public function getPatients(Request $request)
diff --git a/app/Http/Controllers/Web/StatisticController.php b/app/Http/Controllers/Web/StatisticController.php
index 783dd77..7c37153 100644
--- a/app/Http/Controllers/Web/StatisticController.php
+++ b/app/Http/Controllers/Web/StatisticController.php
@@ -71,16 +71,16 @@ class StatisticController extends Controller
$emergencyCount = 0; $planSurgical = 0; $emergencySurgical = 0; $transferredCount = 0;
$deceasedCount = 0;
foreach ($reports as $report) {
- $allCount += $this->getMetrikaResultFromReport($report, 3, $isRangeOneDay);
- $currentCount += $this->getMetrikaResultFromReport($report, 8, false);
- $occupiedBeds += $this->getMetrikaResultFromReport($report, 8, $isRangeOneDay);
- $planCount += $this->getMetrikaResultFromReport($report, 4, $isRangeOneDay);
- $emergencyCount += $this->getMetrikaResultFromReport($report, 12, $isRangeOneDay);
- $planSurgical += $this->getMetrikaResultFromReport($report, 11, $isRangeOneDay);
- $emergencySurgical += $this->getMetrikaResultFromReport($report, 10, $isRangeOneDay);
- $transferredCount += $this->getMetrikaResultFromReport($report, 13, $isRangeOneDay);
- $outcomeCount += $this->getMetrikaResultFromReport($report, 7, $isRangeOneDay);
- $deceasedCount += $this->getMetrikaResultFromReport($report, 9, $isRangeOneDay);
+ $allCount += $this->getMetrikaResultFromReport($report, 3, $isRangeOneDay); // Поступило
+ $currentCount += $this->getMetrikaResultFromReport($report, 8, false); // Состоит
+ $occupiedBeds += $this->getMetrikaResultFromReport($report, 8, $isRangeOneDay); // Состоит
+ $planCount += $this->getMetrikaResultFromReport($report, 4, $isRangeOneDay); // Поступление - Планово
+ $emergencyCount += $this->getMetrikaResultFromReport($report, 12, $isRangeOneDay); // Поступление - Экстренно
+ $planSurgical += $this->getMetrikaResultFromReport($report, 11, $isRangeOneDay); // Операции - Планово
+ $emergencySurgical += $this->getMetrikaResultFromReport($report, 10, $isRangeOneDay); // Операции - Экстренно
+ $transferredCount += $this->getMetrikaResultFromReport($report, 13, $isRangeOneDay); // Поступление - Перевод
+ $outcomeCount += $this->getMetrikaResultFromReport($report, 7, $isRangeOneDay); // Выбыло
+ $deceasedCount += $this->getMetrikaResultFromReport($report, 9, $isRangeOneDay); // Умерло
}
// Независимые метрики (установки по умолчанию и т.п.)
diff --git a/app/Models/LifeMisMigrationPatient.php b/app/Models/LifeMisMigrationPatient.php
new file mode 100644
index 0000000..8c6f718
--- /dev/null
+++ b/app/Models/LifeMisMigrationPatient.php
@@ -0,0 +1,194 @@
+hasOne(MisStationarBranch::class, 'StationarBranchID', 'rf_StationarBranchID');
+ }
+
+ public function diagnosis()
+ {
+ return $this->hasMany(MisDiagnos::class, 'rf_MigrationPatientID', 'MigrationPatientID');
+ }
+
+ public function mkb()
+ {
+ return $this->hasOne(MisMKB::class, 'MKBID', 'rf_MKBID');
+ }
+
+ public function medicalHistory()
+ {
+ return $this->belongsTo(MisMedicalHistory::class, 'rf_MedicalHistoryID', 'MedicalHistoryID');
+ }
+
+ /**
+ * Находятся на лечении
+ */
+ public function scopeCurrentlyInTreatment($query, $branchId = null, DateRange $dateRange = null)
+ {
+ $query->where('rf_kl_VisitResultID', 0)
+ ->where('rf_kl_StatCureResultID', 0)
+ ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()])
+ ->whereHas('medicalHistory', function ($query) use ($branchId, $dateRange) {
+ $query->whereDate('DateExtract', '1900-01-01');
+ })
+ ->where('rf_MedicalHistoryID', '<>', 0);
+
+ if ($branchId) {
+ $query->where('rf_StationarBranchID', $branchId);
+ }
+
+ if ($dateRange) {
+ $query->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]);
+ }
+
+ return $query;
+ }
+
+ public function scopeWhereInDepartment($query, $branchId = null)
+ {
+ $query->where('rf_MedicalHistoryID', '<>', 0);
+
+ if ($branchId) {
+ $query->where('rf_StationarBranchID', $branchId);
+ }
+
+ return $query;
+ }
+
+ /**
+ * Выбывшие пациенты (все исходы)
+ */
+ public function scopeOutcomePatients($query, $branchId = null, DateRange $dateRange = null)
+ {
+ $query->where('rf_kl_VisitResultID', '<>', 0) // не активное лечение
+ ->whereDate('DateOut', '<>', '1900-01-01') // есть дата выбытия
+ ->where('rf_MedicalHistoryID', '<>', 0);
+
+ if ($branchId) {
+ $query->where('rf_StationarBranchID', $branchId);
+ }
+
+ if ($dateRange) {
+ $query->whereBetween('DateOut', [$dateRange->startSql(), $dateRange->endSql()]);
+ }
+
+ return $query;
+ }
+
+ /**
+ * Выписанные пациенты
+ */
+ public function scopeOutcomeDischarged($query, $branchId = null, DateRange $dateRange = null)
+ {
+ // ID выписки
+ $dischargeCodes = [1, 7, 8, 9, 10, 11, 48, 49, 124];
+
+ $query->whereIn('rf_kl_VisitResultID', $dischargeCodes)
+ ->whereDate('DateOut', '<>', '1900-01-01')
+ ->where('rf_MedicalHistoryID', '<>', 0);
+
+ if ($branchId) {
+ $query->where('rf_StationarBranchID', $branchId);
+ }
+
+ if ($dateRange) {
+ $query->whereBetween('DateOut', [$dateRange->startSql(), $dateRange->endSql()]);
+ }
+
+ return $query;
+ }
+
+ /**
+ * Перевод в другое отделение
+ */
+ public function scopeOutcomeTransferred($query, $branchId = null, DateRange $dateRange = null)
+ {
+ // ID перевода
+ $transferCodes = [2, 3, 4, 12, 13, 14];
+
+ $query->whereIn('rf_kl_VisitResultID', $transferCodes)
+ ->whereDate('DateOut', '<>', '1900-01-01')
+ ->where('rf_MedicalHistoryID', '<>', 0);
+
+ if ($branchId) {
+ $query->where('rf_StationarBranchID', $branchId);
+ }
+
+ if ($dateRange) {
+ $query->whereBetween('DateOut', [$dateRange->startSql(), $dateRange->endSql()]);
+ }
+
+ return $query;
+ }
+
+ /**
+ * Умершие пациенты
+ */
+ public function scopeDeceasedOutcome($query, $branchId = null, DateRange $dateRange = null)
+ {
+ // ID умершего
+ $deceasedCodes = [5, 6, 15, 16];
+
+ $query->whereIn('rf_kl_VisitResultID', $deceasedCodes)
+ ->whereDate('DateOut', '<>', '1900-01-01')
+ ->where('rf_MedicalHistoryID', '<>', 0);
+
+ if ($branchId) {
+ $query->where('rf_StationarBranchID', $branchId);
+ }
+
+ if ($dateRange) {
+ $query->whereBetween('DateOut', [$dateRange->startSql(), $dateRange->endSql()]);
+ }
+
+ return $query;
+ }
+
+ public function scopeOutcomeWithoutTransferred($query, $branchId = null, DateRange $dateRange = null)
+ {
+ // ID выписанных, без переводных
+ $outcomeWithoutTransferredIds = [5, 6, 15, 16, 1, 7, 8, 9, 10, 11, 48, 49, 124];
+
+ $query->whereIn('rf_kl_VisitResultID', $outcomeWithoutTransferredIds)
+ ->whereDate('DateOut', '<>', '1900-01-01')
+ ->where('rf_MedicalHistoryID', '<>', 0);
+
+ if ($branchId) {
+ $query->where('rf_StationarBranchID', $branchId);
+ }
+
+ if ($dateRange) {
+ $query->whereBetween('DateOut', [$dateRange->startSql(), $dateRange->endSql()]);
+ }
+
+ return $query;
+ }
+
+ public function scopeExtractedToday($query, $branchId = null, DateRange $dateRange = null)
+ {
+// if (is_null($startDate)) $startDate = Carbon::now()->addDays(-1)->format('Y-m-d');
+// if (is_null($endDate)) $endDate = Carbon::now()->format('Y-m-d');
+
+ $query->where('rf_kl_VisitResultID', '<>', 0)
+ ->where('rf_MedicalHistoryID', '<>', 0)
+ ->when($dateRange, function($query) use ($dateRange) {
+ return $query->whereBetween('DateOut', [$dateRange->startSql(), $dateRange->endSql()]);
+ });
+
+ if ($branchId) {
+ $query->where('rf_StationarBranchID', $branchId);
+ }
+
+ return $query;
+ }
+}
diff --git a/app/Models/MisDocPrvd.php b/app/Models/MisDocPrvd.php
new file mode 100644
index 0000000..5c90ff7
--- /dev/null
+++ b/app/Models/MisDocPrvd.php
@@ -0,0 +1,16 @@
+belongsTo(MisLpuDoctor::class, 'rf_LPUDoctorID');
+ }
+}
diff --git a/app/Models/MisLpuDoctor.php b/app/Models/MisLpuDoctor.php
index 4527c53..d4e9b09 100644
--- a/app/Models/MisLpuDoctor.php
+++ b/app/Models/MisLpuDoctor.php
@@ -22,4 +22,9 @@ class MisLpuDoctor extends Model
return $query->where('rf_DepartmentID', $department->rf_mis_department_id);
}
+
+ public function prvds()
+ {
+ return $this->hasMany(MisDocPrvd::class, 'rf_LPUDoctorID', 'LPUDoctorID');
+ }
}
diff --git a/app/Models/MisMigrationPatient.php b/app/Models/MisMigrationPatient.php
index 481717f..0a999dd 100644
--- a/app/Models/MisMigrationPatient.php
+++ b/app/Models/MisMigrationPatient.php
@@ -88,7 +88,7 @@ class MisMigrationPatient extends Model
/**
* Выписанные пациенты
*/
- public function scopeDischarged($query, $branchId = null, DateRange $dateRange = null)
+ public function scopeOutcomeDischarged($query, $branchId = null, DateRange $dateRange = null)
{
// ID выписки
$dischargeCodes = [1, 7, 8, 9, 10, 11, 48, 49, 124];
@@ -111,7 +111,7 @@ class MisMigrationPatient extends Model
/**
* Перевод в другое отделение
*/
- public function scopeTransferred($query, $branchId = null, DateRange $dateRange = null)
+ public function scopeOutcomeTransferred($query, $branchId = null, DateRange $dateRange = null)
{
// ID перевода
$transferCodes = [2, 3, 4, 12, 13, 14];
@@ -154,6 +154,26 @@ class MisMigrationPatient extends Model
return $query;
}
+ public function scopeOutcomeWithoutTransferred($query, $branchId = null, DateRange $dateRange = null)
+ {
+ // ID выписанных, без переводных
+ $outcomeWithoutTransferredIds = [5, 6, 15, 16, 1, 7, 8, 9, 10, 11, 48, 49, 124];
+
+ $query->whereIn('rf_kl_VisitResultID', $outcomeWithoutTransferredIds)
+ ->whereDate('DateOut', '<>', '1900-01-01')
+ ->where('rf_MedicalHistoryID', '<>', 0);
+
+ if ($branchId) {
+ $query->where('rf_StationarBranchID', $branchId);
+ }
+
+ if ($dateRange) {
+ $query->whereBetween('DateOut', [$dateRange->startSql(), $dateRange->endSql()]);
+ }
+
+ return $query;
+ }
+
public function scopeExtractedToday($query, $branchId = null, DateRange $dateRange = null)
{
// if (is_null($startDate)) $startDate = Carbon::now()->addDays(-1)->format('Y-m-d');
diff --git a/app/Services/AutoReportService.php b/app/Services/AutoReportService.php
new file mode 100644
index 0000000..f27242d
--- /dev/null
+++ b/app/Services/AutoReportService.php
@@ -0,0 +1,279 @@
+createReportForDate($user, $date, $force);
+
+ if ($reportCreated) {
+ $createdCount++;
+ }
+ } catch (\Exception $e) {
+ Log::error("Ошибка создания отчета для {$user->id} на {$date->format('Y-m-d')}: {$e->getMessage()}");
+ throw $e; // или continue в зависимости от требований
+ }
+ }
+
+ return $createdCount;
+ }
+
+ /**
+ * Создать отчет для конкретной даты
+ */
+ public function createReportForDate(User $user, Carbon $date, bool $force = false): bool
+ {
+ // Проверяем, существует ли уже отчет на эту дату
+ $existingReport = Report::where('rf_department_id', $user->rf_department_id)
+ ->whereDate('created_at', $date)
+ ->whereDate('sent_at', $date)
+ ->first();
+
+ if ($existingReport && !$force) {
+ return false; // Отчет уже существует
+ }
+
+ // Если есть существующий отчет и force=true - удаляем его
+ if ($existingReport && $force) {
+ $existingReport->delete();
+ }
+
+ // Создаем DateRange для этой даты
+ // Приводим к Illuminate\Carbon если нужно
+ if (!$date instanceof \Illuminate\Support\Carbon) {
+ $date = \Illuminate\Support\Carbon::instance($date);
+ }
+ $dateRange = $this->dateRangeService->createDateRangeForDate($date, $user);
+
+ // Получаем данные для отчета
+ $reportData = $this->prepareReportData($user, $dateRange, $date);
+
+ // Создаем отчет
+ DB::transaction(function () use ($user, $reportData, $date) {
+ $this->reportService->storeReport($reportData, $user);
+ });
+
+ return true;
+ }
+
+ /**
+ * Подготовить данные для отчета
+ */
+ private function prepareReportData(User $user, DateRange $dateRange, Carbon $date): array
+ {
+ $department = $user->department;
+ $branchId = $this->getBranchId($department->rf_mis_department_id);
+ $isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
+
+ // Получаем метрики
+ $metrics = $this->calculateMetrics(
+ $user,
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange
+ );
+
+ // Получаем количество коек
+ $beds = $this->getBedCount($department);
+
+ // Формируем данные отчета
+ return [
+ 'departmentId' => $department->department_id,
+ 'userId' => $user->rf_lpudoctor_id ?? $user->id,
+ 'dates' => [
+ $dateRange->startTimestamp(),
+ $dateRange->endTimestamp()
+ ],
+ 'sent_at' => $this->dateRangeService->toSqlFormat($date),
+ 'created_at' => $this->dateRangeService->toSqlFormat($date),
+ 'metrics' => $this->formatMetrics($metrics),
+ 'observationPatients' => $this->getObservationPatients($user->rf_department_id, $date),
+ 'unwantedEvents' => [],
+ ];
+ }
+
+ /**
+ * Рассчитать метрики для отчета
+ */
+ private function calculateMetrics(
+ User $user,
+ bool $isHeadOrAdmin,
+ int $branchId,
+ DateRange $dateRange
+ ): array {
+ $metrics = [];
+
+ // 1. Плановые пациенты
+ $metrics['plan'] = $this->patientQueryService->getPlanOrEmergencyPatients(
+ 'plan',
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange,
+ true,
+ false,
+ true,
+ true
+ );
+
+ Log::info($this->patientQueryService->getPlanOrEmergencyPatients(
+ 'plan',
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange,
+ false,
+ false,
+ true,
+ true
+ ));
+
+ // 2. Экстренные пациенты
+ $metrics['emergency'] = $this->patientQueryService->getPlanOrEmergencyPatients(
+ 'emergency',
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange,
+ true,
+ false,
+ true,
+ true
+ );
+
+ // 3. Поступившие сегодня
+ $metrics['recipient'] = $this->patientQueryService->getPlanOrEmergencyPatients(
+ null,
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange,
+ true,
+ false,
+ false,
+ true
+ );
+
+ // 4. Выписанные
+ $metrics['discharged'] = $this->patientQueryService->getOutcomePatients(
+ $branchId,
+ $dateRange,
+ 'discharged'
+ )->count();
+
+ // 5. Переведенные
+ $metrics['transferred'] = $this->patientQueryService->getOutcomePatients(
+ $branchId,
+ $dateRange,
+ 'transferred'
+ )->count();
+
+ // 6. Умершие
+ $metrics['deceased'] = $this->patientQueryService->getOutcomePatients(
+ $branchId,
+ $dateRange,
+ 'deceased'
+ )->count();
+
+ // 7. Текущие пациенты
+ $metrics['current'] = $this->patientQueryService->getAllPatientsInDepartment(
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange,
+ true
+ );
+
+ // 8. Плановые операции
+ $metrics['plan_surgery'] = $this->patientQueryService->getSurgicalPatients(
+ 'plan',
+ $branchId,
+ $dateRange,
+ true
+ );
+
+ // 9. Экстренные операции
+ $metrics['emergency_surgery'] = $this->patientQueryService->getSurgicalPatients(
+ 'emergency',
+ $branchId,
+ $dateRange,
+ true
+ );
+
+ return $metrics;
+ }
+
+ /**
+ * Форматировать метрики для сохранения
+ */
+ private function formatMetrics(array $metrics): array
+ {
+ return [
+ 'metrika_item_3' => $metrics['plan'] ?? 0, // плановые
+ 'metrika_item_4' => $metrics['emergency'] ?? 0, // экстренные
+ 'metrika_item_5' => $metrics['recipient'] ?? 0, // поступившие
+ 'metrika_item_6' => ($metrics['plan_surgery'] ?? 0) + ($metrics['emergency_surgery'] ?? 0), // всего операций
+ 'metrika_item_7' => $metrics['discharged'] ?? 0, // выписанные
+ 'metrika_item_8' => $metrics['current'] ?? 0, // текущие
+ 'metrika_item_9' => $metrics['deceased'] ?? 0, // умершие
+ 'metrika_item_10' => $metrics['plan_surgery'] ?? 0, // плановые операции
+ 'metrika_item_11' => $metrics['emergency_surgery'] ?? 0, // экстренные операции
+ 'metrika_item_12' => $metrics['transferred'] ?? 0, // переведенные
+ 'metrika_item_13' => 0, // под наблюдением (будет заполнено отдельно)
+ ];
+ }
+
+ /**
+ * Получить пациентов под наблюдением на дату
+ */
+ private function getObservationPatients(int $departmentId, Carbon $date): array
+ {
+ // Здесь нужно реализовать логику получения пациентов под наблюдением
+ // на конкретную дату. Возможно, из снапшотов или истории.
+ return []; // временно возвращаем пустой массив
+ }
+
+ /**
+ * Получить ID отделения
+ */
+ private function getBranchId(int $misDepartmentId): ?int
+ {
+ return MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
+ ->value('StationarBranchID');
+ }
+
+ /**
+ * Получить количество коек
+ */
+ private function getBedCount(Department $department): int
+ {
+ $default = $department->metrikaDefault()->where('rf_metrika_item_id', 1)->first();
+ return (int)($default->value ?? 0);
+ }
+}
diff --git a/app/Services/DateRangeService.php b/app/Services/DateRangeService.php
index a85dcdf..49583ce 100644
--- a/app/Services/DateRangeService.php
+++ b/app/Services/DateRangeService.php
@@ -125,4 +125,20 @@ class DateRangeService
{
return $this->toCarbon($date)->format('Y-m-d H:i:s');
}
+
+ public function createDateRangeForDate(Carbon $date, User $user): DateRange
+ {
+ // Для автоматического заполнения используем логику как для врача
+ // (вчера 06:00 - сегодня 06:00)
+ $startDate = $date->copy()->subDay()->setTime(6, 0);
+ $endDate = $date->copy()->setTime(6, 0);
+
+ return new DateRange(
+ startDate: $startDate,
+ endDate: $endDate,
+ startDateRaw: $startDate->format('Y-m-d H:i:s'),
+ endDateRaw: $endDate->format('Y-m-d H:i:s'),
+ isOneDay: true
+ );
+ }
}
diff --git a/app/Services/PatientService.php b/app/Services/PatientService.php
index f84a91b..57e56ea 100644
--- a/app/Services/PatientService.php
+++ b/app/Services/PatientService.php
@@ -2,6 +2,7 @@
namespace App\Services;
+use App\Models\LifeMisMigrationPatient;
use App\Models\MisMedicalHistory;
use App\Models\MisMigrationPatient;
use App\Models\ObservationPatient;
@@ -19,17 +20,28 @@ class PatientService
DateRange $dateRange,
bool $countOnly = false,
bool $onlyIds = false,
- bool $includeCurrent = false
+ bool $includeCurrent = false,
+ bool $fillableAuto = false
) {
// Получаем поступивших сегодня
- $recipientQuery = $this->buildRecipientQuery($type, $isHeadOrAdmin, $branchId, $dateRange);
- $recipientIds = $recipientQuery->pluck('rf_MedicalHistoryID')->toArray();
+ $recipientQuery = $this->buildRecipientQuery($type, $isHeadOrAdmin, $branchId, $dateRange, $fillableAuto);
+ if ($fillableAuto)
+ $recipientIds = $recipientQuery->distinct()->pluck('rf_MedicalHistoryID')->toArray();
+ else
+ $recipientIds = $recipientQuery->pluck('rf_MedicalHistoryID')->toArray();
// Если нужно добавить уже находящихся в отделении
if ($includeCurrent) {
- $currentIds = MisMigrationPatient::currentlyInTreatment($branchId)
- ->pluck('rf_MedicalHistoryID')
- ->toArray();
+ if ($fillableAuto) {
+ $currentIds = LifeMisMigrationPatient::currentlyInTreatment($branchId, $dateRange)
+ ->distinct()
+ ->pluck('rf_MedicalHistoryID')
+ ->toArray();
+ } else {
+ $currentIds = MisMigrationPatient::currentlyInTreatment($branchId)
+ ->pluck('rf_MedicalHistoryID')
+ ->toArray();
+ }
$medicalHistoryIds = array_unique(array_merge($recipientIds, $currentIds));
} else {
@@ -38,14 +50,10 @@ class PatientService
if (empty($medicalHistoryIds)) {
if ($countOnly) return 0;
- if ($onlyIds) return [];
+ if ($onlyIds) return collect();
return collect();
}
- if ($onlyIds) {
- return $medicalHistoryIds;
- }
-
// Получаем истории
$query = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
->with([
@@ -53,7 +61,7 @@ class PatientService
$q->whereBetween('Date', [$dateRange->startSql(), $dateRange->endSql()]);
},
'migrations' => function ($q) use ($branchId) {
- $q->where('rf_StationarBranchID', $branchId) // укажите поле сортировки
+ $q->where('rf_StationarBranchID', $branchId)
->take(1) // берем только одну последнюю
->with(['diagnosis' => function ($q) {
$q->where('rf_DiagnosTypeID', 3)
@@ -75,6 +83,10 @@ class PatientService
return $query->count();
}
+ if ($onlyIds) {
+ return $query->pluck('MedicalHistoryID');
+ }
+
return $query->get()->map(function ($patient) use ($recipientIds, $branchId) {
// Добавляем флаг "поступил сегодня"
$patient->is_recipient_today = in_array($patient->MedicalHistoryID, $recipientIds);
@@ -89,7 +101,8 @@ class PatientService
bool $isHeadOrAdmin,
int $branchId,
DateRange $dateRange,
- bool $countOnly = false
+ bool $countOnly = false,
+ bool $onlyIds = false
) {
// Поступившие сегодня
$recipientIds = $this->buildRecipientQuery(null, $isHeadOrAdmin, $branchId, $dateRange)
@@ -113,9 +126,13 @@ class PatientService
return count($allIds);
}
+ if ($onlyIds) {
+ return collect($allIds);
+ }
+
return MisMedicalHistory::whereIn('MedicalHistoryID', $allIds)
- ->with(['surgicalOperations' => function ($q) use ($startDate, $endDate) {
- $q->whereBetween('Date', [$startDate, $endDate]);
+ ->with(['surgicalOperations' => function ($q) use ($dateRange) {
+ $q->whereBetween('Date', [$dateRange->startSql(), $dateRange->endSql()]);
}])
->orderBy('DateRecipient', 'DESC')
->get()
@@ -128,17 +145,22 @@ class PatientService
/**
* Получить пациентов под наблюдением
*/
- public function getObservationPatients(int $departmentId)
+ public function getObservationPatients(int $departmentId, bool $onlyIds = false)
{
- $patients = MisMedicalHistory::whereHas('observationPatient', function ($q) use ($departmentId) {
+ $query = MisMedicalHistory::whereHas('observationPatient', function ($q) use ($departmentId) {
$q->where('rf_department_id', $departmentId);
- })
- ->with(['observationPatient' => function($query) use ($departmentId) {
+ });
+
+ if (!$onlyIds) {
+ $query->with(['observationPatient' => function ($query) use ($departmentId) {
$query->where('rf_department_id', $departmentId)
->select(['rf_medicalhistory_id', 'observation_patient_id', 'comment']);
}])
- ->orderBy('DateRecipient', 'DESC')
- ->get();
+ ->orderBy('DateRecipient', 'DESC');
+ }
+
+ if ($onlyIds) $patients = $query->pluck('MedicalHistoryID');
+ else $patients = $query->get();
return $patients->map(function ($patient) {
$patient->comment = $patient->observationPatient
@@ -155,11 +177,13 @@ class PatientService
public function getOutcomePatients(
int $branchId,
DateRange $dateRange,
- string $outcomeType = 'all'
+ string $outcomeType = 'all',
+ bool $onlyIds = false
) {
$methodMap = [
- 'discharged' => 'discharged',
- 'transferred' => 'transferred',
+ 'discharged' => 'outcomeDischarged',
+ 'transferred' => 'outcomeTransferred',
+ 'without-transferred' => 'outcomeWithoutTransferred',
'deceased' => 'deceasedOutcome',
'all' => 'outcomePatients',
];
@@ -175,6 +199,8 @@ class PatientService
return collect();
}
+ if ($onlyIds) return collect($medicalHistoryIds);
+
return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
->with(['surgicalOperations'])
->orderBy('DateRecipient', 'DESC')
@@ -282,17 +308,28 @@ class PatientService
?string $type,
bool $isHeadOrAdmin,
int $branchId,
- DateRange $dateRange
+ DateRange $dateRange,
+ bool $fillableAuto = false
) {
// Разная логика для заведующего и врача
if ($isHeadOrAdmin) {
// Заведующий: все поступившие за период
- $query = MisMigrationPatient::whereInDepartment($branchId)
- ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]);
+ if ($fillableAuto) {
+ $query = LifeMisMigrationPatient::whereInDepartment($branchId)
+ ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]);
+ } else {
+ $query = MisMigrationPatient::whereInDepartment($branchId)
+ ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]);
+ }
} else {
// Врач: только поступившие за сутки
- $query = MisMigrationPatient::whereInDepartment($branchId)
- ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]);
+ if ($fillableAuto) {
+ $query = LifeMisMigrationPatient::whereInDepartment($branchId)
+ ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]);
+ } else {
+ $query = MisMigrationPatient::whereInDepartment($branchId)
+ ->whereBetween('DateIngoing', [$dateRange->startSql(), $dateRange->endSql()]);
+ };
}
return $query;
diff --git a/app/Services/ReportService.php b/app/Services/ReportService.php
index d08d7ef..4f5f202 100644
--- a/app/Services/ReportService.php
+++ b/app/Services/ReportService.php
@@ -2,6 +2,7 @@
namespace App\Services;
+use App\Models\Department;
use App\Models\MedicalHistorySnapshot;
use App\Models\MetrikaResult;
use App\Models\MisLpuDoctor;
@@ -46,7 +47,7 @@ class ReportService
/**
* Создать или обновить отчет
*/
- public function storeReport(array $data, User $user): Report
+ public function storeReport(array $data, User $user, $fillableAuto = false): Report
{
DB::beginTransaction();
@@ -58,7 +59,7 @@ class ReportService
$this->saveObservationPatients($report, $data['observationPatients'] ?? [], $user->rf_department_id);
// Сохраняем снапшоты пациентов
- $this->snapshotService->createPatientSnapshots($report, $user, $data['dates']);
+ $this->snapshotService->createPatientSnapshots($report, $user, $data['dates'], $fillableAuto);
DB::commit();
return $report;
@@ -74,17 +75,20 @@ class ReportService
public function getPatientsByStatus(
User $user,
string $status,
- DateRange $dateRange
+ DateRange $dateRange,
+ bool $onlyIds = false,
+ bool $beforeCreate = false,
+ ?bool $includeCurrentPatients = null
) {
$branchId = $this->getBranchId($user->department->rf_mis_department_id);
- $useSnapshots = $this->shouldUseSnapshots($user, $dateRange);
+ $useSnapshots = $this->shouldUseSnapshots($user, $dateRange, $beforeCreate);
if ($useSnapshots) {
return $this->getPatientsFromSnapshots($user, $status, $dateRange, $branchId);
}
- return $this->getPatientsFromReplica($user, $status, $dateRange, $branchId);
+ return $this->getPatientsFromReplica($user, $status, $dateRange, $branchId, $onlyIds, $includeCurrentPatients);
}
/**
@@ -118,9 +122,9 @@ class ReportService
/**
* Определить, нужно ли использовать снапшоты
*/
- private function shouldUseSnapshots(User $user, DateRange $dateRange): bool
+ private function shouldUseSnapshots(User $user, DateRange $dateRange, bool $beforeCreate = false): bool
{
- if ($user->isAdmin() || $user->isHeadOfDepartment()) {
+ if (($user->isAdmin() || $user->isHeadOfDepartment()) && !$beforeCreate) {
return true;
}
@@ -141,7 +145,8 @@ class ReportService
'rf_department_id' => $data['departmentId'],
'rf_user_id' => $user->id,
'rf_lpudoctor_id' => $data['userId'],
- 'sent_at' => now(),
+ 'sent_at' => $data['sent_at'] ?? $this->dateRangeService->toSqlFormat(\Illuminate\Support\Carbon::now()),
+ 'created_at' => $data['created_at'] ?? $this->dateRangeService->toSqlFormat(\Illuminate\Support\Carbon::now()),
];
if (isset($data['reportId']) && $data['reportId']) {
@@ -151,6 +156,13 @@ class ReportService
);
} else {
$report = Report::create($reportData);
+ $department = Department::where('department_id', $reportData['rf_department_id'])->first();
+ $beds = $department->metrikaDefault->where('rf_metrika_item_id', 1)->first();
+ MetrikaResult::create([
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => 1,
+ 'value' => $beds->value
+ ]);
}
return $report;
@@ -265,7 +277,7 @@ class ReportService
$isActiveSendButton = $this->isSendButtonActive($user, $dateRange, $reportToday, $fillableUserId);
$message = null;
- if ($reportToday && $reportToday->rf_lpudoctor_id !== intval($fillableUserId)) {
+ if ($reportToday) {
$reportDoctor = $reportToday->lpuDoctor;
$message = "Отчет уже создан пользователем: $reportDoctor->FAM_V $reportDoctor->IM_V $reportDoctor->OT_V";
}
@@ -329,9 +341,11 @@ class ReportService
'emergency' => $this->getMetrikaResultCount(12, $reportIds),
'outcome' => $this->getMetrikaResultCount(7, $reportIds),
'deceased' => $this->getMetrikaResultCount(9, $reportIds),
+ 'current' => $this->getMetrikaResultCount(8, $reportIds),
// 'discharged' => $this->getMetrikaResultCount('discharged', $reportIds),
'transferred' => $this->getMetrikaResultCount(13, $reportIds),
'recipient' => $this->getMetrikaResultCount(3, $reportIds),
+ 'beds' => $this->getMetrikaResultCount(1, $reportIds)
];
// Получаем ID поступивших пациентов
@@ -350,10 +364,11 @@ class ReportService
return [
'recipientCount' => $snapshotStats['recipient'] ?? 0,
'extractCount' => $snapshotStats['outcome'] ?? 0,
- 'currentCount' => $this->calculateCurrentPatientsFromSnapshots($reportIds, $branchId),
+ 'currentCount' => $snapshotStats['current'] ?? 0,//$this->calculateCurrentPatientsFromSnapshots($reportIds, $branchId),
'deadCount' => $snapshotStats['deceased'] ?? 0,
'surgicalCount' => $surgicalCount,
'recipientIds' => $recipientIds,
+ 'beds' => $snapshotStats['beds'] ?? 0
];
}
@@ -440,6 +455,10 @@ class ReportService
false // только поступившие сегодня
);
+ $misBranch = MisStationarBranch::where('StationarBranchID', $branchId)->first();
+ $beds = Department::where('rf_mis_department_id', $misBranch->rf_DepartmentID)
+ ->first()->metrikaDefault->where('rf_metrika_item_id', 1)->first();
+
return [
'recipientCount' => $recipientCount, // только поступившие сегодня
'extractCount' => $outcomeCount,
@@ -449,14 +468,20 @@ class ReportService
'recipientIds' => $recipientIds, // ID поступивших сегодня
'planCount' => $planCount, // плановые (поступившие + уже лечащиеся)
'emergencyCount' => $emergencyCount, // экстренные (поступившие + уже лечащиеся)
+ 'beds' => $beds->value
];
}
/**
* Получить пациентов из снапшотов
*/
- private function getPatientsFromSnapshots(User $user, string $status, DateRange $dateRange, int $branchId)
- {
+ private function getPatientsFromSnapshots(
+ User $user,
+ string $status,
+ DateRange $dateRange,
+ int $branchId,
+ bool $onlyIds = false
+ ) {
$reports = $this->getReportsForDateRange(
$user->rf_department_id,
$dateRange
@@ -476,21 +501,27 @@ class ReportService
$patientType = $patientTypeMap[$status] ?? null;
if ($patientType === 'observation') {
- return $this->getObservationPatientsFromSnapshots($user->rf_department_id, $reportIds);
+ return $this->patientQueryService->getObservationPatients($user->rf_department_id, $onlyIds); //$this->getObservationPatientsFromSnapshots($user->rf_department_id, $reportIds, $onlyIds);
}
- return $this->snapshotService->getPatientsFromSnapshots($patientType, $reportIds, $branchId);
+ return $this->snapshotService->getPatientsFromSnapshots($patientType, $reportIds, $branchId, $onlyIds);
}
/**
* Получить пациентов из реплики БД
*/
- private function getPatientsFromReplica(User $user, string $status, DateRange $dateRange, int $branchId)
- {
+ private function getPatientsFromReplica(
+ User $user,
+ string $status,
+ DateRange $dateRange,
+ int $branchId,
+ bool $onlyIds = false,
+ ?bool $isIncludeCurrent = null
+ ) {
$isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
// Для плановых и экстренных включаем уже лечащихся
- $includeCurrent = in_array($status, ['plan', 'emergency']);
+ $includeCurrent = $isIncludeCurrent ?? in_array($status, ['plan', 'emergency']);
return match($status) {
'plan', 'emergency' => $this->patientQueryService->getPlanOrEmergencyPatients(
@@ -499,29 +530,40 @@ class ReportService
$branchId,
$dateRange,
false,
- false,
+ $onlyIds,
$includeCurrent
),
- 'observation' => $this->patientQueryService->getObservationPatients($user->rf_department_id),
+ 'observation' => $this->patientQueryService->getObservationPatients($user->rf_department_id, $onlyIds),
+ 'outcome' => $this->patientQueryService->getOutcomePatients(
+ $branchId,
+ $dateRange,
+ 'without-transferred',
+ $onlyIds
+ ), // Выписанные без перевода
'outcome-discharged' => $this->patientQueryService->getOutcomePatients(
$branchId,
$dateRange,
- 'discharged'
+ 'discharged',
+ $onlyIds
),
'outcome-transferred' => $this->patientQueryService->getOutcomePatients(
$branchId,
$dateRange,
- 'transferred'
+ 'transferred',
+ $onlyIds
),
'outcome-deceased' => $this->patientQueryService->getOutcomePatients(
$branchId,
$dateRange,
- 'deceased'
+ 'deceased',
+ $onlyIds
),
'current' => $this->patientQueryService->getAllPatientsInDepartment(
$isHeadOrAdmin,
$branchId,
- $dateRange
+ $dateRange,
+ false,
+ $onlyIds
),
'recipient' => $this->patientQueryService->getPlanOrEmergencyPatients(
null,
@@ -529,7 +571,7 @@ class ReportService
$branchId,
$dateRange,
false,
- false,
+ $onlyIds,
false // только поступившие
),
default => collect()
@@ -666,8 +708,8 @@ class ReportService
return null;
}
- // Если дата не сегодня, не показываем врача
- if (!$dateRange->isEndDateToday()) {
+ // Если дата это период, не показываем врача
+ if (!$dateRange->isOneDay) {
return null;
}
@@ -744,7 +786,7 @@ class ReportService
/**
* Получить пациентов под наблюдением из снапшотов
*/
- private function getObservationPatientsFromSnapshots(int $departmentId, array $reportIds)
+ private function getObservationPatientsFromSnapshots(int $departmentId, array $reportIds, bool $onlyIds = false)
{
$medicalHistoryIds = ObservationPatient::whereIn('rf_report_id', $reportIds)
->where('rf_department_id', $departmentId)
@@ -756,6 +798,10 @@ class ReportService
return collect();
}
+ if ($onlyIds) {
+ return collect($medicalHistoryIds);
+ }
+
return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
->with(['observationPatient' => function($query) use ($departmentId) {
$query->where('rf_department_id', $departmentId)
diff --git a/app/Services/SnapshotService.php b/app/Services/SnapshotService.php
index 36db8c5..16867df 100644
--- a/app/Services/SnapshotService.php
+++ b/app/Services/SnapshotService.php
@@ -3,8 +3,10 @@
namespace App\Services;
use App\Models\MedicalHistorySnapshot;
+use App\Models\MetrikaResult;
use App\Models\MisMedicalHistory;
use App\Models\MisStationarBranch;
+use App\Models\ObservationPatient;
use App\Models\Report;
use App\Models\User;
use Carbon\Carbon;
@@ -13,95 +15,146 @@ use Illuminate\Support\Collection;
class SnapshotService
{
public function __construct(
- protected PatientService $patientService
+ protected PatientService $patientService,
+ protected DateRangeService $dateRangeService,
) {}
/**
* Создать снапшоты пациентов для отчета
*/
- public function createPatientSnapshots(Report $report, User $user, array $dates): void
+ public function createPatientSnapshots(Report $report, User $user, array $dates, $fillableAuto = false): void
{
$branchId = $this->getBranchId($user->department->rf_mis_department_id);
[$startDate, $endDate] = $this->parseDates($dates);
+ $dateRange = $this->dateRangeService->getNormalizedDateRange($user, $startDate, $endDate);
+ $isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
- // Плановые пациенты
- $this->createSnapshotsForType(
- $report,
+ // Массив для хранения подсчитанных метрик
+ $metrics = [];
+
+ // 1. Плановые пациенты
+ $planIds = $this->patientService->getPlanOrEmergencyPatients(
'plan',
- $this->patientService->getPlanOrEmergencyPatients(
- 'plan',
- $user->isHeadOfDepartment() || $user->isAdmin(),
- $branchId,
- $startDate,
- $endDate,
- false,
- true
- )
- );
-
- // Экстренные пациенты
- $this->createSnapshotsForType(
- $report,
- 'emergency',
- $this->patientService->getPlanOrEmergencyPatients(
- 'emergency',
- $user->isHeadOfDepartment() || $user->isAdmin(),
- $branchId,
- $startDate,
- $endDate,
- false,
- true
- )
- );
-
- // Выписанные
- $this->createSnapshotsForType(
- $report,
- 'discharged',
- $this->patientService->getOutcomePatients(
- $branchId,
- $startDate,
- $endDate,
- 'discharged'
- )->pluck('MedicalHistoryID')->toArray()
- );
-
- // Переведенные
- $this->createSnapshotsForType(
- $report,
- 'transferred',
- $this->patientService->getOutcomePatients(
- $branchId,
- $startDate,
- $endDate,
- 'transferred'
- )->pluck('MedicalHistoryID')->toArray()
- );
-
- // Умершие
- $this->createSnapshotsForType(
- $report,
- 'deceased',
- $this->patientService->getOutcomePatients(
- $branchId,
- $startDate,
- $endDate,
- 'deceased'
- )->pluck('MedicalHistoryID')->toArray()
- );
-
- // Поступившие
- $recipientIds = $this->patientService->getPlanOrEmergencyPatients(
- null,
- $user->isHeadOfDepartment() || $user->isAdmin(),
+ $isHeadOrAdmin,
$branchId,
- $startDate,
- $endDate,
+ $dateRange,
false,
+ true,
+ true,
+ $fillableAuto
+ );
+ $this->createSnapshotsForType($report, 'plan', $planIds);
+ $metrics[4] = $this->patientService->getPlanOrEmergencyPatients(
+ 'plan',
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange,
+ true,
+ $fillableAuto
+ ); // metrika_item_3 - плановые
+
+ // 2. Экстренные пациенты
+ $emergencyIds = $this->patientService->getPlanOrEmergencyPatients(
+ 'emergency',
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange,
+ false,
+ true,
+ true,
+ $fillableAuto
+ );
+ $this->createSnapshotsForType($report, 'emergency', $emergencyIds);
+ $metrics[12] = $this->patientService->getPlanOrEmergencyPatients(
+ 'emergency',
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange,
+ true,
+ $fillableAuto
+ );; // metrika_item_12 - экстренные
+
+ // 3. Выписанные
+ $dischargedIds = $this->patientService->getOutcomePatients(
+ $branchId,
+ $dateRange,
+ 'discharged',
true
);
+ $this->createSnapshotsForType($report, 'discharged', $dischargedIds);
+ $metrics[15] = count($dischargedIds); // metrika_item_15 - выписанные
+ // 4. Переведенные
+ $transferredIds = $this->patientService->getOutcomePatients(
+ $branchId,
+ $dateRange,
+ 'transferred',
+ true
+ );
+ $this->createSnapshotsForType($report, 'transferred', $transferredIds);
+ $metrics[13] = count($transferredIds); // metrika_item_13 - переведенные
+
+ // 5. Умершие
+ $deceasedIds = $this->patientService->getOutcomePatients(
+ $branchId,
+ $dateRange,
+ 'deceased',
+ true
+ );
+ $this->createSnapshotsForType($report, 'deceased', $deceasedIds);
+// $metrics[9] = count($deceasedIds); // metrika_item_9 - умершие
+
+ // 6. Поступившие (все новые поступления - плановые + экстренные)
+ $recipientIds = $this->patientService->getPlanOrEmergencyPatients(
+ null,
+ $isHeadOrAdmin,
+ $branchId,
+ $dateRange,
+ false,
+ true,
+ false // только поступившие сегодня
+ );
$this->createSnapshotsForType($report, 'recipient', $recipientIds);
+// $metrics[3] = count($recipientIds); // metrika_item_3 - поступившие
+
+ // 8. Плановые операции
+ $planSurgeryCount = $this->patientService->getSurgicalPatients(
+ 'plan',
+ $branchId,
+ $dateRange,
+ true
+ );
+// $metrics[11] = $planSurgeryCount; // metrika_item_11 - плановые операции
+
+ // 9. Экстренные операции
+ $emergencySurgeryCount = $this->patientService->getSurgicalPatients(
+ 'emergency',
+ $branchId,
+ $dateRange,
+ true
+ );
+// $metrics[10] = $emergencySurgeryCount; // metrika_item_10 - экстренные операции
+
+ // Сохраняем все метрики
+ $this->saveMetrics($report, $metrics);
+ }
+
+ /**
+ * Сохранить метрики в базу
+ */
+ private function saveMetrics(Report $report, array $metrics): void
+ {
+ foreach ($metrics as $metrikaItemId => $value) {
+ MetrikaResult::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_metrika_item_id' => $metrikaItemId,
+ ],
+ [
+ 'value' => $value,
+ ]
+ );
+ }
}
/**
@@ -126,8 +179,12 @@ class SnapshotService
public function getPatientsFromSnapshots(
string $type,
array $reportIds,
- ?int $branchId = null
+ ?int $branchId = null,
+ bool $onlyIds = false
): Collection {
+ // Для плановых и экстренных включаем уже лечащихся
+// $includeCurrent = in_array($type, ['plan', 'emergency']);
+
$medicalHistoryIds = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
->where('patient_type', $type)
->pluck('rf_medicalhistory_id')
@@ -138,6 +195,10 @@ class SnapshotService
return collect();
}
+ if ($onlyIds) {
+ return collect($medicalHistoryIds);
+ }
+
return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
->when($type === 'plan', fn($q) => $q->plan())
->when($type === 'emergency', fn($q) => $q->emergency())
@@ -165,14 +226,21 @@ class SnapshotService
/**
* Создать снапшоты для определенного типа пациентов
*/
- private function createSnapshotsForType(Report $report, string $type, array $medicalHistoryIds): void
+ private function createSnapshotsForType(Report $report, string $type, Collection $medicalHistoryIds): void
{
foreach ($medicalHistoryIds as $id) {
- MedicalHistorySnapshot::create([
- 'rf_report_id' => $report->report_id,
- 'rf_medicalhistory_id' => $id,
- 'patient_type' => $type,
- ]);
+ MedicalHistorySnapshot::updateOrCreate(
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_medicalhistory_id' => $id,
+ 'patient_type' => $type
+ ],
+ [
+ 'rf_report_id' => $report->report_id,
+ 'rf_medicalhistory_id' => $id,
+ 'patient_type' => $type,
+ ]
+ );
}
}
diff --git a/resources/js/Components/DatePickerQuery.vue b/resources/js/Components/DatePickerQuery.vue
index 7d83815..7d42311 100644
--- a/resources/js/Components/DatePickerQuery.vue
+++ b/resources/js/Components/DatePickerQuery.vue
@@ -75,22 +75,32 @@ const formattedValue = computed(() => {
}
})
-watch(() => modelValue.value, (newVal, oldVal) => {
- if (!newVal) return
+const handleDateUpdate = (value) => {
+ console.log('Получено значение:', value)
- if (Array.isArray(newVal)) {
- if (newVal.length === 2 &&
- (!oldVal || newVal[0] !== oldVal[0] || newVal[1] !== oldVal[1])) {
- queryDate.value = newVal
- setQueryDate()
+ // Устанавливаем новое значение
+ modelValue.value = value
+
+ // Для диапазона: отправляем только если обе даты заполнены
+ if (isUseDateRange.value) {
+ if (Array.isArray(value) && value[0] && value[1]) {
+ // Дебаунс для предотвращения двойной отправки
+ setTimeout(() => {
+ // Проверяем что значение не изменилось за время таймаута
+ if (JSON.stringify(modelValue.value) === JSON.stringify(value)) {
+ queryDate.value = value
+ setQueryDate()
+ }
+ }, 100)
}
} else {
- if (newVal !== oldVal) {
- queryDate.value = newVal
+ // Для одиночной даты отправляем сразу
+ if (value) {
+ queryDate.value = [value, value]
setQueryDate()
}
}
-})
+}
@@ -106,7 +116,7 @@ watch(() => modelValue.value, (newVal, oldVal) => {
placement="top-start"
input-readonly
bind-calendar-months
- update-value-on-close
+ @update:value="value => handleDateUpdate(value)"
:type="dateType" />
diff --git a/resources/js/Pages/Auth/Login.vue b/resources/js/Pages/Auth/Login.vue
index 7c8944e..1539334 100644
--- a/resources/js/Pages/Auth/Login.vue
+++ b/resources/js/Pages/Auth/Login.vue
@@ -109,6 +109,7 @@ const handleForgotPassword = async () => {
{
{
{{ authStore.userDepartment.name_full }}
-
- Ответственный: {{ reportStore.reportInfo?.userName }}
+
+ Ответственный: {{ reportStore.reportInfo?.report.userName }}
-
+
diff --git a/resources/js/Pages/Report/Components/ReportSection.vue b/resources/js/Pages/Report/Components/ReportSection.vue
index ee431ad..8f8e99a 100644
--- a/resources/js/Pages/Report/Components/ReportSection.vue
+++ b/resources/js/Pages/Report/Components/ReportSection.vue
@@ -82,15 +82,6 @@ const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
-
-
-
-
-
-
@@ -109,6 +100,15 @@ const isReadonlyMode = computed(() => props.mode.toLowerCase() === 'readonly')
@item-dropped="handleItemDropped"
/>
+
+
+
+
+
+
diff --git a/resources/js/Pages/Report/Components/ReportSectionItem.vue b/resources/js/Pages/Report/Components/ReportSectionItem.vue
index 7baf527..d533d3b 100644
--- a/resources/js/Pages/Report/Components/ReportSectionItem.vue
+++ b/resources/js/Pages/Report/Components/ReportSectionItem.vue
@@ -244,7 +244,6 @@ function rowProps(row) {
style.push(props.isDraggable ? 'cursor: grab;' : 'cursor: arrow;')
if (props.accentIds.length) {
- console.log(props.accentIds.includes(row.id))
if (props.accentIds.includes(row.id)) {
style.push('--n-merged-td-color: #047857')
}
diff --git a/resources/js/Pages/Report/Components/SelectUserModal.vue b/resources/js/Pages/Report/Components/SelectUserModal.vue
index 6ab715d..d9d4b9f 100644
--- a/resources/js/Pages/Report/Components/SelectUserModal.vue
+++ b/resources/js/Pages/Report/Components/SelectUserModal.vue
@@ -63,7 +63,10 @@ const onAfterLeave = () => {
>
-
+
diff --git a/resources/js/Pages/Report/Index.vue b/resources/js/Pages/Report/Index.vue
index 409013c..dee0443 100644
--- a/resources/js/Pages/Report/Index.vue
+++ b/resources/js/Pages/Report/Index.vue
@@ -34,7 +34,10 @@ onMounted(() => {
reportStore.reportInfo.userId = userId
- reportStore.reportInfo = props
+ reportStore.reportInfo = {
+ ...reportStore.reportInfo,
+ ...props
+ }
reportStore.reportForm.metrika_item_3 = props.department.recipientCount
reportStore.reportForm.metrika_item_7 = props.department.extractCount
@@ -46,10 +49,17 @@ onMounted(() => {
reportStore.unwantedEvents = props.report.unwantedEvents
- reportStore.timestampCurrentRange = [
- props.dates.startAt,
- props.dates.endAt,
- ]
+ if (props.report.isHeadOrAdmin) {
+ reportStore.timestampCurrentRange = [
+ props.dates.startAt,
+ props.dates.endAt,
+ ]
+ } else {
+ reportStore.timestampCurrentRange = [
+ props.dates.endAt,
+ props.dates.endAt
+ ]
+ }
// reportStore.getReportInfo()
})
@@ -63,8 +73,14 @@ const mode = computed(() => {
})
watch(() => props, (newProps) => {
+ reportStore.reportInfo = {
+ ...reportStore.reportInfo,
+ ...newProps
+ }
- reportStore.reportInfo = newProps
+ if (newProps.report.isHeadOrAdmin) {
+ reportStore.reportInfo.userId = newProps.report.userId
+ }
reportStore.reportForm.metrika_item_3 = newProps.department.recipientCount
reportStore.reportForm.metrika_item_7 = newProps.department.extractCount
@@ -76,10 +92,17 @@ watch(() => props, (newProps) => {
reportStore.unwantedEvents = newProps.report.unwantedEvents
- reportStore.timestampCurrentRange = [
- newProps.dates.startAt,
- newProps.dates.endAt,
- ]
+ if (props.report.isHeadOrAdmin) {
+ reportStore.timestampCurrentRange = [
+ props.dates.startAt,
+ props.dates.endAt,
+ ]
+ } else {
+ reportStore.timestampCurrentRange = [
+ props.dates.endAt,
+ props.dates.endAt
+ ]
+ }
}, {
deep: true, // важно для глубокого отслеживания
immediate: true // выполнить сразу при создании
diff --git a/resources/js/Stores/report.js b/resources/js/Stores/report.js
index 8ba6830..c54d5c2 100644
--- a/resources/js/Stores/report.js
+++ b/resources/js/Stores/report.js
@@ -86,18 +86,27 @@ export const useReportStore = defineStore('reportStore', () => {
metrics: reportForm.value,
observationPatients: patientsData.value['observation'],
unwantedEvents: unwantedEvents.value,
- dates: timestampCurrentRange.value,
- userId: reportInfo.value.userId,
+ dates: [
+ timestampCurrentRange.value[0],
+ timestampCurrentRange.value[1]
+ ],
+ userId: reportInfo.value.report.userId,
reportId: reportInfo.value.report.report_id,
...assignForm
}
- axios.post('/api/report', form)
- .then(r => {
+ router.post('/report', form, {
+ onSuccess: () => {
window.$message.success('Отчет сохранен')
resetReportForm()
- router.visit('/')
- })
+ }
+ })
+ // axios.post('/api/report', form)
+ // .then(r => {
+ // window.$message.success('Отчет сохранен')
+ // resetReportForm()
+ // router.visit('/')
+ // })
}
const resetReportForm = () => {
diff --git a/routes/web.php b/routes/web.php
index 28418d1..b1e5140 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -24,6 +24,9 @@ Route::get('/dashboard', [\App\Http\Controllers\Web\IndexController::class, 'ind
Route::get('/report', [\App\Http\Controllers\Web\ReportController::class, 'index'])
->middleware(['auth'])
->name('report');
+Route::post('/report', [\App\Http\Controllers\Web\ReportController::class, 'store'])
+ ->middleware(['auth'])
+ ->name('report.store');
Route::get('/statistic', [\App\Http\Controllers\Web\StatisticController::class, 'index'])
->middleware(['auth'])
->name('statistic');