* переписал функции прототипов в сервисы

* оптимизация доставки контента до клиента
* переписал запросы выборок
* убрал из подсчета переведенных
* добавил сохранение метрикам для вывода в дашборд
This commit is contained in:
brusnitsyn
2026-02-04 17:05:13 +09:00
parent 9ee33bc517
commit eab78a0291
16 changed files with 1644 additions and 737 deletions

View File

@@ -3,118 +3,158 @@
namespace App\Http\Controllers\Web;
use App\Http\Controllers\Controller;
use App\Models\MisStationarBranch;
use App\Http\Resources\Mis\FormattedPatientResource;
use App\Models\MetrikaGroup;
use App\Models\MisLpuDoctor;
use App\Models\Report;
use App\Models\UnwantedEvent;
use App\Services\DateRangeService;
use App\Services\MisPatientService;
use App\Services\ReportService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Inertia\Inertia;
class ReportController extends Controller
{
protected DateRangeService $dateService;
protected MisPatientService $misPatientService;
public function __construct(MisPatientService $misPatientService, DateRangeService $dateRangeService)
{
$this->misPatientService = $misPatientService;
$this->dateService = $dateRangeService;
}
public function __construct(
protected ReportService $reportService,
protected DateRangeService $dateRangeService
) {}
public function index(Request $request)
{
$user = \Auth::user();
$user = Auth::user();
$department = $user->department;
$queryStartDate = $request->query('startAt');
$queryEndDate = $request->query('endAt');
[$startDate, $endDate] = $this->dateService->getDateRangeForUser($user, $queryStartDate, $queryEndDate);
$isRangeOneDay = $this->dateService->isRangeOneDay($startDate, $endDate);
$dateRange = $this->dateRangeService->getDateRangeFromRequest($request, $user);
// Если диапазон содержит сутки
if ($isRangeOneDay) {
// Устанавливаем дату отчета, как последний день из выборки
$dateReport = $endDate;
} else {
// Устанавливаем дату отчета, как выборку
$dateReport = [$startDate, $endDate];
}
// Получаем статистику
$statistics = $this->reportService->getReportStatistics($user, $dateRange);
if ($isRangeOneDay) {
// Статистика выводится с нарастающим числом
$reports = $department->reports()
->whereDate('created_at', $dateReport)
->get();
} else {
$reports = $department->reports()
->whereBetween('created_at', $dateReport)
->get();
}
// Получаем метрики
$metrikaGroup = MetrikaGroup::whereMetrikaGroupId(2)->first();
$metrikaItems = $metrikaGroup->metrikaItems;
$isReports = $reports->count() > 0;
$allCount = 0; $outcomeCount = 0; $currentCount = 0; $occupiedBeds = 0; $planCount = 0;
$emergencyCount = 0; $planSurgical = 0; $emergencySurgical = 0; $transferredCount = 0;
$deceasedCount = 0;
if ($isReports) {
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);
}
} else {
$misDepartmentId = $request->user()->department->rf_mis_department_id;
$branchId = MisStationarBranch::where('rf_DepartmentID', $misDepartmentId)
->value('StationarBranchID');
$planCount = $this->misPatientService->getInStationarPatients('plan', $branchId, $dateReport)->count();
}
$bedsCount = $department->metrikaDefault()
->where('rf_metrika_item_id', 1)->value('value');
$percentLoadedBeds = $bedsCount > 0 ? round($occupiedBeds * 100 / $bedsCount) : 0;
// Получаем информацию о текущем отчете
$reportInfo = $this->reportService->getCurrentReportInfo($user, $dateRange);
return Inertia::render('Report/Index', [
'department' => [
'beds' => $bedsCount,
'recipients' => [
'all' => $allCount,
'plan' => $planCount,
'emergency' => $emergencyCount,
'transferred' => $transferredCount,
],
'outcome' => $outcomeCount,
'consist' => $currentCount,
'percentLoadedBeds' => $percentLoadedBeds,
'surgical' => [
'plan' => $planSurgical,
'emergency' => $emergencySurgical
],
'deceased' => $deceasedCount,
'beds' => $department->beds,
'percentLoadedBeds' => $this->calculateBedOccupancy($department, $user),
...$statistics,
],
'dates' => [
'startAt' => $dateRange->startTimestamp(),
'endAt' => $dateRange->endTimestamp()
],
'report' => $reportInfo,
'metrikaItems' => $metrikaItems,
'userId' => $reportInfo['userId'],
'userName' => $reportInfo['userName']
]);
}
private function getMetrikaResultFromReport(Report $report, int $metrikaItem, bool $sum = true)
public function store(Request $request)
{
if ($sum) {
return (int) ($report->metrikaResults()
->where('rf_metrika_item_id', $metrikaItem)
->sum(DB::raw('CAST(value AS INTEGER)')) ?: 0);
}
$validated = $request->validate([
'metrics' => 'required|array',
'observationPatients' => 'nullable|array',
'departmentId' => 'required|integer',
'unwantedEvents' => 'nullable|array',
'dates' => 'required|array',
'userId' => 'required|integer',
'reportId' => 'nullable|integer'
]);
return (int) ($report->metrikaResults()
->where('rf_metrika_item_id', $metrikaItem)
->value('value') ?: 0);
$report = $this->reportService->storeReport($validated, Auth::user());
return response()->json([
'message' => 'success',
'report_id' => $report->report_id
]);
}
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);
}
public function removeObservation(Request $request)
{
$validated = $request->validate(['id' => 'required|integer']);
$this->reportService->removeObservationPatient($validated['id']);
return response()->json(['message' => 'Удалено'], 200);
}
public function removeUnwantedEvent(UnwantedEvent $unwantedEvent)
{
$unwantedEvent->delete();
return response()->json(['message' => 'Удалено'], 200);
}
public function getDepartmentUsers()
{
$users = MisLpuDoctor::select(['LPUDoctorID', 'FAM_V', 'IM_V', 'OT_V'])
->active()
->inMyDepartment()
->get();
return response()->json($users, 200);
}
/**
* Рассчитать загруженность коек
*/
private function calculateBedOccupancy($department, $user): int
{
$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;
return $beds > 0 ? round(intval($occupiedBeds) * 100 / $beds) : 0;
}
}