Загрузка данных
# ---*--- Начало gui/admin_db_inter.py ---*---
import os
import shutil
import sqlite3
import tkinter as tk
from tkinter import ttk, messagebox
from datetime import datetime
from pathlib import Path
from .admin_db_work import DBFileManager
class AdminDBInter(tk.Toplevel):
def __init__(self, parent):
super().__init__(parent)
self.parent_main = parent
self.title("Управление базами данных")
self.geometry("600x400")
self.resizable(True, True)
self.transient(parent)
self.grab_set()
# Здесь тоже используем правильный импорт из пакета administrator
self.file_manager = DBFileManager()
self.build_ui()
self.refresh_backups_list()
self.sync_active_flag()
def build_ui(self):
container = ttk.Frame(self)
container.pack(fill="both", expand=True, padx=10, pady=10)
top_panel = ttk.Frame(container)
top_panel.pack(fill="x", pady=10)
self.use_master_db = tk.BooleanVar(value=(self.file_manager._get_active_name() == "masterdata"))
style = ttk.Style()
style.configure("RedText.TCheckbutton", foreground="red")
ttk.Checkbutton(
top_panel,
text="Использовать основную базу данных (masterdata.db)",
variable=self.use_master_db,
style="RedText.TCheckbutton",
command=self.toggle_active_db
).pack(side="left", padx=10)
tools_panel = ttk.Frame(container)
tools_panel.pack(fill="x", pady=10)
ttk.Button(tools_panel, text="Создать резервную копию", command=self.do_backup).pack(side="left", padx=5)
ttk.Button(tools_panel, text="Восстановить из копии", command=self.do_restore).pack(side="left", padx=5)
ttk.Button(tools_panel, text="Мигрировать данные", command=self.do_migrate).pack(side="left", padx=5)
backup_columns = ("Дата", "Файл")
self.backups_tree = ttk.Treeview(container, columns=backup_columns, show="headings", height=10)
for col in backup_columns:
self.backups_tree.heading(col, text=col)
self.backups_tree.column(col, width=270)
self.backups_tree.pack(fill="both", expand=True, pady=10)
def refresh_backups_list(self):
self.backups_tree.delete(*self.backups_tree.get_children())
backup_dir = Path(self.file_manager.backup_dir)
if not backup_dir.exists():
return
# Сортируем по дате создания файла на диске, а не по имени
files = sorted(backup_dir.glob("*.db"), key=os.path.getctime, reverse=True)
for file_path in files:
# Выводим только имя файла без лишних преобразований
display_name = file_path.name
# Дата модификации файла в читаемом виде
mod_time = datetime.fromtimestamp(file_path.stat().st_mtime).strftime("%d.%m %H:%M")
self.backups_tree.insert("", "end", values=(mod_time, display_name))
def sync_active_flag(self):
is_master = self.file_manager._get_active_name() == "masterdata"
self.use_master_db.set(is_master)
def toggle_active_db(self):
target = "masterdata" if self.use_master_db.get() else "database"
self.file_manager._set_active_name(target)
messagebox.showinfo("Готово", f"Теперь активной будет {target}.db\nПерезапустите приложение для полной смены контекста.")
def do_backup(self):
try:
fname = self.file_manager.create_backup()
self.refresh_backups_list()
messagebox.showinfo("Бэкап", f"Копия создана:\n{fname}\nПуть: {self.file_manager.backup_dir}")
except Exception as e:
messagebox.showerror("Ошибка", str(e))
def do_restore(self):
# Игнорируем выделение в таблице. Ищем самый свежий файл сами.
backup_dir = Path(self.file_manager.backup_dir)
if not backup_dir.exists():
messagebox.showwarning("Внимание", "Папка с бэкапами пуста.")
return
files = sorted(backup_dir.glob("*.db"), key=os.path.getctime, reverse=True)
if not files:
messagebox.showwarning("Внимание", "Не найдено ни одного файла .db в папке backups.")
return
latest_backup = files[0]
try:
self.file_manager.restore_from_file(latest_backup.name)
messagebox.showinfo("Успех", f"База восстановлена из {latest_backup.name}\nПриложение нужно перезапустить.")
except Exception as e:
print(f"[CRITICAL RESTORE ERROR] {e}")
import traceback
traceback.print_exc() # Выведем полную ошибку в консоль
messagebox.showerror("Ошибка", f"Критическая ошибка при восстановлении:\n{str(e)}")
def do_migrate(self):
answer = messagebox.askyesnocancel(
"Миграция данных",
"Перенести ВСЕ данные из НЕАКТИВНОЙ базы в АКТИВНУЮ?\nАктивная база будет ПОЛНОСТЬЮ ЗАТЕРТА данными из другой.\nДействие необратимо."
)
if answer is None or not answer:
return
current = self.file_manager._get_active_name()
source = "masterdata" if current == "database" else "database"
try:
self.file_manager.migrate_data(source, current)
messagebox.showinfo("Миграция", f"Данные перенесены из {source}.db в {current}.db\nПерезапустите приложение.")
except Exception as e:
messagebox.showerror("Ошибка", str(e))
# ---*--- Конец файла ---*---