From f151cf1bfea90720ad60471ec16153aa6f7f3876 Mon Sep 17 00:00:00 2001 From: DokoGen Date: Mon, 3 Aug 2026 23:45:18 +0400 Subject: [PATCH] =?UTF-8?q?feat:=20=D1=80=D0=B5=D0=B1=D1=80=D0=B5=D0=BD?= =?UTF-8?q?=D0=B4=D0=B8=D0=BD=D0=B3=20=D0=BF=D0=BE=D0=B4=20dokogenPZI=20(?= =?UTF-8?q?=D0=BE=D1=81=D0=BD=D0=BE=D0=B2=D0=B0=20=D0=B8=D0=B7=20dokogen18?= =?UTF-8?q?7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dokogen.spec | 2 +- dokogen/__init__.py | 2 +- ...ный_лист_187_ФЗ.xlsx => Опросный_лист_PZI.xlsx} | Bin dokogen/help_docs.py | 16 ++++++++-------- dokogen/importer.py | 18 +++++++++--------- dokogen/models.py | 4 ++-- dokogen/ui.py | 16 ++++++++-------- dokogen/variables.py | 8 ++++---- dokogen/verify.py | 2 +- main.py | 2 +- test_generator.py | 4 ++-- 11 files changed, 37 insertions(+), 37 deletions(-) rename dokogen/data/{Опросный_лист_187_ФЗ.xlsx => Опросный_лист_PZI.xlsx} (100%) diff --git a/dokogen.spec b/dokogen.spec index 694527b..f872b78 100644 --- a/dokogen.spec +++ b/dokogen.spec @@ -11,7 +11,7 @@ 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'), - # Пустой опросник 187-ФЗ (для «Справка → Пустой опросник») + # Пустой опросник PZI (для «Справка → Пустой опросник») ('dokogen/data', 'dokogen/data'), # Иконка приложения (для окна программы в exe) ('dokogen/icon.ico', 'dokogen'), diff --git a/dokogen/__init__.py b/dokogen/__init__.py index 1244144..fabf766 100644 --- a/dokogen/__init__.py +++ b/dokogen/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""DokoGen — Пакет генератора документов 187-ФЗ""" +"""DokoGen — Пакет генератора документов PZI""" from .models import Company, CommissionMember, InformationSystem, PaperDocument from .declension import inflect_name, decline, company_name_decline, get_short_fio, get_initials diff --git a/dokogen/data/Опросный_лист_187_ФЗ.xlsx b/dokogen/data/Опросный_лист_PZI.xlsx similarity index 100% rename from dokogen/data/Опросный_лист_187_ФЗ.xlsx rename to dokogen/data/Опросный_лист_PZI.xlsx diff --git a/dokogen/help_docs.py b/dokogen/help_docs.py index ec11dbe..e7501ed 100644 --- a/dokogen/help_docs.py +++ b/dokogen/help_docs.py @@ -5,7 +5,7 @@ рядом с программой (при сборке .exe — рядом с exe): - Инструкция_пользователя.docx - Инструкция_администратора.docx -- Опросный_лист_187_ФЗ.xlsx (пустой шаблон) +- Опросный_лист_PZI.xlsx (пустой шаблон) """ import os @@ -45,7 +45,7 @@ def variables_reference_path(): def survey_path(): - return os.path.join(docs_dir(), 'Опросный_лист_187_ФЗ.xlsx') + return os.path.join(docs_dir(), 'Опросный_лист_PZI.xlsx') def _h(doc, text, size=14): @@ -83,7 +83,7 @@ def _generate_variables_reference(path): _p(doc, 'Список переменных для шаблонов Word. Переменная подставляется в текст ' 'как есть: {{имя_переменной}}. Циклы: ... .') - groups = {'A': 'Общие переменные', 'B': '187-ФЗ (персональные данные)'} + groups = {'A': 'Общие переменные', 'B': 'PZI (персональные данные)'} 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, 'ДоКоГеНеРаТоР — 187-ФЗ') + _h(doc, 'ДоКоГеНеРаТоР — PZI') _h(doc, 'Инструкция пользователя', 13) _h(doc, '1. Что это за программа', 12) - _p(doc, 'Программа автоматически заполняет шаблоны документов по 187-ФЗ ' + _p(doc, 'Программа автоматически заполняет шаблоны документов по PZI ' '(акты обследования, политики, инструкции, приказы и т.д.) данными ' 'об организации, информационных системах, комиссии и сотрудниках. ' 'Данные можно ввести вручную на вкладках или импортировать из ' @@ -173,7 +173,7 @@ def _generate_user_manual(path): def _generate_admin_manual(path): """Инструкция администратора: словари, API-ключи, лимиты.""" doc = docx.Document() - _h(doc, 'ДоКоГеНеРаТоР — 187-ФЗ') + _h(doc, 'ДоКоГеНеРаТоР — PZI') _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', 'Опросный_лист_187_ФЗ.xlsx'), - os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Опросный_лист_187_ФЗ.xlsx'), + os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data', 'Опросный_лист_PZI.xlsx'), + os.path.join(os.path.dirname(os.path.abspath(__file__)), 'Опросный_лист_PZI.xlsx'), ] for c in candidates: if os.path.exists(c): diff --git a/dokogen/importer.py b/dokogen/importer.py index ba51816..1c5bd67 100644 --- a/dokogen/importer.py +++ b/dokogen/importer.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""DokoGen — Модуль импорта из Excel (опросный лист 187-ФЗ)""" +"""DokoGen — Модуль импорта из Excel (опросный лист PZI)""" import re import traceback @@ -122,8 +122,8 @@ def clean_value(val): return text -def import_187fz(filepath: str, log_fn: Optional[Callable] = None, settings_path: Optional[str] = None) -> dict: - """Импорт данных из опросного листа Excel (187-ФЗ). +def import_pzifz(filepath: str, log_fn: Optional[Callable] = None, settings_path: Optional[str] = None) -> dict: + """Импорт данных из опросного листа Excel (PZI). settings_path — путь к JSON-файлу настроек импорта (что и откуда брать). Если None — файл import_settings.json рядом с программой; если его нет — @@ -154,9 +154,9 @@ def import_187fz(filepath: str, log_fn: Optional[Callable] = None, settings_path return data try: - _import_187_common(wb, data, settings, log_fn) - _import_187_is_list(wb, data, settings, log_fn) - _import_187_employees(wb, data, settings, log_fn) + _import_pzi_common(wb, data, settings, log_fn) + _import_pzi_is_list(wb, data, settings, log_fn) + _import_pzi_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_187fz(filepath: str, log_fn: Optional[Callable] = None, settings_path return data -def _import_187_common(wb, data, settings, log_fn): +def _import_pzi_common(wb, data, settings, log_fn): """Импорт общих сведений по словарю настроек. Для каждого поля: сначала пробуем конкретную ячейку (cell), @@ -247,7 +247,7 @@ def _import_187_common(wb, data, settings, log_fn): break -def _import_187_is_list(wb, data, settings, log_fn): +def _import_pzi_is_list(wb, data, settings, log_fn): """Импорт информационных систем из остальных листов.""" exclude_kws = settings.get('is_sheet_exclude_keywords', ['общие сведения', 'сотрудники']) is_sheets = [] @@ -447,7 +447,7 @@ def _import_187_is_list(wb, data, settings, log_fn): log_fn(f"\n✅ Всего импортировано ИС: {len(is_list)}") -def _import_187_employees(wb, data, settings, log_fn): +def _import_pzi_employees(wb, data, settings, log_fn): """Импорт комиссии и сотрудников из листа «Сотрудники».""" sheet_name = None sheet_kw = settings.get('employees_sheet_keyword', 'сотруд') diff --git a/dokogen/models.py b/dokogen/models.py index 88bed71..fd276d6 100644 --- a/dokogen/models.py +++ b/dokogen/models.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -"""DokoGen — Модели данных (только 187-ФЗ, только нужные поля)""" +"""DokoGen — Модели данных (только PZI, только нужные поля)""" from dataclasses import dataclass, field, asdict from typing import List, Dict, Any @@ -49,7 +49,7 @@ class PaperDocument: @dataclass class Company: - """Организация — основной объект (187-ФЗ)""" + """Организация — основной объект (PZI)""" # Полное название full_name: str = "" company_name_1: str = "" # именительный diff --git a/dokogen/ui.py b/dokogen/ui.py index a87746d..c99ea52 100644 --- a/dokogen/ui.py +++ b/dokogen/ui.py @@ -31,7 +31,7 @@ class DokoGenApp: def __init__(self, root: tk.Tk): self.root = root - root.title("ДоКоГеНеРаТоР — 187-ФЗ (КИИ)") + root.title("ДоКоГеНеРаТоР — PZI") root.geometry("1200x800") root.minsize(900, 600) self._set_app_icon() @@ -44,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_187.json' + '.autosave', 'autosave_pzifz.json' ) # Путь к файлу настроек импорта (словарь «что и откуда брать») @@ -1757,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='187fz', + direction='pzifz', ) results = [] @@ -1846,7 +1846,7 @@ class DokoGenApp: def import_from_survey(self): path = filedialog.askopenfilename( - title="Выберите опросный лист (187-ФЗ)", + title="Выберите опросный лист (PZI)", filetypes=[("Excel", "*.xlsx *.xls")] ) if not path: @@ -1856,8 +1856,8 @@ class DokoGenApp: # Импорт в отдельном потоке def _run(): try: - from .importer import import_187fz - data = import_187fz(path, self.log, settings_path=self.import_settings_path) + from .importer import import_pzifz + data = import_pzifz(path, self.log, settings_path=self.import_settings_path) if data: self._apply_imported_data(data) except ImportError: @@ -2203,7 +2203,7 @@ class DokoGenApp: def show_about(self): messagebox.showinfo("О программе", - "ДоКоГеНеРаТоР — 187-ФЗ\n" + "ДоКоГеНеРаТоР — PZI\n" "Версия 1.0\n" "Генератор документов из шаблонов") @@ -2251,7 +2251,7 @@ class DokoGenApp: def download_survey(self): from .help_docs import ensure_docs, survey_path ensure_docs() - self._save_resource(survey_path(), "Опросный_лист_187_ФЗ.xlsx", "Сохранить пустой опросник") + self._save_resource(survey_path(), "Опросный_лист_PZI.xlsx", "Сохранить пустой опросник") def main(): diff --git a/dokogen/variables.py b/dokogen/variables.py index 140199e..56c656a 100644 --- a/dokogen/variables.py +++ b/dokogen/variables.py @@ -19,7 +19,7 @@ def _norm_name(s): # ОПИСАНИЕ ПЕРЕМЕННЫХ # ============================================================ # Формат: (имя_переменной, группа, описание, ключ_резолвера) -# Группы: A — общие, B — 187-ФЗ +# Группы: A — общие, B — PZI VARIABLE_DEFS = [ # === Полное название организации (6 падежей) === @@ -68,7 +68,7 @@ VARIABLE_DEFS = [ ('{{document_date}}', 'A', 'Дата документа', 'doc_date'), ('{{document_number}}', 'A', 'Номер документа', 'doc_number'), - # === 187-ФЗ === + # === PZI === ('{{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 = "187fz", + direction: str = "pzifz", ) -> 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 == '187fz' and group not in ('A', 'B'): + if direction == 'pzifz' and group not in ('A', 'B'): continue value = _resolve(source, ctx) replacements[var_name] = str(value) if value else '—' diff --git a/dokogen/verify.py b/dokogen/verify.py index 249bdc7..e817664 100644 --- a/dokogen/verify.py +++ b/dokogen/verify.py @@ -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 = ( - "Ты — юрист по защите персональных данных (187-ФЗ). Проверь реквизиты организации. " + "Ты — юрист по защите персональных данных (PZI). Проверь реквизиты организации. " "Верни ТОЛЬКО JSON: " '{"оценка": "ok|warning|error", ' '"замечания": ["..."], ' diff --git a/main.py b/main.py index 8e0999a..76dab58 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -"""DokoGen — Генератор документов 187-ФЗ +"""DokoGen — Генератор документов PZI Точка входа: python main.py """ import sys diff --git a/test_generator.py b/test_generator.py index a010332..65fd448 100644 --- a/test_generator.py +++ b/test_generator.py @@ -87,7 +87,7 @@ def test_zip_loop_expansion(): is_list=company.information_systems, doc_number='001', doc_date='31.07.2026', - direction='187fz' + direction='pzifz' ) 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='187fz' + direction='pzifz' ) try: