
Добавил:
hiiamfool
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:
import tkinter as tk
from tkinter import *
from tkinter import ttk
import sqlite3
from tkinter import messagebox
path = "C:/Users/admin/source/repos/UNIVERSITY_repos/4 course/7 sem/mispris/coursework-2/furniture.db"
class DatabaseApp:
def __init__(self, root):
self.root = root
self.root.title("coursework")
root.geometry("1000x600")
self.conn = sqlite3.connect(path)
self.cursor = self.conn.cursor()
self.tree = ttk.Treeview(root, show="headings")
self.tree.grid(row=0, column=0, columnspan=6, sticky="nsew", padx=6, pady=10)
self.load_button = ttk.Button(root, text="Load Products", command=self.load_products)
self.load_button.grid(row=1, column=0, sticky="ew", padx=6, pady=2)
self.add_product_button = ttk.Button(root, text="Add product", command=self.add_product)
self.add_product_button.grid(row=2, column=0, sticky="ew", padx=6, pady=2)
self.edit_button = ttk.Button(root, text="Edit Selected", command=self.edit_product)
self.edit_button.grid(row=3, column=0, sticky="ew", padx=6, pady=2)
self.delete_button = ttk.Button(root, text="Delete Selected", command=self.delete_product)
self.delete_button.grid(row=4, column=0, sticky="ew", padx=6, pady=2)
self.load_find_components_by_objectbutton = ttk.Button(root, text="find components by object ", command=self.load_find_components_by_object)
self.load_find_components_by_objectbutton.grid(row=5, column=0, sticky="ew", padx=6, pady=2)
self.find_components_recursive_object_button = ttk.Button(root, text="find components recursive", command=self.find_components_recursive)
self.find_components_recursive_object_button.grid(row=6, column=0, sticky="ew", padx=6, pady=2)
self.load_existing_acceptable_components_by_object_button = ttk.Button(root, text="available components category", command=self.load_existing_acceptable_components_by_object)
self.load_existing_acceptable_components_by_object_button.grid(row=7, column=0, sticky="ew", padx=6, pady=2)
self.load_existing_acceptable_components_by_object_recursive_button = ttk.Button(root, text="available components recursive category", command=self.load_existing_acceptable_components_by_object_recursive)
self.load_existing_acceptable_components_by_object_recursive_button.grid(row=8, column=0, sticky="ew", padx=6, pady=2)
self.load_category_button = ttk.Button(root, text="Load Categories", command=self.load_categories)
self.load_category_button.grid(row=1, column=1, sticky="ew", padx=6, pady=2)
self.add_category_button = ttk.Button(root, text="Add Category", command=self.add_category)
self.add_category_button.grid(row=2, column=1, sticky="ew", padx=6, pady=2)
self.edit_category_button = ttk.Button(root, text="Edit Category", command=self.edit_category)
self.edit_category_button.grid(row=3, column=1, sticky="ew", padx=6, pady=2)
self.delete_category_button = ttk.Button(root, text="Delete Category", command=self.delete_category)
self.delete_category_button.grid(row=4, column=1, sticky="ew", padx=6, pady=2)
self.show_parents_button = ttk.Button(root, text="Show Parents", command=self.show_category_parents)
self.show_parents_button.grid(row=5, column=1, sticky="ew", padx=6, pady=2)
self.show_children_button = ttk.Button(root, text="Show Children", command=self.show_category_children)
self.show_children_button.grid(row=6, column=1, sticky="ew", padx=6, pady=2)
self.show_products_button = ttk.Button(root, text="Show products", command=self.show_products_for_category)
self.show_products_button.grid(row=7, column=1, sticky="ew", padx=6, pady=2)
self.load_acceptable_components_by_class_button = ttk.Button(root, text="Show acceptable components by class", command=self.load_acceptable_components_by_class)
self.load_acceptable_components_by_class_button.grid(row=8, column=1, sticky="ew", padx=6, pady=2)
self.load_acceptable_components_by_class_recursive_button = ttk.Button(root, text="Show acceptable components by class recoursive", command=self.load_acceptable_components_by_class_recursive)
self.load_acceptable_components_by_class_recursive_button.grid(row=9, column=1, sticky="ew", padx=6, pady=2)
self.load_unit_button = ttk.Button(root, text="Load Unit", command=self.load_unit)
self.load_unit_button.grid(row=1, column=2, sticky="ew", padx=6, pady=2)
self.add_unit_button = ttk.Button(root, text="Add Unit", command=self.add_unit)
self.add_unit_button.grid(row=2, column=2, sticky="ew", padx=6, pady=2)
self.edit_unit_button = ttk.Button(root, text="Edit Selected", command=self.edit_unit)
self.edit_unit_button.grid(row=3, column=2, sticky="ew", padx=6, pady=2)
self.delete_unit_button = ttk.Button(root, text="Delete Selected", command=self.delete_unit)
self.delete_unit_button.grid(row=4, column=2, sticky="ew", padx=6, pady=2)
self.load_acceptable_components_button = ttk.Button(root, text="Load acceptable components", command=self.load_acceptable_component)
self.load_acceptable_components_button.grid(row=1, column=3, sticky="ew", padx=6, pady=2)
self.create_acceptable_component_button = ttk.Button(root, text="create acceptable component", command=self.create_acceptable_component)
self.create_acceptable_component_button.grid(row=2, column=3, sticky="ew", padx=6, pady=2)
self.inherit_acceptable_components_button = ttk.Button(root, text="inherit acceptable components", command=self.inherit_acceptable_components)
self.inherit_acceptable_components_button.grid(row=3, column=3, sticky="ew", padx=6, pady=2)
self.delete_acceptable_component_button = ttk.Button(root, text="Delete acceptable components", command=self.delete_acceptable_component)
self.delete_acceptable_component_button.grid(row=4, column=3, sticky="ew", padx=6, pady=2)
self.load_prod_position_union_button = ttk.Button(root, text="Load prod position union", command=self.load_prod_position_union)
self.load_prod_position_union_button.grid(row=1, column=4, sticky="ew", padx=6, pady=2)
self.create_prod_position_union_button = ttk.Button(root, text="create prod position union", command=self.create_prod_position_union)
self.create_prod_position_union_button.grid(row=2, column=4, sticky="ew", padx=6, pady=2)
self.delete_prod_position_union_button = ttk.Button(root, text="Delete prod position row", command=self.delete_prod_position_union)
self.delete_prod_position_union_button.grid(row=3, column=4, sticky="ew", padx=6, pady=2)
self.edit_prod_position_union_quantity_button = ttk.Button(root, text="New quantity prod position", command=self.edit_prod_position_union_quantity)
self.edit_prod_position_union_quantity_button.grid(row=4, column=4, sticky="ew", padx=6, pady=2)
self.fill_example_data_button = ttk.Button(self.root, text="Fill Example Data", command=self.fill_example_data)
self.fill_example_data_button.grid(row=1, column=5, sticky="ew", padx=6, pady=2)
self.delete_all_data_button = ttk.Button(self.root, text="Delete All Data", command=self.delete_all_data)
self.delete_all_data_button.grid(row=2, column=5, sticky="ew", padx=6, pady=2)
# Configure row and column to resize
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
root.columnconfigure(2, weight=1)
root.columnconfigure(3, weight=1)
root.columnconfigure(4, weight=1)
root.columnconfigure(5, weight=1)
def create_category_table():
self.cursor.execute('''CREATE TABLE IF NOT EXISTS category
(id INTEGER PRIMARY KEY AUTOINCREMENT,
id_parent INTEGER CHECK (id_parent != id),
category_name TEXT UNIQUE,
id_unit INTEGER,
FOREIGN KEY (id_parent) REFERENCES category(id))''')
self.conn.commit()
def create_product_table():
self.cursor.execute('''CREATE TABLE IF NOT EXISTS product
(id INTEGER PRIMARY KEY AUTOINCREMENT,
id_category INTEGER,
id_unit INTEGER,
product_name TEXT NOT NULL,
quantity INTEGER DEFAULT 0,
price REAL DEFAULT 0,
FOREIGN KEY (id_unit) REFERENCES unit(id),
FOREIGN KEY (id_category) REFERENCES category(id))''')
self.conn.commit()
def create_unit_table():
self.cursor.execute('''CREATE TABLE IF NOT EXISTS unit
(id INTEGER PRIMARY KEY AUTOINCREMENT,
unit_name TEXT NOT NULL UNIQUE,
unit_name_short TEXT NOT NULL)''')
self.conn.commit()
def create_acceptable_components_table():
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS acceptable_components (
id INTEGER PRIMARY KEY AUTOINCREMENT,
class_id INTEGER NOT NULL,
component_id INTEGER NOT NULL,
UNIQUE(class_id, component_id),
FOREIGN KEY (class_id) REFERENCES category(id) ON DELETE CASCADE,
FOREIGN KEY (component_id) REFERENCES category(id) ON DELETE CASCADE
)
''')
self.conn.commit()
def create_prod_position_union_table():
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS prod_position_union (
id INTEGER PRIMARY KEY AUTOINCREMENT,
prod_id INTEGER NOT NULL,
comp_id INTEGER NOT NULL,
quantity INTEGER NOT NULL CHECK (quantity > 0),
UNIQUE(prod_id, comp_id),
FOREIGN KEY (prod_id) REFERENCES product(id) ON DELETE CASCADE,
FOREIGN KEY (comp_id) REFERENCES product(id) ON DELETE CASCADE
)
''')
self.conn.commit()
def creating_tables():
create_category_table()
create_product_table()
create_unit_table()
# coursework-2
create_acceptable_components_table()
create_prod_position_union_table()
creating_tables()
def load_unit(self):
# Очистка текущих данных из Treeview
for row in self.tree.get_children():
self.tree.delete(row)
# Получение данных из таблицы unit
self.cursor.execute("SELECT * FROM unit")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
# Очистка старых заголовков столбцов
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
# Вставка данных в Treeview
for row in rows:
self.tree.insert("", "end", values=row)
def load_products(self):
# Очистка текущих данных из Treeview
for row in self.tree.get_children():
self.tree.delete(row)
# Получение данных из таблицы product
self.cursor.execute("SELECT * FROM product")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
# Очистка старых заголовков столбцов
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
# Вставка данных в Treeview
for row in rows:
self.tree.insert("", END, values=row)
def load_categories(self):
# Очистка текущих данных из Treeview
for row in self.tree.get_children():
self.tree.delete(row)
# Получение данных из таблицы category
self.cursor.execute("SELECT * FROM category")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
# Очистка старых заголовков столбцов
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
# Вставка данных в Treeview
for row in rows:
self.tree.insert("", END, values=row)
def add_category(self):
add_window = Toplevel(self.root)
add_window.title("Add Category")
Label(add_window, text="Category Name").grid(row=0, column=0)
category_name_entry = Entry(add_window)
category_name_entry.grid(row=0, column=1)
Label(add_window, text="Parent Category Name (optional)").grid(row=1, column=0)
parent_category_entry = Entry(add_window)
parent_category_entry.grid(row=1, column=1)
def save_new_category():
category_name = category_name_entry.get()
parent_name = parent_category_entry.get()
if not category_name:
messagebox.showerror("Error", "Category name cannot be empty.")
return
if parent_name:
self.cursor.execute("SELECT id FROM category WHERE category_name = ?", (parent_name,))
result = self.cursor.fetchone()
if result:
parent_id = result[0]
else:
messagebox.showerror("Error", f"Parent category '{parent_name}' not found.")
return
else:
parent_id = None
try:
if parent_id is not None:
self.cursor.execute('''
INSERT INTO category (category_name, id_parent)
VALUES (?, ?)
''', (category_name, parent_id))
else:
self.cursor.execute('''
INSERT INTO category (category_name, id_parent)
VALUES (?, NULL)
''', (category_name,))
self.conn.commit()
self.load_categories()
add_window.destroy()
print('Категория успешно добавлена.')
except Exception as _ex:
print(f'Error {_ex} - такое название категории уже есть!')
messagebox.showerror("Error", f"Error {_ex} - такое название категории уже есть!")
Button(add_window, text="Save", command=save_new_category).grid(row=2, column=0, columnspan=2)
def edit_category(self):
try:
selected_item = self.tree.selection()[0]
selected_category = self.tree.item(selected_item)['values']
category_id = selected_category[0]
edit_window = Toplevel(self.root)
edit_window.title("Edit Category")
entries = {}
row_count = 0
for col in self.tree["columns"]:
Label(edit_window, text=col).grid(row=row_count, column=0)
entry = Entry(edit_window)
entry.grid(row=row_count, column=1)
if col == "id":
entry.insert(0, selected_category[row_count])
entry.config(state="readonly")
elif col == "id_parent":
self.cursor.execute("SELECT id_parent FROM category WHERE id = ?", (category_id,))
parent_id = self.cursor.fetchone()[0]
if parent_id:
entry.insert(0, parent_id)
else:
entry.insert(0, selected_category[row_count])
entries[col] = entry
row_count += 1
def update_category():
update_values = []
id_parent = None
set_clause_parts = []
for col in self.tree["columns"]:
if col == "id":
continue
value = entries[col].get()
if col == "id_parent":
if value:
if value == str(category_id):
messagebox.showerror("Error", "A category cannot be its own parent.")
return
self.cursor.execute("SELECT id FROM category WHERE id = ?", (value,))
result = self.cursor.fetchone()
if result:
id_parent = result[0]
else:
messagebox.showerror("Error", f"Parent category with id '{value}' not found.")
return
if self.check_cyclic_dependency(id_parent, category_id):
messagebox.showerror("Error", "Cyclic dependency detected.")
return
set_clause_parts.append(f"{col} = ?")
update_values.append(id_parent)
else:
set_clause_parts.append(f"{col} = ?")
update_values.append(value)
set_clause = ", ".join(set_clause_parts)
# print(f'set_clause - {set_clause}')
self.cursor.execute(f"UPDATE category SET {set_clause} WHERE id = ?", update_values + [category_id])
self.conn.commit()
self.load_categories()
edit_window.destroy()
Button(edit_window, text="Save", command=update_category).grid(row=row_count, column=0, columnspan=2)
except IndexError:
pass
def check_cyclic_dependency(self, new_parent_id, category_id):
def fetch_parent_category(cat_id):
self.cursor.execute("SELECT id_parent FROM category WHERE id = ?", (cat_id,))
return self.cursor.fetchone()[0]
current_id = new_parent_id
while current_id is not None:
if current_id == category_id:
return True
current_id = fetch_parent_category(current_id)
return False
def add_unit(self):
add_window = Toplevel(self.root)
add_window.title("Add Unit")
Label(add_window, text="Unit Name").grid(row=0, column=0)
unit_name_entry = Entry(add_window)
unit_name_entry.grid(row=0, column=1)
Label(add_window, text="Unit Name Short").grid(row=1, column=0)
unit_name_short_entry = Entry(add_window)
unit_name_short_entry.grid(row=1, column=1)
def save_new_unit():
unit_name = unit_name_entry.get()
unit_name_short = unit_name_short_entry.get()
if not unit_name:
messagebox.showerror("Error", "Unit name cannot be empty.")
return
if not unit_name_short:
messagebox.showerror("Error", "Unit name short cannot be empty.")
return
try:
self.cursor.execute('''
INSERT INTO unit (unit_name, unit_name_short)
VALUES (?, ?)
''', (unit_name, unit_name_short))
self.conn.commit()
self.load_unit()
add_window.destroy()
print('Unit successfully added.')
except Exception as e:
messagebox.showerror("Error", f"Error {e} - something went wrong when adding the unit!")
Button(add_window, text="Save", command=save_new_unit).grid(row=2, column=0, columnspan=2)
def edit_unit(self):
try:
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
unit_id = selected_product[0]
edit_window = Toplevel(self.root)
edit_window.title("Edit Product")
entries = {}
row_count = 0
# print(f'\n self.tree["columns"] = {self.tree["columns"]} \n')
for col in self.tree["columns"]:
Label(edit_window, text=col).grid(row=row_count, column=0)
entry = Entry(edit_window)
entry.grid(row=row_count, column=1)
if col == "id":
entry.insert(0, selected_product[row_count])
entry.config(state="readonly")
else:
entry.insert(0, selected_product[row_count])
entries[col] = entry
row_count += 1
def update_unit():
update_values = {}
unit_name = None
for col in self.tree["columns"]:
if col == "id":
continue
value = entries[col].get()
if col == "unit_name":
if not value.isdigit():
self.cursor.execute("SELECT COUNT(*) FROM unit WHERE unit_name = ?", (value,))
result = self.cursor.fetchone()[0]
# print(f'value in update_unit() - {value}')
# print(f'result in update_unit() - {result}')
if result == 0:
unit_name = value
else:
messagebox.showerror("Error", f"Unit_name already exists.")
return
else:
messagebox.showerror("Error", "unit_name must NOT be a number.")
return
update_values[col] = unit_name
if col == "unit_name_short":
if not value.isdigit():
update_values[col] = value
else:
messagebox.showerror("Error", "unit_name_short must NOT be a number.")
return
set_clause_parts = [f"{col} = ?" for col in update_values.keys()]
# print(f'\nset_clause_parts - {set_clause_parts}\n')
set_clause = ", ".join(set_clause_parts)
# print(f'\n set_clause -- {set_clause} \n')
update_values_list = list(update_values.values())
# print(f'update_values_list - {update_values_list}')
update_values_list.append(unit_id)
# print(f'update_values_list ----------- {update_values_list}')
self.cursor.execute(f"UPDATE unit SET {set_clause} WHERE id = ?", update_values_list)
self.conn.commit()
self.load_unit()
edit_window.destroy()
Button(edit_window, text="Save", command=update_unit).grid(row=row_count, column=0, columnspan=2)
except IndexError:
pass
def delete_unit(self):
try:
selected_item = self.tree.selection()[0]
selected_unit = self.tree.item(selected_item)['values']
id_unit = selected_unit[0]
self.cursor.execute("DELETE FROM unit WHERE id = ?", (id_unit,))
self.cursor.execute("UPDATE product SET id_unit = NULL WHERE id_unit = ?", (id_unit,))
# self.load_products()
self.conn.commit()
self.load_unit()
except IndexError:
pass
def add_product(self):
add_window = Toplevel(self.root)
add_window.title("Add Product")
Label(add_window, text="Product Name").grid(row=0, column=0)
product_name_entry = Entry(add_window)
product_name_entry.grid(row=0, column=1)
Label(add_window, text="id Category").grid(row=1, column=0)
id_category_entry = Entry(add_window)
id_category_entry.grid(row=1, column=1)
Label(add_window, text="id unit").grid(row=2, column=0)
id_unit_entry = Entry(add_window)
id_unit_entry.grid(row=2, column=1)
Label(add_window, text="Quantity (optional)").grid(row=3, column=0)
quantity_entry = Entry(add_window)
quantity_entry.grid(row=3, column=1)
Label(add_window, text="Price (optional)").grid(row=4, column=0)
price_entry = Entry(add_window)
price_entry.grid(row=4, column=1)
def save_new_product():
product_name = product_name_entry.get()
id_category = id_category_entry.get()
id_unit = id_unit_entry.get()
quantity = quantity_entry.get()
price = price_entry.get()
try:
if quantity:
quantity = int(quantity_entry.get())
except Exception as _ex:
print(f'in add_product() error: {_ex}')
messagebox.showerror("Error", "Quantity type should be type = int.")
return
try:
if price:
price = int(price_entry.get())
except Exception as _ex:
print(f'in add_product() error: {_ex}')
messagebox.showerror("Error", "Price type should be type = int.")
return
# print(f'type(quantity) - {type(quantity)}')
# print(f'type(price) - {type(price)}')
if not product_name:
messagebox.showerror("Error", "Product name cannot be empty.")
return
self.cursor.execute("SELECT COUNT(*) FROM category WHERE id = ?", (id_category,))
result = self.cursor.fetchone()
# print(f'result on add_prod() - {result}')
## а мб все же так надо???
if result[0] == 0:
messagebox.showerror("Error", f"Parent category with id - '{id_category}' not found.")
return
# if id_category == 0:
# messagebox.showerror("Error", f"Parent category with id - '{id_category}' not found.")
# return
if id_unit:
self.cursor.execute("SELECT COUNT(*) FROM unit WHERE id = ?", (id_unit,))
result_unit_id = self.cursor.fetchone()
if result_unit_id[0] == 0:
messagebox.showerror("Error", f"unit with id - '{id_unit}' not found.")
return
# try:
self.cursor.execute('''
INSERT INTO product (id_category, product_name, id_unit, quantity, price)
VALUES (?, ?, ?, ?, ?)
''', (id_category, product_name, id_unit, quantity, price))
self.conn.commit()
self.load_products()
add_window.destroy()
print('Изделие успешно добавлено.')
# except Exception as _ex:
# messagebox.showerror("Error", f"Error {_ex} - что-то пошло не так при добавлении изделия!")
Button(add_window, text="Save", command=save_new_product).grid(row=5, column=0, columnspan=2)
def edit_product(self):
try:
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
product_id = selected_product[0]
edit_window = Toplevel(self.root)
edit_window.title("Edit Product")
entries = {}
row_count = 0
# print(f'\n self.tree["columns"] = {self.tree["columns"]} \n')
for col in self.tree["columns"]:
Label(edit_window, text=col).grid(row=row_count, column=0)
entry = Entry(edit_window)
entry.grid(row=row_count, column=1)
if col == "id":
entry.insert(0, selected_product[row_count])
entry.config(state="readonly")
else:
entry.insert(0, selected_product[row_count])
entries[col] = entry
row_count += 1
def update_product():
update_values = {}
id_category = None
for col in self.tree["columns"]:
if col == "id":
continue
value = entries[col].get()
if col == "id_category":
if value.isdigit():
self.cursor.execute("SELECT COUNT(*) FROM category WHERE id = ?", (value,))
result = self.cursor.fetchone()
if result[0] > 0:
id_category = value
else:
messagebox.showerror("Error", f"Category with id '{value}' not found.")
return
else:
messagebox.showerror("Error", "id_category must be a number.")
return
update_values[col] = id_category
if col == "quantity":
if not value.isdigit():
messagebox.showerror("Error", "Quantity must be a number.")
return
else:
update_values[col] = value
if col == "price":
if not value.isdigit():
messagebox.showerror("Error", "Price must be a number.")
return
else:
update_values[col] = value
if col == 'id_unit':
if value:
self.cursor.execute("SELECT COUNT(*) FROM unit WHERE id = ?", (value,))
result_unit_id = self.cursor.fetchone()
if result_unit_id[0] == 0:
messagebox.showerror("Error", f"unit with id - '{value}' not found.")
return
else:
update_values[col] = value
else:
update_values[col] = value
set_clause_parts = [f"{col} = ?" for col in update_values.keys()]
# print(f'\nset_clause_parts - {set_clause_parts}\n')
set_clause = ", ".join(set_clause_parts)
# print(f'\n set_clause ---- {set_clause} \n')
update_values_list = list(update_values.values())
# print(f'update_values_list - {update_values_list}')
update_values_list.append(product_id)
self.cursor.execute(f"UPDATE product SET {set_clause} WHERE id = ?", update_values_list)
self.conn.commit()
self.load_products()
edit_window.destroy()
Button(edit_window, text="Save", command=update_product).grid(row=row_count, column=0, columnspan=2)
except IndexError:
pass
def delete_product(self):
try:
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
product_id = selected_product[0]
self.cursor.execute("DELETE FROM product WHERE id = ?", (product_id,))
self.conn.commit()
self.load_products()
except IndexError:
pass
def fill_example_data(self):
# Проверка, пусты ли все таблицы
self.cursor.execute("SELECT COUNT(*) FROM product")
if self.cursor.fetchone()[0] != 0:
messagebox.showinfo("Info", "Tables are not empty. No data added.")
return
self.cursor.execute("SELECT COUNT(*) FROM category")
if self.cursor.fetchone()[0] != 0:
messagebox.showinfo("Info", "Tables are not empty. No data added.")
return
self.cursor.execute("SELECT COUNT(*) FROM unit")
if self.cursor.fetchone()[0] != 0:
messagebox.showinfo("Info", "Tables are not empty. No data added.")
return
# Вызов функции для заполнения контрольным примером
self.add_example_data()
self.load_products()
messagebox.showinfo("Success", "Example data has been successfully added.")
def load_products(self):
# Очистка текущих данных из Treeview
for row in self.tree.get_children():
self.tree.delete(row)
# Получение данных из таблицы product
self.cursor.execute("SELECT * FROM product")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
# Очистка старых заголовков столбцов
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
# Вставка данных в Treeview
for row in rows:
self.tree.insert("", END, values=row)
def delete_category(self):
try:
selected_item = self.tree.selection()[0]
# print(f'selected_item - {selected_item}')
selected_category = self.tree.item(selected_item)['values']
# print(f'selected_category - {selected_category}')
category_name = selected_category[-1]
# print(f'category_name - {category_name}')
if self.is_category_exists(category_name):
self.cursor.execute("SELECT id FROM category WHERE category_name = ?;", (category_name,))
delete_id = self.cursor.fetchone()[0]
# Перемещаем все подкатегории удаляемой категории в категорию "неопределенные"
self.cursor.execute("UPDATE category SET id_parent = (SELECT id FROM category WHERE category_name = 'неопределенные') WHERE id_parent = ?", (delete_id,))
self.cursor.execute("SELECT id_parent FROM category WHERE category_name = ?", ('неопределенные',))
cat_id_undef = self.cursor.fetchone()
if cat_id_undef:
self.cursor.execute("UPDATE category SET id_parent = NULL WHERE category_name = ?", ('неопределенные',))
# self.conn.commit()
# Перемещаем все изделия удаляемой категории в категорию "неопределенные"
self.cursor.execute("UPDATE product SET id_category = (SELECT id FROM category WHERE category_name = 'неопределенные') WHERE id_category = ?", (delete_id,))
# Удаляем категорию
self.cursor.execute("DELETE FROM category WHERE id = ?", (delete_id,))
self.conn.commit()
self.load_categories()
print('Категория успешно удалена.')
else:
print('Указанная категория не существует.')
messagebox.showerror("Error", "Указанная категория не существует.")
except Exception as _ex:
print(f"Произошла ошибка при удалении категории: {_ex}")
messagebox.showerror("Error", f"Произошла ошибка при удалении категории: {_ex}")
def is_category_exists(self, category_name):
self.cursor.execute("SELECT COUNT(*) FROM category WHERE category_name = ?", (category_name,))
count = self.cursor.fetchone()[0]
return count > 0
# additional interface function only (several getters)
def show_category_parents(self):
try:
selected_item = self.tree.selection()[0]
selected_category = self.tree.item(selected_item)['values']
category_id = selected_category[0]
self.cursor.execute("SELECT category_name FROM category WHERE id = ?", (category_id,))
clicked_category_name = self.cursor.fetchone()[0]
# Получаем все предки выбранной категории
parents = []
while category_id:
self.cursor.execute("SELECT id, id_parent, category_name FROM category WHERE id = ?", (category_id,))
result = self.cursor.fetchone()
if not result:
break
id, parent_id, category_name = result
# print(f'\n\nresult - {result}\n\n')
parents.append([id, parent_id, category_name])
category_id = parent_id
# Отображаем новое окно с предками категории
parent_window = Toplevel(self.root)
parent_window.minsize(600, 300)
parent_window.title("Category Parents")
# Получаем имена столбцов из таблицы category
self.cursor.execute("PRAGMA table_info(category)")
columns_info = self.cursor.fetchall()
column_names = [info[1] for info in columns_info]
# Создаем Treeview для отображения предков
parent_tree = ttk.Treeview(parent_window, columns=column_names, show='headings')
parent_tree.pack(expand=True, fill='both')
self.cursor.execute("SELECT id, id_parent, category_name FROM category WHERE category_name = ?", (clicked_category_name,))
result_to_del = self.cursor.fetchone()
id_self, parent_id_self, category_name_self = result_to_del
parents.remove([id_self, parent_id_self, category_name_self])
# Устанавливаем заголовки столбцов
for col in column_names:
parent_tree.heading(col, text=col)
parent_tree.column(col, width=100)
# Вставляем данные предков в Treeview
for parent in reversed(parents): # Обратный порядок для отображения от корня к категории
parent_tree.insert('', 'end', values=parent)
except IndexError:
messagebox.showerror("Error", "No category selected.")
def show_category_children(self):
try:
selected_item = self.tree.selection()[0]
selected_category = self.tree.item(selected_item)['values']
category_id = selected_category[0]
# Рекурсивно получаем всех потомков выбранной категории
children = self.get_all_children(category_id)
# Отображаем новое окно с потомками категории
child_window = Toplevel(self.root)
child_window.minsize(300, 100)
child_window.title("Category Children")
# Получаем имена столбцов из таблицы category
self.cursor.execute("PRAGMA table_info(category)")
columns_info = self.cursor.fetchall()
column_names = [info[1] for info in columns_info]
# Создаем Treeview для отображения предков
parent_tree = ttk.Treeview(child_window, columns=column_names, show='headings')
parent_tree.pack(expand=True, fill='both')
# Устанавливаем заголовки столбцов
for col in column_names:
parent_tree.heading(col, text=col)
parent_tree.column(col, width=100)
for parent in children: # Обратный порядок для отображения от корня к категории
parent_tree.insert('', 'end', values=parent)
except IndexError:
messagebox.showerror("Error", "No category selected.")
def get_all_children(self, category_id):
children = []
# Получаем все дочерние категории для данного родителя
self.cursor.execute("SELECT id, id_parent, category_name FROM category WHERE id_parent = ?", (category_id,))
result = self.cursor.fetchall()
# print(f'\nresult in children - {result}\n')
for row in result:
id, id_parent, category_name = row
children.append([id, id_parent, category_name]) # Добавляем имя дочерней категории
children.extend(self.get_all_children(row[0])) # Рекурсивно добавляем всех потомков для каждой дочерней категории
return children
def show_products_for_category(self):
def get_all_children(category_id):
children = []
self.cursor.execute("SELECT id FROM category WHERE id_parent = ?", (category_id,))
results = self.cursor.fetchall()
for result in results:
children.append(result[0])
children.extend(get_all_children(result[0])) # Assuming id is the first column
return children
try:
selected_item = self.tree.selection()[0]
selected_category = self.tree.item(selected_item)['values']
category_id = selected_category[0]
# Получаем все дочерние категории выбранной категории
all_category_ids = [category_id] + get_all_children(category_id)
# Получаем все изделия для выбранной категории и всех дочерних категорий
products = []
for cat_id in all_category_ids:
self.cursor.execute("SELECT * FROM product WHERE id_category = ?", (cat_id,))
products.extend(self.cursor.fetchall())
column_names = [description[0] for description in self.cursor.description]
# Отображаем новое окно со списком изделий для выбранной категории и её дочерних категорий
products_window = Toplevel(self.root)
products_window.minsize(600, 400)
products_window.title("Products for Category")
# Создаем Treeview для отображения изделий
product_tree = ttk.Treeview(products_window, columns=column_names, show='headings')
product_tree.pack(expand=True, fill='both')
# Устанавливаем заголовки для столбцов
for col in column_names:
product_tree.heading(col, text=col)
product_tree.column(col, width=100)
# Вставляем данные изделий в Treeview
for product in products:
product_tree.insert('', 'end', values=product)
except IndexError:
messagebox.showerror("Error", "No category selected.")
# coursework-2
def load_acceptable_component(self):
for row in self.tree.get_children():
self.tree.delete(row)
self.cursor.execute("SELECT * FROM acceptable_components")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
for row in rows:
self.tree.insert("", END, values=row)
# new_class_id, new_component_id
def create_acceptable_component(self):
add_window = Toplevel(self.root)
add_window.title("Add acceptable component")
Label(add_window, text="Component name").grid(row=0, column=0)
component_name_entry = Entry(add_window)
component_name_entry.grid(row=0, column=1)
Label(add_window, text="Class name").grid(row=1, column=0)
class_name_entry = Entry(add_window)
class_name_entry.grid(row=1, column=1)
def save_new_component():
class_name = class_name_entry.get()
component_name = component_name_entry.get()
self.cursor.execute("SELECT id FROM category WHERE category_name = ?", (class_name,))
new_class_id = self.cursor.fetchone()
if new_class_id:
new_class_id = new_class_id[0]
else:
messagebox.showerror("Error", f"Class name with id - '{new_class_id}' not found.")
return
self.cursor.execute("SELECT id FROM category WHERE category_name = ?", (component_name,))
new_component_id = self.cursor.fetchone()
if new_component_id:
new_component_id = new_component_id[0]
else:
messagebox.showerror("Error", f"Component name with id - '{new_component_id}' not found.")
return
if new_class_id == new_component_id:
messagebox.showerror("Error: нельзя создать цикл с одинаковыми class_id и component_id!")
return
try:
# Recursive query to check for cycles in acceptable_components
self.cursor.execute('''
WITH RECURSIVE cycle_check(class_id, comp_id) AS (
SELECT class_id, component_id
FROM acceptable_components
WHERE class_id = ?
UNION ALL
SELECT ac.class_id, ac.component_id
FROM acceptable_components ac
INNER JOIN cycle_check cc ON ac.class_id = cc.comp_id
)
SELECT 1 FROM cycle_check WHERE comp_id = ?
''', (new_component_id, new_class_id))
# If a result exists, it means adding the new entry would create a cycle
if self.cursor.fetchone():
print(f"Error: добавление пары ({new_class_id}, {new_component_id}) создаёт цикл!")
return 0 # Failure
# Insert the new relationship if no cycle is detected
self.cursor.execute('''
INSERT INTO acceptable_components (class_id, component_id)
VALUES (?, ?)
''', (new_class_id, new_component_id))
self.conn.commit()
self.load_acceptable_component()
add_window.destroy()
print(f"Компонент успешно добавлен: class_id={new_class_id}, component_id={new_component_id}")
return 1 # Success
except sqlite3.OperationalError as e:
print(f"SQL Error: {e}")
return 0 # Failure
except sqlite3.IntegrityError:
print("Error: нарушение ограничений UNIQUE или FOREIGN KEY.")
return 0 # Failure
Button(add_window, text="Save", command=save_new_component).grid(row=5, column=0, columnspan=2)
# cl_id - для какого класса наследуемся
def inherit_acceptable_components(self):
add_window = Toplevel(self.root)
add_window.title("Inherit acceptable components")
Label(add_window, text="Class name").grid(row=0, column=0)
class_name_entry = Entry(add_window)
class_name_entry.grid(row=0, column=1)
def save_new_inherit_acceptable_components():
class_name = class_name_entry.get()
self.cursor.execute("SELECT id FROM category WHERE category_name = ?", (class_name,))
cl_id = self.cursor.fetchone()
if cl_id:
cl_id = cl_id[0]
else:
messagebox.showerror("Error", f"Category name with id - '{cl_id}' not found.")
return
inserted_count = 0
try:
self.cursor.execute('SELECT id_parent FROM category WHERE id = ?', (cl_id,))
parent_cl_id = self.cursor.fetchone()
if parent_cl_id is None:
messagebox.showerror("Parent class ID not found")
return
self.cursor.execute('''
SELECT component_id FROM acceptable_components
WHERE class_id = ?
''', (parent_cl_id[0],))
components = self.cursor.fetchall()
# Insert acceptable components for the child class
for (component_id,) in components:
self.cursor.execute('''
INSERT OR IGNORE INTO acceptable_components (class_id, component_id)
VALUES (?, ?)
''', (cl_id, component_id))
inserted_count += self.cursor.rowcount
self.conn.commit()
messagebox.showinfo("Success", f"произведено {inserted_count} наследований.")
add_window.destroy()
print(f'произведено {inserted_count} наследований')
except Exception as e:
print(f"Error: {e}")
return inserted_count
Button(add_window, text="Save", command=save_new_inherit_acceptable_components).grid(row=5, column=0, columnspan=2)
def load_prod_position_union(self):
for row in self.tree.get_children():
self.tree.delete(row)
self.cursor.execute("SELECT * FROM prod_position_union")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
for row in rows:
self.tree.insert("", END, values=row)
# new_object_id, new_component_id, new_quantity
def create_prod_position_union(self):
add_window = Toplevel(self.root)
add_window.title("Add prod position union")
Label(add_window, text="Product name").grid(row=0, column=0)
product_name_entry = Entry(add_window)
product_name_entry.grid(row=0, column=1)
Label(add_window, text="Component product name").grid(row=1, column=0)
component_name_entry = Entry(add_window)
component_name_entry.grid(row=1, column=1)
Label(add_window, text="Quantity").grid(row=2, column=0)
quantity_entry = Entry(add_window)
quantity_entry.grid(row=2, column=1)
def save_new_prod_position_union():
product_name = product_name_entry.get()
component_name = component_name_entry.get()
quantity_str = quantity_entry.get()
try:
quantity = int(quantity_str)
except ValueError:
messagebox.showerror("Error", "Quantity must be a valid integer.")
return
if (quantity <= 0):
messagebox.showerror("Error", f"quantity cant be <= 0.")
return
self.cursor.execute("SELECT id FROM product WHERE product_name = ?", (product_name,))
new_object_id = self.cursor.fetchone()
if new_object_id:
new_object_id = new_object_id[0]
else:
messagebox.showerror("Error", f"Product name with id - '{new_object_id}' not found.")
return
self.cursor.execute("SELECT id FROM product WHERE product_name = ?", (component_name,))
new_component_id = self.cursor.fetchone()
if new_component_id:
new_component_id = new_component_id[0]
else:
messagebox.showerror("Error", f"Component with id - '{new_component_id}' not found.")
return
try:
self.cursor.execute('SELECT id_category FROM product WHERE id = ?', (new_object_id,))
obj_class_id = self.cursor.fetchone()
if obj_class_id is None:
messagebox.showerror("Object ID not found")
return
self.cursor.execute('SELECT id_category FROM product WHERE id = ?', (new_component_id,))
comp_class_id = self.cursor.fetchone()
if comp_class_id is None:
messagebox.showerror("Component ID not found")
return
self.cursor.execute('''
SELECT 1
FROM acceptable_components
WHERE class_id = ? AND component_id = ?
''', (obj_class_id[0], comp_class_id[0]))
if self.cursor.fetchone() is None:
messagebox.showerror("Invalid composition for the object!")
return
self.cursor.execute('''
INSERT INTO prod_position_union (prod_id, comp_id, quantity)
VALUES (?, ?, ?)
''', (new_object_id, new_component_id, quantity))
self.conn.commit()
self.load_prod_position_union()
add_window.destroy()
print('таблица prod_position_union успешно обновлена новым значением.')
return 1 # Success
except Exception as e:
print(f"Error: {e}")
return 0 # Failure
Button(add_window, text="Save", command=save_new_prod_position_union).grid(row=5, column=0, columnspan=2)
def delete_prod_position_union(self):
try:
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
prod_position_union_id = selected_product[0]
self.cursor.execute("DELETE FROM prod_position_union WHERE id = ?", (prod_position_union_id,))
self.conn.commit()
self.load_prod_position_union()
except IndexError:
pass
def delete_acceptable_component(self):
try:
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
acceptable_component_id = selected_product[0]
self.cursor.execute("DELETE FROM acceptable_components WHERE id = ?", (acceptable_component_id,))
self.conn.commit()
self.load_acceptable_component()
except IndexError:
pass
def edit_prod_position_union_quantity(self):
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
prod_position_union_id = selected_product[0]
add_window = Toplevel(self.root)
add_window.title("Enter new quantity")
Label(add_window, text="Product name").grid(row=0, column=0)
quantity_entry = Entry(add_window)
quantity_entry.grid(row=0, column=1)
def save_quantity():
quantity_str = quantity_entry.get()
try:
quantity = int(quantity_str)
except ValueError:
messagebox.showerror("Error", "Quantity must be a valid integer.")
return
if (quantity <= 0):
messagebox.showerror("Error", f"quantity cant be <= 0.")
return
try:
self.cursor.execute('''
UPDATE prod_position_union
SET quantity = ?
WHERE id = ?
''', (quantity, prod_position_union_id))
self.conn.commit()
self.load_prod_position_union()
add_window.destroy()
except IndexError:
pass
Button(add_window, text="Save", command=save_quantity).grid(row=5, column=0, columnspan=2)
def load_acceptable_components_by_class(self):
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
class_id = selected_product[0]
# Clear the treeview
for row in self.tree.get_children():
self.tree.delete(row)
# Fetch component IDs
self.cursor.execute("SELECT component_id FROM acceptable_components WHERE class_id = ?", (class_id,))
component_ids = self.cursor.fetchall()
if not component_ids:
print(f"No components found for class_id {class_id}.")
return
# Fetch component names for each ID
result = []
for component_id in component_ids:
print(f'component_id - {component_id}')
self.cursor.execute("SELECT category_name FROM category WHERE id = ?", (component_id[0],))
name = self.cursor.fetchone()
if name:
print(f'component_id[0], name[0] - {component_id[0], name[0]}')
result.append((component_id[0], name[0]))
print(f'Для класса с id = {class_id}, составные части: {result}')
for res in result:
print(f'res = {res}')
# Explicitly set up the columns
self.tree["columns"] = ("component_id", "category_name")
self.tree.heading("#0", text="", anchor="w") # Clear default column
self.tree.column("#0", width=0, stretch=False) # Hide the first empty column
for col in self.tree["columns"]:
self.tree.heading(col, text=col, anchor="w")
self.tree.column(col, anchor="w", width=150) # Set width for each column
# self.tree.insert("", "end", values=result)
# Insert rows into the treeview
for row in result:
self.tree.insert("", "end", values=(row[0], row[1]))
# self.tree.insert("", END, values=row)
def load_find_components_by_object(self):
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
object_id = selected_product[0]
for row in self.tree.get_children():
self.tree.delete(row)
self.cursor.execute("SELECT comp_id, quantity FROM prod_position_union WHERE prod_id = ?", (object_id,))
components = self.cursor.fetchall()
if not components:
return []
result = []
for comp_id, quantity in components:
self.cursor.execute("SELECT product_name, quantity FROM product WHERE id = ?", (comp_id,))
name = self.cursor.fetchone()
if name:
result.append(( [name[0]], [ quantity]))
print(f'для объекта с id = {object_id}, составные части: {result}')
column_names = [description[0] for description in self.cursor.description]
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
for row in result:
self.tree.insert("", END, values=row)
def load_acceptable_components_by_class_recursive(self):
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
class_id = selected_product[0]
for row in self.tree.get_children():
self.tree.delete(row)
def find_components(class_id, result):
self.cursor.execute("SELECT component_id FROM acceptable_components WHERE class_id = ?", (class_id,))
components = self.cursor.fetchall()
for component in components:
component_id = component[0]
result.add(component_id)
find_components(component_id, result)
result = set()
find_components(class_id, result)
# Fetch component names for the result set
component_names = []
for component_id in result:
self.cursor.execute("SELECT category_name FROM category WHERE id = ?", (component_id,))
component_name = self.cursor.fetchone()
if component_name:
component_names.append((component_name[0], component_id))
print(f'результат подходящих компонент для id {class_id} - ({component_names})')
column_names = [description[0] for description in self.cursor.description]
print(f'column_names - - - -{column_names}')
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=120) # Устанавливаем ширину столбцов
for row in component_names:
self.tree.insert("", END, values=row)
# object_id
def find_components_recursive(self):
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
object_id = selected_product[0]
for row in self.tree.get_children():
self.tree.delete(row)
# Recursive function to find components
def find_components(obj_id, result):
self.cursor.execute("SELECT comp_id, quantity FROM prod_position_union WHERE prod_id = ?", (obj_id,))
components = self.cursor.fetchall()
for comp_id, quantity in components:
result[comp_id] = result.get(comp_id, 0) + quantity
find_components(comp_id, result)
result = {}
find_components(object_id, result)
# Fetch component names for the result
final_result = []
for comp_id, total_quantity in result.items():
self.cursor.execute("SELECT product_name FROM product WHERE id = ?", (comp_id,))
name = self.cursor.fetchone()
if name:
final_result.append((name[0], comp_id, total_quantity))
print(f'для объекта с id = {object_id} компоненты, найденные рекурсивно: {final_result}')
column_names = [description[0] for description in self.cursor.description]
print(f'column_names - - - -{column_names}')
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=120) # Устанавливаем ширину столбцов
for row in final_result:
self.tree.insert("", END, values=row)
def load_existing_acceptable_components_by_object(self):
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
object_id = selected_product[0]
for row in self.tree.get_children():
self.tree.delete(row)
self.cursor.execute("SELECT id_category FROM product WHERE id = ?", (object_id,))
id_category = self.cursor.fetchone()[0]
# Find the class_id of the object
self.cursor.execute("SELECT id_parent FROM category WHERE id = ?", (id_category,))
class_info = self.cursor.fetchone()
if not class_info:
return []
class_id = class_info[0]
self.cursor.execute('''
SELECT component_id FROM acceptable_components WHERE class_id = ?
''', (class_id,))
components = self.cursor.fetchall()
# Fetch component names for the result
result = []
for component in components:
component_id = component[0]
self.cursor.execute("SELECT category_name FROM category WHERE id = ?", (component_id,))
name = self.cursor.fetchone()
if name:
# result.append((component_id, name[0]))
result.append((name[0]))
print(f'result - {result}')
column_names = [description[0] for description in self.cursor.description]
print(f'column_names - - - -{column_names}')
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=120) # Устанавливаем ширину столбцов
for row in result:
self.tree.insert("", END, values=row)
def load_existing_acceptable_components_by_object_recursive(self):
selected_item = self.tree.selection()[0]
selected_product = self.tree.item(selected_item)['values']
obj_id = selected_product[0]
self.cursor.execute("SELECT id_category FROM product WHERE id = ?", (obj_id,))
class_id = self.cursor.fetchone()
if not class_id:
return []
class_id = class_id[0]
for row in self.tree.get_children():
self.tree.delete(row)
def find_acceptable_components_by_class_recursive(class_id):
try:
def find_components(class_id, result):
self.cursor.execute("SELECT component_id FROM acceptable_components WHERE class_id = ?", (class_id,))
components = self.cursor.fetchall()
for component in components:
component_id = component[0]
result.add(component_id)
find_components(component_id, result)
result = set()
find_components(class_id, result)
# Fetch component names for the result set
component_names = []
for component_id in result:
self.cursor.execute("SELECT category_name FROM category WHERE id = ?", (component_id,))
component_name = self.cursor.fetchone()
if component_name:
component_names.append((component_id, component_name[0]))
print(f'результат подходящих компонент для id {class_id} - ({component_names})')
return component_names
except Exception as e:
print(f"Error occurred while finding acceptable components: {e}")
return []
def find_components(cl_id):
components = []
acceptable_components = find_acceptable_components_by_class_recursive(cl_id)
for component in acceptable_components:
component_id = component[0]
self.cursor.execute("SELECT id, product_name FROM product WHERE id_category = ?", (component_id,))
obj_data = self.cursor.fetchone()
if obj_data:
# components.append({
# obj_data[1]
# })
components.append({
'component_name': obj_data[1],
'component_id': obj_data[0]
})
return components
components = find_components(class_id)
column_names = [description[0] for description in self.cursor.description]
print(f'column_names - - - -{column_names}')
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=120)
for row in components:
self.tree.insert("", END, values=(row['component_id'], row['component_name']))
# coursework-2
def delete_all_data(self):
def dropAllTables():
try:
# Список таблиц в порядке, в котором их нужно удалить (сначала те, которые не содержат внешних ключей)
tables_order = ['category', 'unit', 'product', 'prod_position_union', 'acceptable_components','sqlite_sequence']
# Удаление данных из таблиц с внешними ключами
for table_name in tables_order[::-1]:
self.cursor.execute(f"DELETE FROM {table_name};")
# Удаление самих таблиц
self.cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';")
tables = self.cursor.fetchall()
for table in tables:
table_name = table[0]
self.cursor.execute(f"DROP TABLE IF EXISTS {table_name};")
self.conn.commit()
print("Все таблицы успешно удалены.")
except Exception as _ex:
print(f"Произошла ошибка при удалении таблиц: {_ex}")
def confirm_delete():
if messagebox.askokcancel("Confirm Delete", "Are you sure you want to delete all data from all tables?"):
try:
# self.cursor.execute("DELETE FROM product")
# self.cursor.execute("DELETE FROM category")
# self.cursor.execute("DELETE FROM unit")
dropAllTables()
self.conn.commit()
# повторное создание таблиц для сброса id autoincrement
self.cursor.execute('''CREATE TABLE IF NOT EXISTS category
(id INTEGER PRIMARY KEY AUTOINCREMENT,
id_parent INTEGER,
category_name TEXT UNIQUE,
id_unit INTEGER,
FOREIGN KEY (id_parent) REFERENCES category(id))''')
self.conn.commit()
self.cursor.execute('''CREATE TABLE IF NOT EXISTS product
(id INTEGER PRIMARY KEY AUTOINCREMENT,
id_category INTEGER,
id_unit INTEGER,
product_name TEXT NOT NULL,
quantity INTEGER DEFAULT 0,
price REAL DEFAULT 0,
FOREIGN KEY (id_unit) REFERENCES unit(id),
FOREIGN KEY (id_category) REFERENCES category(id))''')
self.conn.commit()
self.cursor.execute('''CREATE TABLE IF NOT EXISTS unit
(id INTEGER PRIMARY KEY AUTOINCREMENT,
unit_name TEXT NOT NULL UNIQUE,
unit_name_short TEXT NOT NULL)''')
self.conn.commit()
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS acceptable_components (
id INTEGER PRIMARY KEY AUTOINCREMENT,
class_id INTEGER NOT NULL,
component_id INTEGER NOT NULL,
UNIQUE(class_id, component_id),
FOREIGN KEY (class_id) REFERENCES category(id) ON DELETE CASCADE,
FOREIGN KEY (component_id) REFERENCES category(id) ON DELETE CASCADE
)
''')
self.conn.commit()
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS prod_position_union (
id INTEGER PRIMARY KEY AUTOINCREMENT,
prod_id INTEGER NOT NULL,
comp_id INTEGER NOT NULL,
quantity INTEGER NOT NULL CHECK (quantity > 0),
UNIQUE(prod_id, comp_id),
FOREIGN KEY (prod_id) REFERENCES product(id) ON DELETE CASCADE,
FOREIGN KEY (comp_id) REFERENCES product(id) ON DELETE CASCADE
)
''')
self.conn.commit()
# повторное создание таблиц для сброса id autoincrement
messagebox.showinfo("Success", "All data successfully deleted.")
self.load_products()
except Exception as e:
messagebox.showerror("Error", f"Error {e} occurred while deleting data.")
confirm_delete_window = Toplevel(self.root)
confirm_delete_window.title("Confirm Delete")
Label(confirm_delete_window, text="Are you sure you want to delete all data from all tables?").grid(row=0, column=0, columnspan=2, padx=6, pady=10)
Button(confirm_delete_window, text="OK", command=confirm_delete).grid(row=1, column=0, padx=6, pady=10)
Button(confirm_delete_window, text="Cancel", command=confirm_delete_window.destroy).grid(row=1, column=1, padx=6, pady=10)
def add_example_data(self):
self.cursor.execute("INSERT INTO unit (unit_name, unit_name_short) VALUES ('килограмм', 'кг')")
self.cursor.execute("INSERT INTO unit (unit_name, unit_name_short) VALUES ('штук', 'шт')")
self.cursor.execute("INSERT INTO unit (unit_name, unit_name_short) VALUES ('метр', 'м')")
self.cursor.execute("INSERT INTO unit (unit_name, unit_name_short) VALUES ('квадратный метр', 'м2')")
self.cursor.execute("INSERT INTO unit (unit_name, unit_name_short) VALUES ('кубический метр', 'м3')")
self.cursor.execute("INSERT INTO unit (unit_name, unit_name_short) VALUES ('миллиметр', 'мм')")
self.cursor.execute("INSERT INTO unit (unit_name, unit_name_short) VALUES ('ватт', 'вт')")
self.cursor.execute("INSERT INTO unit (unit_name, unit_name_short) VALUES ('вольт', 'в')")
self.cursor.execute("INSERT INTO unit (unit_name, unit_name_short) VALUES ('ампер', 'а')")
# добавление корневых категорий
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, NULL)', ('неопределенные',)) #1
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, NULL)', ('изделия',)) #2
##
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, ?)', ("столы", 2)) #3
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, ?)', ("столы-металл", 3)) #4
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('стол_arizone', 4, 2, 110, 2500.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('стол_garden_story', 4, 2, 54, 5665.0)")
#
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, ?)', ("столы-дерево", 3)) #5
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('стол_эстер', 5, 2, 124, 6460.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('стол_кентуки', 5, 2, 1340, 2400.0)")
##
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, ?)', ("стулья", 2)) #6
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, ?)', ("стулья-пластик", 6)) #7
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('стул_rambo', 7, 2, 435, 1580.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('стул_keter', 7, 2, 252, 1300.0)")
#
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, ?)', ("стулья-металл", 6)) #8
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('стул_arizone', 8, 2, 245, 3400.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('стул_giardino', 8, 2, 25, 2400.0)")
##
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, ?)', ("кресла", 2)) #9
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, ?)', ("кресла-кресло_кокон", 9)) #10
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('кресло-m-group', 10, 2, 24, 12000.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('кресло-гамак', 10, 2, 14, 15500.0)")
#
self.cursor.execute('INSERT INTO category (category_name, id_parent) VALUES (?, ?)', ("кресла-двухместное_кресло", 9)) #11
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('кресло-gemini_promob', 11, 2, 4, 8999.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('кресло-парящая_кровать', 11, 2, 54, 9999.0)")
# coursework-2
self.cursor.execute('INSERT INTO category (category_name, id_parent, id_unit) VALUES (?, ?, ?)', ("ножка стола", 3, 6)) #12
self.cursor.execute('INSERT INTO category (category_name, id_parent, id_unit) VALUES (?, ?, ?)', ("основание ножки стола", 12, 6)) #13
self.cursor.execute('INSERT INTO category (category_name, id_parent, id_unit) VALUES (?, ?, ?)', ("крепление ножки стола", 12, 6)) #14
self.cursor.execute('INSERT INTO category (category_name, id_parent, id_unit) VALUES (?, ?, ?)', ("столешница стола", 3, 6)) #15
self.cursor.execute('INSERT INTO category (category_name, id_parent, id_unit) VALUES (?, ?, ?)', ("основная часть столешница", 15, 6)) #16
self.cursor.execute('INSERT INTO category (category_name, id_parent, id_unit) VALUES (?, ?, ?)', ("крепления столешницы стола", 15, 6)) #17
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('ножка_стола_стальная', 12, 6, 440, 200.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('основание-ножка_стола_стальная', 13, 6, 880, 10.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('крепление-ножка_стола_стальная', 14, 6, 880, 10.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('столешница_стола_стальная', 15, 6, 110, 800.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('основа-столешница_стола_стальная', 16, 6, 110, 400.0)")
self.cursor.execute("INSERT INTO product (product_name, id_category, id_unit, quantity, price) VALUES ('крепление-столешница_стола_стальная', 17, 6, 110, 200.0)")
self.cursor.execute('INSERT INTO acceptable_components (class_id, component_id) VALUES (?, ?)', (3, 12)) # для "столы" ножки
self.cursor.execute('INSERT INTO acceptable_components (class_id, component_id) VALUES (?, ?)', (3, 15)) # для "столы" столешницы
# чтобы отдельно не писать для каждого стола можно вызвать функцию
# inherit_acceptable_components(cl_name), где cl_name - класс для которого
# хотим наследоваться
# self.cursor.execute('INSERT INTO acceptable_components (class_id, component_id) VALUES (?, ?)', (4, 12))
self.cursor.execute('INSERT INTO acceptable_components (class_id, component_id) VALUES (?, ?)', (12, 13))
self.cursor.execute('INSERT INTO acceptable_components (class_id, component_id) VALUES (?, ?)', (12, 14))
self.cursor.execute('INSERT INTO acceptable_components (class_id, component_id) VALUES (?, ?)', (15, 16))
self.cursor.execute('INSERT INTO acceptable_components (class_id, component_id) VALUES (?, ?)', (15, 17))
self.cursor.execute('INSERT INTO prod_position_union (prod_id, comp_id, quantity) VALUES (?, ?, ?)', (1, 13, 4)) # ножка_стола_стальная
self.cursor.execute('INSERT INTO prod_position_union (prod_id, comp_id, quantity) VALUES (?, ?, ?)', (13, 14, 1)) # основание-ножка_стола_стальная
self.cursor.execute('INSERT INTO prod_position_union (prod_id, comp_id, quantity) VALUES (?, ?, ?)', (13, 15, 1)) # крепление-ножка_стола_стальная
self.cursor.execute('INSERT INTO prod_position_union (prod_id, comp_id, quantity) VALUES (?, ?, ?)', (1, 16, 4)) # столешница_стола_стальная
self.cursor.execute('INSERT INTO prod_position_union (prod_id, comp_id, quantity) VALUES (?, ?, ?)', (16, 17, 1)) # основа-столешница_стола_стальная
self.cursor.execute('INSERT INTO prod_position_union (prod_id, comp_id, quantity) VALUES (?, ?, ?)', (16, 18, 1)) # крепление-столешница_стола_стальная
self.conn.commit()
def __del__(self):
self.conn.close()
###################################################################################################################
class DatabaseUserApp:
def __init__(self, root):
self.root = root
self.root.title("coursework")
root.geometry("1000x600")
self.conn = sqlite3.connect(path)
self.cursor = self.conn.cursor()
self.tree = ttk.Treeview(root, show="headings")
self.tree.grid(row=0, column=0, columnspan=5, sticky="nsew", padx=6, pady=10)
self.load_button = ttk.Button(root, text="Load Products", command=self.load_products)
self.load_button.grid(row=1, column=0, sticky="ew", padx=6, pady=2)
self.load_find_components_by_objectbutton = ttk.Button(root, text="find components by object ", command=self.load_find_components_by_object)
self.load_find_components_by_objectbutton.grid(row=5, column=0, sticky="ew", padx=6, pady=2)
self.find_components_recursive_object_button = ttk.Button(root, text="find components recursive", command=self.find_components_recursive)
self.find_components_recursive_object_button.grid(row=6, column=0, sticky="ew", padx=6, pady=2)
self.load_existing_acceptable_components_by_object_button = ttk.Button(root, text="available components category", command=self.load_existing_acceptable_components_by_object)
self.load_existing_acceptable_components_by_object_button.grid(row=7, column=0, sticky="ew", padx=6, pady=2)
self.load_existing_acceptable_components_by_object_recursive_button = ttk.Button(root, text="available components recursive category", command=self.load_existing_acceptable_components_by_object_recursive)
self.load_existing_acceptable_components_by_object_recursive_button.grid(row=8, column=0, sticky="ew", padx=6, pady=2)
self.load_category_button = ttk.Button(root, text="Load Categories", command=self.load_categories)
self.load_category_button.grid(row=1, column=1, sticky="ew", padx=6, pady=2)
self.show_parents_button = ttk.Button(root, text="Show Parents", command=self.show_category_parents)
self.show_parents_button.grid(row=5, column=1, sticky="ew", padx=6, pady=2)
self.show_children_button = ttk.Button(root, text="Show Children", command=self.show_category_children)
self.show_children_button.grid(row=6, column=1, sticky="ew", padx=6, pady=2)
self.show_products_button = ttk.Button(root, text="Show products", command=self.show_products_for_category)
self.show_products_button.grid(row=7, column=1, sticky="ew", padx=6, pady=2)
self.load_acceptable_components_by_class_button = ttk.Button(root, text="Show acceptable components by class", command=self.load_acceptable_components_by_class)
self.load_acceptable_components_by_class_button.grid(row=8, column=1, sticky="ew", padx=6, pady=2)
self.load_acceptable_components_by_class_recursive_button = ttk.Button(root, text="Show acceptable components by class recoursive", command=self.load_acceptable_components_by_class_recursive)
self.load_acceptable_components_by_class_recursive_button.grid(row=9, column=1, sticky="ew", padx=6, pady=2)
self.load_unit_button = ttk.Button(root, text="Load Unit", command=self.load_unit)
self.load_unit_button.grid(row=1, column=2, sticky="ew", padx=6, pady=2)
self.load_acceptable_components_button = ttk.Button(root, text="Load acceptable components", command=self.load_acceptable_component)
self.load_acceptable_components_button.grid(row=1, column=3, sticky="ew", padx=6, pady=2)
self.load_prod_position_union_button = ttk.Button(root, text="Load prod position union", command=self.load_prod_position_union)
self.load_prod_position_union_button.grid(row=1, column=4, sticky="ew", padx=6, pady=2)
# Configure row and column to resize
root.rowconfigure(0, weight=1)
root.columnconfigure(0, weight=1)
root.columnconfigure(1, weight=1)
root.columnconfigure(2, weight=1)
root.columnconfigure(3, weight=1)
root.columnconfigure(4, weight=1)
def create_category_table():
self.cursor.execute('''CREATE TABLE IF NOT EXISTS category
(id INTEGER PRIMARY KEY AUTOINCREMENT,
id_parent INTEGER CHECK (id_parent != id),
category_name TEXT UNIQUE,
id_unit INTEGER,
FOREIGN KEY (id_parent) REFERENCES category(id))''')
self.conn.commit()
def create_product_table():
self.cursor.execute('''CREATE TABLE IF NOT EXISTS product
(id INTEGER PRIMARY KEY AUTOINCREMENT,
id_category INTEGER,
id_unit INTEGER,
product_name TEXT NOT NULL,
quantity INTEGER DEFAULT 0,
price REAL DEFAULT 0,
FOREIGN KEY (id_unit) REFERENCES unit(id),
FOREIGN KEY (id_category) REFERENCES category(id))''')
self.conn.commit()
def create_unit_table():
self.cursor.execute('''CREATE TABLE IF NOT EXISTS unit
(id INTEGER PRIMARY KEY AUTOINCREMENT,
unit_name TEXT NOT NULL UNIQUE,
unit_name_short TEXT NOT NULL)''')
self.conn.commit()
def create_acceptable_components_table():
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS acceptable_components (
id INTEGER PRIMARY KEY AUTOINCREMENT,
class_id INTEGER NOT NULL,
component_id INTEGER NOT NULL,
UNIQUE(class_id, component_id),
FOREIGN KEY (class_id) REFERENCES category(id) ON DELETE CASCADE,
FOREIGN KEY (component_id) REFERENCES category(id) ON DELETE CASCADE
)
''')
self.conn.commit()
def create_prod_position_union_table():
self.cursor.execute('''
CREATE TABLE IF NOT EXISTS prod_position_union (
id INTEGER PRIMARY KEY AUTOINCREMENT,
prod_id INTEGER NOT NULL,
comp_id INTEGER NOT NULL,
quantity INTEGER NOT NULL CHECK (quantity > 0),
UNIQUE(prod_id, comp_id),
FOREIGN KEY (prod_id) REFERENCES product(id) ON DELETE CASCADE,
FOREIGN KEY (comp_id) REFERENCES product(id) ON DELETE CASCADE
)
''')
self.conn.commit()
def creating_tables():
create_category_table()
create_product_table()
create_unit_table()
# coursework-2
create_acceptable_components_table()
create_prod_position_union_table()
creating_tables()
def load_unit(self):
# Очистка текущих данных из Treeview
for row in self.tree.get_children():
self.tree.delete(row)
# Получение данных из таблицы unit
self.cursor.execute("SELECT * FROM unit")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
# Очистка старых заголовков столбцов
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
# Вставка данных в Treeview
for row in rows:
self.tree.insert("", "end", values=row)
def load_products(self):
# Очистка текущих данных из Treeview
for row in self.tree.get_children():
self.tree.delete(row)
# Получение данных из таблицы product
self.cursor.execute("SELECT * FROM product")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
# Очистка старых заголовков столбцов
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
# Вставка данных в Treeview
for row in rows:
self.tree.insert("", END, values=row)
def load_categories(self):
# Очистка текущих данных из Treeview
for row in self.tree.get_children():
self.tree.delete(row)
# Получение данных из таблицы category
self.cursor.execute("SELECT * FROM category")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
# Очистка старых заголовков столбцов
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
# Вставка данных в Treeview
for row in rows:
self.tree.insert("", END, values=row)
def load_products(self):
# Очистка текущих данных из Treeview
for row in self.tree.get_children():
self.tree.delete(row)
# Получение данных из таблицы product
self.cursor.execute("SELECT * FROM product")
rows = self.cursor.fetchall()
column_names = [description[0] for description in self.cursor.description]
# Очистка старых заголовков столбцов
self.tree["columns"] = column_names
for col in self.tree["columns"]:
self.tree.heading(col, text=col)
self.tree.column(col, width=100) # Устанавливаем ширину столбцов
# Вставка данных в Treeview
for row in rows:
self.tree.insert("", END, values=row)
# additional interface function only (several getters)
def show_category_parents(self):
try:
selected_item = self.tree.selection()[0]
selected_category = self.tree.item(selected_item)['values']
category_id = selected_category[0]
self.cursor.execute("SELECT category_name FROM category WHERE id = ?", (category_id,))
clicked_category_name = self.cursor.fetchone()[0]
# Получаем все предки выбранной категории
parents = []
while category_id:
self.cursor.execute("SELECT id, id_parent, category_name FROM category WHERE id = ?", (category_id,))
result = self.cursor.fetchone()
if not result:
break
id, parent_id, category_name = result
# print(f'\n\nresult - {result}\n\n')
parents.append([id, parent_id, category_name])
category_id = parent_id
# Отображаем новое окно с предками категории
parent_window = Toplevel(self.root)
parent_window.minsize(600, 300)
parent_window.title("Category Parents")
# Получаем имена столбцов из таблицы category
self.cursor.execute("PRAGMA table_info(category)")
columns_info = self.cursor.fetchall()
column_names = [info[1] for info in columns_info]
# Создаем Treeview для отображения предков
parent_tree = ttk.Treeview(parent_window, columns=column_names, show='headings')
parent_tree.pack(expand=True, fill='both')
self.cursor.execute("SELECT id, id_parent, category_name FROM category WHERE category_name = ?", (clicked_category_name,))
result_to_del = self.cursor.fetchone()
id_self, parent_id_self, category_name_self = result_to_del
parents.remove([id_self, parent_id_self, category_name_self])
# Устанавливаем заголовки столбцов
for col in column_names:
parent_tree.heading(col, text=col)
parent_tree.column(col, width=100)
# Вставляем данные предков в Treeview
for parent in reversed(parents): # Обратный порядок для отображения от корня к категории
parent_tree.insert('', 'end', values=parent)
except IndexError:
messagebox.showerror("Error", "No category selected.")
def show_category_children(self):
try:
selected_item = self.tree.selection()[0]
selected_category = self.tree.item(selected_item)['values']
category_id = selected_category[0]
# Рекурсивно получаем всех потомков выбранной категории
children = self.get_all_children(category_id)
# Отображаем новое окно с потомками категории
child_window = Toplevel(self.root)
child_window.minsize(300, 100)
child_window.title("Category Children")
# Получаем имена столбцов из таблицы category
self.cursor.execute("PRAGMA table_info(category)")
columns_info = self.cursor.fetchall()
column_names = [info[1] for info in columns_info]
# Создаем Treeview для отображения предков
parent_tree = ttk.Treeview(child_window, columns=column_names, show='headings')
parent_tree.pack(expand=True, fill='both')
# Устанавливаем заголовки столбцов
for col in column_names:
parent_tree.heading(col, text=col)
parent_tree.column(col, width=100)
for parent in children: # Обратный порядок для отображения от корня к категории
parent_tree.insert('', 'end', values=parent)
except IndexError:
messagebox.showerror("Error", "No category selected.")
def get_all_children(self, category_id):
children = []
# Получаем все дочерние категории для данного родителя
self.cursor.execute("SELECT id, id_parent, category_name FROM category WHERE id_parent = ?", (category_id,))
result = self.cursor.fetchall()
# print(f'\nresult in children - {result}\n')
for row in result:
id, id_parent, category_name = row
children.append([id, id_parent, category_name]) # Добавляем имя дочерней категории
children.extend(self.get_all_children(row[0])) # Рекурсивно добавляем всех потомков для каждой дочерней категории
return children
def show_products_for_category(self):
def get_all_children(category_id):
children = []
self.cursor.execute("SELECT id FROM category WHERE id_parent = ?", (category_
Соседние файлы в папке курсач