Загрузка данных


# === Окно для работы с базами данных ===
class DatabaseWindow(tk.Toplevel):

    def __init__(self, parent):
        super().__init__(parent)
        
        # Убираем сохранение собственного атрибута .parent
        # self.parent = parent 

        self.title("Управление базами данных")
        self.geometry("600x400")

        # --- ИСПРАВЛЕНИЕ ЗДЕСЬ ---
        # Вызываем функцию центрирования только по себе.
        # Функция сама найдет главного родителя через self.master
        center_on_parent(self) 
        
        # Основная структура интерфейса
        self.build_ui()

    def build_ui(self):
        # Основной контейнер
        container = ttk.Frame(self)
        container.pack(fill="both", expand=True)

        # Верхняя панель настроек
        top_panel = ttk.Frame(container)
        top_panel.pack(fill="x", pady=10)

        # Переключатель баз данных
        self.use_master_db = tk.BooleanVar(value=False)
        style = ttk.Style()
        style.configure("RedText.TCheckbutton", foreground="red")
        master_db_checkbox = ttk.Checkbutton(
            top_panel,
            text="Использовать основную базу данных",
            variable=self.use_master_db,
            style="RedText.TCheckbutton",
        )
        master_db_checkbox.pack(side="left", padx=10)

        # Панель инструментов
        tools_panel = ttk.Frame(container)
        tools_panel.pack(fill="x", pady=10)

        # Кнопка резервного копирования текущей базы
        btn_current_backup = ttk.Button(
            tools_panel,
            text="Создать резервную копию текущей базы",
            command=self.backup_current_database,
        )
        btn_current_backup.pack(side="left", padx=10)

        # Кнопка восстановления базы данных
        btn_restore = ttk.Button(
            tools_panel, text="Восстановить базу данных", command=self.restore_database
        )
        btn_restore.pack(side="left", padx=10)

        # Кнопка миграции баз данных
        btn_migrate = ttk.Button(
            tools_panel, text="Мигрировать данные", command=self.migrate_databases
        )
        btn_migrate.pack(side="left", padx=10)

        # Таблица резервных копий
        backup_columns = ("Дата", "Файл")
        self.backups_tree = ttk.Treeview(
            container, columns=backup_columns, show="headings"
        )
        for col in backup_columns:
            self.backups_tree.heading(col, text=col)
            self.backups_tree.column(col, width=200)
        self.backups_tree.pack(fill="both", expand=True)

        # Загружаем существующие резервные копии
        self.load_backups()

    def load_backups(self):
        """Загружает список существующих резервных копий в дерево."""
        self.backups_tree.delete(*self.backups_tree.get_children())  # Очищаем дерево

        # Директория резервных копий
        backup_dir = "backups/"
        os.makedirs(backup_dir, exist_ok=True)

        # Список всех резервных копий
        backups = []
        for filename in os.listdir(backup_dir):
            if filename.endswith(".db"):  # Фильтруем только файлы SQLite
                filepath = os.path.join(backup_dir, filename)
                creation_time = datetime.fromtimestamp(
                    os.path.getmtime(filepath)
                ).strftime("%Y-%m-%d %H:%M:%S")
                backups.append({"file": filename, "creation_time": creation_time})

        # Сортируем резервные копии по дате создания
        sorted_backups = sorted(backups, key=lambda b: b["creation_time"], reverse=True)

        # Добавляем записи в TreeView
        for backup in sorted_backups:
            self.backups_tree.insert(
                "", "end", values=(backup["creation_time"], backup["file"])
            )

    def backup_current_database(self):
        """Создает резервную копию текущей базы данных."""
        db_filename = "database.db" if not self.use_master_db.get() else "masterdata.db"

        # Полный путь к файлу резервной копии
        backup_dir = "backups/"
        os.makedirs(backup_dir, exist_ok=True)
        now = datetime.now()
        backup_filename = f"{now.strftime('%Y-%m-%d_%H-%M-%S')}__{db_filename}"
        backup_filepath = os.path.join(backup_dir, backup_filename)

        try:
            shutil.copy(db_filename, backup_filepath)
            messagebox.showinfo(
                "Резервное копирование",
                f"Резервная копия успешно создана:\n{backup_filepath}",
            )
            self.load_backups()  # Обновляем список резервных копий
        except Exception as e:
            messagebox.showerror("Ошибка", str(e))

    def restore_database(self):
        """Восстанавливает выбранную резервную копию."""
        selected_item = self.backups_tree.selection()
        if len(selected_item) > 0:
            backup_filename = self.backups_tree.item(selected_item)[0]["values"][1]
            backup_filepath = os.path.join("backups/", backup_filename)

            active_db = (
                "database.db" if not self.use_master_db.get() else "masterdata.db"
            )

            try:
                shutil.copy(backup_filepath, active_db)
                messagebox.showinfo(
                    "Восстановление",
                    f"База данных успешно восстановлена из резервной копии.\nАктивная база данных обновлена.",
                )
                self.load_backups()  # Обновляем список резервных копий
            except Exception as e:
                messagebox.showerror("Ошибка", str(e))
        else:
            messagebox.showwarning(
                "Предупреждение", "Сначала выберите резервную копию для восстановления."
            )

    def migrate_databases(self):
        """Выполняет миграцию данных между двумя базами данных."""
        if not self.use_master_db.get():
            src_db = "database.db"
            dest_db = "masterdata.db"
        else:
            src_db = "masterdata.db"
            dest_db = "database.db"

        # Создание временной копии исходной базы данных
        temp_src_db = f"{src_db}_temp"
        shutil.copy(src_db, temp_src_db)

        # Перемещение данных
        try:
            # Открытие обеих баз данных
            conn_src = sqlite3.connect(temp_src_db)
            conn_dest = sqlite3.connect(dest_db)

            # Копирование содержимого одной базы в другую
            conn_src.backup(conn_dest)

            # Закрытие соединений
            conn_src.close()
            conn_dest.close()

            # Сообщение об успехе
            messagebox.showinfo("Миграция", "Данные успешно перенесены.")
        except Exception as e:
            messagebox.showerror("Ошибка", str(e))