Тех. меры: только при присвоенной категории и по факту СЗИ (без СЗИ нет «Регистрации и мониторинга»/«Антивируса»); промт СЗИ: при «без категории» — базовый минимум + провести категорирование, переданы характеристики объекта (интернет/ПО/архитектура); показатель 10 и 10.1–10.7: авторасчёт по методичке ФСТЭК (операции за год / дни) и порогам ПП-127

This commit is contained in:
LocoAgent
2026-08-05 14:39:03 +04:00
parent 07bf25ebc3
commit 9f8bf3999d
5 changed files with 218 additions and 18 deletions
+91 -4
View File
@@ -2241,7 +2241,52 @@ class DokoGenApp:
canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
if num == '9':
if num == '10' or str(num).startswith('10.'):
# Показатель 10 — прекращение финансовых операций (банковская сфера)
is_base = str(num) == '10'
if is_base:
ttk.Label(frm, text="Показатель 10 — прекращение (нарушение) проведения клиентами операций "
"по переводу денежных средств",
font=('Arial', 10, 'bold')).pack(anchor=tk.W)
ttk.Label(frm, text="Применим для: системно значимых кредитных организаций, операторов услуг "
"платёжной инфраструктуры значимых платёжных систем, операторов платформы "
"цифрового рубля и др.\n"
"Формула: №10 = операции за год (млн ед.) / календарные дни в году "
"(среднедневное количество операций).\n"
"Пороги: ≤ 70 млн/день → III; > 70 и ≤ 120 → II; > 120 → I.",
foreground='gray', wraplength=760, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6))
else:
ttk.Label(frm, text=f"Показатель {num} — прекращение (нарушение) проведения операций "
"(подпоказатель 10.x)",
font=('Arial', 10, 'bold')).pack(anchor=tk.W)
ttk.Label(frm, text="Значение показателя вводится в единицах, установленных ПП-127 "
"(трлн руб., тыс. шт., млрд руб., количество договоров, млн ед.); "
"категория определяется по порогам ПП-127.",
foreground='gray', wraplength=760, justify=tk.LEFT).pack(anchor=tk.W, pady=(2, 6))
def _row(label, key, default=''):
ttk.Label(frm, text=label, wraplength=900, justify=tk.LEFT).pack(anchor=tk.W, pady=(4, 0))
e = ttk.Entry(frm, width=80)
e.insert(0, str(default or ''))
e.pack(fill=tk.X)
return e
_ops = getattr(self.model, 'ops_count', '') or ''
_days = getattr(self.model, 'calendar_days', '') or '365'
_v10 = getattr(self.model, 'criterion10_value', '') or ''
if is_base:
e_ops = _row("Количество операций за прошедший год (млн ед.):", 'ops', _ops)
e_days = _row("Количество календарных дней в году (по умолчанию 365):", 'days', _days)
else:
e_val10 = _row("Значение показателя (в единицах ПП-127):", 'val10', _v10)
result_frame = ttk.Frame(frm)
result_frame.pack(fill=tk.BOTH, expand=True, pady=(8, 0))
result = tk.Text(result_frame, height=12, wrap=tk.WORD, state=tk.NORMAL)
result_scroll = ttk.Scrollbar(result_frame, orient=tk.VERTICAL, command=result.yview)
result.configure(yscrollcommand=result_scroll.set)
result.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
result_scroll.pack(side=tk.RIGHT, fill=tk.Y)
elif num == '9':
ttk.Label(frm, text="Показатель 9 — ущерб бюджетам РФ (применим ко всем субъектам КИИ)",
font=('Arial', 10, 'bold')).pack(anchor=tk.W)
ttk.Label(frm, text="Формула: №9 = ΔБ / Бусредн × 100%, где ΔБ = ΔНП + ΔНДПИ + ΔДИВ + ΔВСО + ΔНС\n"
@@ -2353,7 +2398,34 @@ class DokoGenApp:
def _calc():
lines = []
if num == '8':
if num == '10' or str(num).startswith('10.'):
from .variables import _criterion_10_cat
if str(num) == '10':
ops = _num(e_ops.get())
days = _num(e_days.get())
if days is None or days <= 0:
days = 365
if ops is None:
result.delete('1.0', tk.END)
result.insert('1.0', "Заполните количество операций за год (млн ед.).")
return
val = ops / days
lines.append(f"Количество операций за прошедший год: {ops:,.0f} млн ед.")
lines.append(f"Количество календарных дней в году: {days:.0f}")
lines.append(f"№10 = операции / дни = {ops:,.0f} / {days:.0f} = {val:.6f} млн ед./день")
else:
val = _num(e_val10.get())
if val is None:
result.delete('1.0', tk.END)
result.insert('1.0', "Заполните значение показателя.")
return
lines.append(f"Значение показателя {num}: {val:,.6f}")
cat = _criterion_10_cat(num, val)
if cat:
lines.append(f"Категория значимости: {cat} (по порогам ПП-127)")
else:
lines.append("Категория значимости: — (значение ниже порога III)")
elif num == '8':
d = _num(e_dincome.get())
b = _num(e_budget.get())
if d is None or b is None or b <= 0:
@@ -2505,8 +2577,9 @@ class DokoGenApp:
combo.pack(side=tk.RIGHT, padx=6)
_combos[num] = combo
# Кнопка «🧮» — авторасчёт показателя (п. 8 «ущерб субъекту КИИ» и п. 9 «ущерб бюджетам»)
if grp_num in ('8', '9'):
# Кнопка «🧮» — авторасчёт показателя (п. 8 «ущерб субъекту КИИ»,
# п. 9 «ущерб бюджетам», п. 10 «прекращение финансовых операций»)
if grp_num in ('8', '9', '10'):
ttk.Button(row, text='🧮', width=3,
command=lambda n=num, nm=name, v=var, c=combo:
_open_calc_dialog(n, nm, v, c)
@@ -3773,6 +3846,13 @@ class DokoGenApp:
'category': isys.category or '',
'sphere': isys.sphere or '',
'object_type': isys.object_type or '',
'description': isys.description or '',
'architecture': isys.architecture or '',
'hw_sw': isys.hw_sw or '',
'os_sw': isys.os_sw or '',
'app_sw': isys.app_sw or '',
'net_category': isys.net_category or '',
'is_internet': bool(getattr(isys, 'is_internet', False)),
'threats': isys.threats or '',
'attacker_category': isys.attacker_category or '',
'defense_tools': list(self.defense_tools_listbox.get(0, tk.END)) or [],
@@ -3838,6 +3918,13 @@ class DokoGenApp:
'category': isys.category or '',
'sphere': isys.sphere or '',
'object_type': isys.object_type or '',
'description': isys.description or '',
'architecture': isys.architecture or '',
'hw_sw': isys.hw_sw or '',
'os_sw': isys.os_sw or '',
'app_sw': isys.app_sw or '',
'net_category': isys.net_category or '',
'is_internet': bool(getattr(isys, 'is_internet', False)),
'threats': isys.threats or '',
'attacker_category': isys.attacker_category or '',
'defense_tools': list(self.defense_tools_listbox.get(0, tk.END)) or [],