орг. меры: словарик заменён на текст заказчика (15 пунктов), автогенерация с учётом ответов по физической безопасности из опросника (да/нет), импорт ответов в модель

This commit is contained in:
LocoAgent
2026-08-05 13:39:24 +04:00
parent 614044a6ca
commit 28fa7edaa8
6 changed files with 407 additions and 53 deletions
+54 -1
View File
@@ -357,7 +357,10 @@ def _build_loop_data(company: Company, is_list: List) -> Dict[str, List[Dict]]:
'incidents': getattr(isys, 'incidents', '') or '',
'criteria_values': getattr(isys, 'criteria_values', '') or '',
'criteria_justification': getattr(isys, 'criteria_justification', '') or '',
'org_measures': getattr(isys, 'org_measures', '') or '',
# Орг. меры: если не заполнены вручную — автогенерация по опроснику
# (с учётом ответов раздела «Физическая безопасность»).
'org_measures': (getattr(isys, 'org_measures', '') or '')
or _build_org_measures_text(company, isys),
'tech_measures': getattr(isys, 'tech_measures', '') or '',
})
loops['information_systems'] = items
@@ -505,6 +508,56 @@ def _calc_criterion_8_9(company, isys, num):
return text, cat
def _build_org_measures_text(company, isys=None):
"""Формирует текст организационных мер из словаря org_measures.json
с учётом ответов раздела «Физическая безопасность» опросника.
Если в опроснике указано «нет» (охрана, сигнализация, тревожная кнопка,
видеонаблюдение, металлические двери и т.п.) — соответствующие пункты
из текста убираются. Пункты, не привязанные к средствам, остаются всегда.
"""
import os as _os
items = _load_json('org_measures.json')
if not isinstance(items, list):
items = []
ps = getattr(company, 'physical_security', None) or {}
def _no(*keys):
"""True, если хотя бы по одному ключу явно указано «нет»/«не имеется»."""
for k in keys:
v = str(ps.get(k) or '').strip().lower()
if v in ('нет', 'не имеется', 'нет,', '0', 'false'):
return True
return False
rules = [
# (подстрока пункта, ключи physical_security, при которых пункт УБИРАЕМ)
('Физическая охрана периметра', ('physicalGuard', 'physicalTurnstile', 'physicalVisitorLog')),
('Имеется система видеонаблюдения', ('physicalVideoSurveillance',)),
('Здания не имеют окон', ('physicalMetalDoors',)),
('охранно-пожарная сигнализация и тревожная кнопка', ('physicalFireAlarm', 'physicalPanicButton')),
('охранно-пожарная сигнализация', ('physicalFireAlarm',)),
('тревожная кнопка', ('physicalPanicButton',)),
('турникетом на проходной', ('physicalTurnstile',)),
('СКУД', ('physicalTurnstile',)),
('учет посетителей', ('physicalVisitorLog',)),
]
out = []
for line in items:
line = str(line).strip()
if not line:
continue
drop = False
for sub, keys in rules:
if sub in line and _no(*keys):
drop = True
break
if not drop:
out.append(line)
return '\n'.join(out) if out else ''
def _build_categorization_indicators(company, is_list):
"""Строки таблицы показателей критериев значимости для шаблона
«Сведения о результатах категорирования» (цикл categorization_indicators).