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


import tkinter as tk
from tkinter import messagebox
from bd import get_connection

SORT_OPTIONS = {
    "Название": "name",
    "Цена": "price",
    "Категория": "category"
}

def set_icon(window):
    try:
        window.iconbitmap("Icon.ico")
    except Exception:
        pass

def add_logo(window):
    try:
        logo_img = tk.PhotoImage(file="logo.png")
        logo_img = logo_img.subsample(4, 4)
        label = tk.Label(window, image=logo_img, bg="white")
        label.image = logo_img
        label.pack(pady=(10, 0))
    except Exception:
        pass

def load_products(list_frame, search_text="", order_by="name"):
    for widget in list_frame.winfo_children():
        widget.destroy()

    conn = get_connection()
    cur = conn.cursor()
    query = f"SELECT article, name, price, category, stock_qty FROM products WHERE name ILIKE %s ORDER BY {order_by}"
    cur.execute(query, (f"%{search_text}%",))
    products = cur.fetchall()
    conn.close()

    header = tk.Label(list_frame, text=f"{'Артикул':<10}{'Название':<20}{'Цена':<10}{'Категория':<18}{'Кол-во'}", bg="white", font=("Courier New", 10, "bold"))
    header.pack(anchor="w")

    for article, name, price, category, qty in products:
        line = f"{article:<10}{name:<20}{str(price):<10}{category:<18}{qty}"
        tk.Label(list_frame, text=line, bg="white", font=("Courier New", 10)).pack(anchor="w")

def open_add_product_window(list_frame):
    win = tk.Toplevel()
    win.title("Добавить товар")
    win.configure(bg="white")
    set_icon(win)

    fields = {}
    labels = ["Артикул", "Название", "Ед. изм.", "Цена", "Поставщик", "Производитель", "Категория", "Скидка", "Кол-во на складе"]
    for i, label in enumerate(labels):
        tk.Label(win, text=label, bg="white", font=("Times New Roman", 10)).grid(row=i, column=0, sticky="w", padx=10, pady=5)
        entry = tk.Entry(win, font=("Times New Roman", 10))
        entry.grid(row=i, column=1, padx=10, pady=5)
        fields[label] = entry

    def save():
        if not fields["Артикул"].get() or not fields["Название"].get() or not fields["Цена"].get():
            messagebox.showerror("Ошибка", "Заполните артикул, название и цену")
            return
        conn = get_connection()
        cur = conn.cursor()
        cur.execute(
            "INSERT INTO products (article, name, unit, price, supplier, manufacturer, category, discount, stock_qty) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s)",
            (
                fields["Артикул"].get(), fields["Название"].get(), fields["Ед. изм."].get(),
                fields["Цена"].get(), fields["Поставщик"].get(), fields["Производитель"].get(),
                fields["Категория"].get(), fields["Скидка"].get() or 0, fields["Кол-во на складе"].get() or 0
            )
        )
        conn.commit()
        conn.close()
        win.destroy()
        load_products(list_frame)

    tk.Button(win, text="Сохранить", bg="#00FA9A", font=("Times New Roman", 10), command=save).grid(row=len(labels), column=0, columnspan=2, pady=15)

def open_delete_product_window(list_frame):
    win = tk.Toplevel()
    win.title("Удалить товар")
    win.configure(bg="white")
    set_icon(win)

    tk.Label(win, text="Артикул товара", bg="white", font=("Times New Roman", 10)).pack(padx=10, pady=(10, 0))
    article_entry = tk.Entry(win, font=("Times New Roman", 10))
    article_entry.pack(padx=10, pady=5)

    def delete():
        if not article_entry.get():
            messagebox.showerror("Ошибка", "Введите артикул")
            return
        conn = get_connection()
        cur = conn.cursor()
        cur.execute("DELETE FROM order_items WHERE product_article = %s", (article_entry.get(),))
        cur.execute("DELETE FROM products WHERE article = %s", (article_entry.get(),))
        conn.commit()
        conn.close()
        win.destroy()
        load_products(list_frame)

    tk.Button(win, text="Удалить", bg="#E24B4A", font=("Times New Roman", 10), command=delete).pack(pady=15)

def open_edit_product_window(list_frame):
    win = tk.Toplevel()
    win.title("Редактировать товар")
    win.configure(bg="white")
    set_icon(win)

    tk.Label(win, text="Артикул товара", bg="white", font=("Times New Roman", 10)).grid(row=0, column=0, sticky="w", padx=10, pady=5)
    article_entry = tk.Entry(win, font=("Times New Roman", 10))
    article_entry.grid(row=0, column=1, padx=10, pady=5)

    tk.Label(win, text="Новая цена", bg="white", font=("Times New Roman", 10)).grid(row=1, column=0, sticky="w", padx=10, pady=5)
    price_entry = tk.Entry(win, font=("Times New Roman", 10))
    price_entry.grid(row=1, column=1, padx=10, pady=5)

    tk.Label(win, text="Новое кол-во на складе", bg="white", font=("Times New Roman", 10)).grid(row=2, column=0, sticky="w", padx=10, pady=5)
    qty_entry = tk.Entry(win, font=("Times New Roman", 10))
    qty_entry.grid(row=2, column=1, padx=10, pady=5)

    def save():
        if not article_entry.get():
            messagebox.showerror("Ошибка", "Введите артикул")
            return
        conn = get_connection()
        cur = conn.cursor()
        cur.execute(
            "UPDATE products SET price = %s, stock_qty = %s WHERE article = %s",
            (price_entry.get(), qty_entry.get(), article_entry.get())
        )
        conn.commit()
        conn.close()
        win.destroy()
        load_products(list_frame)

    tk.Button(win, text="Сохранить", bg="#00FA9A", font=("Times New Roman", 10), command=save).grid(row=3, column=0, columnspan=2, pady=15)

def load_orders(list_frame):
    for widget in list_frame.winfo_children():
        widget.destroy()

    conn = get_connection()
    cur = conn.cursor()
    cur.execute("""
        SELECT o.id, u.full_name, o.order_date, o.delivery_date, o.status
        FROM orders o
        JOIN users u ON u.id = o.client_id
        ORDER BY o.id
    """)
    orders = cur.fetchall()
    conn.close()

    header = tk.Label(list_frame, text=f"{'№':<5}{'Клиент':<28}{'Дата заказа':<14}{'Доставка':<14}{'Статус'}", bg="white", font=("Courier New", 10, "bold"))
    header.pack(anchor="w")

    for order_id, client, order_date, delivery_date, status in orders:
        line = f"{order_id:<5}{client:<28}{str(order_date):<14}{str(delivery_date):<14}{status}"
        tk.Label(list_frame, text=line, bg="white", font=("Courier New", 10)).pack(anchor="w")

def open_add_order_window(list_frame):
    win = tk.Toplevel()
    win.title("Добавить заказ")
    win.configure(bg="white")
    set_icon(win)

    labels = ["ID клиента", "Дата заказа (ГГГГ-ММ-ДД)", "Дата доставки (ГГГГ-ММ-ДД)", "ID пункта выдачи", "Код получения", "Статус"]
    fields = {}
    for i, label in enumerate(labels):
        tk.Label(win, text=label, bg="white", font=("Times New Roman", 10)).grid(row=i, column=0, sticky="w", padx=10, pady=5)
        entry = tk.Entry(win, font=("Times New Roman", 10))
        entry.grid(row=i, column=1, padx=10, pady=5)
        fields[label] = entry

    def save():
        if not fields["ID клиента"].get() or not fields["Дата заказа (ГГГГ-ММ-ДД)"].get():
            messagebox.showerror("Ошибка", "Заполните хотя бы ID клиента и дату заказа")
            return
        conn = get_connection()
        cur = conn.cursor()
        cur.execute(
            "INSERT INTO orders (client_id, order_date, delivery_date, pickup_point_id, pickup_code, status) VALUES (%s,%s,%s,%s,%s,%s)",
            (
                fields["ID клиента"].get(),
                fields["Дата заказа (ГГГГ-ММ-ДД)"].get(),
                fields["Дата доставки (ГГГГ-ММ-ДД)"].get() or None,
                fields["ID пункта выдачи"].get() or None,
                fields["Код получения"].get() or None,
                fields["Статус"].get() or "Новый"
            )
        )
        conn.commit()
        conn.close()
        win.destroy()
        load_orders(list_frame)

    tk.Button(win, text="Сохранить", bg="#00FA9A", font=("Times New Roman", 10), command=save).grid(row=len(labels), column=0, columnspan=2, pady=15)

def open_edit_order_window(list_frame):
    win = tk.Toplevel()
    win.title("Изменить статус заказа")
    win.configure(bg="white")
    set_icon(win)

    tk.Label(win, text="Номер заказа", bg="white", font=("Times New Roman", 10)).grid(row=0, column=0, sticky="w", padx=10, pady=5)
    id_entry = tk.Entry(win, font=("Times New Roman", 10))
    id_entry.grid(row=0, column=1, padx=10, pady=5)

    tk.Label(win, text="Новый статус", bg="white", font=("Times New Roman", 10)).grid(row=1, column=0, sticky="w", padx=10, pady=5)
    status_entry = tk.Entry(win, font=("Times New Roman", 10))
    status_entry.grid(row=1, column=1, padx=10, pady=5)

    def save():
        if not id_entry.get() or not status_entry.get():
            messagebox.showerror("Ошибка", "Заполните номер заказа и статус")
            return
        conn = get_connection()
        cur = conn.cursor()
        cur.execute("UPDATE orders SET status = %s WHERE id = %s", (status_entry.get(), id_entry.get()))
        conn.commit()
        conn.close()
        win.destroy()
        load_orders(list_frame)

    tk.Button(win, text="Сохранить", bg="#00FA9A", font=("Times New Roman", 10), command=save).grid(row=2, column=0, columnspan=2, pady=15)

def open_delete_order_window(list_frame):
    win = tk.Toplevel()
    win.title("Удалить заказ")
    win.configure(bg="white")
    set_icon(win)

    tk.Label(win, text="Номер заказа", bg="white", font=("Times New Roman", 10)).pack(padx=10, pady=(10, 0))
    id_entry = tk.Entry(win, font=("Times New Roman", 10))
    id_entry.pack(padx=10, pady=5)

    def delete():
        if not id_entry.get():
            messagebox.showerror("Ошибка", "Введите номер заказа")
            return
        conn = get_connection()
        cur = conn.cursor()
        cur.execute("DELETE FROM order_items WHERE order_id = %s", (id_entry.get(),))
        cur.execute("DELETE FROM orders WHERE id = %s", (id_entry.get(),))
        conn.commit()
        conn.close()
        win.destroy()
        load_orders(list_frame)

    tk.Button(win, text="Удалить", bg="#E24B4A", font=("Times New Roman", 10), command=delete).pack(pady=15)

def open_orders_window(role):
    win = tk.Toplevel()
    win.title("Заказы")
    win.configure(bg="white")
    win.geometry("680x420")
    set_icon(win)

    list_frame = tk.Frame(win, bg="white")

    if role == "Администратор":
        actions = tk.Frame(win, bg="white")
        actions.pack(fill="x", padx=10, pady=10)
        tk.Button(actions, text="Добавить заказ", bg="#00FA9A", font=("Times New Roman", 10), command=lambda: open_add_order_window(list_frame)).pack(side="left", padx=(0, 10))
        tk.Button(actions, text="Изменить статус", bg="#00FA9A", font=("Times New Roman", 10), command=lambda: open_edit_order_window(list_frame)).pack(side="left", padx=(0, 10))
        tk.Button(actions, text="Удалить заказ", bg="#E24B4A", font=("Times New Roman", 10), command=lambda: open_delete_order_window(list_frame)).pack(side="left")

    list_frame.pack(fill="both", expand=True, padx=10)
    load_orders(list_frame)

def open_catalog(role, full_name):
    login_window.destroy()
    catalog = tk.Tk()
    catalog.title(f"ООО Обувь — товары ({role})")
    catalog.geometry("680x500")
    catalog.configure(bg="white")
    set_icon(catalog)
    add_logo(catalog)

    tk.Label(catalog, text=f"Вы вошли как: {full_name} ({role})", bg="white", font=("Times New Roman", 12)).pack(pady=10)

    list_frame = tk.Frame(catalog, bg="white")

    if role in ("Менеджер", "Администратор"):
        controls = tk.Frame(catalog, bg="white")
        controls.pack(fill="x", padx=10, pady=(0, 5))

        tk.Label(controls, text="Поиск:", bg="white", font=("Times New Roman", 10)).pack(side="left")
        search_entry = tk.Entry(controls, font=("Times New Roman", 10))
        search_entry.pack(side="left", padx=(5, 15))

        sort_var = tk.StringVar(value="Название")
        tk.Label(controls, text="Сортировка:", bg="white", font=("Times New Roman", 10)).pack(side="left")
        sort_menu = tk.OptionMenu(controls, sort_var, *SORT_OPTIONS.keys())
        sort_menu.pack(side="left", padx=(5, 15))

        tk.Button(
            controls, text="Применить", bg="#7FFF00", font=("Times New Roman", 10),
            command=lambda: load_products(list_frame, search_entry.get(), SORT_OPTIONS[sort_var.get()])
        ).pack(side="left")

        actions = tk.Frame(catalog, bg="white")
        actions.pack(fill="x", padx=10, pady=(0, 10))

        tk.Button(actions, text="Заказы", bg="#7FFF00", font=("Times New Roman", 10), command=lambda: open_orders_window(role)).pack(side="left", padx=(0, 10))

        if role == "Администратор":
            tk.Button(actions, text="Добавить товар", bg="#00FA9A", font=("Times New Roman", 10), command=lambda: open_add_product_window(list_frame)).pack(side="left", padx=(0, 10))
            tk.Button(actions, text="Редактировать товар", bg="#00FA9A", font=("Times New Roman", 10), command=lambda: open_edit_product_window(list_frame)).pack(side="left", padx=(0, 10))
            tk.Button(actions, text="Удалить товар", bg="#E24B4A", font=("Times New Roman", 10), command=lambda: open_delete_product_window(list_frame)).pack(side="left")

    list_frame.pack(fill="both", expand=True, padx=10)
    load_products(list_frame)

    catalog.mainloop()

def check_login(login_entry, password_entry):
    login = login_entry.get()
    password = password_entry.get()
    conn = get_connection()
    cur = conn.cursor()
    cur.execute("SELECT id, role, full_name FROM users WHERE login = %s AND password = %s", (login, password))
    user = cur.fetchone()
    conn.close()
    if user:
        open_catalog(user[1], user[2])
    else:
        messagebox.showerror("Ошибка", "Неверный логин или пароль")

login_window = tk.Tk()
login_window.title("ООО Обувь — вход")
login_window.geometry("300x320")
login_window.configure(bg="white")
set_icon(login_window)
add_logo(login_window)

tk.Label(login_window, text="Логин", bg="white", font=("Times New Roman", 11)).pack(pady=(15, 0))
login_entry = tk.Entry(login_window, font=("Times New Roman", 11))
login_entry.pack()

tk.Label(login_window, text="Пароль", bg="white", font=("Times New Roman", 11)).pack(pady=(10, 0))
password_entry = tk.Entry(login_window, show="*", font=("Times New Roman", 11))
password_entry.pack()

tk.Button(login_window, text="Войти", bg="#00FA9A", font=("Times New Roman", 11), command=lambda: check_login(login_entry, password_entry)).pack(pady=20)

tk.Button(login_window, text="Продолжить как гость", bg="white", font=("Times New Roman", 9, "underline"), relief="flat", command=lambda: open_catalog("Гость", "Гость")).pack()

login_window.mainloop()