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


import random

import pymysql
import sys
from PyQt6 import QtWidgets
from PyQt6.QtGui import QIcon, QPixmap
from PyQt6.QtWidgets import *
from PyQt6 import QtCore
from PyQt6 import QtGui
from PyQt6.QtWidgets import QApplication
from PyQt6.QtWidgets import QMainWindow
from auth import Ui_AuthWindow
from main_win import Ui_MainWindow
from edit import Ui_EditAddWin
import os
import shutil
from order_edit import Ui_OrderWindow

class Database:
    def __init__(self):
        self.conn = pymysql.connect(
            host='localhost',
            user='root',
            database='shoes_shop',
            password='12345',
            cursorclass=pymysql.cursors.DictCursor
        )
        self.cursor = self.conn.cursor()

    def check_user(self, login, password):
        self.cursor.execute("SELECT * FROM users WHERE login = %s AND password = %s",(login,password))
        return self.cursor.fetchone()

    def load_products(self):
        self.cursor.execute("""SELECT p.id, p.article, p.name, p.unit, p.price, p.description, p.discount, p.stock_quantity, p.photo, c.name AS category_name, m.name AS manufacturer_name, s.name AS supplier_name 
        FROM products p
        JOIN categories c ON p.category_id = c.id
        JOIN manufacturers m ON p.manufacturer_id = m.id
        JOIN suppliers s ON p.supplier_id = s.id
        """)
        return self.cursor.fetchall()

    def load_categories(self):
        self.cursor.execute("SELECT * FROM categories")
        return self.cursor.fetchall()

    def load_suppliers(self):
        self.cursor.execute("SELECT * FROM suppliers")
        return self.cursor.fetchall()

    def load_manufacturers(self):
        self.cursor.execute("SELECT * FROM manufacturers")
        return self.cursor.fetchall()

    def searching(self, text):
        self.cursor.execute("""SELECT p.article, p.name, p.unit, p.price, p.description, p.discount, p.stock_quantity, p.photo, c.name AS category_name, m.name AS manufacturer_name, s.name AS supplier_name 
        FROM products p
        JOIN categories c ON p.category_id = c.id
        JOIN manufacturers m ON p.manufacturer_id = m.id
        JOIN suppliers s ON p.supplier_id = s.id
        WHERE p.name LIKE %s OR p.description LIKE %s
        """, (f"%{text}%", f"%{text}%"))
        return self.cursor.fetchall()

    def load_orders(self):
        self.cursor.execute("""SELECT o.code, o.status, o.order_date, o.delivery_date, p.address
        FROM orders o
        JOIN pickup_points p ON o.pickup_point_id = p.id
        """)
        return self.cursor.fetchall()

    def edit_product(self, name, unit, price, description, discount, stock_quantity, photo, category_id, manufacturer_id, supplier_id, id_prod):
        self.cursor.execute("""UPDATE products 
        SET `name` = %s, unit=%s, `price`=%s, description=%s, discount=%s, stock_quantity=%s,`photo`=%s,category_id=%s, manufacturer_id=%s, supplier_id=%s
        WHERE id = %s
        """, (name, unit, price, description, discount, stock_quantity, photo, category_id, manufacturer_id, supplier_id, id_prod))
        self.conn.commit()

    def add_product(self, name, unit, price, description, discount, stock_quantity, photo, category_id, manufacturer_id, supplier_id):
        raand = random.randint(1,999999)
        self.cursor.execute(f"""INSERT INTO products (article, name, unit, price, description, discount, stock_quantity, photo, category_id, manufacturer_id, supplier_id)
        VALUES ({raand}, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        """, (name, unit, price, description, discount, stock_quantity, photo, category_id, manufacturer_id, supplier_id))
        self.conn.commit()

    def del_product(self, prod_id):
        try:
            self.cursor.execute("""DELETE FROM products WHERE id = %s""", (prod_id))
            self.conn.commit()
        except Exception as e:
            print(e)




class AuthWin(QMainWindow, Ui_AuthWindow):
    def __init__(self):
        super().__init__()
        self.db = Database()
        self.setupUi(self)

        self.auth_btn.clicked.connect(self.auth)
        self.pushButton.clicked.connect(self.guest)
        self.setWindowIcon(QIcon("images/Icon.ico"))

    def auth(self):
        self.login = self.login_line.text()
        self.password = self.password_line.text()
        if not self.login or not self.password:
            QMessageBox.warning(self,"error","заполните все поля")
            return
        self.user = self.db.check_user(self.login, self.password)
        if not self.user:
            QMessageBox.warning(self, "error", "неверный логин или пароль")
            return
        else:
            QMessageBox.information(self, "успех", f"вы вошли как {self.user['full_name']}")
            self.win = MainWindow(self.user)
            self.win.show()
            self.close()
            return

    def guest(self):
        self.win = MainWindow()
        self.win.show()
        self.close()

class OrderEdit(QMainWindow, Ui_OrderWindow):
    def __init__(self, order = None, main_win = None):
        super().__init__()
        self.setupUi(self)
        self.main_win = main_win
        self.db = main_win.db
        self.order = order
        

class EditAddWin(QMainWindow, Ui_EditAddWin):
    def __init__(self, product = None, main_win = None):
        super().__init__()
        self.setupUi(self)
        self.main_win = main_win
        self.db = main_win.db
        self.product = product
        self.categories = self.db.load_categories()
        self.suppliers = self.db.load_suppliers()
        self.manufacturers = self.db.load_manufacturers()


        if self.product:
            self.photo_path = self.product['photo']
        else:
            self.photo_path = "images/picture.png"

        for man in self.manufacturers:
            self.manu_cmb.addItem(man['name'])
        for cat in self.categories:
            self.cat_cmb.addItem(cat['name'])
        for sup in self.suppliers:
            self.sup_cmb.addItem(sup['name'])

        if product:
            try:
                self.manu_cmb.setCurrentText(product['manufacturer_name'])
                self.cat_cmb.setCurrentText(product['category_name'])
                self.sup_cmb.setCurrentText(product['supplier_name'])
                self.name_ln.setText(product['name'])
                self.desc_ln.setText(product['description'])
                self.disc_ln.setText(str(product['discount']))
                self.unit_ln.setText(product['unit'])
                self.kolvo_ln.setText(str(product['stock_quantity']))
                self.price_ln.setText(str(product['price']))

                photo = QPixmap(f"images/{product['photo']}").scaled(300,200)
                self.photo_lbl.setPixmap(photo)
            except Exception as e:
                print(e)


        self.save_btn_2.clicked.connect(self.add_photo)
        self.save_btn.clicked.connect(self.save_edit)

    def add_photo(self):

        file, _ = QFileDialog.getOpenFileName(self, "выберите фото","","Images (*.png *.jpeg *.jpg)")
        if file:
            filename = os.path.basename(file)
            dest = os.path.join("images",filename)
            shutil.copy(file,dest)

            self.photo_path = filename
            pixmap = QPixmap(dest).scaled(300,200)
            self.photo_lbl.setPixmap(pixmap)

    def save_edit(self):
        # Проверка обязательных полей
        if not self.name_ln.text().strip():
            QMessageBox.warning(self, "Ошибка", "Введите название товара")
            return

        if not self.unit_ln.text().strip():
            QMessageBox.warning(self, "Ошибка", "Введите единицу измерения")
            return

        if not self.desc_ln.text().strip():
            QMessageBox.warning(self, "Ошибка", "Введите описание товара")
            return

        # Проверка цены
        try:
            price = float(self.price_ln.text())
            if price < 0:
                QMessageBox.warning(self, "Ошибка", "Цена не может быть отрицательной")
                return
        except ValueError:
            QMessageBox.warning(self, "Ошибка", "Цена должна быть числом")
            return

        # Проверка скидки
        try:
            discount = int(self.disc_ln.text())
            if discount < 0 or discount > 100:
                QMessageBox.warning(self, "Ошибка", "Скидка должна быть от 0 до 100")
                return
        except ValueError:
            QMessageBox.warning(self, "Ошибка", "Скидка должна быть целым числом")
            return

        # Проверка количества
        try:
            stock_quantity = int(self.kolvo_ln.text())
            if stock_quantity < 0:
                QMessageBox.warning(self, "Ошибка", "Количество не может быть отрицательным")
                return
        except ValueError:
            QMessageBox.warning(self, "Ошибка", "Количество должно быть целым числом")
            return

        cat_id = self.cat_cmb.currentIndex() + 1
        man_id = self.manu_cmb.currentIndex() + 1
        sup_id = self.sup_cmb.currentIndex() + 1

        try:
            if self.product:
                self.db.edit_product(
                    self.name_ln.text().strip(),
                    self.unit_ln.text().strip(),
                    price,
                    self.desc_ln.text().strip(),
                    discount,
                    stock_quantity,
                    self.photo_path,
                    cat_id,
                    man_id,
                    sup_id,
                    int(self.product['id'])
                )

                QMessageBox.information(
                    self,
                    "Успех",
                    "Данные товара успешно изменены"
                )

            else:
                self.db.add_product(
                    self.name_ln.text().strip(),
                    self.unit_ln.text().strip(),
                    price,
                    self.desc_ln.text().strip(),
                    discount,
                    stock_quantity,
                    self.photo_path,
                    cat_id,
                    man_id,
                    sup_id
                )

                QMessageBox.information(
                    self,
                    "Успех",
                    "Товар успешно добавлен"
                )

            if self.main_win:
                self.main_win.products = self.main_win.db.load_products()
                self.main_win.update_products()

            self.close()

        except Exception as e:
            import traceback
            traceback.print_exc()
            QMessageBox.warning(self, "Ошибка", str(e))





class MainWindow(QMainWindow, Ui_MainWindow):
    def __init__(self, user = None):
        super().__init__()
        self.setupUi(self)
        self.db = Database()
        self.user_data = user
        self.products = self.db.load_products()
        if user:
            self.role = user['role_id']
        else:
            self.role = 'guest'

        self.setup_ui()
        self.update_products()
        self.update_orders()
        self.apply_role()
        self.setWindowIcon(QIcon("images/Icon.ico"))


    def setup_ui(self):
        if self.user_data:
            self.fio_lbl.setText(self.user_data['full_name'])
        else:
            self.fio_lbl.setText("Гость")

        logo = QPixmap("images/Icon.png")
        self.logo_lbl.setPixmap(logo.scaled(50,50))
        self.logout_btn.clicked.connect(self.logout)

        self.filter_cmb.addItem("Все")

        self.suppliers = self.db.load_suppliers()
        for supplier in self.suppliers:
            self.filter_cmb.addItem(supplier['name'])
        self.sort_cmb.addItems(["По возрастанию кол-ва","По убыванию кол-ва"])
        self.search_line.textChanged.connect(self.searching)
        self.sort_cmb.currentTextChanged.connect(self.update_products)
        self.filter_cmb.currentTextChanged.connect(self.update_products)

        self.prod_wid = QWidget()
        self.prod_lay = QVBoxLayout(self.prod_wid)
        self.products_scroll.setWidget(self.prod_wid)
        self.products_scroll.setWidgetResizable(True)

        self.order_wid = QWidget()
        self.order_lay = QVBoxLayout(self.order_wid)
        self.orders_scroll.setWidget(self.order_wid)
        self.orders_scroll.setWidgetResizable(True)

        self.add_prod_btn.clicked.connect(self.add_win)

    def add_win(self):
        self.addwin = EditAddWin(main_win=self)
        self.addwin.show()

    def searching(self):
        text = self.search_line.text()
        if text:
            self.products = self.db.searching(text)
        else:
            self.products = self.db.load_products()
        self.update_products()

    def update_products(self):
        self.products = self.db.load_products()
        items = []
        while self.prod_lay.count():
            item = self.prod_lay.takeAt(0)
            if item.widget():
                item.widget().deleteLater()

        supplier = self.filter_cmb.currentText()
        for product in self.products:
            if supplier == product['supplier_name'] or supplier == "Все":
                items.append(product)

        sort_index = self.sort_cmb.currentIndex()
        if sort_index == 0:
            items.sort(key=lambda m: int(m['stock_quantity']))
        elif sort_index == 1:
            items.sort(key=lambda m: int(m['stock_quantity']), reverse=True)

        for product in items:
            try:
                card = QFrame()
                card.setFixedHeight(250)
                card.setFrameShape(QFrame.Shape.Box)
                lay = QHBoxLayout(card)
                title = QLabel(f"<b>{product['category_name']} | {product['name']}</b>")
                desc = QLabel(f"Описание товара:{product['description']}")
                desc.setWordWrap(True)
                supplier = QLabel(f"Производитель: {product['supplier_name']}")
                manufacturers = QLabel(f"Поставщик: {product['manufacturer_name']}")
                kolvo = QLabel(f"Количество на складе: {product['stock_quantity']} {product['unit']}")
                discount = int(product['discount'])

                if discount > 0:
                    final_price = float(product['price']) * (1 - discount / 100)
                    price = QLabel(f"""<s style="color:red">{product['price']:.2f} руб.</s>
                    {final_price:.2f} руб.
                    """)
                else:
                    price = QLabel(f"{product['price']}")

                if discount > 15:
                    card.setStyleSheet("background-color:#2E8B57; font-family: Times New Roman; font-size: 15px")
                elif product['stock_quantity'] <= 0:
                    card.setStyleSheet("background-color:lightblue; font-family: Times New Roman; font-size: 15px")


                info_wid = QWidget()
                layout = QVBoxLayout(info_wid)
                layout.addWidget(title)
                layout.addWidget(desc)
                layout.addWidget(supplier)
                layout.addWidget(manufacturers)
                layout.addWidget(price)
                layout.addWidget(kolvo)

                discount_wid = QFrame()
                discount_wid.setFixedSize(130,220)
                discount_wid.setFrameShape(QFrame.Shape.Box)
                discount_lay = QVBoxLayout(discount_wid)

                disc = QLabel(f"{discount}%")
                disc.setAlignment(QtCore.Qt.AlignmentFlag.AlignCenter)
                discount_lay.addWidget(disc)

                image_lbl = QLabel()
                image = QPixmap(f"images/{product['photo']}").scaled(160,160)
                if image.isNull():
                    image = QPixmap("images/picture.png").scaled(160,160)
                image_lbl.setPixmap(image)

                del_btn = QPushButton("Удалить")
                del_btn.clicked.connect(lambda m, product = product: self.deleted(product))



                lay.addWidget(image_lbl)
                # lay.addStretch()
                lay.addWidget(info_wid)
                lay.addStretch()
                lay.addWidget(discount_wid)
                lay.addWidget(del_btn)


                if self.role == 1:
                    card.mousePressEvent = lambda event, p=product: self.open_product(p)


            except Exception as e:
                print(e)

            self.prod_lay.addWidget(card)

    def deleted(self, product):
        try:
            self.db.del_product(product['id'])
            QMessageBox.information(self, "успех","товар удален")


            self.products = self.db.load_products()
            self.update_products()
        except Exception as e:
            print("Нельзя удалить товар, который находится в заказе")

    def open_product(self, product):
        self.edit_add_win = EditAddWin(product, main_win=self)
        self.edit_add_win.show()

    def update_orders(self):
        while self.order_lay.count():
            item = self.order_lay.takeAt(0)
            if item.widget():
                item.widget().deleteLater()

        self.orders = self.db.load_orders()

        for order in self.orders:
            card = QFrame()
            card.setFixedHeight(250)
            card.setFrameShape(QFrame.Shape.Box)
            lay = QHBoxLayout(card)
            articul = QLabel(f"<b>Артикул заказа - {order['code']}</b>")
            status = QLabel(f"Статус заказа: {order['status']}")
            address = QLabel(f"Адрес пункта выдачи: {order['address']}")
            date_ord = QLabel(f"Дата заказа:{order['order_date']}")
            date_del = QLabel(f"Дата доставки:{order['delivery_date']}")

            info_wid = QWidget()
            info_lay = QVBoxLayout(info_wid)
            info_lay.addWidget(articul)
            info_lay.addWidget(status)
            info_lay.addWidget(address)
            info_lay.addWidget(date_ord)
            lay.addWidget(info_wid)
            lay.addStretch()
            lay.addWidget(date_del)

        self.order_lay.addWidget(card)

        if self.role == 1:
            try:
                card.mousePressEvent = lambda m, order = order: self.edit_order(order)
            except Exception as e:
                print(e)

    def edit_order(self, order):
        self.edit_win = OrderEdit(order, main_win = self)
        self.edit_win.show()






    def apply_role(self):
        if self.role == 3 or self.role == "guest":
            self.sort_filt_widget.hide()
            self.tabWidget.removeTab(1)
        if self.role != 1:
            self.add_ord_btn.hide()
            self.add_prod_btn.hide()



    def logout(self):
        self.close()
        self.auth_win = AuthWin()
        self.auth_win.show()





if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = AuthWin()
    win.show()
    sys.exit(app.exec())