fix: импорт средств защиты — каждая программа отдельным средством

Проблема: clean_value заменял переносы строк на пробелы, из-за чего
список программ в одной ячейке (каждая с новой строки) склеивался
в одну строку. Теперь сырые значения ячеек сохраняются (raw_rows),
разбивка по \n/;/, названия не режутся (KES ≠ KSC).
This commit is contained in:
2026-08-04 15:46:34 +04:00
parent 4e7c3463f4
commit 9489e6a37d
+31 -16
View File
@@ -268,12 +268,15 @@ def _import_187_is_list(wb, data, settings, log_fn):
for sheet_name in is_sheets: for sheet_name in is_sheets:
ws = wb[sheet_name] ws = wb[sheet_name]
rows = [] rows = []
raw_rows = []
for row in ws.iter_rows(min_row=1, values_only=True): for row in ws.iter_rows(min_row=1, values_only=True):
raw_vals = list(row)
vals = [clean_value(c) for c in row] vals = [clean_value(c) for c in row]
field = (vals[0] or '').strip() if vals else '' field = (vals[0] or '').strip() if vals else ''
if not field: if not field:
continue continue
rows.append(vals) rows.append(vals)
raw_rows.append(raw_vals)
if len(rows) < 2: if len(rows) < 2:
continue continue
@@ -313,28 +316,40 @@ def _import_187_is_list(wb, data, settings, log_fn):
return False return False
def _split_entries(text): def _split_entries(text):
"""Разбивает слипшиеся названия СЗИ: по переносам строк, ';' и по границе """Разбивает список средств защиты на ОТДЕЛЬНЫЕ программы.
'цифра + заглавная буква' (напр. '15.1.0.22239Kaspersky' → два названия)."""
if not text: В опроснике каждая программа записана с новой строки (разделитель \n),
также поддерживаются ';' и ','. Название программы при этом НЕ режется
(напр. 'Kaspersky Endpoint Security' остаётся одним средством, KES ≠ KSC).
"""
if text is None:
return [] return []
parts = re.split(r'[\n;]+', text) # 1) разбиваем по переносам строк и ';'
parts = re.split(r'[\n\r;]+', str(text))
out = [] out = []
for p in parts: for p in parts:
p = p.strip() # 2) дополнительно по запятой (если список через запятую)
if not p: for sub in re.split(r'\s*,\s*', p):
continue sub = sub.strip()
# граница: цифра/точка → заглавная буква без пробела if not sub:
sub = re.split(r'(?<=[0-9.])(?=[А-ЯЁA-Z])', p) continue
for s in sub: # 3) запасной вариант: слипшиеся без разделителя «15.1.0.22239Kaspersky»
s = s.strip() sub_parts = re.split(r'(?<=[0-9.])(?=[А-ЯЁA-Z])', sub)
if s and s not in out: for s in sub_parts:
out.append(s) s = s.strip()
if not s:
continue
cleaned = clean_value(s)
if cleaned and cleaned not in out:
out.append(cleaned)
return out return out
for vals in rows: for idx, vals in enumerate(rows):
field = (vals[0] or '').strip() field = (vals[0] or '').strip()
field_lower = field.lower() field_lower = field.lower()
val_b = clean_value(vals[1]) if len(vals) > 1 else '' raw_row = raw_rows[idx] if idx < len(raw_rows) else vals
raw_b = raw_row[1] if len(raw_row) > 1 else None # сырое значение (с переносами строк!)
val_b = clean_value(raw_b) if raw_b is not None else ''
is_checked = val_b.upper() in ('ДА', 'YES', '', '', '1', 'TRUE', 'ЕСТЬ') is_checked = val_b.upper() in ('ДА', 'YES', '', '', '1', 'TRUE', 'ЕСТЬ')
# --- Наименование объекта --- # --- Наименование объекта ---
@@ -479,7 +494,7 @@ def _import_187_is_list(wb, data, settings, log_fn):
for kw, label in defense_keywords.items(): for kw, label in defense_keywords.items():
if re.search(kw, field_lower): if re.search(kw, field_lower):
if val_b and 'выбрать' not in field_lower: if val_b and 'выбрать' not in field_lower:
for tool in _split_entries(val_b): for tool in _split_entries(raw_b if raw_b is not None else val_b):
if tool not in is_obj['defense_tools']: if tool not in is_obj['defense_tools']:
is_obj['defense_tools'].append(tool) is_obj['defense_tools'].append(tool)
matched = True matched = True