feat: вкладка «Бумажные документы» + импорт из опросника
- Новая вкладка: название документа + место хранения, добавить/удалить
- Импорт из опросника: «Названия документов» (строка 61) и «Место
хранения» (строка 62) → цикл {{paper_documents}} ({{document}}/{{storage}})
- Сохранение/автосохранение/генерация собирают данные вкладки
- Загрузка файла проекта восстанавливает список документов
This commit is contained in:
+129
@@ -116,6 +116,7 @@ class DokoGenApp:
|
|||||||
self._build_is_tab()
|
self._build_is_tab()
|
||||||
self._build_commission_tab()
|
self._build_commission_tab()
|
||||||
self._build_users_tab()
|
self._build_users_tab()
|
||||||
|
self._build_paper_tab()
|
||||||
self._build_generation_tab()
|
self._build_generation_tab()
|
||||||
self._build_log_tab()
|
self._build_log_tab()
|
||||||
|
|
||||||
@@ -548,6 +549,102 @@ class DokoGenApp:
|
|||||||
if emp['position'] or emp['fio']:
|
if emp['position'] or emp['fio']:
|
||||||
self.model.employees_access.append(emp)
|
self.model.employees_access.append(emp)
|
||||||
|
|
||||||
|
# ---------- ВКЛАДКА "БУМАЖНЫЕ ДОКУМЕНТЫ" ----------
|
||||||
|
def _build_paper_tab(self):
|
||||||
|
tab = ttk.Frame(self.notebook)
|
||||||
|
self.notebook.add(tab, text="Бумажные документы")
|
||||||
|
|
||||||
|
canvas = tk.Canvas(tab, highlightthickness=0)
|
||||||
|
scrollbar = ttk.Scrollbar(tab, orient=tk.VERTICAL, command=canvas.yview)
|
||||||
|
scrollable = ttk.Frame(canvas)
|
||||||
|
scrollable.bind("<Configure>",
|
||||||
|
lambda e: canvas.configure(scrollregion=canvas.bbox("all")))
|
||||||
|
canvas.create_window((0, 0), window=scrollable, anchor="nw")
|
||||||
|
canvas.configure(yscrollcommand=scrollbar.set)
|
||||||
|
canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||||
|
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||||
|
|
||||||
|
frame = ttk.Frame(scrollable, padding=10)
|
||||||
|
frame.pack(fill=tk.BOTH, expand=True)
|
||||||
|
|
||||||
|
ttk.Label(frame, text="Бумажные носители ПДн (документы)",
|
||||||
|
font=('Arial', 11, 'bold')).pack(anchor=tk.W, pady=(0, 10))
|
||||||
|
|
||||||
|
# Заголовки
|
||||||
|
header = ttk.Frame(frame)
|
||||||
|
header.pack(fill=tk.X)
|
||||||
|
for w, col in [(45, "Название документа"), (45, "Место хранения")]:
|
||||||
|
ttk.Label(header, text=col, font=('', 9, 'bold'),
|
||||||
|
width=w, anchor=tk.W).pack(side=tk.LEFT, padx=2)
|
||||||
|
|
||||||
|
self._paper_frame = ttk.Frame(frame)
|
||||||
|
self._paper_frame.pack(fill=tk.X, pady=5)
|
||||||
|
|
||||||
|
btn_frame = ttk.Frame(frame)
|
||||||
|
btn_frame.pack(fill=tk.X, pady=5)
|
||||||
|
ttk.Button(btn_frame, text="+ Добавить документ",
|
||||||
|
command=self._add_paper_row_ui).pack(side=tk.LEFT, padx=2)
|
||||||
|
ttk.Button(btn_frame, text="- Удалить выбранный",
|
||||||
|
command=self._delete_paper_selected).pack(side=tk.LEFT, padx=2)
|
||||||
|
|
||||||
|
self._paper_count_label = ttk.Label(frame, text="Добавлено: 0")
|
||||||
|
self._paper_count_label.pack(anchor=tk.W, pady=5)
|
||||||
|
|
||||||
|
self._paper_entries = []
|
||||||
|
# Загрузка существующих
|
||||||
|
for p in self.model.paper_documents_list:
|
||||||
|
self._add_paper_row(p.name, p.storage)
|
||||||
|
self._update_paper_count()
|
||||||
|
|
||||||
|
def _add_paper_row(self, name="", storage=""):
|
||||||
|
"""Добавляет одну строку документа."""
|
||||||
|
row = ttk.Frame(self._paper_frame)
|
||||||
|
row.pack(fill=tk.X, pady=2)
|
||||||
|
|
||||||
|
name_entry = ttk.Entry(row, width=45)
|
||||||
|
name_entry.insert(0, name)
|
||||||
|
name_entry.pack(side=tk.LEFT, padx=2)
|
||||||
|
|
||||||
|
storage_entry = ttk.Entry(row, width=45)
|
||||||
|
storage_entry.insert(0, storage)
|
||||||
|
storage_entry.pack(side=tk.LEFT, padx=2)
|
||||||
|
|
||||||
|
del_btn = ttk.Button(row, text="✖", width=3,
|
||||||
|
command=lambda: self._delete_paper_row(row))
|
||||||
|
del_btn.pack(side=tk.LEFT, padx=5)
|
||||||
|
|
||||||
|
self._paper_entries.append((row, name_entry, storage_entry))
|
||||||
|
self._update_paper_count()
|
||||||
|
|
||||||
|
def _add_paper_row_ui(self):
|
||||||
|
self._add_paper_row()
|
||||||
|
|
||||||
|
def _delete_paper_row(self, row_frame):
|
||||||
|
self._paper_entries = [e for e in self._paper_entries if e[0] != row_frame]
|
||||||
|
row_frame.destroy()
|
||||||
|
self._update_paper_count()
|
||||||
|
|
||||||
|
def _delete_paper_selected(self):
|
||||||
|
if self._paper_entries:
|
||||||
|
row_frame = self._paper_entries[-1][0]
|
||||||
|
self._delete_paper_row(row_frame)
|
||||||
|
|
||||||
|
def _update_paper_count(self):
|
||||||
|
count = len(self._paper_entries)
|
||||||
|
if hasattr(self, '_paper_count_label'):
|
||||||
|
self._paper_count_label.config(text=f"Добавлено: {count}")
|
||||||
|
|
||||||
|
def _collect_paper_documents(self):
|
||||||
|
"""Собирает данные бумажных документов из GUI в модель."""
|
||||||
|
self.model.paper_documents_list.clear()
|
||||||
|
for row, name_e, storage_e in self._paper_entries:
|
||||||
|
name = name_e.get().strip()
|
||||||
|
storage = storage_e.get().strip()
|
||||||
|
if name or storage:
|
||||||
|
self.model.paper_documents_list.append(
|
||||||
|
PaperDocument(name=name, storage=storage)
|
||||||
|
)
|
||||||
|
|
||||||
# ---------- ВКЛАДКА "ГЕНЕРАЦИЯ" ----------
|
# ---------- ВКЛАДКА "ГЕНЕРАЦИЯ" ----------
|
||||||
def _build_generation_tab(self):
|
def _build_generation_tab(self):
|
||||||
tab = ttk.Frame(self.notebook)
|
tab = ttk.Frame(self.notebook)
|
||||||
@@ -710,6 +807,15 @@ class DokoGenApp:
|
|||||||
)
|
)
|
||||||
self._update_emp_count()
|
self._update_emp_count()
|
||||||
|
|
||||||
|
# Бумажные документы
|
||||||
|
if hasattr(self, '_paper_entries'):
|
||||||
|
for row_frame, _, _ in self._paper_entries:
|
||||||
|
row_frame.destroy()
|
||||||
|
self._paper_entries.clear()
|
||||||
|
for p in c.paper_documents_list:
|
||||||
|
self._add_paper_row(p.name, p.storage)
|
||||||
|
self._update_paper_count()
|
||||||
|
|
||||||
# Шаблоны
|
# Шаблоны
|
||||||
self._on_templates_changed()
|
self._on_templates_changed()
|
||||||
|
|
||||||
@@ -1163,6 +1269,7 @@ class DokoGenApp:
|
|||||||
self._collect_commission()
|
self._collect_commission()
|
||||||
self._collect_is()
|
self._collect_is()
|
||||||
self._collect_employees()
|
self._collect_employees()
|
||||||
|
self._collect_paper_documents()
|
||||||
|
|
||||||
# Проверка
|
# Проверка
|
||||||
if not self._validate_before_generate():
|
if not self._validate_before_generate():
|
||||||
@@ -1446,6 +1553,26 @@ class DokoGenApp:
|
|||||||
)
|
)
|
||||||
self._update_emp_count()
|
self._update_emp_count()
|
||||||
|
|
||||||
|
# Бумажные документы (из «Названия документов» / «Место хранения»)
|
||||||
|
if data.get('paperDocuments'):
|
||||||
|
self.model.paper_documents_list.clear()
|
||||||
|
names = [n.strip() for n in data['paperDocuments'].replace('\n', ';').split(';') if n.strip()]
|
||||||
|
storages = [s.strip() for s in (data.get('paperStorage') or '').replace('\n', ';').split(';') if s.strip()]
|
||||||
|
for i, name in enumerate(names):
|
||||||
|
storage = storages[i] if i < len(storages) else (storages[0] if storages else '')
|
||||||
|
self.model.paper_documents_list.append(
|
||||||
|
PaperDocument(name=name, storage=storage)
|
||||||
|
)
|
||||||
|
# Обновляем GUI
|
||||||
|
if hasattr(self, '_paper_entries'):
|
||||||
|
for row_frame, _, _ in self._paper_entries:
|
||||||
|
row_frame.destroy()
|
||||||
|
self._paper_entries.clear()
|
||||||
|
for p in self.model.paper_documents_list:
|
||||||
|
self._add_paper_row(p.name, p.storage)
|
||||||
|
self._update_paper_count()
|
||||||
|
self.log(f" Бумажные документы: {len(self.model.paper_documents_list)} шт.")
|
||||||
|
|
||||||
self.log("✅ Импорт применён")
|
self.log("✅ Импорт применён")
|
||||||
self.root.after(0, _apply)
|
self.root.after(0, _apply)
|
||||||
|
|
||||||
@@ -1490,6 +1617,7 @@ class DokoGenApp:
|
|||||||
self._collect_commission()
|
self._collect_commission()
|
||||||
self._collect_is()
|
self._collect_is()
|
||||||
self._collect_employees()
|
self._collect_employees()
|
||||||
|
self._collect_paper_documents()
|
||||||
try:
|
try:
|
||||||
with open(filename, 'w', encoding='utf-8') as f:
|
with open(filename, 'w', encoding='utf-8') as f:
|
||||||
json.dump(self.model.to_dict(), f, ensure_ascii=False, indent=2)
|
json.dump(self.model.to_dict(), f, ensure_ascii=False, indent=2)
|
||||||
@@ -1515,6 +1643,7 @@ class DokoGenApp:
|
|||||||
self._collect_commission()
|
self._collect_commission()
|
||||||
self._collect_is()
|
self._collect_is()
|
||||||
self._collect_employees()
|
self._collect_employees()
|
||||||
|
self._collect_paper_documents()
|
||||||
try:
|
try:
|
||||||
os.makedirs(os.path.dirname(self._autosave_path), exist_ok=True)
|
os.makedirs(os.path.dirname(self._autosave_path), exist_ok=True)
|
||||||
with open(self._autosave_path, 'w', encoding='utf-8') as f:
|
with open(self._autosave_path, 'w', encoding='utf-8') as f:
|
||||||
|
|||||||
Reference in New Issue
Block a user