Compare commits

..
10 Commits
Author SHA1 Message Date
prog1764 de522360b8 feat: ребрендинг под dokogenMU (основа из dokogen187) 2026-08-03 23:45:16 +04:00
prog1764 da4946cb59 feat: ребрендинг под 187-ФЗ (КИИ)
- Все упоминания 152-ФЗ заменены на 187-ФЗ (заголовок окна, справка,
  импорт, переменные, docstring'и, spec)
- import_152fz -> import_187fz, direction '152fz' -> '187fz'
- autosave_152 -> autosave_187
- Опросный_лист_152_ФЗ.xlsx -> Опросный_лист_187_ФЗ.xlsx
- Промпт ИИ: 'юрист по защите персональных данных (152-ФЗ)' -> 187-ФЗ
2026-08-03 23:25:18 +04:00
prog1764 ac122451b3 fix: _set_app_icon разрывал __init__ (NameError: root is not defined) 2026-08-03 22:29:54 +04:00
prog1764 eee1842421 feat: иконка на окне программы (заголовок/панель задач) + в ресурсах exe 2026-08-03 22:05:44 +04:00
kneon223557 bb987894b2 Обновить dokogen/api_settings.py 2026-08-03 22:03:38 +04:00
kneon223557 19b74fc72a Обновить dokogen/dictionaries/pd_items.json 2026-08-03 22:02:28 +04:00
kneon223557 5a407f2568 Обновить dokogen/dictionaries/pd_categories.json 2026-08-03 22:01:52 +04:00
kneon223557 faefa786c5 Обновить dokogen/dictionaries/pd_actions.json 2026-08-03 22:01:20 +04:00
prog1764 4893899d5d feat: иконка — 64/128px из нового оригинала (512x512) 2026-08-03 21:59:26 +04:00
prog1764 73edfdf533 feat: иконка — 48px из нового оригинала (512) 2026-08-03 21:58:12 +04:00
16 changed files with 132 additions and 90 deletions
+3 -1
View File
@@ -11,8 +11,10 @@ from PyInstaller.utils.hooks import collect_data_files, collect_submodules
datas = [
# Справочники (defense_tools.json, pd_actions.json, pd_items.json, pd_categories.json)
('dokogen/dictionaries', 'dokogen/dictionaries'),
# Пустой опросник 152-ФЗ (для «Справка → Пустой опросник»)
# Пустой опросник MU (для «Справка → Пустой опросник»)
('dokogen/data', 'dokogen/data'),
# Иконка приложения (для окна программы в exe)
('dokogen/icon.ico', 'dokogen'),
]
# ---------- Словари pymorphy3 (обязательно!) ----------
+1 -1
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
"""DokoGen — Пакет генератора документов 152-ФЗ"""
"""DokoGen — Пакет генератора документов MU"""
from .models import Company, CommissionMember, InformationSystem, PaperDocument
from .declension import inflect_name, decline, company_name_decline, get_short_fio, get_initials
+2 -2
View File
@@ -14,8 +14,8 @@ import sys
import json
DEFAULT_SETTINGS = {
'dadata_token': '',
'ai_api_key': '',
'dadata_token': '431aa11706bf83f571cef0319259289aa750bcb1',
'ai_api_key': 'sk-3c7e6673f245412697d0e14b6096435f',
'ai_model': 'deepseek-chat',
'ai_base_url': 'https://api.deepseek.com',
}
+15 -20
View File
@@ -1,22 +1,17 @@
[
"Сбор персональных данных",
"Запись персональных данных",
"Систематизация персональных данных",
"Накопление персональных данных",
"Хранение персональных данных",
"Уточнение (обновление, изменение) персональных данных",
"Извлечение персональных данных",
"Использование персональных данных",
"Передача (распространение, предоставление, доступ) персональных данных",
"Обезличивание персональных данных",
"Блокирование персональных данных",
"Удаление персональных данных",
"Уничтожение персональных данных",
"Трансграничная передача персональных данных",
"Автоматизированная обработка персональных данных",
"Неавтоматизированная обработка персональных данных",
"Смешанная обработка персональных данных",
"Формирование и ведение баз данных",
"Передача данных третьим лицам",
"Внутренняя передача данных между подразделениями"
"сбор",
"систематизация",
"хранение",
"извлечение",
"передача (предоставление доступа)",
"блокирование",
"уничтожение",
"запись",
"накопление",
"уточнение (обновление, изменение)",
"использование",
"обезличивание",
"удаление",
"распространение",
"иные действия"
]
+14 -6
View File
@@ -1,8 +1,16 @@
[
"работники оператора",
"клиенты",
"контрагенты",
"родственники работников",
"соискатели",
"иные лица"
"Сотрудникам организации",
"Соискателям",
"Родственникам сотрудников",
"Уволенным сотрудникам",
"Контрагентам",
"Представителям контрагентов",
"Клиентам",
"Посетителям сайта",
"Выгодоприобретателям по договорам",
"Субъект персональных данных, предоставивший согласие на трансграничную передачу персональных данных",
"Учащимя",
"Студентам",
"Законным представителям",
"Иным категориям субъектов персональных данных, персональные данные которых обрабатываются"
]
+38 -22
View File
@@ -1,28 +1,44 @@
[
"Фамилия, имя, отчество",
"Фамилия, Имя, Отчество",
"Год рождения",
"Месяц рождения",
"Дата рождения",
"Место рождения",
"Паспортные данные",
"Адрес регистрации",
"Адрес проживания",
"ИНН",
"СНИЛС",
"Номер телефона",
"Адрес электронной почты",
"Образование",
"Профессия",
"Сведения о доходах",
"Семейное положение",
"Состав семьи",
"Состояние здоровья",
"Национальность",
"Гражданство",
"Сведения о судимости",
"Фотография",
"Биометрические данные",
"Рабочий e-mail",
"Социальное положение",
"Имущественное положение",
"Сведения о доходах",
"Пол",
"Адрес электронной почты",
"Адрес места жительства",
"Адрес регистрации",
"Номер телефона",
"Страховой номер индивидуального лицевого счета (СНИЛС)",
"Идентификационный номер налогоплательщика (ИНН);",
"Сведения о гражданстве",
"Данные документа, удостоверяющего личность",
"Данные водительского удостоверения",
"Данные документа, удостоверяющего личность за пределами Российской Федерации",
"Данные документа, содержащиеся в свидетельстве о рождении",
"Реквизиты банковских карт",
"Номер расчетного счета",
"Номер лицевого счета",
"Профессия",
"Должность",
"Табельный номер",
"Сведения о воинском учете",
"Сведения о командировках"
"Сведения о трудовой деятельности (в том числе стаж работы, данные о трудовой занятости на текущее время с указанием наименования и расчетного счета организации)",
"Сведения об отношении к воинской обязанности, о воинском учете",
"Иные персональные данные",
"Сведения, собираемые посредством метрических программ (например, Яндекс.Метрика)",
"Сведения об образовании",
"Фото-видео изображение лица",
"Данные голоса человека",
"Сведения о состоянии здоровья",
"Национальная принадлежность",
"Политические взгляды",
"Религиозные или философские убеждения",
"Сведения о судимости",
"Данные изображения лица, полученные с помощью фото- видео устройств, на основании которых можно установить его личность и которые используются оператором для установления личности субъекта персональных данных (биометрия)",
"Данные голоса человека, на основании которых можно установить его личность и которые используются оператором для установления личности субъекта персональных данных (биометрия)",
"Изображение папиллярных узоров пальцев рук",
"Иные биометрические персональные данные"
]
+8 -8
View File
@@ -5,7 +5,7 @@
рядом с программой (при сборке .exe рядом с exe):
- Инструкция_пользователя.docx
- Инструкция_администратора.docx
- Опросный_лист_152_ФЗ.xlsx (пустой шаблон)
- Опросный_лист_MU.xlsx (пустой шаблон)
"""
import os
@@ -45,7 +45,7 @@ def variables_reference_path():
def survey_path():
return os.path.join(docs_dir(), 'Опросный_лист_152_ФЗ.xlsx')
return os.path.join(docs_dir(), 'Опросный_лист_MU.xlsx')
def _h(doc, text, size=14):
@@ -83,7 +83,7 @@ def _generate_variables_reference(path):
_p(doc, 'Список переменных для шаблонов Word. Переменная подставляется в текст '
'как есть: {{имя_переменной}}. Циклы: <!-- loop:имя --> ... <!-- loop_end -->.')
groups = {'A': 'Общие переменные', 'B': '152-ФЗ (персональные данные)'}
groups = {'A': 'Общие переменные', 'B': 'MU (персональные данные)'}
by_group = {'A': [], 'B': []}
for var, group, desc, _ in VARIABLE_DEFS:
by_group.setdefault(group, []).append((var, desc))
@@ -108,11 +108,11 @@ def _generate_variables_reference(path):
def _generate_user_manual(path):
"""Инструкция пользователя: программа, циклы, переменные, проверки."""
doc = docx.Document()
_h(doc, 'ДоКоГеНеРаТоР — 152-ФЗ')
_h(doc, 'ДоКоГеНеРаТоР — MU')
_h(doc, 'Инструкция пользователя', 13)
_h(doc, '1. Что это за программа', 12)
_p(doc, 'Программа автоматически заполняет шаблоны документов по 152-ФЗ '
_p(doc, 'Программа автоматически заполняет шаблоны документов по MU '
'(акты обследования, политики, инструкции, приказы и т.д.) данными '
'об организации, информационных системах, комиссии и сотрудниках. '
'Данные можно ввести вручную на вкладках или импортировать из '
@@ -173,7 +173,7 @@ def _generate_user_manual(path):
def _generate_admin_manual(path):
"""Инструкция администратора: словари, API-ключи, лимиты."""
doc = docx.Document()
_h(doc, 'ДоКоГеНеРаТоР — 152-ФЗ')
_h(doc, 'ДоКоГеНеРаТоР — MU')
_h(doc, 'Инструкция администратора', 13)
_h(doc, '1. Файлы настроек рядом с программой', 12)
@@ -240,8 +240,8 @@ def _ensure_survey():
return target
# Ищем шаблон опросника: рядом с программой или встроенный
candidates = [
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'Опросный_лист_152_ФЗ.xlsx'),
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Опросный_лист_152_ФЗ.xlsx'),
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'Опросный_лист_MU.xlsx'),
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Опросный_лист_MU.xlsx'),
]
for c in candidates:
if os.path.exists(c):
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

+9 -9
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
"""DokoGen — Модуль импорта из Excel (опросный лист 152-ФЗ)"""
"""DokoGen — Модуль импорта из Excel (опросный лист MU)"""
import re
import traceback
@@ -122,8 +122,8 @@ def clean_value(val):
return text
def import_152fz(filepath: str, log_fn: Optional[Callable] = None, settings_path: Optional[str] = None) -> dict:
"""Импорт данных из опросного листа Excel (152-ФЗ).
def import_mufz(filepath: str, log_fn: Optional[Callable] = None, settings_path: Optional[str] = None) -> dict:
"""Импорт данных из опросного листа Excel (MU).
settings_path путь к JSON-файлу настроек импорта (что и откуда брать).
Если None файл import_settings.json рядом с программой; если его нет
@@ -154,9 +154,9 @@ def import_152fz(filepath: str, log_fn: Optional[Callable] = None, settings_path
return data
try:
_import_152_common(wb, data, settings, log_fn)
_import_152_is_list(wb, data, settings, log_fn)
_import_152_employees(wb, data, settings, log_fn)
_import_mu_common(wb, data, settings, log_fn)
_import_mu_is_list(wb, data, settings, log_fn)
_import_mu_employees(wb, data, settings, log_fn)
except Exception as e:
log_fn(f"❌ Ошибка при импорте: {e}")
log_fn(traceback.format_exc())
@@ -179,7 +179,7 @@ def import_152fz(filepath: str, log_fn: Optional[Callable] = None, settings_path
return data
def _import_152_common(wb, data, settings, log_fn):
def _import_mu_common(wb, data, settings, log_fn):
"""Импорт общих сведений по словарю настроек.
Для каждого поля: сначала пробуем конкретную ячейку (cell),
@@ -247,7 +247,7 @@ def _import_152_common(wb, data, settings, log_fn):
break
def _import_152_is_list(wb, data, settings, log_fn):
def _import_mu_is_list(wb, data, settings, log_fn):
"""Импорт информационных систем из остальных листов."""
exclude_kws = settings.get('is_sheet_exclude_keywords', ['общие сведения', 'сотрудники'])
is_sheets = []
@@ -447,7 +447,7 @@ def _import_152_is_list(wb, data, settings, log_fn):
log_fn(f"\n✅ Всего импортировано ИС: {len(is_list)}")
def _import_152_employees(wb, data, settings, log_fn):
def _import_mu_employees(wb, data, settings, log_fn):
"""Импорт комиссии и сотрудников из листа «Сотрудники»."""
sheet_name = None
sheet_kw = settings.get('employees_sheet_keyword', 'сотруд')
+2 -2
View File
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
"""DokoGen — Модели данных (только 152-ФЗ, только нужные поля)"""
"""DokoGen — Модели данных (только MU, только нужные поля)"""
from dataclasses import dataclass, field, asdict
from typing import List, Dict, Any
@@ -49,7 +49,7 @@ class PaperDocument:
@dataclass
class Company:
"""Организация — основной объект (152-ФЗ)"""
"""Организация — основной объект (MU)"""
# Полное название
full_name: str = ""
company_name_1: str = "" # именительный
+29 -8
View File
@@ -31,9 +31,10 @@ class DokoGenApp:
def __init__(self, root: tk.Tk):
self.root = root
root.title("ДоКоГеНеРаТоР — 152-ФЗ (Персональные данные)")
root.title("ДоКоГеНеРаТоР — MU")
root.geometry("1200x800")
root.minsize(900, 600)
self._set_app_icon()
self.model = Company()
self.current_file: Optional[str] = None
@@ -43,7 +44,7 @@ class DokoGenApp:
self._last_template_dir: str = ""
self._autosave_path = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
'.autosave', 'autosave_152.json'
'.autosave', 'autosave_mufz.json'
)
# Путь к файлу настроек импорта (словарь «что и откуда брать»)
@@ -81,6 +82,26 @@ class DokoGenApp:
self._load_autosave()
self._start_autosave_timer()
def _set_app_icon(self):
"""Устанавливает иконку приложения на окно (заголовок, панель задач).
Работает и из исходников, и из exe (frozen):
- исходники: dokogen/icon.ico рядом с модулем
- exe: dokogen/icon.ico из _MEIPASS (ресурсы PyInstaller)
"""
try:
if getattr(sys, 'frozen', False):
base = getattr(sys, '_MEIPASS', os.path.dirname(sys.executable))
ico = os.path.join(base, 'dokogen', 'icon.ico')
if not os.path.exists(ico):
ico = os.path.join(os.path.dirname(sys.executable), 'icon.ico')
else:
ico = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'icon.ico')
if os.path.exists(ico):
self.root.iconbitmap(ico)
except Exception:
pass
# ==================== МЕНЮ ====================
def _build_menu(self):
menubar = tk.Menu(self.root)
@@ -1736,7 +1757,7 @@ class DokoGenApp:
is_list=self.model.information_systems,
doc_number=self.doc_number_var.get(),
doc_date=self.doc_date_var.get(),
direction='152fz',
direction='mufz',
)
results = []
@@ -1825,7 +1846,7 @@ class DokoGenApp:
def import_from_survey(self):
path = filedialog.askopenfilename(
title="Выберите опросный лист (152-ФЗ)",
title="Выберите опросный лист (MU)",
filetypes=[("Excel", "*.xlsx *.xls")]
)
if not path:
@@ -1835,8 +1856,8 @@ class DokoGenApp:
# Импорт в отдельном потоке
def _run():
try:
from .importer import import_152fz
data = import_152fz(path, self.log, settings_path=self.import_settings_path)
from .importer import import_mufz
data = import_mufz(path, self.log, settings_path=self.import_settings_path)
if data:
self._apply_imported_data(data)
except ImportError:
@@ -2182,7 +2203,7 @@ class DokoGenApp:
def show_about(self):
messagebox.showinfo("О программе",
"ДоКоГеНеРаТоР — 152-ФЗ\n"
"ДоКоГеНеРаТоР — MU\n"
"Версия 1.0\n"
"Генератор документов из шаблонов")
@@ -2230,7 +2251,7 @@ class DokoGenApp:
def download_survey(self):
from .help_docs import ensure_docs, survey_path
ensure_docs()
self._save_resource(survey_path(), "Опросный_лист_152_ФЗ.xlsx", "Сохранить пустой опросник")
self._save_resource(survey_path(), "Опросный_лист_MU.xlsx", "Сохранить пустой опросник")
def main():
+4 -4
View File
@@ -19,7 +19,7 @@ def _norm_name(s):
# ОПИСАНИЕ ПЕРЕМЕННЫХ
# ============================================================
# Формат: (имя_переменной, группа, описание, ключ_резолвера)
# Группы: A — общие, B — 152-ФЗ
# Группы: A — общие, B — MU
VARIABLE_DEFS = [
# === Полное название организации (6 падежей) ===
@@ -68,7 +68,7 @@ VARIABLE_DEFS = [
('{{document_date}}', 'A', 'Дата документа', 'doc_date'),
('{{document_number}}', 'A', 'Номер документа', 'doc_number'),
# === 152-ФЗ ===
# === MU ===
('{{is_security_requirements}}', 'B', 'Требования уровня защищённости', 'security_reqs'),
('{{is_list}}', 'B', 'Список всех ИС (нумерованный)', 'is_list'),
('{{is_name}}', 'B', 'Наименование первой ИС', 'is:name'),
@@ -138,7 +138,7 @@ def build_replacements(
is_list: List = None,
doc_number: str = "",
doc_date: str = "",
direction: str = "152fz",
direction: str = "mufz",
) -> Dict[str, str]:
"""Строит полный словарь замен {{переменная}} → значение."""
if is_list is None:
@@ -159,7 +159,7 @@ def build_replacements(
replacements = {}
for var_name, group, desc, source in VARIABLE_DEFS:
if direction == '152fz' and group not in ('A', 'B'):
if direction == 'mufz' and group not in ('A', 'B'):
continue
value = _resolve(source, ctx)
replacements[var_name] = str(value) if value else ''
+1 -1
View File
@@ -399,7 +399,7 @@ def check_company_ai(company_data, api_key, model='deepseek-chat', base_url=None
if not api_key:
return None, "Не задан API-ключ ИИ (Файл → Настройки → API)"
system = (
"Ты — юрист по защите персональных данных (152-ФЗ). Проверь реквизиты организации. "
"Ты — юрист по защите персональных данных (MU). Проверь реквизиты организации. "
"Верни ТОЛЬКО JSON: "
'{"оценка": "ok|warning|error", '
'"замечания": ["..."], '
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""DokoGen — Генератор документов 152-ФЗ
"""DokoGen — Генератор документов MU
Точка входа: python main.py
"""
import sys
+2 -2
View File
@@ -87,7 +87,7 @@ def test_zip_loop_expansion():
is_list=company.information_systems,
doc_number='001',
doc_date='31.07.2026',
direction='152fz'
direction='mufz'
)
loops = replacements.get('_loops', {})
@@ -135,7 +135,7 @@ def test_zip_loop_expansion():
is_list=company.information_systems,
doc_number='001',
doc_date='31.07.2026',
direction='152fz'
direction='mufz'
)
try: