'Черновик', 2 => 'Сдан']; public function key(): string { return 'shifts'; } public function label(): string { return 'Смены / дежурства'; } public function description(): string { return 'Показатели сданных дежурных смен отделения'; } public function category(): string { return 'Дежурства'; } protected function dateField(): string { return 'rd.period_start'; } protected function baseQuery(AnalyticsQuery $query): Builder { return DB::table('report_duties as rd') ->leftJoin('duty_report_metric_results as m', 'm.rf_report_id', '=', 'rd.id') ->where('rd.rf_department_id', $query->department->department_id) ->where('rd.status_id', 2) ->where('rd.period_start', '>=', $query->dateRange->startSql()) ->where('rd.period_end', '<=', $query->dateRange->endSql()); } public function dimensions(): array { return [ new Dimension('shift_date', 'Дата смены', 'date', 'CAST(rd.period_start AS date)'), new Dimension( 'doctor', 'Врач', 'string', 'rd.rf_lpudoctor_id', labels: fn (array $ids) => MisLpuDoctor::whereIn('LPUDoctorID', $ids)->get() ->mapWithKeys(fn ($d) => [$d->LPUDoctorID => trim("{$d->FAM_V} {$d->IM_V} {$d->OT_V}") ?: "Врач #{$d->LPUDoctorID}"]) ->all(), ), new Dimension( 'department', 'Отделение', 'string', 'rd.rf_department_id', labels: fn (array $ids) => Department::whereIn('department_id', $ids)->get() ->mapWithKeys(fn ($d) => [$d->department_id => $d->name_full ?? $d->name_short]) ->all(), ), new Dimension( 'status', 'Статус', 'string', 'rd.status_id', labels: fn () => self::STATUS_OPTIONS, ), ]; } public function measures(): array { return [ new Measure('shifts_count', 'Количество смен', 'count', 'COUNT(DISTINCT rd.id)'), new Measure('beds', 'Коек', 'count', $this->sum(MetrikaConfig::BEDS)), new Measure('recipient_plan', 'Поступило плановых', 'count', $this->sum(MetrikaConfig::PLAN)), new Measure('recipient_emergency', 'Поступило экстренных', 'count', $this->sum(MetrikaConfig::EMERGENCY)), new Measure('discharged', 'Выписано', 'count', $this->sum(MetrikaConfig::DISCHARGED)), new Measure('transferred', 'Переведено', 'count', $this->sum(MetrikaConfig::TRANSFERRED)), new Measure('deceased', 'Умерло', 'count', $this->sum(MetrikaConfig::DECEASED)), new Measure('surgery_plan', 'Операции плановые', 'count', $this->sum(MetrikaConfig::PLAN_SURGERY)), new Measure('surgery_emergency', 'Операции экстренные', 'count', $this->sum(MetrikaConfig::EMERGENCY_SURGERY)), new Measure('occupancy_percent', 'Занятость, %', 'percent', $this->avg(MetrikaConfig::DEPARTMENT_LOADED)), new Measure('avg_bed_days', 'Ср. койко-день', null, $this->avg(MetrikaConfig::AVERAGE_BED_DAYS)), new Measure('lethality_percent', 'Летальность, %', 'percent', $this->avg(MetrikaConfig::LETHALITY)), new Measure('staff_count', 'Мед. персонал', 'count', $this->avg(MetrikaConfig::STAFF_COUNT)), ]; } public function filters(): array { return [ new FilterDef('doctor', 'Врач', 'rd.rf_lpudoctor_id', 'select', null, 'doctors'), ]; } private function sum(int $metricId): string { return "SUM(CASE WHEN m.rf_metrika_item_id = {$metricId} THEN NULLIF(m.value, '')::numeric ELSE 0 END)"; } private function avg(int $metricId): string { return "AVG(CASE WHEN m.rf_metrika_item_id = {$metricId} THEN NULLIF(m.value, '')::numeric END)"; } }