feat: ОКИИ — ОКВЭД (импорт+DaData), доменное имя, поля 236 приказа ФСТЭК

- ОКВЭД: починен импорт (split по запятым/точкам с запятой), добавлен okvedExtra и domainName в DEFAULT_SETTINGS + merge полей по var в load_settings (старый import_settings.json теперь дополняется)
- DaData: проверка и подстановка основного/доп. ОКВЭД
- Вкладка «Организация»: поле «Доменное имя и внешний IP» + импорт из опросника
- Вкладка «Объекты КИИ»: поля 236 приказа — сведения (назначение, сфера, тип, архитектура, типовой отраслевой объект), субъект (12 полей), сети и ПО (категория сети, оператор, цель/способ взаимодействия, ПО/аппаратные средства, ОС, прикладные), безопасность (нарушитель, угрозы, инциденты, показатели критериев, обоснование, орг./тех. меры)
- importer: распознавание полей 236 из опросника, variables: новые переменные шаблонов
This commit is contained in:
2026-08-04 14:42:33 +04:00
parent ce1b56066a
commit 2037925986
7 changed files with 502 additions and 14 deletions
+139 -7
View File
@@ -248,7 +248,11 @@ def _import_187_common(wb, data, settings, log_fn):
def _import_187_is_list(wb, data, settings, log_fn):
"""Импорт объектов КИИ из остальных листов (ОБЪЕКТ №1, №2, ...)."""
"""Импорт объектов КИИ из остальных листов (ОБЪЕКТ №1, №2, ...).
Заполняет поля 236 приказа ФСТЭК: сфера, назначение, тип, архитектура,
сети электросвязи, ПО, СЗИ, сведения о субъекте.
"""
exclude_kws = settings.get('is_sheet_exclude_keywords', ['общие сведения', 'сотрудники'])
is_sheets = []
for sn in wb.sheetnames:
@@ -277,6 +281,20 @@ def _import_187_is_list(wb, data, settings, log_fn):
is_obj = {
'name': '', 'description': '', 'usersList': [],
'isInternet': False, 'defense_tools': [], 'software': '',
# 236 приказ
'sphere': '', 'purpose': '', 'object_type': '', 'architecture': '',
'typical_object': '',
'subject_name': '', 'subject_address': '',
'subject_chief_position': '', 'subject_chief_fio': '',
'subject_security_position': '', 'subject_security_fio': '',
'subject_department': '', 'subject_department_chief': '',
'subject_phone': '', 'subject_email': '',
'subject_inn': '', 'subject_kpp': '',
'net_category': '', 'net_operator': '', 'net_purpose': '', 'net_method': '',
'hw_sw': '', 'os_sw': '', 'app_sw': '',
'attacker_category': '', 'threats': '', 'incidents': '',
'criteria_values': '', 'criteria_justification': '',
'org_measures': '', 'tech_measures': '',
}
defense_keywords = {
@@ -290,23 +308,137 @@ def _import_187_is_list(wb, data, settings, log_fn):
'гарантирован': 'Доверенная загрузка',
}
def _set(field_lower, key, val):
"""Записать значение, если ключевое слово найдено в вопросе."""
if val and 'выбрать' not in field_lower:
is_obj[key] = val
return True
return False
for vals in rows:
field = (vals[0] or '').strip()
field_lower = field.lower()
val_b = clean_value(vals[1]) if len(vals) > 1 else ''
is_checked = val_b.upper() in ('ДА', 'YES', '', '', '1', 'TRUE', 'ЕСТЬ')
# --- Наименование объекта ---
if 'наименование объекта' in field_lower or 'название объекта' in field_lower:
is_obj['name'] = val_b
log_fn(f" Объект КИИ: {val_b}")
continue
if 'описание объекта' in field_lower or 'описание окки' in field_lower:
# --- Описание ---
if 'описание окки' in field_lower or 'описание объекта' in field_lower:
if val_b:
is_obj['description'] = val_b
continue
if 'операционная' in field_lower or 'прикладные программы' in field_lower or 'наименования программно' in field_lower:
if val_b:
is_obj['software'] = (is_obj['software'] + '; ' + val_b) if is_obj['software'] else val_b
# --- Сфера деятельности ---
if 'сфера' in field_lower and 'деятельност' in field_lower:
if _set(field_lower, 'sphere', val_b):
log_fn(f" Сфера: {val_b[:60]}")
continue
# --- Назначение объекта ---
if 'назначение объекта' in field_lower:
if _set(field_lower, 'purpose', val_b):
log_fn(f" Назначение: {val_b[:60]}")
continue
# --- Тип объекта ---
if 'тип объекта' in field_lower:
if _set(field_lower, 'object_type', val_b):
log_fn(f" Тип объекта: {val_b[:60]}")
continue
# --- Архитектура ---
if 'архитектура' in field_lower:
if _set(field_lower, 'architecture', val_b):
log_fn(f" Архитектура: {val_b[:60]}")
continue
# --- Типовой отраслевой объект ---
if 'типового отраслевого' in field_lower or 'типовой отраслевой' in field_lower:
if _set(field_lower, 'typical_object', val_b):
log_fn(f" Типовой объект: {val_b[:60]}")
continue
# --- Субъект ---
if 'наименование организации эксплуатирующ' in field_lower or ('наименование субъекта' in field_lower):
if _set(field_lower, 'subject_name', val_b):
log_fn(f" Субъект: {val_b[:60]}")
continue
if 'адрес местонахождения' in field_lower:
if _set(field_lower, 'subject_address', val_b):
log_fn(f" Адрес субъекта: {val_b[:60]}")
continue
if 'инн лица, эксплуатирующего' in field_lower or 'инн субъекта' in field_lower:
if _set(field_lower, 'subject_inn', val_b):
log_fn(f" ИНН субъекта: {val_b[:60]}")
continue
if 'кпп его обособленных' in field_lower or 'кпп субъекта' in field_lower:
if _set(field_lower, 'subject_kpp', val_b):
log_fn(f" КПП субъекта: {val_b[:60]}")
continue
if 'элемент (компонент) объекта, который эксплуатируется' in field_lower:
if _set(field_lower, 'subject_department', val_b):
log_fn(f" Элемент объекта: {val_b[:60]}")
continue
# --- Сети электросвязи ---
if 'категория сети электросвязи' in field_lower:
if _set(field_lower, 'net_category', val_b):
log_fn(f" Категория сети: {val_b[:60]}")
continue
if 'наименование провайдера' in field_lower or 'оператор связи' in field_lower:
if _set(field_lower, 'net_operator', val_b):
log_fn(f" Оператор: {val_b[:60]}")
continue
if 'цель взаимодействия' in field_lower:
if _set(field_lower, 'net_purpose', val_b):
log_fn(f" Цель взаимодействия: {val_b[:60]}")
continue
if 'способ взаимодействия' in field_lower:
if _set(field_lower, 'net_method', val_b):
log_fn(f" Способ взаимодействия: {val_b[:60]}")
continue
# --- ПО и аппаратные средства ---
if 'наименования программно-аппаратных средств' in field_lower:
if _set(field_lower, 'hw_sw', val_b):
log_fn(f" ПО/аппаратные средства: {val_b[:60]}")
continue
if 'операционная' in field_lower and 'система' in field_lower:
if _set(field_lower, 'os_sw', val_b):
log_fn(f" ОС: {val_b[:60]}")
continue
if 'прикладные программы' in field_lower:
if _set(field_lower, 'app_sw', val_b):
log_fn(f" Прикладные программы: {val_b[:60]}")
continue
if 'общесистемн' in field_lower:
if _set(field_lower, 'os_sw', val_b):
log_fn(f" Общесистемное ПО: {val_b[:60]}")
continue
# --- Безопасность / 236 приказ ---
if 'категория нарушителя' in field_lower:
if _set(field_lower, 'attacker_category', val_b):
log_fn(f" Категория нарушителя: {val_b[:60]}")
continue
if 'основные угрозы' in field_lower or 'угрозы безопасности' in field_lower:
if _set(field_lower, 'threats', val_b):
log_fn(f" Угрозы: {val_b[:60]}")
continue
if 'компьютерных инцидентов' in field_lower or 'инцидент' in field_lower:
if _set(field_lower, 'incidents', val_b):
log_fn(f" Инциденты: {val_b[:60]}")
continue
if 'показателей критериев' in field_lower or 'показатели критериев' in field_lower:
if _set(field_lower, 'criteria_values', val_b):
log_fn(f" Показатели: {val_b[:60]}")
continue
if 'обоснование полученных' in field_lower or 'обоснование значений' in field_lower:
if _set(field_lower, 'criteria_justification', val_b):
log_fn(f" Обоснование: {val_b[:60]}")
continue
if 'организационные меры' in field_lower:
if _set(field_lower, 'org_measures', val_b):
log_fn(f" Орг. меры: {val_b[:60]}")
continue
if 'технические меры' in field_lower:
if _set(field_lower, 'tech_measures', val_b):
log_fn(f" Тех. меры: {val_b[:60]}")
continue
if 'интернет' in field_lower:
is_obj['isInternet'] = is_checked
@@ -321,7 +453,7 @@ def _import_187_is_list(wb, data, settings, log_fn):
if cleaned and cleaned not in is_obj['usersList']:
is_obj['usersList'].append(cleaned)
continue
# Средства защиты
# --- Средства защиты ---
matched = False
for kw, label in defense_keywords.items():
if re.search(kw, field_lower):
@@ -332,7 +464,7 @@ def _import_187_is_list(wb, data, settings, log_fn):
if matched:
continue
if val_b and 'выбрать' not in field_lower and field_lower not in ('значение', 'примечание'):
# Остальные заполненные поля — в описание (адрес, сфера, тип и т.д.)
# Остальные заполненные поля — в описание (адрес, балансовая стоимость и т.д.)
if not is_obj['description']:
is_obj['description'] = f"{field}: {val_b}"
else: