Импорт: доп. ОКВЭД нарезаются по кодам (переносы внутри названий больше не рвут записи), угрозы с переносом внутри названия склеиваются (УБИ.209 «памяти\r\nядра процессора» → одна строка)
This commit is contained in:
+10
-16
@@ -22,7 +22,7 @@ from . import (
|
||||
from .verify import (
|
||||
check_declension_morpher, check_company_dadata,
|
||||
check_declension_ai, check_company_ai,
|
||||
COMPANY_FIELDS, compare_company_values,
|
||||
COMPANY_FIELDS, compare_company_values, normalize_threats,
|
||||
)
|
||||
from .api_settings import load_api_settings, save_api_settings
|
||||
|
||||
@@ -761,8 +761,9 @@ class DokoGenApp:
|
||||
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)
|
||||
from .verify import split_okved_extra
|
||||
_applied = 0
|
||||
for code in comp['okved_extra']:
|
||||
for code in split_okved_extra(comp['okved_extra']):
|
||||
if str(code).strip():
|
||||
self.okved_extra_listbox.insert(tk.END, resolve_okved(str(code).strip(), _tok3))
|
||||
_applied += 1
|
||||
@@ -4661,21 +4662,14 @@ class DokoGenApp:
|
||||
entry.insert(0, resolve_okved(data['okved'], _tok))
|
||||
if data.get('okvedExtra'):
|
||||
if hasattr(self, 'okved_extra_listbox'):
|
||||
from .verify import resolve_okved
|
||||
from .verify import resolve_okved, split_okved_extra
|
||||
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):
|
||||
import re as _re
|
||||
# Перенос строки внутри одной записи («27.32.2 Производство\nсиловых кабелей»)
|
||||
# не должен создавать вторую запись — сначала склеиваем переносы в пробел,
|
||||
# затем режем только по запятой / точке с запятой.
|
||||
extra = _re.sub(r'\s*[\n\r]+\s*', ' ', extra)
|
||||
parts = [p.strip() for p in _re.split(r'[;]+|\s*,\s*', extra) if p.strip()]
|
||||
else:
|
||||
parts = [str(p).strip() for p in extra if str(p).strip()]
|
||||
for p in parts:
|
||||
# Доп. ОКВЭД могут быть склеены с переносами внутри названий
|
||||
# («25.93 — Производство изделий из проволоки\nцепей и пружин 32.12.1 — …») —
|
||||
# нарезаем по кодам ОКВЭД, затем нормализуем каждый в «код название».
|
||||
for p in split_okved_extra(data['okvedExtra']):
|
||||
self.okved_extra_listbox.insert(tk.END, resolve_okved(p, _tok2))
|
||||
|
||||
# Объекты КИИ
|
||||
@@ -4713,8 +4707,8 @@ class DokoGenApp:
|
||||
attacker_category=is_data.get('attacker_category', ''),
|
||||
attacker_level=is_data.get('attacker_level', ''),
|
||||
attacker_types=is_data.get('attacker_types', ''),
|
||||
threats=is_data.get('threats', ''),
|
||||
incidents=is_data.get('incidents', ''),
|
||||
threats=normalize_threats(is_data.get('threats', '')),
|
||||
incidents=normalize_threats(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', ''),
|
||||
|
||||
@@ -544,6 +544,51 @@ def _norm_threat_text(text):
|
||||
return s.lower()
|
||||
|
||||
|
||||
def normalize_threats(text):
|
||||
"""Склеить переносы внутри названий угроз.
|
||||
|
||||
В опросниках встречается «УБИ.209 Угроза … памяти\r\nядра процессора» —
|
||||
перенос строки внутри одного названия. Строка, не начинающаяся с «УБИ.»,
|
||||
считается продолжением предыдущей угрозы.
|
||||
"""
|
||||
if not text:
|
||||
return ''
|
||||
lines = [ln.strip() for ln in str(text).split('\n') if ln.strip()]
|
||||
out = []
|
||||
for ln in lines:
|
||||
if re.match(r'^уби\.?\s*\d+', ln, re.IGNORECASE):
|
||||
out.append(ln)
|
||||
elif out:
|
||||
out[-1] = out[-1] + ' ' + ln
|
||||
else:
|
||||
out.append(ln)
|
||||
return '\n'.join(out)
|
||||
|
||||
|
||||
def split_okved_extra(value):
|
||||
"""Разбить okvedExtra (строка или список строк с переносами) на записи «код название».
|
||||
|
||||
В опросниках доп. ОКВЭД часто идут склеенными:
|
||||
«25.93 — Производство изделий из проволоки\nцепей и пружин 32.12.1 — …»
|
||||
Здесь «цепей и пружин» — продолжение названия 25.93, а 32.12.1 — новый код.
|
||||
Нарезаем по кодам ОКВЭД (двузначный код с точками в начале записи).
|
||||
"""
|
||||
if isinstance(value, (list, tuple)):
|
||||
text = ' '.join(str(x) for x in value)
|
||||
else:
|
||||
text = str(value or '')
|
||||
text = text.replace('\r', ' ').replace('\n', ' ')
|
||||
# Нарезаем по началу кода ОКВЭД: «25.93», «32.12.1», «43.2» …
|
||||
# Перед кодом не должно быть цифры или точки (чтобы не разрезать «25.93» на «25» и «93»)
|
||||
parts = re.split(r'(?<!\d)(?<!\.)(?=\d{2}(?:\.\d+)*\b)', text)
|
||||
out = []
|
||||
for p in parts:
|
||||
p = p.strip().strip('-—– ').strip()
|
||||
if p and re.match(r'^\d{2}(?:\.\d+)*', p):
|
||||
out.append(p)
|
||||
return out
|
||||
|
||||
|
||||
def filter_threats_by_dict(lines, threats_full=None):
|
||||
"""Приводит строки угроз (от ИИ или оператора) к каноническому виду по словарю УБИ.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user