user(); $userDepartment = $user->department; $data = []; $departments = Department::select('department_id', 'name_short') ->orderBy('name_short')->get(); foreach ($departments as $department) { $allCount = MetrikaResult::whereHas('report', function ($query) use ($userDepartment, $department) { $query->where('rf_department_id', $department->department_id); })->where('rf_metrika_item_id', 3) ->sum(DB::raw('value::integer')); $leaveCount = MetrikaResult::whereHas('report', function ($query) use ($userDepartment, $department) { $query->where('rf_department_id', $department->department_id); })->where('rf_metrika_item_id', 7) ->sum(DB::raw('value::integer')); $consistCount = optional(MetrikaResult::where('rf_metrika_item_id', 8) ->whereHas('report', function (Builder $query) use ($department) { $query->where('rf_department_id', $department->department_id); })->join('reports', 'metrika_results.rf_report_id', '=', 'reports.report_id') ->select('metrika_results.value') ->orderBy('reports.sent_at', 'desc') )->value('value') ?? 0; $beds = (int)optional($department->metrikaDefault() ->where('rf_metrika_item_id', 1) ->first())->value ?? 0; $occupiedBeds = (int)optional(Report::where('rf_department_id', $department->department_id) ->join('metrika_results', 'reports.report_id', '=', 'metrika_results.rf_report_id') ->where('metrika_results.rf_metrika_item_id', 8) ->orderBy('reports.sent_at', 'desc') ->first())->value ?? 0; $percentLoadedBeds = $beds > 0 ? round($occupiedBeds * 100 / $beds) : 0; $data[] = [ 'department' => $department->name_short, 'beds' => $beds, 'all' => $allCount, 'plan' => '0', 'emergency' => '0', 'leave' => $leaveCount, 'consist' => $consistCount, 'percentLoadedBeds' => $percentLoadedBeds, ]; } return Inertia::render('Statistic/Index', [ 'data' => $data ]); } public function indexOld(Request $request) { $user = Auth::user(); $validator = Validator::make($request->all(), [ 'sent_at' => 'required|string' ]); $groupId = (int)$request->query('groupId'); if ($validator->fails()) { return response()->json([ 'success' => false, 'errors' => $validator->errors() ], 422); } $timestamps = explode(',', $request->sent_at); $startAt = intval($timestamps[0] / 1000); $endAt = intval($timestamps[1] / 1000); // Проверяем период (максимум 1 год) $daysDiff = ($endAt - $startAt) / (60 * 60 * 24); if ($daysDiff > 365) { return response()->json([ 'success' => false, 'message' => 'Период не может превышать 1 год' ], 400); } $dateStart = date('Y-m-d', $startAt); $dateEnd = date('Y-m-d', $endAt); $group = MetrikaGroup::findOrFail($groupId); // Оптимизированный агрегированный запрос $aggregatedData = DB::table('metrika_results as mr') ->join('metrika_result_values as mv', 'mr.metrika_result_id', '=', 'mv.rf_metrika_result_id') ->join('reports as r', 'mr.rf_report_id', '=', 'r.report_id') ->where('mr.rf_metrika_group_id', $groupId) ->whereBetween('r.sent_at', [$dateStart, $dateEnd]) ->when(!$user->isAdmin() && !$user->isHeadOfDepartment(), function ($query) use ($user) { return $query->where('r.rf_user_id', $user->id); }) ->select([ 'mv.rf_metrika_item_id', DB::raw('SUM(CAST(mv.value AS DECIMAL(10,2))) as total_sum'), DB::raw('COUNT(DISTINCT r.report_id) as reports_count'), DB::raw('AVG(CAST(mv.value AS DECIMAL(10,2))) as avg_value') ]) ->groupBy('mv.rf_metrika_item_id') ->get() ->keyBy('rf_metrika_item_id'); if ($aggregatedData->isEmpty()) { return response()->json([ 'success' => false, 'message' => 'Данные за указанный период не найдены' ], 404); } // Получаем названия метрик одним запросом $itemIds = $aggregatedData->pluck('rf_metrika_item_id')->toArray(); $items = MetrikaItem::whereIn('metrika_item_id', $itemIds) ->pluck('name', 'metrika_item_id'); // Формируем ответ $formValues = []; foreach ($aggregatedData as $itemId => $data) { $formValues["metrika_item_{$itemId}"] = [ 'sum' => (float) $data->total_sum, 'average' => (float) $data->avg_value, 'reports_count' => $data->reports_count, 'item_name' => $items[$itemId] ?? 'Неизвестный показатель' ]; } // Получаем структуру формы $formData = MetrikaForm::getFormData($groupId); return Inertia::render('Statistic/Index', [ 'is_view_only' => true, 'period' => [ 'start' => $dateStart, 'end' => $dateEnd, 'days' => $daysDiff + 1 ], 'group' => [ 'id' => $group->metrika_group_id, 'name' => $group->name, 'description' => $group->description, ], 'metrics' => [ 'total_items' => count($formValues), 'total_reports' => $aggregatedData->first()->reports_count ?? 0, 'values' => $formValues, 'aggregation' => 'sum_and_average' ], 'form' => [ 'fields' => $formData, 'sections' => $this->groupFieldsBySection($formData) ] ]); } private function groupFieldsBySection($fields) { $sections = []; foreach ($fields as $field) { $section = $field['section'] ?? 'general'; if (!isset($sections[$section])) { $sections[$section] = [ 'name' => $this->getSectionName($section), 'fields' => [] ]; } $sections[$section]['fields'][] = $field; } return array_values($sections); } private function getSectionName($section) { $names = [ 'general' => 'Основные показатели', 'admissions' => 'Поступления', 'discharges' => 'Выписки', 'additional' => 'Дополнительная информация' ]; return $names[$section] ?? ucfirst($section); } }