feat: автоподбор применимости показателей критериев значимости по сфере
- dictionaries/criteria_applicability.json: для каждой сферы перечень применимых показателей ПП РФ № 127, построен из признаков значимости Распоряжения ПРФ № 360-р (например: ОПК → только 13 оборонзаказ, показатель 1 «ущерб жизни и здоровью» не применим; банки → только 10; связь → только 4) - окно ПП 127: неприменимые для сферы показатели блокируются и помечаются серым «(не применим для сферы)», исключаются из расчёта категории; если применимых показателей для сферы нет — категория «без категории»
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
{
|
||||
"Здравоохранение": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14"
|
||||
],
|
||||
"Наука": [
|
||||
"1",
|
||||
"11",
|
||||
"13",
|
||||
"7",
|
||||
"8",
|
||||
"9"
|
||||
],
|
||||
"Транспорт": [
|
||||
"10",
|
||||
"11",
|
||||
"3"
|
||||
],
|
||||
"Связь": [
|
||||
"4"
|
||||
],
|
||||
"Энергетика": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14"
|
||||
],
|
||||
"Государственная регистрация прав": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14"
|
||||
],
|
||||
"Банковская сфера и финансовый рынок": [
|
||||
"10"
|
||||
],
|
||||
"Топливно-энергетический комплекс": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14"
|
||||
],
|
||||
"Атомная энергетика": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14"
|
||||
],
|
||||
"Оборонная промышленность": [
|
||||
"13"
|
||||
],
|
||||
"Ракетно-космическая промышленность": [
|
||||
"10"
|
||||
],
|
||||
"Горнодобывающая промышленность": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14"
|
||||
],
|
||||
"Металлургическая промышленность": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14"
|
||||
],
|
||||
"Химическая промышленность": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14"
|
||||
],
|
||||
"Иная сфера деятельности": [
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"7",
|
||||
"8",
|
||||
"9",
|
||||
"10",
|
||||
"11",
|
||||
"12",
|
||||
"13",
|
||||
"14"
|
||||
]
|
||||
}
|
||||
+45
-8
@@ -1831,6 +1831,18 @@ class DokoGenApp:
|
||||
messagebox.showerror("Ошибка", f"Не удалось загрузить таблицу ПП 127: {e}")
|
||||
return
|
||||
|
||||
# Применимость показателей по сфере объекта (Распоряжение ПРФ № 360-р)
|
||||
applicable = None # None = все показатели применимы
|
||||
try:
|
||||
_app_path = os.path.join(os.path.dirname(__file__), 'dictionaries', 'criteria_applicability.json')
|
||||
with open(_app_path, encoding='utf-8') as _f:
|
||||
_app = _json.load(_f)
|
||||
_sphere = self.is_sphere_combo.get() if hasattr(self, 'is_sphere_combo') else ''
|
||||
if _sphere and _sphere in _app:
|
||||
applicable = set(_app[_sphere])
|
||||
except Exception:
|
||||
applicable = None
|
||||
|
||||
dialog = tk.Toplevel(self.root)
|
||||
dialog.title("Показатели критериев значимости (ПП РФ № 127)")
|
||||
dialog.geometry("980x700")
|
||||
@@ -1855,10 +1867,16 @@ class DokoGenApp:
|
||||
"объектов критической информационной инфраструктуры РФ» (приложение). "
|
||||
"По каждому показателю выберите значение, которому соответствует объект. "
|
||||
"Категория определяется по наивысшей из выбранных.",
|
||||
foreground='gray', wraplength=920, justify=tk.LEFT).pack(anchor=tk.W, pady=(0, 8))
|
||||
foreground='gray', wraplength=920, justify=tk.LEFT).pack(anchor=tk.W, pady=(0, 4))
|
||||
if applicable is not None:
|
||||
_sphere_txt = self.is_sphere_combo.get() if hasattr(self, 'is_sphere_combo') else ''
|
||||
ttk.Label(body, text=f"Сфера объекта: «{_sphere_txt}». Показатели, не применимые для этой сферы "
|
||||
f"(по Распоряжению ПРФ № 360-р), отмечены серым и исключены из расчёта.",
|
||||
foreground='#1a6e1a', wraplength=920, justify=tk.LEFT).pack(anchor=tk.W, pady=(0, 8))
|
||||
|
||||
rows = [] # (num, name, values{III:..,II:..,I:..}, var)
|
||||
rows = [] # (num, name, values{III:..,II:..,I:..}, var, applicable)
|
||||
|
||||
import re as _re
|
||||
for crit in criteria:
|
||||
grp = ttk.LabelFrame(body, text=crit.get('criteria', ''), padding=6)
|
||||
grp.pack(fill=tk.X, pady=4)
|
||||
@@ -1866,12 +1884,18 @@ class DokoGenApp:
|
||||
num = ind.get('num', '')
|
||||
name = ind.get('name', '')
|
||||
values = ind.get('values', {})
|
||||
# Группа показателя: '1'→'1', '2а'→'2', '10.1'→'10', '13б'→'13'
|
||||
m = _re.match(r'(\d+)', num)
|
||||
grp_num = m.group(1) if m else num
|
||||
applicable_here = applicable is None or grp_num in applicable
|
||||
row = ttk.Frame(grp)
|
||||
row.pack(fill=tk.X, pady=2)
|
||||
# Номер показателя
|
||||
ttk.Label(row, text=num, width=4, font=('Arial', 9, 'bold')).pack(side=tk.LEFT)
|
||||
lbl_num = ttk.Label(row, text=num, width=4, font=('Arial', 9, 'bold'))
|
||||
lbl_num.pack(side=tk.LEFT)
|
||||
# Текст показателя
|
||||
ttk.Label(row, text=name, wraplength=640, justify=tk.LEFT).pack(side=tk.LEFT)
|
||||
lbl_name = ttk.Label(row, text=name, wraplength=640, justify=tk.LEFT)
|
||||
lbl_name.pack(side=tk.LEFT)
|
||||
# Выбор значения (категория)
|
||||
var = tk.StringVar(value='')
|
||||
options = ['']
|
||||
@@ -1882,7 +1906,15 @@ class DokoGenApp:
|
||||
combo = ttk.Combobox(row, textvariable=var, state='readonly', width=34,
|
||||
values=options)
|
||||
combo.pack(side=tk.RIGHT, padx=6)
|
||||
rows.append((num, name, values, var))
|
||||
if not applicable_here:
|
||||
# Показатель не применим для сферы объекта — блокируем
|
||||
combo.config(state='disabled')
|
||||
lbl_num.config(foreground='gray')
|
||||
lbl_name.config(foreground='gray')
|
||||
if hasattr(lbl_name, 'config'):
|
||||
pass
|
||||
lbl_name.config(text=name + ' (не применим для сферы)')
|
||||
rows.append((num, name, values, var, applicable_here))
|
||||
|
||||
# Обоснование
|
||||
ttk.Label(body, text="Обоснование полученных значений:", font=('Arial', 9, 'bold')).pack(
|
||||
@@ -1898,9 +1930,11 @@ class DokoGenApp:
|
||||
result_lbl.pack(anchor=tk.W, pady=(6, 0))
|
||||
|
||||
def _selected():
|
||||
"""Список выбранных: [(num, name, категория, значение)]."""
|
||||
"""Список выбранных: [(num, name, категория, значение)] — только применимые показатели."""
|
||||
out = []
|
||||
for num, name, values, var in rows:
|
||||
for num, name, values, var, applicable_here in rows:
|
||||
if not applicable_here:
|
||||
continue
|
||||
s = var.get().strip()
|
||||
if not s:
|
||||
continue
|
||||
@@ -1923,7 +1957,10 @@ class DokoGenApp:
|
||||
def _calc():
|
||||
selected = _selected()
|
||||
if not selected:
|
||||
result_lbl.config(text="Категория значимости: — (ничего не выбрано)")
|
||||
if applicable is not None and not any(a for _, _, _, _, a in rows):
|
||||
result_lbl.config(text="Категория значимости: без категории (для этой сферы нет применимых показателей)")
|
||||
else:
|
||||
result_lbl.config(text="Категория значимости: — (ничего не выбрано)")
|
||||
return
|
||||
cat = _calc_category(selected)
|
||||
result_lbl.config(text=f"Категория значимости: {cat} (выбрано показателей: {len(selected)})")
|
||||
|
||||
Reference in New Issue
Block a user