master-floor/ressult/gui/orders_panel.py
2025-11-26 19:31:33 +03:00

344 lines
14 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# gui/orders_panel.py
"""
Панель управления заказами и продажами
"""
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QHBoxLayout, QLabel,
QTableWidget, QTableWidgetItem, QPushButton,
QHeaderView, QMessageBox, QDateEdit, QComboBox,
QLineEdit, QFormLayout, QDialog, QDoubleSpinBox)
from PyQt6.QtCore import Qt, QDate
from PyQt6.QtGui import QFont
import requests
class OrderForm(QDialog):
"""Форма для добавления/редактирования заказа"""
order_saved = pyqtSignal()
def __init__(self, parent=None, order_data=None, auth=None, partners=None):
super().__init__(parent)
self.order_data = order_data
self.auth = auth
self.partners = partners or []
self.setup_ui()
def setup_ui(self):
self.setWindowTitle("Добавить заказ" if not self.order_data else "Редактировать заказ")
self.setModal(True)
self.resize(400, 300)
layout = QVBoxLayout()
# Форма ввода данных
form_layout = QFormLayout()
# Выбор партнера
self.partner_combo = QComboBox()
self.partner_combo.addItem("Выберите партнера", None)
for partner in self.partners:
self.partner_combo.addItem(partner['company_name'], partner['partner_id'])
form_layout.addRow("Партнер*:", self.partner_combo)
# Название продукта
self.product_name = QLineEdit()
self.product_name.setPlaceholderText("Введите название продукта")
form_layout.addRow("Продукт*:", self.product_name)
# Количество
self.quantity = QDoubleSpinBox()
self.quantity.setRange(0.01, 100000.0)
self.quantity.setDecimals(2)
form_layout.addRow("Количество*:", self.quantity)
# Дата продажи
self.sale_date = QDateEdit()
self.sale_date.setDate(QDate.currentDate())
self.sale_date.setCalendarPopup(True)
form_layout.addRow("Дата продажи*:", self.sale_date)
layout.addLayout(form_layout)
# Кнопки
buttons_layout = QHBoxLayout()
self.save_button = QPushButton("Сохранить")
self.save_button.clicked.connect(self.save_order)
self.save_button.setStyleSheet("""
QPushButton {
background-color: #28a745;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
font-weight: bold;
}
QPushButton:hover {
background-color: #218838;
}
""")
self.cancel_button = QPushButton("Отмена")
self.cancel_button.clicked.connect(self.reject)
buttons_layout.addWidget(self.save_button)
buttons_layout.addWidget(self.cancel_button)
buttons_layout.addStretch()
layout.addLayout(buttons_layout)
self.setLayout(layout)
# Если редактирование, заполняем форму
if self.order_data:
self.fill_form()
def fill_form(self):
"""Заполнение формы данными заказа"""
data = self.order_data
# Устанавливаем партнера
partner_index = self.partner_combo.findData(data.get('partner_id'))
if partner_index >= 0:
self.partner_combo.setCurrentIndex(partner_index)
self.product_name.setText(data.get('product_name', ''))
self.quantity.setValue(float(data.get('quantity', 0)))
# Устанавливаем дату
sale_date = data.get('sale_date')
if sale_date:
date = QDate.fromString(sale_date, 'yyyy-MM-dd')
if date.isValid():
self.sale_date.setDate(date)
def validate_form(self):
"""Валидация данных формы"""
errors = []
if not self.partner_combo.currentData():
errors.append("Выберите партнера")
if not self.product_name.text().strip():
errors.append("Введите название продукта")
if self.quantity.value() <= 0:
errors.append("Количество должно быть больше 0")
return errors
def save_order(self):
"""Сохранение заказа"""
errors = self.validate_form()
if errors:
QMessageBox.warning(self, "Ошибка валидации", "\n".join(errors))
return
order_data = {
'partner_id': self.partner_combo.currentData(),
'product_name': self.product_name.text().strip(),
'quantity': self.quantity.value(),
'sale_date': self.sale_date.date().toString('yyyy-MM-dd')
}
try:
if self.order_data:
# Обновление существующего заказа
response = requests.put(
f"http://localhost:8000/api/v1/sales/{self.order_data['sale_id']}",
json=order_data,
auth=self.auth,
timeout=10
)
else:
# Создание нового заказа
response = requests.post(
"http://localhost:8000/api/v1/sales",
json=order_data,
auth=self.auth,
timeout=10
)
if response.status_code == 200:
self.order_saved.emit()
QMessageBox.information(self, "Успех", "Заказ успешно сохранен")
self.accept()
elif response.status_code == 401:
QMessageBox.warning(self, "Ошибка авторизации", "Сессия истекла. Пожалуйста, войдите снова.")
else:
error_msg = response.json().get('detail', 'Неизвестная ошибка')
QMessageBox.warning(self, "Ошибка", f"Не удалось сохранить заказ: {error_msg}")
except requests.exceptions.ConnectionError:
QMessageBox.critical(self, "Ошибка", "Не удалось подключиться к серверу")
except Exception as e:
QMessageBox.critical(self, "Ошибка", f"Ошибка подключения: {str(e)}")
class OrdersPanel(QWidget):
"""Панель управления заказами"""
def __init__(self, auth=None):
super().__init__()
self.auth = auth
self.partners = []
self.setup_ui()
self.load_partners()
self.load_orders()
def setup_ui(self):
"""Настройка интерфейса панели заказов"""
layout = QVBoxLayout()
layout.setContentsMargins(10, 10, 10, 10)
layout.setSpacing(10)
# Заголовок
title = QLabel("Управление заказами")
title.setFont(QFont("Arial", 16, QFont.Weight.Bold))
title.setAlignment(Qt.AlignmentFlag.AlignCenter)
layout.addWidget(title)
# Панель управления
control_layout = QHBoxLayout()
self.add_button = QPushButton("Добавить заказ")
self.add_button.clicked.connect(self.show_add_order_form)
self.add_button.setStyleSheet("""
QPushButton {
background-color: #007acc;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
font-weight: bold;
}
QPushButton:hover {
background-color: #005a9e;
}
""")
self.refresh_button = QPushButton("Обновить")
self.refresh_button.clicked.connect(self.load_orders)
control_layout.addWidget(self.add_button)
control_layout.addWidget(self.refresh_button)
control_layout.addStretch()
layout.addLayout(control_layout)
# Таблица заказов
self.orders_table = QTableWidget()
self.orders_table.setColumnCount(6)
self.orders_table.setHorizontalHeaderLabels([
"ID", "Партнер", "Продукт", "Количество", "Дата", "Действия"
])
self.orders_table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
self.orders_table.setStyleSheet("""
QTableWidget {
border: 1px solid #ddd;
border-radius: 4px;
background-color: white;
}
QTableWidget::item {
padding: 8px;
}
""")
layout.addWidget(self.orders_table)
self.setLayout(layout)
def load_partners(self):
"""Загрузка списка партнеров"""
try:
response = requests.get(
"http://localhost:8000/api/v1/partners",
auth=self.auth,
timeout=10
)
if response.status_code == 200:
self.partners = response.json()
except:
self.partners = []
def load_orders(self):
"""Загрузка списка заказов"""
try:
response = requests.get(
"http://localhost:8000/api/v1/sales",
auth=self.auth,
timeout=10
)
if response.status_code == 200:
orders = response.json()
self.display_orders(orders)
elif response.status_code == 401:
QMessageBox.warning(self, "Ошибка авторизации", "Сессия истекла")
except Exception as e:
QMessageBox.warning(self, "Ошибка", f"Не удалось загрузить заказы: {str(e)}")
def display_orders(self, orders):
"""Отображение заказов в таблице"""
self.orders_table.setRowCount(len(orders))
for row, order in enumerate(orders):
self.orders_table.setItem(row, 0, QTableWidgetItem(str(order.get('sale_id', ''))))
self.orders_table.setItem(row, 1, QTableWidgetItem(order.get('company_name', 'Неизвестно')))
self.orders_table.setItem(row, 2, QTableWidgetItem(order.get('product_name', '')))
self.orders_table.setItem(row, 3, QTableWidgetItem(str(order.get('quantity', ''))))
self.orders_table.setItem(row, 4, QTableWidgetItem(order.get('sale_date', '')))
# Кнопки действий
actions_widget = QWidget()
actions_layout = QHBoxLayout(actions_widget)
actions_layout.setContentsMargins(4, 4, 4, 4)
actions_layout.setSpacing(4)
delete_button = QPushButton("Удалить")
delete_button.setStyleSheet("""
QPushButton {
background-color: #dc3545;
color: white;
border: none;
padding: 4px 8px;
border-radius: 3px;
font-size: 11px;
}
QPushButton:hover {
background-color: #c82333;
}
""")
delete_button.clicked.connect(lambda checked, o=order: self.delete_order(o))
actions_layout.addWidget(delete_button)
actions_layout.addStretch()
self.orders_table.setCellWidget(row, 5, actions_widget)
def show_add_order_form(self):
"""Открытие формы добавления заказа"""
form = OrderForm(self, auth=self.auth, partners=self.partners)
form.order_saved.connect(self.load_orders)
form.exec()
def delete_order(self, order):
"""Удаление заказа"""
reply = QMessageBox.question(
self,
"Подтверждение удаления",
f"Вы уверены, что хотите удалить заказ #{order.get('sale_id')}?",
QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
QMessageBox.StandardButton.No
)
if reply == QMessageBox.StandardButton.Yes:
try:
response = requests.delete(
f"http://localhost:8000/api/v1/sales/{order['sale_id']}",
auth=self.auth,
timeout=10
)
if response.status_code == 200:
self.load_orders()
elif response.status_code == 401:
QMessageBox.warning(self, "Ошибка авторизации", "Сессия истекла")
except Exception as e:
QMessageBox.warning(self, "Ошибка", f"Не удалось удалить заказ: {str(e)}")