fix: аудит dokogen187 — критические и высокие замечания
- api_settings: убраны реальные API-ключи из кода (env/файл) — 1.1 - verify: промт ИИ для проверки реквизитов больше не ссылается на 187-ФЗ как на закон о ПДн («юрист по ПДн (187-ФЗ)» → специалист по реквизитам) - ui: дата ПП РФ №127 исправлена 08.02.2019 → 08.02.2018 (3 места) - help_docs: группа B переименована «187-ФЗ (персональные данные)» → «187-ФЗ (критическая информационная инфраструктура)» - generator: убран дубль хвоста параграфа в _highlight_unmatched - importer: «магия дат» (числа 10001-79999 → дата Excel) теперь только для полей-дат (as_date), финансовые поля не ломаются - ui (_collect_is): убраны дубли пар маппинга attacker_level/attacker_types - ui (импорт): убрано наследие 152-ФЗ ispdnPosition/ispdnFio из маппинга - test_generator: переписан под модель 187-ФЗ (category/sphere/object_type вместо pd_count/threat_type/defence_level) - criteria_justifications: п.9 для здравоохранения согласован с кодом (убран «критерий неприменим» — противоречие с «применим ко всем») - criteria_applicability: Транспорт (добавлены п.1, п.2; убран п.10), Банковская сфера (добавлены п.8, п.9) — требуется экспертная сверка - ui: Бусредн вынесен в константу DEFAULT_BUDGET_AVG (данные Минфина, обновлять ежегодно); автозаполнение п.9 унифицировано с авторасчётом (ΔБ = ΔНП+ΔНДПИ+ΔДИВ+ΔВСО+ΔНС) - ui: п.8 — предупреждение при неполных данных (менее 5 лет доходов) - models: поля ndpi/div/vso/ns для п.9; комментарий income_loss уточнён - .gitignore: api_settings.json/.env не попадают в git
This commit is contained in:
@@ -3,3 +3,8 @@ __pycache__/
|
|||||||
.autosave/
|
.autosave/
|
||||||
Сгенерированные_документы/
|
Сгенерированные_документы/
|
||||||
*.result.docx
|
*.result.docx
|
||||||
|
|
||||||
|
# Секреты и локальные настройки — НЕ коммитить
|
||||||
|
api_settings.json
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
|||||||
+10
-4
@@ -13,11 +13,17 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
|
|
||||||
|
# ВНИМАНИЕ: реальные ключи НЕ хранятся в коде (утечка в git-историю — см. аудит).
|
||||||
|
# Источники ключей (по приоритету):
|
||||||
|
# 1) переменные окружения DADATA_TOKEN / DEEPSEEK_API_KEY / DEEPSEEK_MODEL / DEEPSEEK_BASE_URL
|
||||||
|
# 2) файл api_settings.json рядом с программой
|
||||||
|
# 3) DEFAULT_SETTINGS ниже (пустые значения)
|
||||||
|
|
||||||
DEFAULT_SETTINGS = {
|
DEFAULT_SETTINGS = {
|
||||||
'dadata_token': '431aa11706bf83f571cef0319259289aa750bcb1',
|
'dadata_token': os.environ.get('DADATA_TOKEN', ''),
|
||||||
'ai_api_key': 'sk-3c7e6673f245412697d0e14b6096435f',
|
'ai_api_key': os.environ.get('DEEPSEEK_API_KEY', ''),
|
||||||
'ai_model': 'deepseek-chat',
|
'ai_model': os.environ.get('DEEPSEEK_MODEL', 'deepseek-chat'),
|
||||||
'ai_base_url': 'https://api.deepseek.com',
|
'ai_base_url': os.environ.get('DEEPSEEK_BASE_URL', 'https://api.deepseek.com'),
|
||||||
}
|
}
|
||||||
|
|
||||||
# Старые ключи (для совместимости со старым файлом api_settings.json)
|
# Старые ключи (для совместимости со старым файлом api_settings.json)
|
||||||
|
|||||||
@@ -23,9 +23,10 @@
|
|||||||
"9"
|
"9"
|
||||||
],
|
],
|
||||||
"Транспорт": [
|
"Транспорт": [
|
||||||
"10",
|
"1",
|
||||||
"11",
|
"2",
|
||||||
"3"
|
"3",
|
||||||
|
"11"
|
||||||
],
|
],
|
||||||
"Связь": [
|
"Связь": [
|
||||||
"4"
|
"4"
|
||||||
@@ -61,6 +62,8 @@
|
|||||||
"14"
|
"14"
|
||||||
],
|
],
|
||||||
"Банковская сфера и финансовый рынок": [
|
"Банковская сфера и финансовый рынок": [
|
||||||
|
"8",
|
||||||
|
"9",
|
||||||
"10"
|
"10"
|
||||||
],
|
],
|
||||||
"Топливно-энергетический комплекс": [
|
"Топливно-энергетический комплекс": [
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
"6": "Организация сферы здравоохранения не является органом государственной власти, в связи с этим критерий неприменим.",
|
"6": "Организация сферы здравоохранения не является органом государственной власти, в связи с этим критерий неприменим.",
|
||||||
"7": "Организация сферы здравоохранения не является субъектом политической сферы деятельности, в связи с этим критерий неприменим.",
|
"7": "Организация сферы здравоохранения не является субъектом политической сферы деятельности, в связи с этим критерий неприменим.",
|
||||||
"8": "Организация сферы здравоохранения не является государственной корпорацией, государственным унитарным предприятием, государственной компанией, стратегическим акционерным обществом, стратегическим предприятием, в связи с этим критерий неприменим.",
|
"8": "Организация сферы здравоохранения не является государственной корпорацией, государственным унитарным предприятием, государственной компанией, стратегическим акционерным обществом, стратегическим предприятием, в связи с этим критерий неприменим.",
|
||||||
"9": "Объект КИИ задействован только в предоставлении медицинских услуг, освобожденных от налогообложения, в связи с этим критерий неприменим.",
|
"9": "Объект КИИ задействован в предоставлении медицинских услуг. Показатель 9 применим ко всем субъектам КИИ; при расчёте учитывается, что медицинские услуги освобождены от налогообложения (значение показателя может быть минимальным).",
|
||||||
"10": "Организация сферы здравоохранения не является субъектом банковской сферы деятельности.",
|
"10": "Организация сферы здравоохранения не является субъектом банковской сферы деятельности.",
|
||||||
"10.1": "Организация сферы здравоохранения не является центральным контрагентом.",
|
"10.1": "Организация сферы здравоохранения не является центральным контрагентом.",
|
||||||
"10.2": "Организация сферы здравоохранения не является центральным депозитарием.",
|
"10.2": "Организация сферы здравоохранения не является центральным депозитарием.",
|
||||||
|
|||||||
@@ -692,9 +692,6 @@ def _highlight_unmatched(doc):
|
|||||||
pos = m.end()
|
pos = m.end()
|
||||||
if pos < len(full):
|
if pos < len(full):
|
||||||
_add_run_with_tabs(para, full[pos:], first)
|
_add_run_with_tabs(para, full[pos:], first)
|
||||||
run = para.add_run(full[pos:])
|
|
||||||
if first is not None:
|
|
||||||
_copy_run_style(first, run)
|
|
||||||
|
|
||||||
for para in doc.paragraphs:
|
for para in doc.paragraphs:
|
||||||
_process_para(para)
|
_process_para(para)
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ def _generate_variables_reference(path):
|
|||||||
_p(doc, 'Список переменных для шаблонов Word. Переменная подставляется в текст '
|
_p(doc, 'Список переменных для шаблонов Word. Переменная подставляется в текст '
|
||||||
'как есть: {{имя_переменной}}. Циклы: <!-- loop:имя --> ... <!-- loop_end -->.')
|
'как есть: {{имя_переменной}}. Циклы: <!-- loop:имя --> ... <!-- loop_end -->.')
|
||||||
|
|
||||||
groups = {'A': 'Общие переменные', 'B': '187-ФЗ (персональные данные)'}
|
groups = {'A': 'Общие переменные', 'B': '187-ФЗ (критическая информационная инфраструктура)'}
|
||||||
by_group = {'A': [], 'B': []}
|
by_group = {'A': [], 'B': []}
|
||||||
for var, group, desc, _ in VARIABLE_DEFS:
|
for var, group, desc, _ in VARIABLE_DEFS:
|
||||||
by_group.setdefault(group, []).append((var, desc))
|
by_group.setdefault(group, []).append((var, desc))
|
||||||
|
|||||||
+12
-5
@@ -97,13 +97,18 @@ def normalize_address(text: str) -> str:
|
|||||||
return ''.join(out)
|
return ''.join(out)
|
||||||
|
|
||||||
|
|
||||||
def clean_value(val):
|
def clean_value(val, as_date=False):
|
||||||
"""Очистка и нормализация значения ячейки Excel."""
|
"""Очистка и нормализация значения ячейки Excel.
|
||||||
|
|
||||||
|
as_date=True — конвертировать серийный номер Excel в дату (только для
|
||||||
|
полей-дат, напр. ogrnDate). Для финансовых полей НЕ вызывается,
|
||||||
|
иначе число 50 000 руб. превратится в «дату» (см. аудит importer.py:105-109).
|
||||||
|
"""
|
||||||
if val is None:
|
if val is None:
|
||||||
return ''
|
return ''
|
||||||
if isinstance(val, (int, float)):
|
if isinstance(val, (int, float)):
|
||||||
# Попытка распознать дату (серийный номер Excel)
|
# Попытка распознать дату (серийный номер Excel) — только для полей-дат
|
||||||
if 10000 < val < 80000:
|
if as_date and 10000 < val < 80000:
|
||||||
serial = int(val)
|
serial = int(val)
|
||||||
if serial > 60:
|
if serial > 60:
|
||||||
serial -= 1
|
serial -= 1
|
||||||
@@ -253,7 +258,7 @@ def _import_187_common(wb, data, settings, log_fn):
|
|||||||
if sn.lower() == sheet_part.lower():
|
if sn.lower() == sheet_part.lower():
|
||||||
target_ws = wb[sn]
|
target_ws = wb[sn]
|
||||||
break
|
break
|
||||||
val = clean_value(cell_value(target_ws, coord))
|
val = clean_value(cell_value(target_ws, coord), as_date=('дата' in name.lower() or 'date' in key.lower()))
|
||||||
if val:
|
if val:
|
||||||
if key in ('chiefFio', 'responsibleFio', 'ispdnFio', 'adminFio'):
|
if key in ('chiefFio', 'responsibleFio', 'ispdnFio', 'adminFio'):
|
||||||
val = _extract_single_fio(val)
|
val = _extract_single_fio(val)
|
||||||
@@ -273,6 +278,8 @@ def _import_187_common(wb, data, settings, log_fn):
|
|||||||
if val:
|
if val:
|
||||||
if key in ('chiefFio', 'responsibleFio', 'ispdnFio', 'adminFio'):
|
if key in ('chiefFio', 'responsibleFio', 'ispdnFio', 'adminFio'):
|
||||||
val = _extract_single_fio(val)
|
val = _extract_single_fio(val)
|
||||||
|
elif 'дата' in name.lower() or 'date' in key.lower():
|
||||||
|
val = clean_value(val, as_date=True)
|
||||||
data[key] = val
|
data[key] = val
|
||||||
log_fn(f" {name} [по ключу]: {val}")
|
log_fn(f" {name} [по ключу]: {val}")
|
||||||
break
|
break
|
||||||
|
|||||||
+7
-1
@@ -135,9 +135,15 @@ class Company:
|
|||||||
income_year_3: str = "" # Доход за 3 года назад (руб.)
|
income_year_3: str = "" # Доход за 3 года назад (руб.)
|
||||||
income_year_4: str = "" # Доход за 2 года назад (руб.)
|
income_year_4: str = "" # Доход за 2 года назад (руб.)
|
||||||
income_year_5: str = "" # Доход за прошлый год (руб.)
|
income_year_5: str = "" # Доход за прошлый год (руб.)
|
||||||
income_loss: str = "" # Суммарный экономический ущерб от нарушения
|
income_loss: str = "" # Снижение уровня дохода (суммарный ущерб) от нарушения
|
||||||
# критических процессов (руб.) — ΔДоходов для п. 8
|
# критических процессов (руб.) — ΔДоходов для п. 8
|
||||||
|
|
||||||
|
# Показатель 9: компоненты ΔБ (унификация автозаполнения и авторасчёта)
|
||||||
|
ndpi: str = "" # Снижение выплат от налога на добычу ПИ ΔНДПИ (руб.)
|
||||||
|
div: str = "" # Снижение выплат от дивидендов ΔДИВ (руб.)
|
||||||
|
vso: str = "" # Снижение выплат сторонним организациям ΔВСО (руб.)
|
||||||
|
ns: str = "" # Снижение сборов ΔНС (руб.)
|
||||||
|
|
||||||
# Списки
|
# Списки
|
||||||
commission: List[CommissionMember] = field(default_factory=list)
|
commission: List[CommissionMember] = field(default_factory=list)
|
||||||
information_systems: List[InformationSystem] = field(default_factory=list)
|
information_systems: List[InformationSystem] = field(default_factory=list)
|
||||||
|
|||||||
+34
-20
@@ -26,6 +26,11 @@ from .verify import (
|
|||||||
)
|
)
|
||||||
from .api_settings import load_api_settings, save_api_settings
|
from .api_settings import load_api_settings, save_api_settings
|
||||||
|
|
||||||
|
# Бусредн — средний доход федерального бюджета за 3 года (данные Минфина).
|
||||||
|
# ВАЖНО: значение устаревает — обновлять ежегодно по данным Минфина или
|
||||||
|
# запрашивать у оператора в диалоге авторасчёта (поле редактируется).
|
||||||
|
DEFAULT_BUDGET_AVG = 21228053357700.0
|
||||||
|
|
||||||
|
|
||||||
class DokoGenApp:
|
class DokoGenApp:
|
||||||
"""Главное окно приложения."""
|
"""Главное окно приложения."""
|
||||||
@@ -353,7 +358,7 @@ class DokoGenApp:
|
|||||||
("Доход за 3 года назад (руб.):", "income_year_3"),
|
("Доход за 3 года назад (руб.):", "income_year_3"),
|
||||||
("Доход за 2 года назад (руб.):", "income_year_4"),
|
("Доход за 2 года назад (руб.):", "income_year_4"),
|
||||||
("Доход за прошлый год (руб.):", "income_year_5"),
|
("Доход за прошлый год (руб.):", "income_year_5"),
|
||||||
("Суммарный экономический ущерб от нарушения критических процессов (руб.):", "income_loss"),
|
("Снижение уровня дохода от нарушения критических процессов (руб.):", "income_loss"),
|
||||||
]
|
]
|
||||||
for j, (label, key) in enumerate(income_fields):
|
for j, (label, key) in enumerate(income_fields):
|
||||||
ttk.Label(f_fin, text=label).grid(row=len(fin_fields) + 1 + j, column=0, sticky=tk.W, pady=2)
|
ttk.Label(f_fin, text=label).grid(row=len(fin_fields) + 1 + j, column=0, sticky=tk.W, pady=2)
|
||||||
@@ -1419,8 +1424,6 @@ class DokoGenApp:
|
|||||||
('is_app_sw_listbox', 'app_sw'),
|
('is_app_sw_listbox', 'app_sw'),
|
||||||
('is_attacker_category_combo', 'attacker_category'),
|
('is_attacker_category_combo', 'attacker_category'),
|
||||||
('is_attacker_level_combo', 'attacker_level'),
|
('is_attacker_level_combo', 'attacker_level'),
|
||||||
('is_attacker_types_listbox', 'attacker_types'),
|
|
||||||
('is_attacker_level_combo', 'attacker_level'),
|
|
||||||
('is_attacker_types_listbox', 'attacker_types'),
|
('is_attacker_types_listbox', 'attacker_types'),
|
||||||
('is_threats_listbox', 'threats'),
|
('is_threats_listbox', 'threats'),
|
||||||
('is_incidents_listbox', 'incidents'),
|
('is_incidents_listbox', 'incidents'),
|
||||||
@@ -2079,7 +2082,7 @@ class DokoGenApp:
|
|||||||
def _open_criteria_127_dialog(self):
|
def _open_criteria_127_dialog(self):
|
||||||
"""Окно заполнения показателей критериев значимости по ПП РФ № 127.
|
"""Окно заполнения показателей критериев значимости по ПП РФ № 127.
|
||||||
|
|
||||||
Таблица перенесена дословно из Постановления Правительства РФ от 08.02.2019 № 127:
|
Таблица перенесена дословно из Постановления Правительства РФ от 08.02.2018 № 127:
|
||||||
5 критериев (социальная, политическая, экономическая, экологическая,
|
5 критериев (социальная, политическая, экономическая, экологическая,
|
||||||
значимость для обороны страны), показатели 1-14 с подпунктами,
|
значимость для обороны страны), показатели 1-14 с подпунктами,
|
||||||
значения сразу привязаны к категориям III / II / I.
|
значения сразу привязаны к категориям III / II / I.
|
||||||
@@ -2169,7 +2172,7 @@ class DokoGenApp:
|
|||||||
|
|
||||||
ttk.Label(body, text="Показатели критериев значимости объекта КИИ",
|
ttk.Label(body, text="Показатели критериев значимости объекта КИИ",
|
||||||
font=('Arial', 11, 'bold')).pack(anchor=tk.W, pady=(0, 2))
|
font=('Arial', 11, 'bold')).pack(anchor=tk.W, pady=(0, 2))
|
||||||
ttk.Label(body, text="Постановление Правительства РФ от 08.02.2019 № 127 «Об утверждении Правил категорирования "
|
ttk.Label(body, text="Постановление Правительства РФ от 08.02.2018 № 127 «Об утверждении Правил категорирования "
|
||||||
"объектов критической информационной инфраструктуры РФ» (приложение). "
|
"объектов критической информационной инфраструктуры РФ» (приложение). "
|
||||||
"По каждому показателю выберите значение, которому соответствует объект. "
|
"По каждому показателю выберите значение, которому соответствует объект. "
|
||||||
"Категория определяется по наивысшей из выбранных.",
|
"Категория определяется по наивысшей из выбранных.",
|
||||||
@@ -2247,7 +2250,7 @@ class DokoGenApp:
|
|||||||
"нарушения (в опроснике её нет, вводится вручную; можно приравнять к ущербу из показателя 8).",
|
"нарушения (в опроснике её нет, вводится вручную; можно приравнять к ущербу из показателя 8).",
|
||||||
foreground='#8a6d00', wraplength=900, justify=tk.LEFT).pack(anchor=tk.W)
|
foreground='#8a6d00', wraplength=900, justify=tk.LEFT).pack(anchor=tk.W)
|
||||||
e_budget = _row("Доход федерального бюджета, усреднённый за 3 года Бусредн (руб.):", 'budget',
|
e_budget = _row("Доход федерального бюджета, усреднённый за 3 года Бусредн (руб.):", 'budget',
|
||||||
'21228053357700')
|
f'{DEFAULT_BUDGET_AVG:.0f}')
|
||||||
ttk.Label(frm, text="⚠️ Бусредн — средний доход федерального бюджета за 3 года (данные Минфина, "
|
ttk.Label(frm, text="⚠️ Бусредн — средний доход федерального бюджета за 3 года (данные Минфина, "
|
||||||
"подставлено значение по умолчанию; при необходимости уточните).",
|
"подставлено значение по умолчанию; при необходимости уточните).",
|
||||||
foreground='#8a6d00', wraplength=900, justify=tk.LEFT).pack(anchor=tk.W)
|
foreground='#8a6d00', wraplength=900, justify=tk.LEFT).pack(anchor=tk.W)
|
||||||
@@ -2275,19 +2278,22 @@ class DokoGenApp:
|
|||||||
|
|
||||||
e_profit = e_tax = None
|
e_profit = e_tax = None
|
||||||
# Доходы за 5 лет — из данных организации (поля «Доходы за 5 лет»)
|
# Доходы за 5 лет — из данных организации (поля «Доходы за 5 лет»)
|
||||||
_incs = [_num(getattr(self.model, f'income_year_{i}', '') or '') for i in range(1, 6)]
|
_incs_raw = [getattr(self.model, f'income_year_{i}', '') or '' for i in range(1, 6)]
|
||||||
_incs = [x for x in _incs if x is not None]
|
_incs = [_num(x) for x in _incs_raw]
|
||||||
_d_avg = (sum(_incs) / len(_incs)) if _incs else None
|
_incs_filled = [x for x in _incs if x is not None]
|
||||||
|
_d_avg = (sum(_incs_filled) / len(_incs_filled)) if _incs_filled else None
|
||||||
_d_loss = _num(getattr(self.model, 'income_loss', '') or '')
|
_d_loss = _num(getattr(self.model, 'income_loss', '') or '')
|
||||||
e_dincome = _row("Суммарный экономический ущерб от нарушения критических процессов (руб.):",
|
e_dincome = _row("Снижение уровня дохода от нарушения критических процессов (руб.):",
|
||||||
'dincome', f"{_d_loss:,.0f}" if _d_loss else '')
|
'dincome', f"{_d_loss:,.0f}" if _d_loss else '')
|
||||||
ttk.Label(frm, text="⚠️ Ущерб — поле «Суммарный ущерб (показатель 8)» из вкладки «Организация» "
|
ttk.Label(frm, text="⚠️ ΔДоходов — поле «Снижение уровня дохода (показатель 8)» из вкладки «Организация» "
|
||||||
"(подставлено автоматически, можно поправить).",
|
"(подставлено автоматически, можно поправить).",
|
||||||
foreground='#8a6d00', wraplength=900, justify=tk.LEFT).pack(anchor=tk.W)
|
foreground='#8a6d00', wraplength=900, justify=tk.LEFT).pack(anchor=tk.W)
|
||||||
e_budget = _row("Доходы субъекта КИИ, усреднённые за 5 лет (руб.):",
|
e_budget = _row("Доходы субъекта КИИ, усреднённые за 5 лет (руб.):",
|
||||||
'budget', f"{_d_avg:,.0f}" if _d_avg else '')
|
'budget', f"{_d_avg:,.0f}" if _d_avg else '')
|
||||||
ttk.Label(frm, text="⚠️ Доходы за 5 лет — среднее по полям «Доход за …» из вкладки «Организация» "
|
_n_years = len(_incs_filled)
|
||||||
"(подставлено автоматически, можно поправить).",
|
ttk.Label(frm, text=f"⚠️ Доходы за 5 лет — среднее по заполненным годам ({_n_years} из 5). "
|
||||||
|
"ПП-127 требует усреднение за прошедший пятилетний период: "
|
||||||
|
"при неполных данных результат методологически некорректен — заполните все 5 лет.",
|
||||||
foreground='#8a6d00', wraplength=900, justify=tk.LEFT).pack(anchor=tk.W)
|
foreground='#8a6d00', wraplength=900, justify=tk.LEFT).pack(anchor=tk.W)
|
||||||
result = tk.Text(frm, height=8, wrap=tk.WORD, state=tk.NORMAL)
|
result = tk.Text(frm, height=8, wrap=tk.WORD, state=tk.NORMAL)
|
||||||
result.pack(fill=tk.BOTH, expand=True, pady=(8, 0))
|
result.pack(fill=tk.BOTH, expand=True, pady=(8, 0))
|
||||||
@@ -2302,7 +2308,7 @@ class DokoGenApp:
|
|||||||
result.insert('1.0', "Заполните оба поля (ущерб и доходы за 5 лет).")
|
result.insert('1.0', "Заполните оба поля (ущерб и доходы за 5 лет).")
|
||||||
return
|
return
|
||||||
val = d / b * 100
|
val = d / b * 100
|
||||||
lines.append(f"Суммарный экономический ущерб от нарушения критических процессов: {d:,.0f} руб.")
|
lines.append(f"Снижение уровня дохода от нарушения критических процессов: {d:,.0f} руб.")
|
||||||
lines.append(f"Доходы субъекта КИИ, усреднённые за 5 лет: {b:,.0f} руб.")
|
lines.append(f"Доходы субъекта КИИ, усреднённые за 5 лет: {b:,.0f} руб.")
|
||||||
lines.append(f"№8 = ущерб / доходы за 5 лет × 100% = {d:,.0f} / {b:,.0f} × 100 = {val:.2f} %")
|
lines.append(f"№8 = ущерб / доходы за 5 лет × 100% = {d:,.0f} / {b:,.0f} × 100 = {val:.2f} %")
|
||||||
if val > 20:
|
if val > 20:
|
||||||
@@ -2585,7 +2591,7 @@ class DokoGenApp:
|
|||||||
if chosen:
|
if chosen:
|
||||||
auto_parts.append(
|
auto_parts.append(
|
||||||
"Категория значимости объекта КИИ определена в соответствии с Правилами категорирования "
|
"Категория значимости объекта КИИ определена в соответствии с Правилами категорирования "
|
||||||
"объектов критической информационной инфраструктуры РФ (ПП РФ от 08.02.2019 № 127). "
|
"объектов критической информационной инфраструктуры РФ (ПП РФ от 08.02.2018 № 127). "
|
||||||
f"Объект отнесён к {cat} категории значимости. Основания: "
|
f"Объект отнесён к {cat} категории значимости. Основания: "
|
||||||
+ "; ".join(f"показатель {num} ({c} категория)" for num, _, c, _ in chosen) + "."
|
+ "; ".join(f"показатель {num} ({c} категория)" for num, _, c, _ in chosen) + "."
|
||||||
)
|
)
|
||||||
@@ -2685,12 +2691,18 @@ class DokoGenApp:
|
|||||||
parent=dialog, minvalue=0)
|
parent=dialog, minvalue=0)
|
||||||
if dincome is None:
|
if dincome is None:
|
||||||
continue
|
continue
|
||||||
budget = 21228053357700.0 # Бусредн (доход федерального бюджета за 3 года)
|
budget = DEFAULT_BUDGET_AVG # Бусредн (доход федерального бюджета за 3 года)
|
||||||
knp = tax / profit
|
knp = tax / profit
|
||||||
dnp = dincome * knp
|
dnp = dincome * knp
|
||||||
if dincome > profit:
|
if dincome > profit:
|
||||||
dnp = tax
|
dnp = tax
|
||||||
val = dnp / budget * 100
|
# Унификация с авторасчётом: ΔБ = ΔНП + ΔНДПИ + ΔДИВ + ΔВСО + ΔНС
|
||||||
|
ndpi = _num2(getattr(self.model, 'ndpi', '') or '') or 0
|
||||||
|
div = _num2(getattr(self.model, 'div', '') or '') or 0
|
||||||
|
vso = _num2(getattr(self.model, 'vso', '') or '') or 0
|
||||||
|
ns = _num2(getattr(self.model, 'ns', '') or '') or 0
|
||||||
|
db = dnp + ndpi + div + vso + ns
|
||||||
|
val = db / budget * 100
|
||||||
if val > 0.001:
|
if val > 0.001:
|
||||||
cat = 'I'
|
cat = 'I'
|
||||||
elif val > 0.0006:
|
elif val > 0.0006:
|
||||||
@@ -2708,8 +2720,10 @@ class DokoGenApp:
|
|||||||
calc_txt = (
|
calc_txt = (
|
||||||
f"Коэффициент КНП = налог/прибыль = {tax:,.0f} / {profit:,.0f} = {knp:.4f}\n"
|
f"Коэффициент КНП = налог/прибыль = {tax:,.0f} / {profit:,.0f} = {knp:.4f}\n"
|
||||||
f"ΔНП = ΔДоходов × КНП = {dincome:,.0f} × {knp:.4f} = {dnp:,.1f} руб.\n"
|
f"ΔНП = ΔДоходов × КНП = {dincome:,.0f} × {knp:.4f} = {dnp:,.1f} руб.\n"
|
||||||
|
f"ΔНДПИ = {ndpi:,.0f}, ΔДИВ = {div:,.0f}, ΔВСО = {vso:,.0f}, ΔНС = {ns:,.0f} руб.\n"
|
||||||
|
f"ΔБ = ΔНП + ΔНДПИ + ΔДИВ + ΔВСО + ΔНС = {db:,.1f} руб.\n"
|
||||||
f"Бусредн (доход федерального бюджета за 3 года) = {budget:,.0f} руб.\n"
|
f"Бусредн (доход федерального бюджета за 3 года) = {budget:,.0f} руб.\n"
|
||||||
f"№9 = ΔБ / Бусредн × 100% = {dnp:,.1f} / {budget:,.0f} × 100 = {val:.6f} %\n"
|
f"№9 = ΔБ / Бусредн × 100% = {db:,.1f} / {budget:,.0f} × 100 = {val:.6f} %\n"
|
||||||
f"Категория значимости: {cat or '— (не присваивается)'}"
|
f"Категория значимости: {cat or '— (не присваивается)'}"
|
||||||
)
|
)
|
||||||
prefix = f"Показатель {num}. {name} — рекомендация по расчёту:"
|
prefix = f"Показатель {num}. {name} — рекомендация по расчёту:"
|
||||||
@@ -4136,8 +4150,8 @@ class DokoGenApp:
|
|||||||
'chief_fio': 'chiefFio',
|
'chief_fio': 'chiefFio',
|
||||||
'responsible_position': 'responsiblePosition',
|
'responsible_position': 'responsiblePosition',
|
||||||
'responsible_fio': 'responsibleFio',
|
'responsible_fio': 'responsibleFio',
|
||||||
'admin_position': ('administratorPosition', 'ispdnPosition'),
|
'admin_position': 'administratorPosition',
|
||||||
'admin_fio': ('administratorFio', 'ispdnFio'),
|
'admin_fio': 'administratorFio',
|
||||||
}
|
}
|
||||||
for entry_key, data_keys in officials_map.items():
|
for entry_key, data_keys in officials_map.items():
|
||||||
entry = self._official_entries.get(entry_key)
|
entry = self._official_entries.get(entry_key)
|
||||||
|
|||||||
+2
-1
@@ -694,7 +694,8 @@ def check_company_ai(company_data, api_key, model='deepseek-chat', base_url=None
|
|||||||
if not api_key:
|
if not api_key:
|
||||||
return None, "Не задан API-ключ ИИ (Файл → Настройки → API)"
|
return None, "Не задан API-ключ ИИ (Файл → Настройки → API)"
|
||||||
system = (
|
system = (
|
||||||
"Ты — юрист по защите персональных данных (187-ФЗ). Проверь реквизиты организации. "
|
"Ты — специалист по проверке реквизитов организации (ИНН/КПП/ОГРН). "
|
||||||
|
"Проверь реквизиты организации. "
|
||||||
"Верни ТОЛЬКО JSON: "
|
"Верни ТОЛЬКО JSON: "
|
||||||
'{"оценка": "ok|warning|error", '
|
'{"оценка": "ok|warning|error", '
|
||||||
'"замечания": ["..."], '
|
'"замечания": ["..."], '
|
||||||
|
|||||||
+8
-8
@@ -30,8 +30,8 @@ def create_test_template():
|
|||||||
doc.add_paragraph('<!-- loop:information_systems -->')
|
doc.add_paragraph('<!-- loop:information_systems -->')
|
||||||
doc.add_paragraph('=== IS: {{item.name}} ===')
|
doc.add_paragraph('=== IS: {{item.name}} ===')
|
||||||
doc.add_paragraph('Category: {{item.category}}')
|
doc.add_paragraph('Category: {{item.category}}')
|
||||||
doc.add_paragraph('Threat type: {{item.threat_type}}')
|
doc.add_paragraph('Sphere: {{item.sphere}}')
|
||||||
doc.add_paragraph('Defence level: {{item.defence_level}}')
|
doc.add_paragraph('Object type: {{item.object_type}}')
|
||||||
doc.add_paragraph('')
|
doc.add_paragraph('')
|
||||||
|
|
||||||
# Inner loop: commission
|
# Inner loop: commission
|
||||||
@@ -72,12 +72,12 @@ def test_zip_loop_expansion():
|
|||||||
CommissionMember(role='Член комиссии', position='Бухгалтер', fio='Сидорова А.А.'),
|
CommissionMember(role='Член комиссии', position='Бухгалтер', fio='Сидорова А.А.'),
|
||||||
],
|
],
|
||||||
information_systems=[
|
information_systems=[
|
||||||
InformationSystem(name='ИС-1 "Бухгалтерия"', category='специальные',
|
InformationSystem(name='ОКИИ-1 "Платёжный шлюз"', category='1',
|
||||||
pd_count='менее 100 000', threat_type='1', defence_level='2'),
|
sphere='Банковская сфера и финансовый рынок', object_type='АСУ'),
|
||||||
InformationSystem(name='ИС-2 "Кадры"', category='иные',
|
InformationSystem(name='ОКИИ-2 "Кадры"', category='2',
|
||||||
pd_count='более 100 000', threat_type='3', defence_level='4'),
|
sphere='Наука', object_type='ИС'),
|
||||||
InformationSystem(name='ИС-3 "Склад"', category='общедоступные',
|
InformationSystem(name='ОКИИ-3 "Склад"', category='3',
|
||||||
pd_count='менее 100 000', threat_type='2', defence_level='3'),
|
sphere='Здравоохранение', object_type='ИС'),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user