Files
dokogen187/dokogen/help_docs.py
T
prog1764 ce1b56066a feat: переделка под ОКИИ (187-ФЗ) — объекты КИИ вместо ИС, категории 1-3, ОКВЭД, убраны ПДн/бумажные носители
- вкладка «Информационные системы» → «Объекты КИИ», убрана «Структура объекта»
- «Тип угроз»/«УЗ» → категория значимости 1/2/3/без категории
- удалены Категории ПДн, кол-во записей, перечень/субъекты/действия с ПДн + словари
- «Пользователи ИС» → «Пользователи ОКИИ», средства защиты оставлены
- вкладка «Бумажные документы» удалена полностью (GUI + логика + модели)
- ОКВЭД: поля во вкладке «Организация», словарь okved.json, выбор галочками, импорт
- нормализация регистра адреса DaData (КАПС → нормальный)
- importer: объекты КИИ (наименование объекта, ПО, СЗИ, пользователи)
2026-08-04 13:58:23 +04:00

282 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""DokoGen — справка и инструкции (Word) + пустой опросник (Excel).
Файлы генерируются при первом обращении и кладутся в папку docs/
рядом с программой (при сборке .exe — рядом с exe):
- Инструкция_пользователя.docx
- Инструкция_администратора.docx
- Опросный_лист_187_ФЗ.xlsx (пустой шаблон)
"""
import os
import sys
import shutil
try:
import docx
from docx.shared import Pt, Cm
from docx.enum.text import WD_ALIGN_PARAGRAPH
DOCX_AVAILABLE = True
except ImportError:
DOCX_AVAILABLE = False
def docs_dir():
"""Папка docs рядом с exe (frozen) или рядом с модулем."""
if getattr(sys, 'frozen', False):
base = os.path.dirname(sys.executable)
else:
base = os.path.dirname(os.path.abspath(__file__))
d = os.path.join(base, 'docs')
os.makedirs(d, exist_ok=True)
return d
def user_manual_path():
return os.path.join(docs_dir(), 'Инструкция_пользователя.docx')
def admin_manual_path():
return os.path.join(docs_dir(), 'Инструкция_администратора.docx')
def variables_reference_path():
return os.path.join(docs_dir(), 'Переменные_шаблонов.docx')
def survey_path():
return os.path.join(docs_dir(), 'Опросный_лист_187_ФЗ.xlsx')
def _h(doc, text, size=14):
p = doc.add_paragraph()
run = p.add_run(text)
run.bold = True
run.font.size = Pt(size)
return p
def _p(doc, text, bold=False):
p = doc.add_paragraph()
run = p.add_run(text)
run.bold = bold
run.font.size = Pt(11)
return p
def _bullet(doc, text):
p = doc.add_paragraph(style='List Bullet')
run = p.add_run(text)
run.font.size = Pt(11)
return p
def _generate_variables_reference(path):
"""Справочник переменных шаблонов (Word)."""
try:
from .variables import VARIABLE_DEFS
except Exception:
VARIABLE_DEFS = []
doc = docx.Document()
_h(doc, 'Переменные шаблонов')
_p(doc, 'Список переменных для шаблонов Word. Переменная подставляется в текст '
'как есть: {{имя_переменной}}. Циклы: <!-- loop:имя --> ... <!-- loop_end -->.')
groups = {'A': 'Общие переменные', 'B': '187-ФЗ (персональные данные)'}
by_group = {'A': [], 'B': []}
for var, group, desc, _ in VARIABLE_DEFS:
by_group.setdefault(group, []).append((var, desc))
for gkey, title in groups.items():
items = by_group.get(gkey, [])
if not items:
continue
_h(doc, title, 12)
for var, desc in items:
_bullet(doc, f'{var}{desc}')
_h(doc, 'Циклы', 12)
_bullet(doc, 'information_systems — объекты КИИ ({{item.name}}, {{item.description}}, {{item.category}}, {{item.defense_tools_list}}, {{item.users}}, {{item.software}} и др.).')
_bullet(doc, 'commission — комиссия ({{item.role}}, {{item.position}}, {{item.fio}}, {{item.fio_initials}}, {{item.fio_short}}, {{item.signature}}).')
_bullet(doc, 'employees_access — сотрудники с доступом ({{item.position}}, {{item.fio}}).')
doc.save(path)
def _generate_user_manual(path):
"""Инструкция пользователя: программа, циклы, переменные, проверки."""
doc = docx.Document()
_h(doc, 'ДоКоГеНеРаТоР — 187-ФЗ')
_h(doc, 'Инструкция пользователя', 13)
_h(doc, '1. Что это за программа', 12)
_p(doc, 'Программа автоматически заполняет шаблоны документов по 187-ФЗ '
'(акты обследования, политики, инструкции, приказы и т.д.) данными '
'об организации, информационных системах, комиссии и сотрудниках. '
'Данные можно ввести вручную на вкладках или импортировать из '
'опросного листа Excel.')
_h(doc, '2. Основные вкладки', 12)
_bullet(doc, 'Организация — реквизиты, адреса, руководитель, склонения названий, проверка данных (Морфер / DaData / ИИ).')
_bullet(doc, 'Объекты КИИ — наименование, описание, категория значимости, средства защиты, пользователи ОКИИ.')
_bullet(doc, 'Комиссия — состав комиссии по категорированию объектов КИИ.')
_bullet(doc, 'Пользователи — сотрудники с доступом к объектам КИИ.')
_bullet(doc, 'Генерация — выбор шаблонов и запуск генерации.')
_bullet(doc, 'Лог — журнал действий, экспорт в файл.')
_h(doc, '3. Переменные в шаблонах', 12)
_p(doc, 'В шаблонах Word используются переменные в двойных фигурных скобках, '
'например {{company_full_name}}, {{inn}}, {{chief_fio_initials}}. '
'Полный список — в пункте меню «Справка → Переменные шаблонов».')
_p(doc, 'Переменные, которые не удалось заменить (нет данных), подсвечиваются '
'КРАСНЫМ маркером. Незаполненная информация заменяется прочерком «—» '
'и подсвечивается ЖЁЛТЫМ.')
_h(doc, '4. Циклы (повторяющиеся блоки)', 12)
_p(doc, 'Если в документе нужно повторить блок для каждой ИС, комиссии, '
'сотрудника или объекта КИИ — используются маркеры цикла:')
_p(doc, '<!-- loop:information_systems --> ... {{item.name}} ... <!-- loop_end -->', bold=True)
_p(doc, 'Доступные циклы:')
_bullet(doc, 'information_systems — объекты КИИ ({{item.name}}, {{item.description}}, {{item.category}}, {{item.defense_tools_list}}, {{item.users}}, {{item.software}} и др.).')
_bullet(doc, 'commission — комиссия ({{item.role}}, {{item.position}}, {{item.fio}}, {{item.fio_initials}}, {{item.fio_short}}, {{item.signature}}).')
_bullet(doc, 'employees_access — сотрудники с доступом ({{item.position}}, {{item.fio}}).')
_p(doc, 'Внутри цикла переменные пишутся через точку: {{item.поле}}. '
'Допускается и синтаксис без точки: {{item_поле}}.')
_h(doc, '5. Импорт из опросника', 12)
_p(doc, 'Меню «Генерация → Импорт из опросника» (или кнопка «📥 Импорт»). '
'Выберите заполненный опросный лист Excel — данные подтянутся '
'автоматически. Что именно импортировать и откуда — настраивается '
'в файле import_settings.json (см. инструкцию администратора).')
_h(doc, '6. Проверка данных', 12)
_bullet(doc, 'Склонение — Морфер 3.0 (бесплатно, без ключа) или ИИ.')
_bullet(doc, 'Реквизиты — DaData (по ИНН) или ИИ.')
_bullet(doc, 'ИИ-результаты помечаются дисклеймером «сгенерировано ИИ — перепроверьте».')
_bullet(doc, 'Ключи API задаются в меню «Файл → Настройки».')
_h(doc, '7. Генерация', 12)
_p(doc, '1) Укажите папку с шаблонами (кнопка «📁 Шаблоны»).\n'
'2) Выберите нужные шаблоны в списке.\n'
'3) Укажите папку для результатов.\n'
'4) Нажмите «⚡ Генерация».')
_p(doc, 'Результаты сохраняются в выбранную папку. Если какой-то документ '
'не создался — смотрите вкладку «Лог»: там будет причина.')
doc.save(path)
def _generate_admin_manual(path):
"""Инструкция администратора: словари, API-ключи, лимиты."""
doc = docx.Document()
_h(doc, 'ДоКоГеНеРаТоР — 187-ФЗ')
_h(doc, 'Инструкция администратора', 13)
_h(doc, '1. Файлы настроек рядом с программой', 12)
_bullet(doc, 'api_settings.json — API-ключи (DaData, ИИ).')
_bullet(doc, 'import_settings.json — словарь импорта: что и откуда брать из опросника.')
_bullet(doc, 'dictionaries/ — справочники: defense_tools.json, okved.json.')
_bullet(doc, 'dokogen.log — журнал работы (пишется автоматически).')
_bullet(doc, 'docs/ — инструкции и пустой опросник (создаются автоматически).')
_h(doc, '2. Словари (папка dictionaries)', 12)
_p(doc, 'JSON-файлы со списками значений для выпадающих списков. '
'Формат — простой массив строк:')
_p(doc, '[\n "Антивирусное ПО",\n "СКЗИ (криптография)",\n "Межсетевой экран"\n]', bold=True)
_p(doc, 'Чтобы добавить значение — откройте файл в Блокноте, добавьте строку '
'через запятую и сохраните. Программа перечитает файл при следующем '
'открытии окна выбора.')
_h(doc, '3. Словарь импорта (import_settings.json)', 12)
_p(doc, 'Определяет, какие поля опросника импортируются и откуда. Каждое правило:')
_p(doc, '{"name": "Полное наименование организации", "var": "fullName", '
'"cell": "\'Общие сведения\'!B2", "keywords": "полное наименование организации"}', bold=True)
_bullet(doc, 'cell — конкретная ячейка (если заполнена — берём оттуда);')
_bullet(doc, 'keywords — регулярное выражение для поиска строки-вопроса в колонке A;')
_bullet(doc, 'var — ключ в данных программы (fullName, inn, kpp, ogrn и т.д.).')
_p(doc, 'Также настраиваются: common_sheet_keyword (лист «Общие сведения»), '
'employees_sheet_keyword (лист «Сотрудники»), is_sheet_exclude_keywords '
'(какие листы НЕ ИС), value_column (колонка значения, 1 = B).')
_h(doc, '4. API-ключи (меню «Файл → Настройки»)', 12)
_p(doc, 'DaData — проверка организации по ИНН/ОГРН (наименование, адрес, КПП, руководитель).')
_bullet(doc, 'Где взять: https://dadata.ru → регистрация → раздел API. Бесплатный тариф ~10 000 запросов в день.')
_bullet(doc, 'Ключ: секция «Статический API-ключ» (формат: буквы и цифры).')
_p(doc, 'ИИ (OpenAI-совместимый: DeepSeek, ChatGPT и др.) — проверка склонений и реквизитов.')
_bullet(doc, 'DeepSeek: https://platform.deepseek.com → API Keys. Модель deepseek-chat. Дешёвая, ключ пополняется деньгами.')
_bullet(doc, 'ChatGPT/OpenAI: https://platform.openai.com → API Keys. Модели gpt-4o-mini, gpt-4o.')
_bullet(doc, 'Базовый URL: для DeepSeek можно оставить пустым; для OpenAI — https://api.openai.com.')
_p(doc, 'Лимиты запросов: зависят от тарифа. DaData — ~10 000/сутки на бесплатном тарифе. '
'DeepSeek/OpenAI — оплата за токены, лимиты настраиваются в личном кабинете. '
'Рекомендуется не превышать несколько сотен проверок в день, чтобы не упереться в лимиты.')
_h(doc, '5. Морфер 3.0', 12)
_p(doc, 'Бесплатный веб-сервис склонения слов и ФИО. Ключ не требуется — '
'программа обращается к https://ws3.morpher.ru автоматически.')
_h(doc, '6. Логи', 12)
_p(doc, 'Все действия (импорт, генерация, обращения к Морфер/DaData/ИИ с ответами) '
'записываются в файл dokogen.log рядом с программой. Экспорт лога — '
'кнопка «💾 Экспорт логов» на вкладке «Лог». При проблемах присылайте '
'этот файл разработчику.')
_h(doc, '7. Сборка .exe', 12)
_p(doc, 'Программа собирается с PyInstaller: pyinstaller --onefile --windowed main.py. '
'Файлы настроек (api_settings.json, import_settings.json, dictionaries/, docs/) '
'создаются автоматически рядом с .exe при первом запуске и остаются '
'редактируемыми.')
doc.save(path)
def _ensure_survey():
"""Копирует пустой опросник в docs/, если его ещё нет."""
target = survey_path()
if os.path.exists(target):
return target
# Ищем шаблон опросника: рядом с программой или встроенный
candidates = [
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'Опросный_лист_187_ФЗ.xlsx'),
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Опросный_лист_187_ФЗ.xlsx'),
]
for c in candidates:
if os.path.exists(c):
shutil.copy(c, target)
return target
return None
def ensure_docs():
"""Создаёт инструкции и опросник при первом обращении."""
created = []
if DOCX_AVAILABLE:
up = user_manual_path()
if not os.path.exists(up):
try:
_generate_user_manual(up)
created.append(up)
except Exception:
pass
ap = admin_manual_path()
if not os.path.exists(ap):
try:
_generate_admin_manual(ap)
created.append(ap)
except Exception:
pass
vp = variables_reference_path()
if not os.path.exists(vp):
try:
_generate_variables_reference(vp)
created.append(vp)
except Exception:
pass
sp = _ensure_survey()
if sp and os.path.exists(sp):
created.append(sp)
return created