fix: ОКВЭД импорт/DaData/словарь+интернет, доменное имя, вкладка ОКИИ → вложенные вкладки, словарики, СЗИ разбивка, адрес отдельно
- ОКВЭД: resolve_okved (словарь okved.json + DaData suggest okved2), применяется при импорте и DaData; галочки «ОКВЭД осн./доп.» в «что применять» - DaData: показ и подстановка доп. ОКВЭД - доменное имя: поле во вкладке «Организация» + импорт - вкладка «Объекты КИИ»: сверху Наименование/Описание/Категория, остальное вкладками: Основное (назначение, сфера, тип, архитектура, типовой отраслевой объект — со словариками и выпадающими списками), Субъект, Сети и ПО, Безопасность (236), СЗИ, Пользователи ОКИИ - новые словари: spheres.json, object_types.json, architectures.json, typical_objects.json - адрес объекта — в отдельное поле (не в описание) - СЗИ: разбивка слипшихся названий (Kaspersky...)
This commit is contained in:
+122
-66
@@ -359,6 +359,8 @@ class DokoGenApp:
|
||||
'address': tk.BooleanVar(value=True),
|
||||
'requisites': tk.BooleanVar(value=True),
|
||||
'chief': tk.BooleanVar(value=True),
|
||||
'okved': tk.BooleanVar(value=True),
|
||||
'okved_extra': tk.BooleanVar(value=True),
|
||||
}
|
||||
apply_row = ttk.Frame(right)
|
||||
apply_row.pack(fill=tk.X, pady=(4, 0))
|
||||
@@ -368,6 +370,11 @@ class DokoGenApp:
|
||||
ttk.Checkbutton(apply_row, text="адрес", variable=self._apply_flags['address']).pack(side=tk.LEFT)
|
||||
ttk.Checkbutton(apply_row, text="ИНН/КПП/ОГРН", variable=self._apply_flags['requisites']).pack(side=tk.LEFT)
|
||||
ttk.Checkbutton(apply_row, text="руковод.", variable=self._apply_flags['chief']).pack(side=tk.LEFT)
|
||||
apply_row2 = ttk.Frame(right)
|
||||
apply_row2.pack(fill=tk.X, pady=(2, 0))
|
||||
ttk.Label(apply_row2, text="", font=('', 8), width=10).pack(side=tk.LEFT)
|
||||
ttk.Checkbutton(apply_row2, text="ОКВЭД осн.", variable=self._apply_flags['okved']).pack(side=tk.LEFT)
|
||||
ttk.Checkbutton(apply_row2, text="ОКВЭД доп.", variable=self._apply_flags['okved_extra']).pack(side=tk.LEFT)
|
||||
self._verify_result = None
|
||||
|
||||
# ---------- ПРОВЕРКА ДАННЫХ (Морфер / DaData / ИИ) ----------
|
||||
@@ -704,15 +711,18 @@ 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:
|
||||
# ОКВЭД из DaData (с названием из словаря/интернета)
|
||||
from .verify import resolve_okved
|
||||
from .api_settings import load_api_settings as _las3
|
||||
_tok3 = (_las3().get('dadata_token') or '')
|
||||
if want('okved') and 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._company_entries['okved'].insert(0, resolve_okved(comp['okved'], _tok3))
|
||||
if want('okved_extra') and 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())
|
||||
self.okved_extra_listbox.insert(tk.END, resolve_okved(str(code).strip(), _tok3))
|
||||
if want('chief'):
|
||||
if comp.get('chief_position') and 'chief_position' in self._official_entries:
|
||||
self._official_entries['chief_position'].delete(0, tk.END)
|
||||
@@ -748,61 +758,87 @@ class DokoGenApp:
|
||||
fields_frame = ttk.Frame(self._is_edit_panel, padding=10)
|
||||
fields_frame.pack(fill=tk.X)
|
||||
|
||||
# Основные поля
|
||||
# Основные поля (сверху — только название, описание, категория)
|
||||
ttk.Label(fields_frame, text="Наименование:").grid(row=0, column=0, sticky=tk.W, pady=2)
|
||||
self.is_name_entry = ttk.Entry(fields_frame, width=55)
|
||||
self.is_name_entry = ttk.Entry(fields_frame, width=60)
|
||||
self.is_name_entry.grid(row=0, column=1, padx=10, sticky=tk.EW)
|
||||
|
||||
ttk.Label(fields_frame, text="Описание:").grid(row=1, column=0, sticky=tk.W, pady=2)
|
||||
self.is_description_entry = ttk.Entry(fields_frame, width=55)
|
||||
self.is_description_entry = ttk.Entry(fields_frame, width=60)
|
||||
self.is_description_entry.grid(row=1, column=1, padx=10, sticky=tk.EW)
|
||||
|
||||
# Чекбоксы
|
||||
chk_frame = ttk.Frame(fields_frame)
|
||||
chk_frame.grid(row=2, column=1, sticky=tk.W, pady=5)
|
||||
self.is_lan_var = tk.BooleanVar()
|
||||
ttk.Checkbutton(chk_frame, text="ЛВС", variable=self.is_lan_var).pack(side=tk.LEFT, padx=5)
|
||||
self.is_internet_var = tk.BooleanVar()
|
||||
ttk.Checkbutton(chk_frame, text="Интернет", variable=self.is_internet_var).pack(side=tk.LEFT, padx=5)
|
||||
|
||||
# Категория значимости объекта КИИ
|
||||
self.is_category_var = tk.StringVar(value="без категории")
|
||||
ttk.Label(fields_frame, text="Категория значимости:").grid(row=3, column=0, sticky=tk.W, pady=2)
|
||||
ttk.Label(fields_frame, text="Категория значимости:").grid(row=2, column=0, sticky=tk.W, pady=2)
|
||||
cat_frame = ttk.Frame(fields_frame)
|
||||
cat_frame.grid(row=3, column=1, sticky=tk.W, padx=10)
|
||||
cat_frame.grid(row=2, column=1, sticky=tk.W, padx=10)
|
||||
for val in ["1", "2", "3", "без категории"]:
|
||||
ttk.Radiobutton(cat_frame, text=val, variable=self.is_category_var,
|
||||
value=val).pack(side=tk.LEFT, padx=3)
|
||||
|
||||
# Программное обеспечение
|
||||
ttk.Label(fields_frame, text="Программное обеспечение:").grid(row=4, column=0, sticky=tk.W, pady=2)
|
||||
self.is_software_entry = ttk.Entry(fields_frame, width=55)
|
||||
self.is_software_entry.grid(row=4, column=1, padx=10, sticky=tk.EW)
|
||||
|
||||
fields_frame.columnconfigure(1, weight=1)
|
||||
|
||||
# Вложенные списки
|
||||
# ---- Вложенные вкладки ----
|
||||
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)
|
||||
# ===== Вкладка «Основное» =====
|
||||
main_tab = ttk.Frame(nb2)
|
||||
nb2.add(main_tab, text="Основное")
|
||||
main_frame = ttk.Frame(main_tab, padding=8)
|
||||
main_frame.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
# Назначение объекта
|
||||
ttk.Label(main_frame, text="Назначение объекта:").grid(row=0, column=0, sticky=tk.W, pady=2)
|
||||
self.is_purpose_entry = ttk.Entry(main_frame, width=70)
|
||||
self.is_purpose_entry.grid(row=0, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
|
||||
# Сфера деятельности — словарик + выпадающий список
|
||||
ttk.Label(main_frame, text="Сфера деятельности:").grid(row=1, column=0, sticky=tk.W, pady=2)
|
||||
self.is_sphere_combo = ttk.Combobox(main_frame, width=68)
|
||||
self.is_sphere_combo.grid(row=1, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
try:
|
||||
import json as _json
|
||||
_sp = os.path.join(os.path.dirname(__file__), 'dictionaries', 'spheres.json')
|
||||
with open(_sp, encoding='utf-8') as _f:
|
||||
self.is_sphere_combo['values'] = _json.load(_f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Тип объекта — словарик + выпадающий список
|
||||
ttk.Label(main_frame, text="Тип объекта:").grid(row=2, column=0, sticky=tk.W, pady=2)
|
||||
self.is_object_type_combo = ttk.Combobox(main_frame, width=68)
|
||||
self.is_object_type_combo.grid(row=2, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
try:
|
||||
_ot = os.path.join(os.path.dirname(__file__), 'dictionaries', 'object_types.json')
|
||||
with open(_ot, encoding='utf-8') as _f:
|
||||
self.is_object_type_combo['values'] = _json.load(_f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Архитектура объекта — словарик + выпадающий список
|
||||
ttk.Label(main_frame, text="Архитектура объекта:").grid(row=3, column=0, sticky=tk.W, pady=2)
|
||||
self.is_architecture_combo = ttk.Combobox(main_frame, width=68)
|
||||
self.is_architecture_combo.grid(row=3, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
try:
|
||||
_ar = os.path.join(os.path.dirname(__file__), 'dictionaries', 'architectures.json')
|
||||
with open(_ar, encoding='utf-8') as _f:
|
||||
self.is_architecture_combo['values'] = _json.load(_f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# Типовой отраслевой объект КИИ — словарик + выпадающий список
|
||||
ttk.Label(main_frame, text="Типовой отраслевой объект КИИ:").grid(row=4, column=0, sticky=tk.W, pady=2)
|
||||
self.is_typical_object_combo = ttk.Combobox(main_frame, width=68)
|
||||
self.is_typical_object_combo.grid(row=4, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
try:
|
||||
_to = os.path.join(os.path.dirname(__file__), 'dictionaries', 'typical_objects.json')
|
||||
with open(_to, encoding='utf-8') as _f:
|
||||
self.is_typical_object_combo['values'] = _json.load(_f)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
main_frame.columnconfigure(1, weight=1)
|
||||
|
||||
# ===== Вкладка «Субъект» =====
|
||||
subj_tab = ttk.Frame(nb2)
|
||||
@@ -835,19 +871,29 @@ class DokoGenApp:
|
||||
nb2.add(net_tab, text="Сети и ПО")
|
||||
net_frame = ttk.Frame(net_tab, padding=8)
|
||||
net_frame.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
# ЛВС / Интернет
|
||||
chk = ttk.Frame(net_frame)
|
||||
chk.grid(row=0, column=0, columnspan=2, sticky=tk.W, pady=2)
|
||||
self.is_lan_var = tk.BooleanVar()
|
||||
ttk.Checkbutton(chk, text="ЛВС", variable=self.is_lan_var).pack(side=tk.LEFT, padx=5)
|
||||
self.is_internet_var = tk.BooleanVar()
|
||||
ttk.Checkbutton(chk, text="Интернет", variable=self.is_internet_var).pack(side=tk.LEFT, padx=5)
|
||||
|
||||
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"),
|
||||
("Категория сети электросвязи:", "is_net_category_entry", 1),
|
||||
("Оператор связи/провайдер хостинга:", "is_net_operator_entry", 2),
|
||||
("Цель взаимодействия с сетью:", "is_net_purpose_entry", 3),
|
||||
("Способ взаимодействия/тип доступа:", "is_net_method_entry", 4),
|
||||
("ПО и аппаратные средства:", "is_hw_sw_entry", 5),
|
||||
("Общесистемное ПО (ОС, виртуализация):", "is_os_sw_entry", 6),
|
||||
("Прикладные программы:", "is_app_sw_entry", 7),
|
||||
("Программное обеспечение:", "is_software_entry", 8),
|
||||
]
|
||||
for i, (label, attr) in enumerate(net_fields):
|
||||
ttk.Label(net_frame, text=label).grid(row=i, column=0, sticky=tk.W, pady=2)
|
||||
for label, attr, row in net_fields:
|
||||
ttk.Label(net_frame, text=label).grid(row=row, 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)
|
||||
entry.grid(row=row, column=1, padx=8, sticky=tk.EW, pady=1)
|
||||
setattr(self, attr, entry)
|
||||
net_frame.columnconfigure(1, weight=1)
|
||||
|
||||
@@ -872,7 +918,7 @@ class DokoGenApp:
|
||||
setattr(self, attr, entry)
|
||||
sec_frame.columnconfigure(1, weight=1)
|
||||
|
||||
# СЗИ
|
||||
# ===== Вкладка «Средства защиты» =====
|
||||
def_tab = ttk.Frame(nb2)
|
||||
nb2.add(def_tab, text="Средства защиты")
|
||||
def_btn_frame = ttk.Frame(def_tab)
|
||||
@@ -883,7 +929,7 @@ class DokoGenApp:
|
||||
self.defense_tools_listbox = tk.Listbox(def_tab, height=6)
|
||||
self.defense_tools_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||
|
||||
# Пользователи ОКИИ
|
||||
# ===== Вкладка «Пользователи ОКИИ» =====
|
||||
user_tab = ttk.Frame(nb2)
|
||||
nb2.add(user_tab, text="Пользователи ОКИИ")
|
||||
self.users_listbox = tk.Listbox(user_tab, height=6)
|
||||
@@ -1124,10 +1170,10 @@ class DokoGenApp:
|
||||
# Поля 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_sphere_combo', 'sphere'),
|
||||
('is_object_type_combo', 'object_type'),
|
||||
('is_architecture_combo', 'architecture'),
|
||||
('is_typical_object_combo', 'typical_object'),
|
||||
('is_subject_name_entry', 'subject_name'),
|
||||
('is_subject_address_entry', 'subject_address'),
|
||||
('is_subject_chief_position_entry', 'subject_chief_position'),
|
||||
@@ -1364,10 +1410,10 @@ class DokoGenApp:
|
||||
# Поля 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_sphere_combo', 'sphere'),
|
||||
('is_object_type_combo', 'object_type'),
|
||||
('is_architecture_combo', 'architecture'),
|
||||
('is_typical_object_combo', 'typical_object'),
|
||||
('is_subject_name_entry', 'subject_name'),
|
||||
('is_subject_address_entry', 'subject_address'),
|
||||
('is_subject_chief_position_entry', 'subject_chief_position'),
|
||||
@@ -1397,8 +1443,12 @@ class DokoGenApp:
|
||||
]:
|
||||
w = getattr(self, attr, None)
|
||||
if w is not None:
|
||||
w.delete(0, tk.END)
|
||||
w.insert(0, getattr(isys, model_field, '') or '')
|
||||
val = getattr(isys, model_field, '') or ''
|
||||
if isinstance(w, ttk.Combobox):
|
||||
w.set(val)
|
||||
else:
|
||||
w.delete(0, tk.END)
|
||||
w.insert(0, val)
|
||||
|
||||
# Списки
|
||||
for lb, items in [
|
||||
@@ -1970,10 +2020,16 @@ class DokoGenApp:
|
||||
if data.get('okved'):
|
||||
entry = self._company_entries.get('okved')
|
||||
if entry:
|
||||
from .verify import resolve_okved
|
||||
from .api_settings import load_api_settings as _las
|
||||
_tok = (_las().get('dadata_token') or '')
|
||||
entry.delete(0, tk.END)
|
||||
entry.insert(0, data['okved'])
|
||||
entry.insert(0, resolve_okved(data['okved'], _tok))
|
||||
if data.get('okvedExtra'):
|
||||
if hasattr(self, 'okved_extra_listbox'):
|
||||
from .verify import resolve_okved
|
||||
from .api_settings import load_api_settings as _las2
|
||||
_tok2 = (_las2().get('dadata_token') or '')
|
||||
self.okved_extra_listbox.delete(0, tk.END)
|
||||
extra = data['okvedExtra']
|
||||
if isinstance(extra, str):
|
||||
@@ -1982,7 +2038,7 @@ class DokoGenApp:
|
||||
else:
|
||||
parts = [str(p).strip() for p in extra if str(p).strip()]
|
||||
for p in parts:
|
||||
self.okved_extra_listbox.insert(tk.END, p)
|
||||
self.okved_extra_listbox.insert(tk.END, resolve_okved(p, _tok2))
|
||||
|
||||
# Объекты КИИ
|
||||
if data.get('informationSystems'):
|
||||
|
||||
Reference in New Issue
Block a user