* переписал функции прототипов в сервисы
* оптимизация доставки контента до клиента * переписал запросы выборок * убрал из подсчета переведенных * добавил сохранение метрикам для вывода в дашборд
This commit is contained in:
@@ -2,41 +2,65 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Report;
|
||||
use App\Models\MetrikaResult;
|
||||
use App\Models\UnwantedEvent;
|
||||
use App\Models\ObservationPatient;
|
||||
use App\Models\MedicalHistorySnapshot;
|
||||
use App\Models\MetrikaResult;
|
||||
use App\Models\MisLpuDoctor;
|
||||
use App\Models\MisMigrationPatient;
|
||||
use App\Models\MisMedicalHistory;
|
||||
use App\Models\MisStationarBranch;
|
||||
use App\Models\ObservationPatient;
|
||||
use App\Models\Report;
|
||||
use App\Models\UnwantedEvent;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ReportService
|
||||
{
|
||||
private PatientService $patientService;
|
||||
public function __construct(
|
||||
protected DateRangeService $dateRangeService,
|
||||
protected PatientService $patientQueryService,
|
||||
protected SnapshotService $snapshotService
|
||||
) {}
|
||||
|
||||
public function __construct(PatientService $patientService)
|
||||
/**
|
||||
* Получить статистику для отчета
|
||||
*/
|
||||
public function getReportStatistics(User $user, DateRange $dateRange): array
|
||||
{
|
||||
$this->patientService = $patientService;
|
||||
$department = $user->department;
|
||||
$misDepartmentId = $department->rf_mis_department_id;
|
||||
$branchId = $this->getBranchId($misDepartmentId);
|
||||
|
||||
// Определяем, используем ли мы снапшоты
|
||||
$useSnapshots = $this->shouldUseSnapshots($user, $dateRange);
|
||||
|
||||
if ($useSnapshots) {
|
||||
return $this->getStatisticsFromSnapshots($user, $dateRange, $branchId);
|
||||
}
|
||||
|
||||
return $this->getStatisticsFromReplica($user, $dateRange, $branchId);
|
||||
}
|
||||
|
||||
public function createReport(array $data): Report
|
||||
/**
|
||||
* Создать или обновить отчет
|
||||
*/
|
||||
public function storeReport(array $data, User $user): Report
|
||||
{
|
||||
DB::beginTransaction();
|
||||
|
||||
try {
|
||||
$report = Report::create([
|
||||
'rf_department_id' => $data['departmentId'],
|
||||
'rf_user_id' => Auth::id(),
|
||||
'sent_at' => now()
|
||||
]);
|
||||
$report = $this->createOrUpdateReport($data, $user);
|
||||
|
||||
$this->saveMetrics($report, $data['metrics'] ?? []);
|
||||
$this->saveUnwantedEvents($report, $data['unwantedEvents'] ?? []);
|
||||
$this->saveObservationPatients($report, $data['observationPatients'] ?? []);
|
||||
$this->savePatientSnapshots($report, $data);
|
||||
$this->saveObservationPatients($report, $data['observationPatients'] ?? [], $user->rf_department_id);
|
||||
|
||||
// Сохраняем снапшоты пациентов
|
||||
$this->snapshotService->createPatientSnapshots($report, $user, $data['dates']);
|
||||
|
||||
DB::commit();
|
||||
|
||||
return $report;
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
@@ -44,82 +68,707 @@ class ReportService
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить пациентов по статусу
|
||||
*/
|
||||
public function getPatientsByStatus(
|
||||
User $user,
|
||||
string $status,
|
||||
DateRange $dateRange
|
||||
) {
|
||||
$branchId = $this->getBranchId($user->department->rf_mis_department_id);
|
||||
|
||||
$useSnapshots = $this->shouldUseSnapshots($user, $dateRange);
|
||||
|
||||
if ($useSnapshots) {
|
||||
return $this->getPatientsFromSnapshots($user, $status, $dateRange, $branchId);
|
||||
}
|
||||
|
||||
return $this->getPatientsFromReplica($user, $status, $dateRange, $branchId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить количество пациентов по статусу
|
||||
*/
|
||||
public function getPatientsCountByStatus(
|
||||
User $user,
|
||||
string $status,
|
||||
DateRange $dateRange
|
||||
): int {
|
||||
$branchId = $this->getBranchId($user->department->rf_mis_department_id);
|
||||
|
||||
$useSnapshots = $this->shouldUseSnapshots($user, $dateRange);
|
||||
|
||||
if ($useSnapshots) {
|
||||
return $this->getPatientsCountFromSnapshots($user, $status, $dateRange);
|
||||
}
|
||||
|
||||
return $this->getPatientsCountFromReplica($user, $status, $dateRange, $branchId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить ID отделения из стационарного отделения
|
||||
*/
|
||||
private function getBranchId(int $misDepartmentId): ?int
|
||||
{
|
||||
return MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
|
||||
->value('StationarBranchID');
|
||||
}
|
||||
|
||||
/**
|
||||
* Определить, нужно ли использовать снапшоты
|
||||
*/
|
||||
private function shouldUseSnapshots(User $user, DateRange $dateRange): bool
|
||||
{
|
||||
if ($user->isAdmin() || $user->isHeadOfDepartment()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Проверяем, есть ли отчет на сегодня
|
||||
$reportToday = Report::whereDate('sent_at', $dateRange->end())
|
||||
->whereDate('created_at', $dateRange->end())
|
||||
->first();
|
||||
|
||||
return !$dateRange->isEndDateToday() || $reportToday;
|
||||
}
|
||||
|
||||
/**
|
||||
* Создать или обновить отчет
|
||||
*/
|
||||
private function createOrUpdateReport(array $data, User $user): Report
|
||||
{
|
||||
$reportData = [
|
||||
'rf_department_id' => $data['departmentId'],
|
||||
'rf_user_id' => $user->id,
|
||||
'rf_lpudoctor_id' => $data['userId'],
|
||||
'sent_at' => now(),
|
||||
];
|
||||
|
||||
if (isset($data['reportId']) && $data['reportId']) {
|
||||
$report = Report::updateOrCreate(
|
||||
['report_id' => $data['reportId']],
|
||||
$reportData
|
||||
);
|
||||
} else {
|
||||
$report = Report::create($reportData);
|
||||
}
|
||||
|
||||
return $report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохранить метрики отчета
|
||||
*/
|
||||
private function saveMetrics(Report $report, array $metrics): void
|
||||
{
|
||||
foreach ($metrics as $key => $value) {
|
||||
MetrikaResult::create([
|
||||
'rf_report_id' => $report->report_id,
|
||||
'rf_metrika_item_id' => (int) str_replace('metrika_item_', '', $key),
|
||||
'value' => $value
|
||||
]);
|
||||
$metrikaId = (int)str_replace('metrika_item_', '', $key);
|
||||
|
||||
MetrikaResult::updateOrCreate(
|
||||
[
|
||||
'rf_report_id' => $report->report_id,
|
||||
'rf_metrika_item_id' => $metrikaId,
|
||||
],
|
||||
[
|
||||
'value' => $value,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохранить нежелательные события
|
||||
*/
|
||||
private function saveUnwantedEvents(Report $report, array $unwantedEvents): void
|
||||
{
|
||||
if (empty($unwantedEvents)) {
|
||||
$report->unwantedEvents()->delete();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($unwantedEvents as $event) {
|
||||
if (isset($event['unwanted_event_id'])) {
|
||||
if (isset($event['unwanted_event_id']) && $event['unwanted_event_id']) {
|
||||
UnwantedEvent::updateOrCreate(
|
||||
['unwanted_event_id' => $event['unwanted_event_id']],
|
||||
$this->formatUnwantedEventData($report, $event)
|
||||
[
|
||||
'rf_report_id' => $report->report_id,
|
||||
'comment' => $event['comment'] ?? '',
|
||||
'title' => $event['title'] ?? '',
|
||||
'is_visible' => $event['is_visible'] ?? true,
|
||||
]
|
||||
);
|
||||
} else {
|
||||
UnwantedEvent::create($this->formatUnwantedEventData($report, $event));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function formatUnwantedEventData(Report $report, array $event): array
|
||||
{
|
||||
return [
|
||||
'rf_report_id' => $report->report_id,
|
||||
'comment' => $event['comment'] ?? '',
|
||||
'title' => $event['title'] ?? '',
|
||||
'is_visible' => $event['is_visible'] ?? true,
|
||||
];
|
||||
}
|
||||
|
||||
private function saveObservationPatients(Report $report, array $observationPatients): void
|
||||
{
|
||||
foreach ($observationPatients as $patient) {
|
||||
ObservationPatient::create([
|
||||
'rf_department_id' => $report->rf_department_id,
|
||||
'rf_report_id' => $report->report_id,
|
||||
'rf_medicalhistory_id' => $patient['id'],
|
||||
'comment' => $patient['comment'] ?? null
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
private function savePatientSnapshots(Report $report, array $data): void
|
||||
{
|
||||
$snapshotTypes = [
|
||||
'plan' => $this->patientService->getPlanPatients(
|
||||
false,
|
||||
$data['branchId'],
|
||||
$data['startDate'],
|
||||
$data['endDate'],
|
||||
false,
|
||||
true
|
||||
),
|
||||
'emergency' => $this->patientService->getEmergencyPatients(
|
||||
false,
|
||||
$data['branchId'],
|
||||
$data['startDate'],
|
||||
$data['endDate'],
|
||||
false,
|
||||
true
|
||||
)
|
||||
];
|
||||
|
||||
foreach ($snapshotTypes as $type => $patientIds) {
|
||||
foreach ($patientIds as $patientId) {
|
||||
MedicalHistorySnapshot::create([
|
||||
UnwantedEvent::create([
|
||||
'rf_report_id' => $report->report_id,
|
||||
'rf_medicalhistory_id' => $patientId,
|
||||
'patient_type' => $type
|
||||
'comment' => $event['comment'] ?? '',
|
||||
'title' => $event['title'] ?? '',
|
||||
'is_visible' => $event['is_visible'] ?? true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохранить пациентов под наблюдением
|
||||
*/
|
||||
private function saveObservationPatients(
|
||||
Report $report,
|
||||
array $observationPatients,
|
||||
int $departmentId
|
||||
): void {
|
||||
if (empty($observationPatients)) {
|
||||
ObservationPatient::where('rf_department_id', $departmentId)
|
||||
->where('rf_report_id', $report->report_id)
|
||||
->delete();
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($observationPatients as $patient) {
|
||||
ObservationPatient::updateOrCreate(
|
||||
[
|
||||
'rf_medicalhistory_id' => $patient['id'],
|
||||
'rf_department_id' => $departmentId,
|
||||
],
|
||||
[
|
||||
'rf_report_id' => $report->report_id,
|
||||
'rf_mkab_id' => null,
|
||||
'comment' => $patient['comment'] ?? null,
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить информацию о текущем отчете
|
||||
*/
|
||||
public function getCurrentReportInfo(User $user, DateRange $dateRange): array
|
||||
{
|
||||
$department = $user->department;
|
||||
$reportToday = Report::whereDate('sent_at', $dateRange->endSql())
|
||||
->whereDate('created_at', $dateRange->endSql())
|
||||
->first();
|
||||
|
||||
$isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
|
||||
$useSnapshots = $isHeadOrAdmin || !$dateRange->isEndDateToday() || $reportToday;
|
||||
|
||||
// Получаем ID пользователя для заполнения отчета
|
||||
if ($useSnapshots && $isHeadOrAdmin && $reportToday) {
|
||||
$fillableUserId = $reportToday->rf_lpudoctor_id ?? null;
|
||||
} else {
|
||||
$fillableUserId = request()->query('userId', $user->rf_lpudoctor_id);
|
||||
}
|
||||
|
||||
// Получаем нежелательные события
|
||||
$unwantedEvents = $this->getUnwantedEvents($user, $dateRange);
|
||||
|
||||
// Определяем активность кнопки отправки
|
||||
$isActiveSendButton = $this->isSendButtonActive($user, $dateRange, $reportToday, $fillableUserId);
|
||||
|
||||
$message = null;
|
||||
if ($reportToday && $reportToday->rf_lpudoctor_id !== intval($fillableUserId)) {
|
||||
$reportDoctor = $reportToday->lpuDoctor;
|
||||
$message = "Отчет уже создан пользователем: $reportDoctor->FAM_V $reportDoctor->IM_V $reportDoctor->OT_V";
|
||||
}
|
||||
|
||||
// Получаем информацию о враче
|
||||
$lpuDoctor = $this->getDoctorInfo($fillableUserId, $dateRange);
|
||||
|
||||
// Проверяем, является ли диапазон одним днем
|
||||
// $isRangeOneDay = $this->dateRangeService->isRangeOneDay(
|
||||
// $endDate->copy()->subDay()->format('Y-m-d H:i:s'),
|
||||
// $endDate->format('Y-m-d H:i:s')
|
||||
// );
|
||||
|
||||
// Формируем даты для ответа
|
||||
// $date = $isHeadOrAdmin ? [
|
||||
// $endDate->copy()->subDay()->getTimestampMs(),
|
||||
// $endDate->getTimestampMs()
|
||||
// ] : $endDate->getTimestampMs();
|
||||
$date = $isHeadOrAdmin ? [
|
||||
$dateRange->startDate->getTimestampMs(),
|
||||
$dateRange->endDate->getTimestampMs()
|
||||
] : $dateRange->endDate->getTimestampMs();
|
||||
|
||||
return [
|
||||
'report_id' => $reportToday?->report_id,
|
||||
'unwantedEvents' => $unwantedEvents,
|
||||
'isActiveSendButton' => $isActiveSendButton,
|
||||
'message' => $message,
|
||||
'isOneDay' => $dateRange->isOneDay,
|
||||
'isHeadOrAdmin' => $isHeadOrAdmin,
|
||||
'dates' => $date,
|
||||
'userId' => $fillableUserId,
|
||||
'userName' => $lpuDoctor ? "$lpuDoctor->FAM_V $lpuDoctor->IM_V $lpuDoctor->OT_V" : null
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Удалить пациента из наблюдения
|
||||
*/
|
||||
public function removeObservationPatient(int $medicalHistoryId): void
|
||||
{
|
||||
ObservationPatient::where('rf_medicalhistory_id', $medicalHistoryId)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить статистику из снапшотов
|
||||
*/
|
||||
private function getStatisticsFromSnapshots(User $user, DateRange $dateRange, int $branchId): array
|
||||
{
|
||||
// Получаем отчеты за период
|
||||
$reports = $this->getReportsForDateRange(
|
||||
$user->rf_department_id,
|
||||
$dateRange
|
||||
);
|
||||
|
||||
$reportIds = $reports->pluck('report_id')->toArray();
|
||||
|
||||
// Получаем статистику из снапшотов
|
||||
$snapshotStats = [
|
||||
'plan' => $this->getMetrikaResultCount(4, $reportIds),
|
||||
'emergency' => $this->getMetrikaResultCount(12, $reportIds),
|
||||
'outcome' => $this->getMetrikaResultCount(7, $reportIds),
|
||||
'deceased' => $this->getMetrikaResultCount(9, $reportIds),
|
||||
// 'discharged' => $this->getMetrikaResultCount('discharged', $reportIds),
|
||||
'transferred' => $this->getMetrikaResultCount(13, $reportIds),
|
||||
'recipient' => $this->getMetrikaResultCount(3, $reportIds),
|
||||
];
|
||||
|
||||
// Получаем ID поступивших пациентов
|
||||
$recipientIds = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
|
||||
->where('patient_type', 'recipient')
|
||||
->pluck('rf_medicalhistory_id')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
// Получаем количество операций из метрик
|
||||
$surgicalCount = [
|
||||
$this->getMetrikaResultCount(10, $reportIds), // экстренные операции
|
||||
$this->getMetrikaResultCount(11, $reportIds) // плановые операции
|
||||
];
|
||||
|
||||
return [
|
||||
'recipientCount' => $snapshotStats['recipient'] ?? 0,
|
||||
'extractCount' => $snapshotStats['outcome'] ?? 0,
|
||||
'currentCount' => $this->calculateCurrentPatientsFromSnapshots($reportIds, $branchId),
|
||||
'deadCount' => $snapshotStats['deceased'] ?? 0,
|
||||
'surgicalCount' => $surgicalCount,
|
||||
'recipientIds' => $recipientIds,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить статистику из реплики БД
|
||||
*/
|
||||
private function getStatisticsFromReplica(User $user, DateRange $dateRange, int $branchId): array
|
||||
{
|
||||
$isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
|
||||
|
||||
// Плановые: поступившие сегодня + уже лечащиеся
|
||||
$planCount = $this->patientQueryService->getPatientsCountWithCurrent(
|
||||
'plan',
|
||||
$isHeadOrAdmin,
|
||||
$branchId,
|
||||
$dateRange
|
||||
);
|
||||
|
||||
// Экстренные: поступившие сегодня + уже лечащиеся
|
||||
$emergencyCount = $this->patientQueryService->getPatientsCountWithCurrent(
|
||||
'emergency',
|
||||
$isHeadOrAdmin,
|
||||
$branchId,
|
||||
$dateRange
|
||||
);
|
||||
|
||||
// Все пациенты в отделении: поступившие + лечащиеся
|
||||
$currentCount = $this->patientQueryService->getAllPatientsInDepartment(
|
||||
$isHeadOrAdmin,
|
||||
$branchId,
|
||||
$dateRange,
|
||||
true
|
||||
);
|
||||
|
||||
// Поступившие сегодня (только новые поступления)
|
||||
$recipientCount = $this->patientQueryService->getPlanOrEmergencyPatients(
|
||||
null, // все типы
|
||||
$isHeadOrAdmin,
|
||||
$branchId,
|
||||
$dateRange,
|
||||
true,
|
||||
false,
|
||||
false // не включаем уже лечащихся
|
||||
);
|
||||
|
||||
// Выбывшие за период
|
||||
$outcomeCount = $this->patientQueryService->getOutcomePatients(
|
||||
$branchId,
|
||||
$dateRange,
|
||||
'all'
|
||||
)->count();
|
||||
|
||||
// Умершие за период
|
||||
$deadCount = $this->patientQueryService->getOutcomePatients(
|
||||
$branchId,
|
||||
$dateRange,
|
||||
'deceased'
|
||||
)->count();
|
||||
|
||||
// Операции
|
||||
$surgicalCount = [
|
||||
$this->patientQueryService->getSurgicalPatients(
|
||||
'emergency',
|
||||
$branchId,
|
||||
$dateRange,
|
||||
true
|
||||
),
|
||||
$this->patientQueryService->getSurgicalPatients(
|
||||
'plan',
|
||||
$branchId,
|
||||
$dateRange,
|
||||
true
|
||||
)
|
||||
];
|
||||
|
||||
// ID поступивших сегодня (для отметки в таблице)
|
||||
$recipientIds = $this->patientQueryService->getPlanOrEmergencyPatients(
|
||||
null,
|
||||
$isHeadOrAdmin,
|
||||
$branchId,
|
||||
$dateRange,
|
||||
false,
|
||||
true,
|
||||
false // только поступившие сегодня
|
||||
);
|
||||
|
||||
return [
|
||||
'recipientCount' => $recipientCount, // только поступившие сегодня
|
||||
'extractCount' => $outcomeCount,
|
||||
'currentCount' => $currentCount, // все в отделении
|
||||
'deadCount' => $deadCount,
|
||||
'surgicalCount' => $surgicalCount,
|
||||
'recipientIds' => $recipientIds, // ID поступивших сегодня
|
||||
'planCount' => $planCount, // плановые (поступившие + уже лечащиеся)
|
||||
'emergencyCount' => $emergencyCount, // экстренные (поступившие + уже лечащиеся)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить пациентов из снапшотов
|
||||
*/
|
||||
private function getPatientsFromSnapshots(User $user, string $status, DateRange $dateRange, int $branchId)
|
||||
{
|
||||
$reports = $this->getReportsForDateRange(
|
||||
$user->rf_department_id,
|
||||
$dateRange
|
||||
);
|
||||
|
||||
$reportIds = $reports->pluck('report_id')->toArray();
|
||||
|
||||
$patientTypeMap = [
|
||||
'plan' => 'plan',
|
||||
'emergency' => 'emergency',
|
||||
'outcome-discharged' => 'discharged',
|
||||
'outcome-transferred' => 'transferred',
|
||||
'outcome-deceased' => 'deceased',
|
||||
'observation' => 'observation'
|
||||
];
|
||||
|
||||
$patientType = $patientTypeMap[$status] ?? null;
|
||||
|
||||
if ($patientType === 'observation') {
|
||||
return $this->getObservationPatientsFromSnapshots($user->rf_department_id, $reportIds);
|
||||
}
|
||||
|
||||
return $this->snapshotService->getPatientsFromSnapshots($patientType, $reportIds, $branchId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить пациентов из реплики БД
|
||||
*/
|
||||
private function getPatientsFromReplica(User $user, string $status, DateRange $dateRange, int $branchId)
|
||||
{
|
||||
$isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
|
||||
|
||||
// Для плановых и экстренных включаем уже лечащихся
|
||||
$includeCurrent = in_array($status, ['plan', 'emergency']);
|
||||
|
||||
return match($status) {
|
||||
'plan', 'emergency' => $this->patientQueryService->getPlanOrEmergencyPatients(
|
||||
$status,
|
||||
$isHeadOrAdmin,
|
||||
$branchId,
|
||||
$dateRange,
|
||||
false,
|
||||
false,
|
||||
$includeCurrent
|
||||
),
|
||||
'observation' => $this->patientQueryService->getObservationPatients($user->rf_department_id),
|
||||
'outcome-discharged' => $this->patientQueryService->getOutcomePatients(
|
||||
$branchId,
|
||||
$dateRange,
|
||||
'discharged'
|
||||
),
|
||||
'outcome-transferred' => $this->patientQueryService->getOutcomePatients(
|
||||
$branchId,
|
||||
$dateRange,
|
||||
'transferred'
|
||||
),
|
||||
'outcome-deceased' => $this->patientQueryService->getOutcomePatients(
|
||||
$branchId,
|
||||
$dateRange,
|
||||
'deceased'
|
||||
),
|
||||
'current' => $this->patientQueryService->getAllPatientsInDepartment(
|
||||
$isHeadOrAdmin,
|
||||
$branchId,
|
||||
$dateRange
|
||||
),
|
||||
'recipient' => $this->patientQueryService->getPlanOrEmergencyPatients(
|
||||
null,
|
||||
$isHeadOrAdmin,
|
||||
$branchId,
|
||||
$dateRange,
|
||||
false,
|
||||
false,
|
||||
false // только поступившие
|
||||
),
|
||||
default => collect()
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить количество пациентов из снапшотов
|
||||
*/
|
||||
private function getPatientsCountFromSnapshots(User $user, string $status, DateRange $dateRange): int
|
||||
{
|
||||
$reports = $this->getReportsForDateRange(
|
||||
$user->rf_department_id,
|
||||
$dateRange
|
||||
);
|
||||
|
||||
$reportIds = $reports->pluck('report_id')->toArray();
|
||||
|
||||
if ($status === 'outcome') {
|
||||
return MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
|
||||
->whereIn('patient_type', ['discharged', 'transferred', 'deceased'])
|
||||
->distinct('rf_medicalhistory_id')
|
||||
->count('rf_medicalhistory_id');
|
||||
}
|
||||
|
||||
$patientTypeMap = [
|
||||
'plan' => 'plan',
|
||||
'emergency' => 'emergency',
|
||||
'observation' => 'observation',
|
||||
'outcome-discharged' => 'discharged',
|
||||
'outcome-transferred' => 'transferred',
|
||||
'outcome-deceased' => 'deceased'
|
||||
];
|
||||
|
||||
$patientType = $patientTypeMap[$status] ?? null;
|
||||
|
||||
if (!$patientType) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($patientType === 'observation') {
|
||||
return ObservationPatient::whereIn('rf_report_id', $reportIds)
|
||||
->distinct('rf_medicalhistory_id')
|
||||
->count('rf_medicalhistory_id');
|
||||
}
|
||||
|
||||
return MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
|
||||
->where('patient_type', $patientType)
|
||||
->distinct('rf_medicalhistory_id')
|
||||
->count('rf_medicalhistory_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить количество пациентов из реплики БД
|
||||
*/
|
||||
private function getPatientsCountFromReplica(User $user, string $status, DateRange $dateRange, int $branchId): int
|
||||
{
|
||||
$isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
|
||||
|
||||
return match($status) {
|
||||
'plan', 'emergency' => $this->patientQueryService->getPatientsCountWithCurrent(
|
||||
$status,
|
||||
$isHeadOrAdmin,
|
||||
$branchId,
|
||||
$dateRange,
|
||||
),
|
||||
'observation' => ObservationPatient::where('rf_department_id', $user->rf_department_id)->count(),
|
||||
'outcome' => $this->patientQueryService->getOutcomePatients(
|
||||
$branchId,
|
||||
$dateRange,
|
||||
'all'
|
||||
)->count(),
|
||||
'outcome-discharged' => $this->patientQueryService->getOutcomePatients(
|
||||
$branchId,
|
||||
$dateRange,
|
||||
'discharged'
|
||||
)->count(),
|
||||
'outcome-transferred' => $this->patientQueryService->getOutcomePatients(
|
||||
$branchId,
|
||||
$dateRange,
|
||||
'transferred'
|
||||
)->count(),
|
||||
'outcome-deceased' => $this->patientQueryService->getOutcomePatients(
|
||||
$branchId,
|
||||
$dateRange,
|
||||
'deceased'
|
||||
)->count(),
|
||||
default => 0
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить нежелательные события за дату
|
||||
*/
|
||||
private function getUnwantedEvents(User $user, DateRange $dateRange)
|
||||
{
|
||||
return UnwantedEvent::whereHas('report', function ($query) use ($user, $dateRange) {
|
||||
$query->where('rf_department_id', $user->rf_department_id)
|
||||
->whereDate('created_at', $dateRange->endSql());
|
||||
})
|
||||
->get()
|
||||
->map(function ($item) {
|
||||
return [
|
||||
...$item->toArray(),
|
||||
'created_at' => Carbon::parse($item->created_at)->format('Создано d.m.Y в H:i'),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверить активность кнопки отправки отчета
|
||||
*/
|
||||
private function isSendButtonActive(User $user, DateRange $dateRange, ?Report $reportToday, ?int $fillableUserId): bool
|
||||
{
|
||||
// Для врача: только сегодня и если отчета еще нет
|
||||
if (!$user->isHeadOfDepartment() && !$user->isAdmin()) {
|
||||
return $dateRange->isEndDateToday() && !$reportToday;
|
||||
}
|
||||
|
||||
// Для заведующего/админа: если есть отчет и он заполнен текущим пользователем
|
||||
if ($reportToday && $reportToday->rf_lpudoctor_id === intval($fillableUserId)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить информацию о враче
|
||||
*/
|
||||
private function getDoctorInfo(?int $doctorId, DateRange $dateRange): ?MisLpuDoctor
|
||||
{
|
||||
if (!$doctorId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Если дата не сегодня, не показываем врача
|
||||
if (!$dateRange->isEndDateToday()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return MisLpuDoctor::where('LPUDoctorID', $doctorId)->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить отчеты за диапазон дат
|
||||
*/
|
||||
private function getReportsForDateRange(int $departmentId, DateRange $dateRange)
|
||||
{
|
||||
if ($dateRange->isOneDay) {
|
||||
return Report::where('rf_department_id', $departmentId)
|
||||
->whereDate('created_at', $dateRange->endSql())
|
||||
->orderBy('created_at', 'ASC')
|
||||
->get();
|
||||
}
|
||||
|
||||
return Report::where('rf_department_id', $departmentId)
|
||||
->whereBetween('created_at', [$dateRange->startSql(), $dateRange->endSql()])
|
||||
->orderBy('created_at', 'ASC')
|
||||
->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить количество из метрик
|
||||
*/
|
||||
private function getMetrikaResultCount(int $metrikaItemId, array $reportIds): int
|
||||
{
|
||||
$count = 0;
|
||||
$reports = Report::whereIn('report_id', $reportIds)
|
||||
->with('metrikaResults')
|
||||
->get();
|
||||
|
||||
foreach ($reports as $report) {
|
||||
foreach ($report->metrikaResults as $metrikaResult) {
|
||||
if ($metrikaResult->rf_metrika_item_id === $metrikaItemId) {
|
||||
$count += intval($metrikaResult->value) ?? 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Рассчитать текущих пациентов из снапшотов
|
||||
*/
|
||||
private function calculateCurrentPatientsFromSnapshots(array $reportIds, int $branchId): int
|
||||
{
|
||||
// Получаем ID всех пациентов из снапшотов
|
||||
$allPatientIds = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
|
||||
->pluck('rf_medicalhistory_id')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
if (empty($allPatientIds)) {
|
||||
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($allPatientIds, $outcomePatientIds);
|
||||
|
||||
return count($currentPatientIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Получить пациентов под наблюдением из снапшотов
|
||||
*/
|
||||
private function getObservationPatientsFromSnapshots(int $departmentId, array $reportIds)
|
||||
{
|
||||
$medicalHistoryIds = ObservationPatient::whereIn('rf_report_id', $reportIds)
|
||||
->where('rf_department_id', $departmentId)
|
||||
->pluck('rf_medicalhistory_id')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
if (empty($medicalHistoryIds)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
return MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||||
->with(['observationPatient' => function($query) use ($departmentId) {
|
||||
$query->where('rf_department_id', $departmentId)
|
||||
->select(['rf_medicalhistory_id', 'observation_patient_id', 'comment']);
|
||||
}])
|
||||
->orderBy('DateRecipient', 'DESC')
|
||||
->get()
|
||||
->map(function ($patient) {
|
||||
$patient->comment = $patient->observationPatient
|
||||
->pluck('comment')
|
||||
->filter()
|
||||
->implode('; ');
|
||||
return $patient;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user