PyQt6-sup 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ from pathlib import Path
2
+
3
+ PACKAGE_DIR = Path(__file__).parent
4
+
5
+ def get_path(filename):
6
+ """Возвращает путь к любому файлу в пакете."""
7
+ return PACKAGE_DIR / filename
Binary file
@@ -0,0 +1,145 @@
1
+ import os
2
+ import sys
3
+ from product import *
4
+ from db import run_query
5
+ from PyQt6.QtWidgets import *
6
+ from PyQt6.QtCore import Qt
7
+
8
+ class AppWindow(QMainWindow):
9
+ def __init__(self, user):
10
+ super().__init__()
11
+ self.user = user
12
+ self.role = self.user['role_name']
13
+ self.sort_asc = True
14
+
15
+ self.setWindowTitle("Обувной магазин")
16
+ self.resize(800, 500)
17
+
18
+ self.tabs = QTabWidget()
19
+ self.setCentralWidget(self.tabs)
20
+ self.menu_tab = QWidget()
21
+ self.tabs.addTab(self.menu_tab, 'Меню')
22
+ self.setup_menu()
23
+
24
+ def logout(self):
25
+ os.execl(sys.executable, sys.executable, *sys.argv)
26
+
27
+ def add_btn(self, text, func, layout):
28
+ btn = QPushButton(text)
29
+ btn.clicked.connect(func)
30
+ btn.setStyleSheet("background-color: #7FFF00; font-family: Times New Roman;")
31
+ layout.addWidget(btn)
32
+ return btn
33
+
34
+ def setup_menu(self):
35
+ layout = QVBoxLayout(self.menu_tab)
36
+ admin_layout = QHBoxLayout()
37
+
38
+ exit_btn = self.menuBar().addAction('Выйти')
39
+ exit_btn.triggered.connect(self.logout)
40
+
41
+ if self.role == 'admin':
42
+ self.add_btn('Добавить', lambda: ProductManager.add_product(self), admin_layout)
43
+ self.add_btn('Удалить', lambda: ProductManager.delete_product(self), admin_layout)
44
+ self.add_btn('Изменить', lambda: ProductManager.change_product(self), admin_layout)
45
+ if self.role in ['admin', 'manager']:
46
+ self.add_btn('Управление заказами', self.manage_orders, admin_layout)
47
+
48
+ layout.addLayout(admin_layout)
49
+
50
+ if self.role in ['admin', 'manager']:
51
+ filt = QHBoxLayout()
52
+
53
+ self.search = QLineEdit()
54
+ self.search.setPlaceholderText("Поиск...")
55
+ self.search.textChanged.connect(self.load_product)
56
+
57
+ self.supplier_cb = QComboBox()
58
+ self.supplier_cb.addItem('Все поставщики', None)
59
+
60
+ for s in run_query("SELECT name, supplier_id FROM Suppliers", fetch='all'):
61
+ self.supplier_cb.addItem(s['name'], s['supplier_id'])
62
+
63
+ self.supplier_cb.currentIndexChanged.connect(self.load_product)
64
+
65
+ self.sort_btn = QPushButton("Склад: По возростанию")
66
+ self.sort_btn.clicked.connect(self.toggle_sort)
67
+
68
+ filt.addWidget(QLabel('Поиск:'))
69
+ filt.addWidget(self.search)
70
+ filt.addWidget(QLabel('Поставищики:'))
71
+ filt.addWidget(self.supplier_cb)
72
+ filt.addWidget(self.sort_btn)
73
+ layout.addLayout(filt)
74
+
75
+ scroll = QScrollArea(widgetResizable=True)
76
+ self.grid_w = QWidget()
77
+ self.grid = QGridLayout(self.grid_w)
78
+ scroll.setWidget(self.grid_w)
79
+ layout.addWidget(scroll)
80
+ self.load_product()
81
+
82
+ def toggle_sort(self):
83
+ self.sort_asc = not self.sort_asc
84
+ if self.sort_asc:
85
+ self.sort_btn.setText("Склад: По возрастанию")
86
+ else:
87
+ self.sort_btn.setText("Склад: По убыванию")
88
+ self.load_product()
89
+
90
+ def load_product(self):
91
+ for i in reversed(range(self.grid.count())):
92
+ self.grid.itemAt(i).widget().setParent(None)
93
+
94
+ search = ''
95
+ sup_id = None
96
+ product = run_query(PRODUCT_SQL, fetch='all') or []
97
+
98
+ if hasattr(self, 'search'):
99
+ search = self.search.text().strip().lower()
100
+
101
+ if hasattr(self, 'supplier_cb'):
102
+ sup_id = self.supplier_cb.currentData()
103
+
104
+ filtered = []
105
+ for p in product:
106
+ if sup_id and p.get('supplier_id') != sup_id:
107
+ continue
108
+ if search:
109
+ text = ' '.join(str(p.get(k) or ' ') for k in (
110
+ 'name', 'category', 'manufacture', 'supplier', 'unit'
111
+ )).lower()
112
+
113
+ if search not in text:
114
+ continue
115
+ filtered.append(p)
116
+
117
+ filtered.sort(
118
+ key=lambda x: int(x.get('quantity') or 0),
119
+ reverse=not self.sort_asc if hasattr(self, 'sort_asc') else False
120
+ )
121
+
122
+ for i, p in enumerate(filtered):
123
+ card = QFrame()
124
+ card.setFixedHeight(110)
125
+ card.setStyleSheet(card_style(p['quantity'], p['discount']))
126
+ h = QHBoxLayout(card)
127
+
128
+ img = QLabel()
129
+ img.setFixedSize(80, 80)
130
+ img.setPixmap(get_product_pixmap(p.get('image_path')))
131
+
132
+ info = QLabel(
133
+ f"<span style = 'front-size: 12px; font-family: Times New Roman;'><b>{p['name']}</b></span><br>"
134
+ f"Категория: {p.get('category') or '-'} | Бренд: {p.get('manufacture') or '-'}<br>"
135
+ f"Наличие: <b>{p['quantity']} {p['unit']}</b> | Скидка: {float(p.get('discount') or 0):.0f}%<br>"
136
+ f"Цена: {price_html(p['price'], p['discount'])}"
137
+ )
138
+ info.setFixedHeight(100)
139
+
140
+ h.addWidget(img)
141
+ h.addWidget(info)
142
+ self.grid.addWidget(card, i, 0)
143
+
144
+ def manage_orders(self):
145
+ pass
@@ -0,0 +1,32 @@
1
+ import pymysql
2
+
3
+ def get_connection():
4
+ return pymysql.connect(
5
+ host='localhost',
6
+ user='root',
7
+ password='marmag_0607',
8
+ database='shoes_store',
9
+ cursorclass=pymysql.cursors.DictCursor
10
+ )
11
+
12
+ def run_query(query, params=(), fetch=None):
13
+ conn = get_connection()
14
+
15
+ try:
16
+ with conn.cursor() as cursor:
17
+ cursor.execute(query, params)
18
+ if fetch == 'one': return cursor.fetchone()
19
+ if fetch == 'all': return cursor.fetchall()
20
+ conn.commit()
21
+ return cursor.lastrowid
22
+ finally:
23
+ conn.close()
24
+
25
+ def auth(login, password):
26
+ query = """
27
+ SELECT u.user_id, u.username, r.role_name
28
+ FROM Users u
29
+ JOIN Roles r ON r.role_id = u.role_id
30
+ WHERE u.username = %s AND u.passw = %s
31
+ """
32
+ return run_query(query, (login, password), fetch='one')
@@ -0,0 +1,111 @@
1
+ USE shoes_store;
2
+
3
+ CREATE TABLE IF NOT EXISTS Roles(
4
+ role_id INT PRIMARY KEY AUTO_INCREMENT,
5
+ role_name VARCHAR(100)
6
+ );
7
+
8
+ CREATE TABLE IF NOT EXISTS Users(
9
+ user_id INT PRIMARY KEY AUTO_INCREMENT,
10
+ username VARCHAR(100) NOT NULL,
11
+ passw VARCHAR(255) NOT NULL,
12
+ lastname VARCHAR(100),
13
+ firstname VARCHAR(100),
14
+ patronymic VARCHAR(100),
15
+ role_id INT,
16
+
17
+ FOREIGN KEY (role_id) REFERENCES Roles(role_id)
18
+ );
19
+
20
+ CREATE TABLE IF NOT EXISTS Categories(
21
+ category_id INT PRIMARY KEY AUTO_INCREMENT,
22
+ name VARCHAR(100)
23
+ );
24
+
25
+ CREATE TABLE IF NOT EXISTS Manufacturers(
26
+ manufacture_id INT PRIMARY KEY AUTO_INCREMENT,
27
+ name VARCHAR(100)
28
+ );
29
+
30
+ CREATE TABLE IF NOT EXISTS Suppliers(
31
+ supplier_id INT PRIMARY KEY AUTO_INCREMENT,
32
+ name VARCHAR(100)
33
+ );
34
+
35
+ CREATE TABLE IF NOT EXISTS Status(
36
+ status_id INT PRIMARY KEY AUTO_INCREMENT,
37
+ name VARCHAR(100)
38
+ );
39
+
40
+ CREATE TABLE IF NOT EXISTS Products(
41
+ product_id INT PRIMARY KEY AUTO_INCREMENT,
42
+ name VARCHAR(100),
43
+ category_id INT,
44
+ manufacture_id INT,
45
+ supplier_id INT,
46
+ price DECIMAL(10, 2),
47
+ quantity INT,
48
+ unit VARCHAR(10) DEFAULT "шт",
49
+ discount DECIMAL(5, 2) DEFAULT 0.00,
50
+ image_path VARCHAR(255),
51
+
52
+ FOREIGN KEY (category_id) REFERENCES Categories(category_id),
53
+ FOREIGN KEY (manufacture_id) REFERENCES Manufacturers(manufacture_id),
54
+ FOREIGN KEY (supplier_id) REFERENCES Suppliers(supplier_id)
55
+ );
56
+
57
+ CREATE TABLE IF NOT EXISTS Orders(
58
+ order_id INT PRIMARY KEY AUTO_INCREMENT,
59
+ user_id INT,
60
+ status_id INT,
61
+ address VARCHAR(100),
62
+ order_date DATE DEFAULT (CURRENT_DATE),
63
+
64
+ FOREIGN KEY (user_id) REFERENCES Users(user_id),
65
+ FOREIGN KEY (status_id) REFERENCES Status(status_id)
66
+ );
67
+
68
+ CREATE TABLE IF NOT EXISTS OrderItems(
69
+ item_id INT PRIMARY KEY AUTO_INCREMENT,
70
+ order_id INT,
71
+ product_id INT,
72
+ quantity INT,
73
+
74
+ FOREIGN KEY (order_id) REFERENCES Orders(order_id),
75
+ FOREIGN KEY (product_id) REFERENCES Products(product_id)
76
+ );
77
+
78
+ INSERT INTO Roles (role_name) VALUES
79
+ ('admin'),
80
+ ('manager'),
81
+ ('client');
82
+
83
+ INSERT INTO Users (username, passw, lastname, firstname, patronymic, role_id)
84
+ VALUES ('admin', 'admin', 'Абакаров', 'Магомед', 'Камильевич', 1),
85
+ ('manager', 'manager', 'Михаш', 'Михаил', 'Романович', 2),
86
+ ('client', 'client', 'Пучков', 'Максим', 'Ильич', 3);
87
+
88
+ INSERT INTO Categories (name) VALUES
89
+ ('Туфли'),
90
+ ('Кроссовки'),
91
+ ('Сапоги');
92
+
93
+ INSERT INTO Manufacturers (name) VALUES
94
+ ('Palermo'),
95
+ ('Adidas'),
96
+ ('ECCO');
97
+
98
+ INSERT INTO Suppliers (name) VALUES
99
+ ('Италия'),
100
+ ('Германия'),
101
+ ('США');
102
+
103
+ INSERT INTO Status (name) VALUES
104
+ ('Новый'),
105
+ ('В обработке'),
106
+ ('Готов');
107
+
108
+ INSERT INTO Products (name, category_id, manufacture_id, supplier_id, price, quantity, discount, image_path) VALUES
109
+ ('Palermo Brown', 1, 1, 1, 7600.00, 13, 5.00, 'images/palermo.jpg'),
110
+ ('Adidas Black Row', 2, 2, 2, 15500.00, 23, 45.00, 'images/black_row.jpg'),
111
+ ('ECCO Winter', 3, 3, 3, 9800.00, 5, 0.00, 'images/ecco.jpg');
@@ -0,0 +1,53 @@
1
+ import os
2
+ import sys
3
+ from db import auth
4
+ from app import AppWindow
5
+ from PyQt6.QtWidgets import *
6
+ from PyQt6.QtCore import Qt
7
+
8
+ class LoginWindow(QWidget):
9
+ def __init__(self):
10
+ super().__init__()
11
+ self.init_ui()
12
+
13
+ def init_ui(self):
14
+ layout = QVBoxLayout(self)
15
+ self.setWindowTitle("Авторизация")
16
+ self.resize(350, 200)
17
+ self.lbl = QLabel("<center>Авторизация</center>")
18
+ self.lbl.setAlignment(Qt.AlignmentFlag.AlignCenter)
19
+
20
+ self.login_line = QLineEdit()
21
+ self.login_line.setPlaceholderText("Логин")
22
+ self.pass_line = QLineEdit()
23
+ self.pass_line.setPlaceholderText("Пароль")
24
+
25
+ self.btn_login = QPushButton("Войти")
26
+ self.btn_guest = QPushButton("Гость")
27
+
28
+ for w in (self.lbl, self.login_line, self.pass_line, self.btn_login, self.btn_guest):
29
+ layout.addWidget(w)
30
+
31
+ self.btn_login.clicked.connect(self.try_login)
32
+ self.btn_guest.clicked.connect(lambda: self.main_win({'username': 'guest', 'role_name': 'client'}))
33
+
34
+ def try_login(self):
35
+ try:
36
+ user = auth(self.login_line.text(), self.pass_line.text())
37
+ if user:
38
+ QMessageBox.information(self, 'Успешно', 'Welcome')
39
+ self.main_win(user)
40
+ except Exception as e:
41
+ QMessageBox.warning(self, 'Ошибка', 'Упс, что-то не так')
42
+ print(e)
43
+
44
+ def main_win(self, user):
45
+ self.win = AppWindow(user)
46
+ self.win.show()
47
+ self.close()
48
+
49
+ if __name__ == "__main__":
50
+ app = QApplication(sys.argv)
51
+ window = LoginWindow()
52
+ window.show()
53
+ sys.exit(app.exec())
@@ -0,0 +1,87 @@
1
+ import os
2
+ import sys
3
+ from db import run_query
4
+ from PyQt6.QtWidgets import *
5
+ from PyQt6.QtGui import *
6
+ from PyQt6.QtCore import Qt
7
+
8
+ PRODUCT_SQL = """
9
+ SELECT
10
+ p.*,
11
+ c.name AS category,
12
+ m.name AS manufacture,
13
+ s.name AS supplier
14
+ FROM Products p
15
+ LEFT JOIN Categories c ON p.category_id = c.category_id
16
+ LEFT JOIN Manufacturers m ON p.manufacture_id = m.manufacture_id
17
+ LEFT JOIN Suppliers s ON p.supplier_id = s.supplier_id
18
+ """
19
+
20
+ def price_html(price, discount):
21
+ price, discount = float(price), float(discount)
22
+ if discount > 0:
23
+ final = round(price * (1 - discount / 100), 2)
24
+ return (
25
+ f"<span style = 'color: red; text-decoration: line-through;'>{price:.0f} P.</span>"
26
+ f"<span style = 'color: black; font-weight: bold;'>{final:.0f} P.</span>"
27
+ )
28
+ return f"<b>{price:.0f} P.</b>"
29
+
30
+ def get_product_pixmap(path):
31
+ pix = QPixmap(80, 80)
32
+ if path and os.path.exists(path):
33
+ pix.load(path)
34
+ return pix.scaled(80, 80, Qt.AspectRatioMode.KeepAspectRatio, Qt.TransformationMode.SmoothTransformation)
35
+
36
+ pix.fill(QColor('#FFFFFF'))
37
+ return pix
38
+
39
+ def card_style(stock, discount):
40
+ discount = float(discount or 0)
41
+ stock = int(stock or 0)
42
+ st = "border-radius: 5px; border: 1px solid #ddd; padding: 6px;"
43
+ if stock <= 0:
44
+ st += "background-color: #00FA9A"
45
+ elif discount > 15:
46
+ st += "background-color: #2E8B57"
47
+ else:
48
+ st += "background-color: #FFFFFF"
49
+ return st
50
+
51
+ class ProductManager:
52
+ @staticmethod
53
+ def add_product(parent_window):
54
+ name, ok1 = QInputDialog.getText(parent_window, "Добавить", "Название обуви:")
55
+ price, ok2 = QInputDialog.getDouble(parent_window, "Добавить", "Цена (Р):", 5000, 0, 999999, 2)
56
+ stock, ok3 = QInputDialog.getInt(parent_window, "Добавить", "Остаток на складе:", 10, 0, 99999)
57
+
58
+ if ok1 and ok2 and ok3 and name.strip():
59
+ run_query(
60
+ "INSERT INTO Products (name, category_id, manufacture_id, supplier_id, price, unit, quantity, discount) "
61
+ "VALUES (%s, 1, 1, 1, %s, 'шт', %s, 0)", (name, price, stock)
62
+ )
63
+ parent_window.load_product()
64
+
65
+ @staticmethod
66
+ def delete_product(parent_window):
67
+ name, ok = QInputDialog.getText(parent_window, "Удалить товар", "Введите точное название для удаления:")
68
+ if not ok or not name.strip(): return
69
+
70
+ try:
71
+ run_query("DELETE FROM Products WHERE name = %s", (name,))
72
+ parent_window.load_product()
73
+ except Exception:
74
+ QMessageBox.warning(parent_window, "Ошибка", "Не удалось удалить. Возможно, товар есть в заказах.")
75
+
76
+ @staticmethod
77
+ def change_product(parent_window):
78
+ name, ok = QInputDialog.getText(parent_window, "Изменить товар", "Введите точное название товара:")
79
+ prod = run_query("SELECT product_id, price, quantity FROM Products WHERE name=%s", (name,), fetch='one') if ok else None
80
+ if not prod: return
81
+
82
+ price, ok_p = QInputDialog.getDouble(parent_window, "Изменение", "Новая цена:", float(prod['price']), 0, 999999, 2)
83
+ qty, ok_q = QInputDialog.getInt(parent_window, "Изменение", "Новый остаток:", int(prod['quantity']), 0, 99999)
84
+
85
+ if ok_p and ok_q:
86
+ run_query("UPDATE Products SET price=%s, quantity=%s WHERE product_id=%s", (price, qty, prod['product_id']))
87
+ parent_window.load_product()