* исправил фантомный сдвиг даты * переделал получение ФИО врачей из отделений * добавил возможность поиска врача * переписал сохранение отчета
969 lines
35 KiB
PHP
969 lines
35 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers\Api;
|
||
|
||
use App\Http\Controllers\Controller;
|
||
use App\Http\Resources\Mis\FormattedPatientResource;
|
||
use App\Models\MedicalHistorySnapshot;
|
||
use App\Models\MetrikaGroup;
|
||
use App\Models\MetrikaResult;
|
||
use App\Models\MisLpuDoctor;
|
||
use App\Models\MisMedicalHistory;
|
||
use App\Models\MisMigrationPatient;
|
||
use App\Models\MisStationarBranch;
|
||
use App\Models\MisSurgicalOperation;
|
||
use App\Models\ObservationPatient;
|
||
use App\Models\Report;
|
||
use App\Models\UnwantedEvent;
|
||
use App\Models\User;
|
||
use App\Services\DateRangeService;
|
||
use App\Services\MisPatientService;
|
||
use App\Services\ReportService;
|
||
use Illuminate\Http\Request;
|
||
use Illuminate\Support\Carbon;
|
||
use Illuminate\Support\Facades\Auth;
|
||
use Illuminate\Support\Facades\DB;
|
||
use Illuminate\Support\Facades\Session;
|
||
use Illuminate\Support\Str;
|
||
use Inertia\Inertia;
|
||
|
||
class ReportController extends Controller
|
||
{
|
||
public function __construct(
|
||
protected MisPatientService $misPatientService,
|
||
protected ReportService $reportService,
|
||
protected DateRangeService $dateRangeService)
|
||
{ }
|
||
|
||
public function index(Request $request)
|
||
{
|
||
$user = Auth::user();
|
||
$department = $user->department;
|
||
|
||
$startDateCarbon = Carbon::now()->firstOfMonth();
|
||
$endDateCarbon = Carbon::now();
|
||
|
||
// Определяем даты в зависимости от роли
|
||
[$startDate, $endDate] = $this->dateService->getDateRangeForUser($user, $request->query('startAt'), $request->query('endAt'));
|
||
if (Carbon::parse($startDate)->isValid()) {
|
||
$startDateCarbon = Carbon::parse($startDate)->setTimeZone('Asia/Yakutsk');
|
||
}
|
||
if (Carbon::parse($endDate)->isValid()) {
|
||
$endDateCarbon = Carbon::parse($endDate)->setTimeZone('Asia/Yakutsk');
|
||
}
|
||
|
||
$reportIds = [];
|
||
$reports = $this->getReportsForDateRange($user->rf_department_id, $startDate, $endDate);
|
||
$reportIds = $reports->pluck('report_id')->toArray();
|
||
|
||
// Определяем, используем ли мы снапшоты
|
||
$reportToday = Report::whereDate('sent_at', $endDate)
|
||
->whereDate('created_at', $endDate)
|
||
->first();
|
||
$useSnapshots = ($user->isAdmin() || $user->isHeadOfDepartment()) || (Carbon::parse($endDate)->isToday() === false || $reportToday);
|
||
if ($useSnapshots && ($user->isHeadOfDepartment() || $user->isAdmin())) {
|
||
$report = Report::whereDate('sent_at', $endDate)
|
||
->where('rf_department_id', $department->department_id)
|
||
->first();
|
||
$fillableUserId = $report->rf_lpudoctor_id ?? null;
|
||
} else {
|
||
$fillableUserId = $request->query('userId', $user->rf_lpudoctor_id);
|
||
}
|
||
|
||
$beds = (int)$department->metrikaDefault()->where('rf_metrika_item_id', 1)->first()->value;
|
||
$occupiedBeds = optional(Report::where('rf_department_id', $user->rf_department_id)
|
||
->join('metrika_results', 'reports.report_id', '=', 'metrika_results.rf_report_id')
|
||
->where('metrika_results.rf_metrika_item_id', 8)
|
||
->orderBy('sent_at', 'desc')->first())->value ?? 0;
|
||
|
||
$percentLoadedBeds = round(intval($occupiedBeds) * 100 / $beds); //intval($occupiedBeds) * 100 / $beds;
|
||
|
||
$metrikaGroup = MetrikaGroup::whereMetrikaGroupId(2)->first();
|
||
$metrikaItems = $metrikaGroup->metrikaItems;
|
||
|
||
$misDepartmentId = $request->user()->department->rf_mis_department_id;
|
||
|
||
$branchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
|
||
->value('StationarBranchID');
|
||
|
||
$unwantedEvents = UnwantedEvent::whereHas('report', function ($query) use ($user, $startDate, $endDate) {
|
||
$query->where('rf_department_id', $user->rf_department_id)
|
||
->whereDate('created_at', $endDate);
|
||
})
|
||
->get()->map(function ($item) {
|
||
return [
|
||
...$item->toArray(),
|
||
'created_at' => Carbon::parse($item->created_at)->format('Создано d.m.Y в H:i'),
|
||
];
|
||
});
|
||
|
||
// Определяем, является ли пользователь заведующим/администратором
|
||
$isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
|
||
|
||
// Получаем статистику в зависимости от источника данных
|
||
if ($useSnapshots || $reportToday) {
|
||
// Используем снапшоты для статистики
|
||
// $plan = $this->getCountFromSnapshots('plan', $reportIds);
|
||
// $emergency = $this->getCountFromSnapshots('emergency', $reportIds);
|
||
$recipientCount = $this->getPatientsCountFromSnapshot('recipient', $reportIds);
|
||
$outcomeCount = $this->getPatientsCountFromSnapshot('outcome', $reportIds);
|
||
$currentCount = $this->getPatientsCountFromSnapshot('current', $reportIds);
|
||
$deadCount = $this->getPatientsCountFromSnapshot('deceased', $reportIds);
|
||
|
||
// Для операций все равно используем реплику с фильтрацией по датам
|
||
$surgicalCount = [
|
||
$this->getSurgicalPatientsFromSnapshot('plan', $reportIds),
|
||
$this->getSurgicalPatientsFromSnapshot('emergency', $reportIds)
|
||
];
|
||
|
||
$recipientIds = $this->getRecipientIdsFromSnapshots($reportIds);
|
||
} else {
|
||
// Используем реплику для статистики
|
||
$plan = $this->getPlanOrEmergencyPatients(
|
||
'plan',
|
||
$isHeadOrAdmin,
|
||
$branchId,
|
||
$startDate,
|
||
$endDate,
|
||
true,
|
||
today: true
|
||
);
|
||
$emergency = $this->getPlanOrEmergencyPatients(
|
||
'emergency',
|
||
$isHeadOrAdmin,
|
||
$branchId,
|
||
$startDate,
|
||
$endDate,
|
||
true,
|
||
today: true
|
||
);
|
||
$outcomeCount = $this->getAllOutcomePatients(
|
||
$branchId,
|
||
$startDate,
|
||
$endDate,
|
||
true
|
||
);
|
||
$currentCount = $this->getCurrentPatients($branchId, true);
|
||
$deadCount = $this->getDeceasedOutcomePatients($branchId, $startDate, $endDate, true);
|
||
|
||
$surgicalCount = [
|
||
$this->getSurgicalPatients('plan', $isHeadOrAdmin, $branchId, $startDate, $endDate, true),
|
||
$this->getSurgicalPatients('emergency', $isHeadOrAdmin, $branchId, $startDate, $endDate, true)
|
||
];
|
||
|
||
$recipientIds = $this->getPlanOrEmergencyPatients(
|
||
null,
|
||
$isHeadOrAdmin,
|
||
$branchId,
|
||
$startDate,
|
||
$endDate,
|
||
false,
|
||
true,
|
||
true,
|
||
today: true
|
||
);
|
||
}
|
||
|
||
$isActiveSendButton = Carbon::createFromFormat('Y-m-d H:i:s', $endDate)->isToday() &&
|
||
(!$user->isHeadOfDepartment() && !$user->isAdmin()) && $reportToday == null;
|
||
|
||
$reportDoctor = $reportToday?->lpuDoctor;
|
||
$message = null;
|
||
if ($reportToday) {
|
||
if ($reportDoctor && $reportDoctor->LPUDoctorID === intval($fillableUserId)) {
|
||
$isActiveSendButton = true;
|
||
} else {
|
||
$message = "Отчет уже создан пользователем: $reportDoctor->FAM_V $reportDoctor->IM_V $reportDoctor->OT_V";
|
||
}
|
||
|
||
$lpuDoctor = $reportDoctor;
|
||
} else {
|
||
if (Carbon::parse($startDate)->diffInDays(Carbon::parse($endDate)) > 1.0) {
|
||
$lpuDoctor = null;
|
||
} else {
|
||
$lpuDoctor = MisLpuDoctor::where('LPUDoctorID', $fillableUserId)->first();
|
||
}
|
||
}
|
||
|
||
$isRangeOneDay = $this->dateRangeService->isRangeOneDay($startDate, $endDate);
|
||
|
||
$date = $isHeadOrAdmin ? [
|
||
$this->dateRangeService->parseDate($isRangeOneDay ? $endDate : $startDate)->getTimestampMs(),
|
||
$this->dateRangeService->parseDate($endDate)->getTimestampMs()
|
||
] : $this->dateRangeService->parseDate($endDate)->getTimestampMs();
|
||
|
||
return response()->json([
|
||
'department' => [
|
||
'beds' => $beds,
|
||
'percentLoadedBeds' => $percentLoadedBeds,
|
||
|
||
'recipientCount' => $useSnapshots ? $recipientCount : $plan + $emergency, //$recipientCount,
|
||
'extractCount' => $outcomeCount, //$extractedCount,
|
||
'currentCount' => $currentCount,
|
||
'deadCount' => $deadCount,
|
||
'surgicalCount' => $surgicalCount,
|
||
'recipientIds' => $recipientIds,
|
||
],
|
||
'dates' => [
|
||
'startAt' => $startDateCarbon->getTimestampMs(),
|
||
'endAt' => $endDateCarbon->getTimestampMs()
|
||
],
|
||
'report' => [
|
||
'report_id' => $reportToday?->report_id,
|
||
'unwantedEvents' => $unwantedEvents,
|
||
'isActiveSendButton' => $isActiveSendButton,
|
||
'message' => $message,
|
||
'isOneDay' => $isRangeOneDay,
|
||
'isHeadOrAdmin' => $isHeadOrAdmin,
|
||
'dates' => $date
|
||
],
|
||
'metrikaItems' => $metrikaItems,
|
||
'userId' => $fillableUserId,
|
||
'userName' => $lpuDoctor ? "$lpuDoctor->FAM_V $lpuDoctor->IM_V $lpuDoctor->OT_V" : null
|
||
]);
|
||
}
|
||
|
||
private function getSurgicalPatientsFromSnapshot(string $type, array $reportIds)
|
||
{
|
||
$count = 0;
|
||
switch ($type) {
|
||
case 'emergency':
|
||
$count = $this->getMetrikaResult(10, $reportIds);
|
||
break;
|
||
case 'plan':
|
||
$count = $this->getMetrikaResult(11, $reportIds);
|
||
break;
|
||
case 'recipient':
|
||
$count = $this->getMetrikaResult(3, $reportIds);
|
||
break;
|
||
}
|
||
|
||
return $count;
|
||
}
|
||
|
||
private function getPatientsCountFromSnapshot(string $type, array $reportIds)
|
||
{
|
||
$count = 0;
|
||
switch ($type) {
|
||
case 'emergency':
|
||
$count = $this->getMetrikaResult(10, $reportIds);
|
||
break;
|
||
case 'plan':
|
||
$count = $this->getMetrikaResult(11, $reportIds);
|
||
break;
|
||
case 'recipient':
|
||
$count = $this->getMetrikaResult(3, $reportIds);
|
||
break;
|
||
case 'outcome':
|
||
$count = $this->getMetrikaResult(7, $reportIds);
|
||
break;
|
||
case 'deceased':
|
||
$count = $this->getMetrikaResult(9, $reportIds);
|
||
break;
|
||
case 'current':
|
||
$count = $this->getMetrikaResult(8, $reportIds);
|
||
break;
|
||
}
|
||
|
||
return $count;
|
||
}
|
||
|
||
private function getMetrikaResult(int $metrikaItemId, array $reportIds)
|
||
{
|
||
$reports = Report::whereIn('report_id', $reportIds)
|
||
->with('metrikaResults')
|
||
->get();
|
||
|
||
$count = 0;
|
||
foreach ($reports as $report) {
|
||
foreach ($report->metrikaResults as $metrikaResult) {
|
||
if ($metrikaResult->rf_metrika_item_id === $metrikaItemId)
|
||
$count += intval($metrikaResult->value) ?? 0;
|
||
}
|
||
}
|
||
|
||
return $count;
|
||
}
|
||
|
||
/**
|
||
* Получить ID поступивших пациентов из снапшотов
|
||
*/
|
||
private function getRecipientIdsFromSnapshots(array $reportIds)
|
||
{
|
||
$recipientIds = MedicalHistorySnapshot::whereIn('rf_report_id', $reportIds)
|
||
->where('patient_type', 'recipient')
|
||
->pluck('rf_medicalhistory_id')
|
||
->unique()
|
||
->toArray();
|
||
|
||
return $recipientIds;
|
||
}
|
||
|
||
public function store(Request $request)
|
||
{
|
||
$user = Auth::user();
|
||
$misDepartmentId = $user->department->rf_mis_department_id;
|
||
|
||
$branchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
|
||
->value('StationarBranchID');
|
||
|
||
// Определяем, является ли пользователь заведующим/администратором
|
||
$isHeadOrAdmin = $user->isHeadOfDepartment() || $user->isAdmin();
|
||
|
||
$data = $request->validate([
|
||
'metrics' => 'required',
|
||
'observationPatients' => 'nullable',
|
||
'departmentId' => 'required|integer',
|
||
'unwantedEvents' => 'nullable|array',
|
||
'startAt' => 'required|integer',
|
||
'endAt' => 'required|integer',
|
||
'userId' => 'required|integer',
|
||
'reportId' => 'nullable'
|
||
]);
|
||
$metrics = $data['metrics'];
|
||
$observationPatients = $data['observationPatients'];
|
||
$unwantedEvents = $data['unwantedEvents'];
|
||
|
||
// Определяем даты в зависимости от роли
|
||
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
|
||
|
||
$metriks = [];
|
||
foreach ($metrics as $key => $value) {
|
||
$metrika = new MetrikaResult;
|
||
$metrikaId = (int)Str::replace('metrika_item_', '', $key);
|
||
$metrika->rf_metrika_item_id = $metrikaId;
|
||
$metrika->value = $value;
|
||
|
||
$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']) {
|
||
$report = Report::updateOrCreate(
|
||
[
|
||
'report_id' => $data['reportId']
|
||
],
|
||
[
|
||
'rf_department_id' => $data['departmentId'],
|
||
'rf_user_id' => Auth::user()->id,
|
||
'rf_lpudoctor_id' => $data['userId'],
|
||
'created_at' => now(),
|
||
'sent_at' => now()
|
||
]
|
||
);
|
||
} else {
|
||
$report = Report::create([
|
||
'rf_department_id' => $data['departmentId'],
|
||
'rf_user_id' => Auth::user()->id,
|
||
'rf_lpudoctor_id' => $data['userId'],
|
||
'created_at' => now(),
|
||
'sent_at' => now()
|
||
]);
|
||
}
|
||
|
||
if (count($unwantedEvents)) {
|
||
foreach ($unwantedEvents as $unwantedEvent) {
|
||
// Если есть ID - ищем по нему
|
||
if (isset($unwantedEvent['unwanted_event_id']) && $unwantedEvent['unwanted_event_id']) {
|
||
UnwantedEvent::updateOrCreate(
|
||
['unwanted_event_id' => $unwantedEvent['unwanted_event_id']],
|
||
[
|
||
'rf_report_id' => $report->report_id,
|
||
'comment' => $unwantedEvent['comment'] ?? '',
|
||
'title' => $unwantedEvent['title'] ?? '',
|
||
'is_visible' => $unwantedEvent['is_visible'] ?? true,
|
||
]
|
||
);
|
||
} else {
|
||
// Если нет ID - создаем новую запись
|
||
UnwantedEvent::create([
|
||
'rf_report_id' => $report->report_id,
|
||
'comment' => $unwantedEvent['comment'] ?? '',
|
||
'title' => $unwantedEvent['title'] ?? '',
|
||
'is_visible' => $unwantedEvent['is_visible'] ?? true,
|
||
]);
|
||
}
|
||
}
|
||
} else {
|
||
$unwantedEvents = $report->unwantedEvents;
|
||
foreach ($unwantedEvents as $unwantedEvent) {
|
||
$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(
|
||
[
|
||
'rf_report_id' => $report->report_id,
|
||
'rf_metrika_item_id' => $metrika->rf_metrika_item_id
|
||
],
|
||
[
|
||
'rf_report_id' => $report->report_id,
|
||
'rf_metrika_item_id' => $metrika->rf_metrika_item_id,
|
||
'value' => $metrika->value,
|
||
]
|
||
);
|
||
}
|
||
|
||
if (count($observationPatients)) {
|
||
foreach ($observationPatients as $observationPatient) {
|
||
ObservationPatient::updateOrCreate(
|
||
[
|
||
'rf_medicalhistory_id' => $observationPatient['id'],
|
||
'rf_department_id' => $data['departmentId']
|
||
],
|
||
[
|
||
'rf_department_id' => $data['departmentId'],
|
||
'rf_report_id' => $report->report_id,
|
||
'rf_medicalhistory_id' => $observationPatient['id'],
|
||
'rf_mkab_id' => null,
|
||
'comment' => $observationPatient['comment'] ?? null
|
||
]
|
||
);
|
||
}
|
||
} else {
|
||
foreach ($report->observationPatients as $observationPatient) {
|
||
$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),
|
||
]
|
||
);
|
||
|
||
// Сохраняем снимок для каждого типа пациентов
|
||
// Планово
|
||
//$this->getPlanOrEmergencyPatients('plan', false, $branchId, $dateRange->startSql(), $dateRange->endSql(), false, false, true);
|
||
foreach ($planIds as $id) {
|
||
MedicalHistorySnapshot::create([
|
||
'rf_report_id' => $report->report_id,
|
||
'rf_medicalhistory_id' => $id,
|
||
'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,
|
||
]
|
||
);
|
||
|
||
//$this->getPlanOrEmergencyPatients('emergency', false, $branchId, $startDate, $endDate, false, false, true);
|
||
// Экстренно
|
||
foreach ($emergencyIds as $id) {
|
||
MedicalHistorySnapshot::create([
|
||
'rf_report_id' => $report->report_id,
|
||
'rf_medicalhistory_id' => $id,
|
||
'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,
|
||
]
|
||
);
|
||
|
||
//$this->getDischargedPatients($branchId, $startDate, $endDate, true);
|
||
foreach ($dischargedIds as $id) {
|
||
MedicalHistorySnapshot::create([
|
||
'rf_report_id' => $report->report_id,
|
||
'rf_medicalhistory_id' => $id,
|
||
'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),
|
||
]
|
||
);
|
||
|
||
//$this->getTransferredPatients($branchId, $startDate, $endDate, true);
|
||
foreach ($transferredIds as $id) {
|
||
MedicalHistorySnapshot::create([
|
||
'rf_report_id' => $report->report_id,
|
||
'rf_medicalhistory_id' => $id,
|
||
'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),
|
||
]
|
||
);
|
||
|
||
//$this->getDeceasedOutcomePatients($branchId, $startDate, $endDate, false, true);
|
||
foreach ($deceasedIds as $id) {
|
||
MedicalHistorySnapshot::create([
|
||
'rf_report_id' => $report->report_id,
|
||
'rf_medicalhistory_id' => $id,
|
||
'patient_type' => 'deceased'
|
||
]);
|
||
}
|
||
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,
|
||
'rf_medicalhistory_id' => $id,
|
||
'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),
|
||
]
|
||
);
|
||
|
||
// 7. Находящиеся на лечении
|
||
// $currentIds = $this->getCurrentPatients($branchId, false, true);
|
||
// foreach ($currentIds as $id) {
|
||
// MedicalHistorySnapshot::create([
|
||
// 'rf_report_id' => $report->report_id,
|
||
// 'rf_medicalhistory_id' => $id,
|
||
// 'patient_type' => 'current'
|
||
// ]);
|
||
// }
|
||
|
||
\DB::commit();
|
||
|
||
return response()->json([
|
||
'message' => 'success'
|
||
]);
|
||
}
|
||
|
||
public function getPatients(Request $request)
|
||
{
|
||
$user = Auth::user();
|
||
|
||
$validated = $request->validate([
|
||
'status' => 'required|string',
|
||
'startAt' => 'nullable',
|
||
'endAt' => 'nullable',
|
||
]);
|
||
|
||
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
|
||
|
||
$patients = $this->reportService->getPatientsByStatus(
|
||
Auth::user(),
|
||
$validated['status'],
|
||
$dateRange
|
||
);
|
||
|
||
return response()->json(FormattedPatientResource::collection($patients));
|
||
}
|
||
|
||
public function getPatientsCount(Request $request)
|
||
{
|
||
$user = Auth::user();
|
||
|
||
$validated = $request->validate([
|
||
'status' => 'required|string',
|
||
'startAt' => 'nullable',
|
||
'endAt' => 'nullable',
|
||
]);
|
||
|
||
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
|
||
|
||
$count = $this->reportService->getPatientsCountByStatus(
|
||
Auth::user(),
|
||
$validated['status'],
|
||
$dateRange,
|
||
);
|
||
|
||
return response()->json($count);
|
||
}
|
||
|
||
/**
|
||
* Получить пациентов (плановых или экстренных)
|
||
*/
|
||
private function getPlanOrEmergencyPatients(
|
||
?string $status,
|
||
bool $isHeadOrAdmin,
|
||
$branchId,
|
||
$startDate, $endDate,
|
||
bool $returnedCount = false,
|
||
bool $all = false,
|
||
bool $onlyIds = false,
|
||
bool $today = false
|
||
) {
|
||
// Определяем, является ли статус outcome
|
||
$isOutcomeStatus = in_array($status, ['outcome-transferred', 'outcome-discharged', 'outcome-deceased']);
|
||
|
||
if ($isOutcomeStatus) {
|
||
switch ($status) {
|
||
case 'outcome-transferred':
|
||
$query = MisMigrationPatient::transferred($branchId, $startDate, $endDate);
|
||
break;
|
||
case 'outcome-discharged':
|
||
$query = MisMigrationPatient::discharged($branchId, $startDate, $endDate);
|
||
break;
|
||
case 'outcome-deceased':
|
||
$query = MisMigrationPatient::deceasedOutcome($branchId, $startDate, $endDate);
|
||
break;
|
||
}
|
||
} else {
|
||
// Разная логика для заведующего и врача
|
||
if ($isHeadOrAdmin) {
|
||
// Заведующий: используем whereInDepartment
|
||
$query = MisMigrationPatient::whereInDepartment($branchId)
|
||
->whereBetween('DateIngoing', [$startDate, $endDate]);
|
||
} else {
|
||
// Врач: используем currentlyInTreatment + фильтр по дате
|
||
$query = MisMigrationPatient::currentlyInTreatment($branchId)
|
||
->when($today, function ($query) use ($startDate, $endDate) {
|
||
return $query->whereBetween('DateIngoing', [$startDate, $endDate]);
|
||
});
|
||
}
|
||
}
|
||
|
||
$medicalHistoryIds = $query->pluck('rf_MedicalHistoryID')->toArray();
|
||
|
||
if (empty($medicalHistoryIds)) {
|
||
if ($returnedCount) return 0;
|
||
return collect();
|
||
}
|
||
|
||
// Получаем истории
|
||
$query = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||
->with(['surgicalOperations' => function ($query) use ($startDate, $endDate) {
|
||
$query->whereBetween('Date', [$startDate, $endDate]);
|
||
}])
|
||
->orderBy('DateRecipient', 'DESC');
|
||
|
||
// Выбираем план или экстренность
|
||
if (!$all && !$isOutcomeStatus) {
|
||
if ($status === 'plan') {
|
||
$query->plan();
|
||
} else if ($status === 'emergency') {
|
||
$query->emergency();
|
||
}
|
||
}
|
||
|
||
// Для врача добавляем условие "в отделении"
|
||
if (!$isHeadOrAdmin && !$isOutcomeStatus) {
|
||
$query->currentlyHospitalized();
|
||
}
|
||
|
||
if ($onlyIds) {
|
||
return $query->select('MedicalHistoryID')
|
||
->pluck('MedicalHistoryID')->values();
|
||
} else {
|
||
if ($returnedCount) return $query->count();
|
||
else return $query->get();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Получить всех выбывших пациентов
|
||
*/
|
||
private function getAllOutcomePatients($branchId, $startDate, $endDate, bool $returnedCount = false)
|
||
{
|
||
// Сначала получаем миграции с типами выбытия
|
||
$migrations = MisMigrationPatient::outcomePatients($branchId, $startDate, $endDate)
|
||
->select('rf_MedicalHistoryID', 'rf_kl_VisitResultID', 'DateOut')
|
||
->get()
|
||
->groupBy('rf_MedicalHistoryID');
|
||
|
||
if ($migrations->isEmpty()) {
|
||
if ($returnedCount) return 0;
|
||
return collect();
|
||
}
|
||
|
||
$medicalHistoryIds = $migrations->keys()->toArray();
|
||
|
||
// Получаем истории
|
||
$patients = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||
->with(['surgicalOperations'])
|
||
->orderBy('DateRecipient', 'DESC');
|
||
|
||
if ($returnedCount) return $patients->count();
|
||
else $patients = $patients->get();
|
||
|
||
// Добавляем информацию о типе выбытия
|
||
return $patients->map(function ($patient) use ($migrations) {
|
||
$patientMigrations = $migrations->get($patient->MedicalHistoryID, collect());
|
||
|
||
// Определяем основной тип выбытия (берем последнюю миграцию)
|
||
$latestMigration = $patientMigrations->sortByDesc('DateOut')->first();
|
||
|
||
if ($latestMigration) {
|
||
$patient->outcome_type = $this->getOutcomeTypeName($latestMigration->rf_kl_VisitResultID);
|
||
$patient->outcome_date = $latestMigration->DateOut;
|
||
$patient->visit_result_id = $latestMigration->rf_kl_VisitResultID;
|
||
}
|
||
|
||
return $patient;
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Получить понятное название типа выбытия
|
||
*/
|
||
private function getOutcomeTypeName($visitResultId): string
|
||
{
|
||
return match($visitResultId) {
|
||
1, 7, 8, 9, 10, 11, 48, 49, 124 => 'Выписка',
|
||
2, 3, 4, 12, 13, 14 => 'Перевод',
|
||
5, 6, 15, 16 => 'Умер',
|
||
// Добавьте другие коды по мере необходимости
|
||
default => 'Другое (' . $visitResultId . ')'
|
||
};
|
||
}
|
||
|
||
/**
|
||
* Получить умерших пациентов (исход)
|
||
*/
|
||
private function getDeceasedOutcomePatients($branchId, $startDate, $endDate, bool $returnedCount = false, bool $onlyIds = false)
|
||
{
|
||
$medicalHistoryIds = MisMigrationPatient::deceasedOutcome($branchId, $startDate, $endDate)
|
||
->pluck('rf_MedicalHistoryID')
|
||
->unique()
|
||
->toArray();
|
||
|
||
if (empty($medicalHistoryIds)) {
|
||
if ($returnedCount) return 0;
|
||
return collect();
|
||
}
|
||
|
||
if ($onlyIds) {
|
||
return $medicalHistoryIds;
|
||
}
|
||
|
||
$query = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||
->with(['surgicalOperations'])
|
||
->orderBy('DateRecipient', 'DESC');
|
||
|
||
if ($returnedCount) return $query->count();
|
||
else return $query->get();
|
||
}
|
||
|
||
/**
|
||
* Получить пациентов с операциями
|
||
*/
|
||
private function getSurgicalPatients(string $status, bool $isHeadOrAdmin, $branchId, $startDate, $endDate, bool $returnedCount = false)
|
||
{
|
||
$query = MisSurgicalOperation::where('rf_StationarBranchID', $branchId)
|
||
->whereBetween('Date', [$startDate, $endDate])
|
||
->orderBy('Date', 'DESC');
|
||
|
||
if ($status === 'plan') {
|
||
$query->where('rf_TypeSurgOperationInTimeID', 6);
|
||
} else {
|
||
$query->whereIn('rf_TypeSurgOperationInTimeID', [4, 5]);
|
||
}
|
||
|
||
|
||
if ($returnedCount) return $query->count();
|
||
else return $query->get();
|
||
}
|
||
|
||
/**
|
||
* Находятся на лечении
|
||
*/
|
||
private function getCurrentPatients($branchId, bool $returnedCount = false, bool $onlyIds = false)
|
||
{
|
||
// $currentCount = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||
// ->currentlyHospitalized()
|
||
// ->orderBy('DateRecipient', 'DESC')
|
||
// ->count();
|
||
$medicalHistoryIds = MisMigrationPatient::currentlyInTreatment($branchId)
|
||
->pluck('rf_MedicalHistoryID')
|
||
->unique()
|
||
->toArray();
|
||
|
||
if (empty($medicalHistoryIds)) {
|
||
if ($returnedCount) return 0;
|
||
return collect();
|
||
}
|
||
|
||
if ($onlyIds) return $medicalHistoryIds;
|
||
|
||
$patients = MisMedicalHistory::whereIn('MedicalHistoryID', $medicalHistoryIds)
|
||
->currentlyHospitalized()
|
||
->with(['surgicalOperations'])
|
||
->orderBy('DateRecipient', 'DESC');
|
||
|
||
if ($returnedCount) return $patients->count();
|
||
else return $patients->get();
|
||
}
|
||
|
||
public function removeObservation(
|
||
Request $request,
|
||
) {
|
||
$data = $request->validate([
|
||
'id' => 'required'
|
||
]);
|
||
|
||
ObservationPatient::where('rf_medicalhistory_id', $data['id'])->delete();
|
||
|
||
return response()->json()->setStatusCode(200);
|
||
}
|
||
|
||
|
||
|
||
// api/report/unwanted-event
|
||
public function removeUnwantedEvent(UnwantedEvent $unwantedEvent, Request $request)
|
||
{
|
||
$unwantedEvent->delete();
|
||
|
||
return response()->json()->setStatusCode(200);
|
||
}
|
||
|
||
public function getDepartmentUsers(Request $request)
|
||
{
|
||
$user = Auth::user();
|
||
|
||
$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()
|
||
->whereNotIn('LPUDoctorID', [0, 1])
|
||
->get();
|
||
|
||
return response()->json([
|
||
...$users
|
||
])->setStatusCode(200);
|
||
}
|
||
|
||
/**
|
||
* Получить все отчеты в промежутке дат (для агрегации данных)
|
||
*/
|
||
private function getReportsForDateRange($departmentId, $startDate, $endDate)
|
||
{
|
||
if (Carbon::parse($startDate)->diffInDays(Carbon::parse($endDate)) > 1.0)
|
||
return Report::where('rf_department_id', $departmentId)
|
||
->whereBetween('created_at', [$startDate, $endDate])
|
||
->orderBy('created_at', 'ASC')
|
||
->get();
|
||
else
|
||
return Report::where('rf_department_id', $departmentId)
|
||
->whereDate('created_at', $endDate)
|
||
->orderBy('created_at', 'ASC')
|
||
->get();
|
||
}
|
||
}
|