diff --git a/adk-rust/crates/detmir-portal/src/main.rs b/adk-rust/crates/detmir-portal/src/main.rs index 9727ab5..55c2e10 100644 --- a/adk-rust/crates/detmir-portal/src/main.rs +++ b/adk-rust/crates/detmir-portal/src/main.rs @@ -31,7 +31,8 @@ const API_CONTRACT_OPENAPI: &str = include_str!("contracts/openapi.json"); const API_CONTRACT_TYPESCRIPT: &str = include_str!("contracts/typescript.d.ts"); const UEBA_BASELINE_MIN_SAMPLES: usize = 3; const SNAPSHOT_CACHE_TTL: Duration = Duration::from_secs(120); -const DEFAULT_DEPARTMENT_LABEL: &str = "Без подразделения"; +const DEFAULT_DEPARTMENT_LABEL: &str = "Не привязано к подразделению"; +const LEGACY_UNASSIGNED_DEPARTMENT_LABEL: &str = "Без подразделения"; #[cfg(unix)] const SIGKILL: i32 = 9; @@ -2165,7 +2166,10 @@ fn display_name_opt(value: Option<&str>, fallback: &str) -> String { return fallback.to_string(); }; let value = value.trim(); - if value.is_empty() || has_broken_display_chars(value) { + if value.is_empty() + || value == LEGACY_UNASSIGNED_DEPARTMENT_LABEL + || has_broken_display_chars(value) + { fallback.to_string() } else { value.to_string() @@ -2670,7 +2674,7 @@ FORMAT JSONEachRow let top_sql = format!( r#" WITH now() - INTERVAL 24 HOUR AS since -SELECT if(empty(infobase), 'Без подразделения', infobase) AS department, toUInt64(count()) AS events +SELECT if(empty(infobase), 'Не привязано к подразделению', infobase) AS department, toUInt64(count()) AS events FROM {database}.entity_timeline WHERE ts >= since GROUP BY department @@ -10336,6 +10340,10 @@ mod tests { fn display_department_name_replaces_corrupt_runtime_labels() { assert_eq!(display_department_name(Some("Бухгалтерия")), "Бухгалтерия"); assert_eq!(display_department_name(Some("")), DEFAULT_DEPARTMENT_LABEL); + assert_eq!( + display_department_name(Some("Без подразделения")), + DEFAULT_DEPARTMENT_LABEL + ); assert_eq!( display_department_name(Some("\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}")), DEFAULT_DEPARTMENT_LABEL diff --git a/adk-rust/crates/detmir-portal/src/static/app.js b/adk-rust/crates/detmir-portal/src/static/app.js index 7830fd0..d441be9 100644 --- a/adk-rust/crates/detmir-portal/src/static/app.js +++ b/adk-rust/crates/detmir-portal/src/static/app.js @@ -17,6 +17,8 @@ const state = { }, }; +const DEFAULT_DEPARTMENT_LABEL = "Не привязано к подразделению"; + const VIEW_MODES = { executive: { label: "Руководитель", @@ -802,7 +804,7 @@ function departmentRows(report) { const status = item.status || "INFO"; const responsible = item.responsible || departmentResponsible(owners, index); return { - label: item.label || "Без подразделения", + label: item.label || DEFAULT_DEPARTMENT_LABEL, activity, activityText: Number.isFinite(activity) ? `${Math.round(activity)}%` : firstPercent(item.value), deviation: item.deviation || departmentDeviation(item), @@ -1392,7 +1394,7 @@ function renderInvestigationPacks(candidates) {
Последнее событие: ${ui(s.last_event_utc || "нет данных")} · запрос ${ui(s.query_ms ?? 0)} ms.
+${ui(DEFAULT_DEPARTMENT_LABEL)} — событие есть в источнике, но в нем не передана связь с оргструктурой. Последнее событие: ${ui(s.last_event_utc || "нет данных")} · запрос ${ui(s.query_ms ?? 0)} ms.
`} `; @@ -2408,7 +2410,7 @@ function renderBusinessRisk(items) { ${rows.length ? rows.map(item => `