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:
+254
-2
@@ -255,6 +255,7 @@ class DokoGenApp:
|
||||
("КПП:", "kpp"),
|
||||
("ОГРН:", "ogrn"),
|
||||
("Дата ОГРН:", "ogrn_date"),
|
||||
("Доменное имя и внешний IP:", "domain_name"),
|
||||
]
|
||||
for i, (label, key) in enumerate(addr_fields):
|
||||
ttk.Label(f2, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
|
||||
@@ -589,9 +590,12 @@ class DokoGenApp:
|
||||
for key, label in [('full_name', 'Наименование'), ('short_name', 'Краткое'),
|
||||
('address', 'Адрес'), ('inn', 'ИНН'), ('kpp', 'КПП'),
|
||||
('ogrn', 'ОГРН'), ('ogrn_date', 'Дата ОГРН'),
|
||||
('okved', 'Основной ОКВЭД'),
|
||||
('chief_position', 'Руководитель'), ('chief_fio', 'ФИО')]:
|
||||
if d.get(key):
|
||||
lines.append(f"{label}: {d[key]}")
|
||||
if d.get('okved_extra'):
|
||||
lines.append(f"Доп. ОКВЭД: {', '.join(d['okved_extra'])}")
|
||||
else:
|
||||
# ИИ-рецензия: показываем снимок полей (что ИИ увидел), замечания и предложения
|
||||
lines.append(f"Оценка: {d.get('rating', '')}")
|
||||
@@ -700,6 +704,15 @@ class DokoGenApp:
|
||||
if comp.get(data_key) and ui_key in self._company_entries:
|
||||
self._company_entries[ui_key].delete(0, tk.END)
|
||||
self._company_entries[ui_key].insert(0, comp[data_key])
|
||||
# ОКВЭД из DaData
|
||||
if comp.get('okved') and 'okved' in self._company_entries:
|
||||
self._company_entries['okved'].delete(0, tk.END)
|
||||
self._company_entries['okved'].insert(0, comp['okved'])
|
||||
if comp.get('okved_extra') and hasattr(self, 'okved_extra_listbox'):
|
||||
self.okved_extra_listbox.delete(0, tk.END)
|
||||
for code in comp['okved_extra']:
|
||||
if str(code).strip():
|
||||
self.okved_extra_listbox.insert(tk.END, str(code).strip())
|
||||
if want('chief'):
|
||||
if comp.get('chief_position') and 'chief_position' in self._official_entries:
|
||||
self._official_entries['chief_position'].delete(0, tk.END)
|
||||
@@ -772,6 +785,93 @@ class DokoGenApp:
|
||||
nb2 = ttk.Notebook(self._is_edit_panel)
|
||||
nb2.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
|
||||
|
||||
# ===== Вкладка «Сведения (236 приказ)» =====
|
||||
info_tab = ttk.Frame(nb2)
|
||||
nb2.add(info_tab, text="Сведения (236)")
|
||||
info_frame = ttk.Frame(info_tab, padding=8)
|
||||
info_frame.pack(fill=tk.BOTH, expand=True)
|
||||
info_fields = [
|
||||
("Назначение объекта:", "is_purpose_entry"),
|
||||
("Сфера деятельности:", "is_sphere_entry"),
|
||||
("Тип объекта:", "is_object_type_entry"),
|
||||
("Архитектура объекта:", "is_architecture_entry"),
|
||||
("Типовой отраслевой объект КИИ:", "is_typical_object_entry"),
|
||||
]
|
||||
for i, (label, attr) in enumerate(info_fields):
|
||||
ttk.Label(info_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
|
||||
entry = ttk.Entry(info_frame, width=70)
|
||||
entry.grid(row=i, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
setattr(self, attr, entry)
|
||||
info_frame.columnconfigure(1, weight=1)
|
||||
|
||||
# ===== Вкладка «Субъект» =====
|
||||
subj_tab = ttk.Frame(nb2)
|
||||
nb2.add(subj_tab, text="Субъект")
|
||||
subj_frame = ttk.Frame(subj_tab, padding=8)
|
||||
subj_frame.pack(fill=tk.BOTH, expand=True)
|
||||
subj_fields = [
|
||||
("Наименование субъекта:", "is_subject_name_entry"),
|
||||
("Адрес местонахождения:", "is_subject_address_entry"),
|
||||
("Должность руководителя:", "is_subject_chief_position_entry"),
|
||||
("ФИО руководителя:", "is_subject_chief_fio_entry"),
|
||||
("Должность отв. за безопасность:", "is_subject_security_position_entry"),
|
||||
("ФИО отв. за безопасность:", "is_subject_security_fio_entry"),
|
||||
("Структурное подразделение:", "is_subject_department_entry"),
|
||||
("Руководитель подразделения:", "is_subject_department_chief_entry"),
|
||||
("Телефон:", "is_subject_phone_entry"),
|
||||
("Эл. почта:", "is_subject_email_entry"),
|
||||
("ИНН субъекта:", "is_subject_inn_entry"),
|
||||
("КПП обособленных подразделений:", "is_subject_kpp_entry"),
|
||||
]
|
||||
for i, (label, attr) in enumerate(subj_fields):
|
||||
ttk.Label(subj_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
|
||||
entry = ttk.Entry(subj_frame, width=70)
|
||||
entry.grid(row=i, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
setattr(self, attr, entry)
|
||||
subj_frame.columnconfigure(1, weight=1)
|
||||
|
||||
# ===== Вкладка «Сети и ПО» =====
|
||||
net_tab = ttk.Frame(nb2)
|
||||
nb2.add(net_tab, text="Сети и ПО")
|
||||
net_frame = ttk.Frame(net_tab, padding=8)
|
||||
net_frame.pack(fill=tk.BOTH, expand=True)
|
||||
net_fields = [
|
||||
("Категория сети электросвязи:", "is_net_category_entry"),
|
||||
("Оператор связи/провайдер хостинга:", "is_net_operator_entry"),
|
||||
("Цель взаимодействия с сетью:", "is_net_purpose_entry"),
|
||||
("Способ взаимодействия/тип доступа:", "is_net_method_entry"),
|
||||
("ПО и аппаратные средства:", "is_hw_sw_entry"),
|
||||
("Общесистемное ПО (ОС, виртуализация):", "is_os_sw_entry"),
|
||||
("Прикладные программы:", "is_app_sw_entry"),
|
||||
]
|
||||
for i, (label, attr) in enumerate(net_fields):
|
||||
ttk.Label(net_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
|
||||
entry = ttk.Entry(net_frame, width=70)
|
||||
entry.grid(row=i, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
setattr(self, attr, entry)
|
||||
net_frame.columnconfigure(1, weight=1)
|
||||
|
||||
# ===== Вкладка «Безопасность (236)» =====
|
||||
sec_tab = ttk.Frame(nb2)
|
||||
nb2.add(sec_tab, text="Безопасность (236)")
|
||||
sec_frame = ttk.Frame(sec_tab, padding=8)
|
||||
sec_frame.pack(fill=tk.BOTH, expand=True)
|
||||
sec_fields = [
|
||||
("Категория нарушителя:", "is_attacker_category_entry"),
|
||||
("Основные угрозы БИ:", "is_threats_entry"),
|
||||
("Типы компьютерных инцидентов:", "is_incidents_entry"),
|
||||
("Показатели критериев значимости:", "is_criteria_values_entry"),
|
||||
("Обоснование значений показателей:", "is_criteria_justification_entry"),
|
||||
("Организационные меры:", "is_org_measures_entry"),
|
||||
("Технические меры:", "is_tech_measures_entry"),
|
||||
]
|
||||
for i, (label, attr) in enumerate(sec_fields):
|
||||
ttk.Label(sec_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
|
||||
entry = ttk.Entry(sec_frame, width=70)
|
||||
entry.grid(row=i, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
setattr(self, attr, entry)
|
||||
sec_frame.columnconfigure(1, weight=1)
|
||||
|
||||
# СЗИ
|
||||
def_tab = ttk.Frame(nb2)
|
||||
nb2.add(def_tab, text="Средства защиты")
|
||||
@@ -1021,6 +1121,43 @@ class DokoGenApp:
|
||||
isys.is_local_network = self.is_lan_var.get()
|
||||
isys.is_internet = self.is_internet_var.get()
|
||||
isys.category = self.is_category_var.get()
|
||||
# Поля 236 приказа
|
||||
for attr, model_field in [
|
||||
('is_purpose_entry', 'purpose'),
|
||||
('is_sphere_entry', 'sphere'),
|
||||
('is_object_type_entry', 'object_type'),
|
||||
('is_architecture_entry', 'architecture'),
|
||||
('is_typical_object_entry', 'typical_object'),
|
||||
('is_subject_name_entry', 'subject_name'),
|
||||
('is_subject_address_entry', 'subject_address'),
|
||||
('is_subject_chief_position_entry', 'subject_chief_position'),
|
||||
('is_subject_chief_fio_entry', 'subject_chief_fio'),
|
||||
('is_subject_security_position_entry', 'subject_security_position'),
|
||||
('is_subject_security_fio_entry', 'subject_security_fio'),
|
||||
('is_subject_department_entry', 'subject_department'),
|
||||
('is_subject_department_chief_entry', 'subject_department_chief'),
|
||||
('is_subject_phone_entry', 'subject_phone'),
|
||||
('is_subject_email_entry', 'subject_email'),
|
||||
('is_subject_inn_entry', 'subject_inn'),
|
||||
('is_subject_kpp_entry', 'subject_kpp'),
|
||||
('is_net_category_entry', 'net_category'),
|
||||
('is_net_operator_entry', 'net_operator'),
|
||||
('is_net_purpose_entry', 'net_purpose'),
|
||||
('is_net_method_entry', 'net_method'),
|
||||
('is_hw_sw_entry', 'hw_sw'),
|
||||
('is_os_sw_entry', 'os_sw'),
|
||||
('is_app_sw_entry', 'app_sw'),
|
||||
('is_attacker_category_entry', 'attacker_category'),
|
||||
('is_threats_entry', 'threats'),
|
||||
('is_incidents_entry', 'incidents'),
|
||||
('is_criteria_values_entry', 'criteria_values'),
|
||||
('is_criteria_justification_entry', 'criteria_justification'),
|
||||
('is_org_measures_entry', 'org_measures'),
|
||||
('is_tech_measures_entry', 'tech_measures'),
|
||||
]:
|
||||
w = getattr(self, attr, None)
|
||||
if w is not None:
|
||||
setattr(isys, model_field, w.get().strip())
|
||||
# Списки
|
||||
isys.defense_tools_list = list(self.defense_tools_listbox.get(0, tk.END))
|
||||
isys.users_list = list(self.users_listbox.get(0, tk.END))
|
||||
@@ -1224,6 +1361,45 @@ class DokoGenApp:
|
||||
self.is_internet_var.set(isys.is_internet)
|
||||
self.is_category_var.set(isys.category or "без категории")
|
||||
|
||||
# Поля 236 приказа
|
||||
for attr, model_field in [
|
||||
('is_purpose_entry', 'purpose'),
|
||||
('is_sphere_entry', 'sphere'),
|
||||
('is_object_type_entry', 'object_type'),
|
||||
('is_architecture_entry', 'architecture'),
|
||||
('is_typical_object_entry', 'typical_object'),
|
||||
('is_subject_name_entry', 'subject_name'),
|
||||
('is_subject_address_entry', 'subject_address'),
|
||||
('is_subject_chief_position_entry', 'subject_chief_position'),
|
||||
('is_subject_chief_fio_entry', 'subject_chief_fio'),
|
||||
('is_subject_security_position_entry', 'subject_security_position'),
|
||||
('is_subject_security_fio_entry', 'subject_security_fio'),
|
||||
('is_subject_department_entry', 'subject_department'),
|
||||
('is_subject_department_chief_entry', 'subject_department_chief'),
|
||||
('is_subject_phone_entry', 'subject_phone'),
|
||||
('is_subject_email_entry', 'subject_email'),
|
||||
('is_subject_inn_entry', 'subject_inn'),
|
||||
('is_subject_kpp_entry', 'subject_kpp'),
|
||||
('is_net_category_entry', 'net_category'),
|
||||
('is_net_operator_entry', 'net_operator'),
|
||||
('is_net_purpose_entry', 'net_purpose'),
|
||||
('is_net_method_entry', 'net_method'),
|
||||
('is_hw_sw_entry', 'hw_sw'),
|
||||
('is_os_sw_entry', 'os_sw'),
|
||||
('is_app_sw_entry', 'app_sw'),
|
||||
('is_attacker_category_entry', 'attacker_category'),
|
||||
('is_threats_entry', 'threats'),
|
||||
('is_incidents_entry', 'incidents'),
|
||||
('is_criteria_values_entry', 'criteria_values'),
|
||||
('is_criteria_justification_entry', 'criteria_justification'),
|
||||
('is_org_measures_entry', 'org_measures'),
|
||||
('is_tech_measures_entry', 'tech_measures'),
|
||||
]:
|
||||
w = getattr(self, attr, None)
|
||||
if w is not None:
|
||||
w.delete(0, tk.END)
|
||||
w.insert(0, getattr(isys, model_field, '') or '')
|
||||
|
||||
# Списки
|
||||
for lb, items in [
|
||||
(self.defense_tools_listbox, isys.defense_tools_list or []),
|
||||
@@ -1257,6 +1433,37 @@ class DokoGenApp:
|
||||
category=src.category,
|
||||
defense_tools_list=list(src.defense_tools_list),
|
||||
users_list=list(src.users_list),
|
||||
purpose=src.purpose,
|
||||
sphere=src.sphere,
|
||||
object_type=src.object_type,
|
||||
architecture=src.architecture,
|
||||
typical_object=src.typical_object,
|
||||
subject_name=src.subject_name,
|
||||
subject_address=src.subject_address,
|
||||
subject_chief_position=src.subject_chief_position,
|
||||
subject_chief_fio=src.subject_chief_fio,
|
||||
subject_security_position=src.subject_security_position,
|
||||
subject_security_fio=src.subject_security_fio,
|
||||
subject_department=src.subject_department,
|
||||
subject_department_chief=src.subject_department_chief,
|
||||
subject_phone=src.subject_phone,
|
||||
subject_email=src.subject_email,
|
||||
subject_inn=src.subject_inn,
|
||||
subject_kpp=src.subject_kpp,
|
||||
net_category=src.net_category,
|
||||
net_operator=src.net_operator,
|
||||
net_purpose=src.net_purpose,
|
||||
net_method=src.net_method,
|
||||
hw_sw=src.hw_sw,
|
||||
os_sw=src.os_sw,
|
||||
app_sw=src.app_sw,
|
||||
attacker_category=src.attacker_category,
|
||||
threats=src.threats,
|
||||
incidents=src.incidents,
|
||||
criteria_values=src.criteria_values,
|
||||
criteria_justification=src.criteria_justification,
|
||||
org_measures=src.org_measures,
|
||||
tech_measures=src.tech_measures,
|
||||
)
|
||||
self.model.information_systems.append(copy)
|
||||
self._refresh_is_listbox()
|
||||
@@ -1745,6 +1952,20 @@ class DokoGenApp:
|
||||
if data.get('ispdnDepartment'):
|
||||
self.model.security_department = data['ispdnDepartment']
|
||||
|
||||
# Доменное имя и внешний сетевой адрес
|
||||
if data.get('domainName'):
|
||||
entry = self._company_entries.get('domain_name')
|
||||
if entry:
|
||||
entry.delete(0, tk.END)
|
||||
entry.insert(0, data['domainName'])
|
||||
|
||||
# Доменное имя и внешний сетевой адрес
|
||||
if data.get('domainName'):
|
||||
entry = self._company_entries.get('domain_name')
|
||||
if entry:
|
||||
entry.delete(0, tk.END)
|
||||
entry.insert(0, data['domainName'])
|
||||
|
||||
# ОКВЭД (основной и дополнительные)
|
||||
if data.get('okved'):
|
||||
entry = self._company_entries.get('okved')
|
||||
@@ -1756,7 +1977,8 @@ class DokoGenApp:
|
||||
self.okved_extra_listbox.delete(0, tk.END)
|
||||
extra = data['okvedExtra']
|
||||
if isinstance(extra, str):
|
||||
parts = [p.strip() for p in extra.replace(';', '\n').split('\n') if p.strip()]
|
||||
import re as _re
|
||||
parts = [p.strip() for p in _re.split(r'[;,\n]+', extra) if p.strip()]
|
||||
else:
|
||||
parts = [str(p).strip() for p in extra if str(p).strip()]
|
||||
for p in parts:
|
||||
@@ -1774,9 +1996,39 @@ class DokoGenApp:
|
||||
category=is_data.get('category', ''),
|
||||
defense_tools_list=is_data.get('defense_tools', []),
|
||||
users_list=is_data.get('usersList', []),
|
||||
purpose=is_data.get('purpose', is_data.get('description', '')),
|
||||
purpose=is_data.get('purpose', ''),
|
||||
structure=is_data.get('structure', ''),
|
||||
software=is_data.get('software', ''),
|
||||
sphere=is_data.get('sphere', ''),
|
||||
object_type=is_data.get('object_type', ''),
|
||||
architecture=is_data.get('architecture', ''),
|
||||
typical_object=is_data.get('typical_object', ''),
|
||||
subject_name=is_data.get('subject_name', ''),
|
||||
subject_address=is_data.get('subject_address', ''),
|
||||
subject_chief_position=is_data.get('subject_chief_position', ''),
|
||||
subject_chief_fio=is_data.get('subject_chief_fio', ''),
|
||||
subject_security_position=is_data.get('subject_security_position', ''),
|
||||
subject_security_fio=is_data.get('subject_security_fio', ''),
|
||||
subject_department=is_data.get('subject_department', ''),
|
||||
subject_department_chief=is_data.get('subject_department_chief', ''),
|
||||
subject_phone=is_data.get('subject_phone', ''),
|
||||
subject_email=is_data.get('subject_email', ''),
|
||||
subject_inn=is_data.get('subject_inn', ''),
|
||||
subject_kpp=is_data.get('subject_kpp', ''),
|
||||
net_category=is_data.get('net_category', ''),
|
||||
net_operator=is_data.get('net_operator', ''),
|
||||
net_purpose=is_data.get('net_purpose', ''),
|
||||
net_method=is_data.get('net_method', ''),
|
||||
hw_sw=is_data.get('hw_sw', ''),
|
||||
os_sw=is_data.get('os_sw', ''),
|
||||
app_sw=is_data.get('app_sw', ''),
|
||||
attacker_category=is_data.get('attacker_category', ''),
|
||||
threats=is_data.get('threats', ''),
|
||||
incidents=is_data.get('incidents', ''),
|
||||
criteria_values=is_data.get('criteria_values', ''),
|
||||
criteria_justification=is_data.get('criteria_justification', ''),
|
||||
org_measures=is_data.get('org_measures', ''),
|
||||
tech_measures=is_data.get('tech_measures', ''),
|
||||
)
|
||||
self.model.information_systems.append(isys)
|
||||
self._refresh_is_listbox()
|
||||
|
||||
Reference in New Issue
Block a user