Full demo: complete

This commit is contained in:
helldh 2025-11-26 07:34:44 +03:00
parent bce57e79f2
commit 703adc3326
4 changed files with 1500 additions and 0 deletions

807
control1.py Normal file
View file

@ -0,0 +1,807 @@
import sys
import sqlite3
from datetime import datetime
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QLabel, QLineEdit, QTextEdit, QComboBox, QPushButton, QTableWidget,
QTableWidgetItem, QTabWidget, QGroupBox, QMessageBox, QFileDialog,
QSplitter, QHeaderView, QFormLayout, QCheckBox, QDialog)
from PyQt6.QtCore import Qt, pyqtSignal
from PyQt6.QtGui import QIcon, QAction
import os
class DatabaseManager:
def __init__(self):
self.conn = sqlite3.connect('service_requests.db')
self.create_tables()
def create_tables(self):
cursor = self.conn.cursor()
# Таблица пользователей
cursor.execute('''
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL,
role TEXT NOT NULL,
full_name TEXT NOT NULL,
phone TEXT
)
''')
# Таблица заявок
cursor.execute('''
CREATE TABLE IF NOT EXISTS service_requests (
id INTEGER PRIMARY KEY AUTOINCREMENT,
client_name TEXT NOT NULL,
client_phone TEXT NOT NULL,
equipment_type TEXT NOT NULL,
equipment_model TEXT NOT NULL,
problem_description TEXT NOT NULL,
status TEXT DEFAULT 'Новая',
priority TEXT DEFAULT 'Средний',
request_type TEXT DEFAULT 'Ремонт',
assigned_operator TEXT,
assigned_master TEXT,
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_date TIMESTAMP,
observer_group TEXT
)
''')
# Таблица истории заявок
cursor.execute('''
CREATE TABLE IF NOT EXISTS request_history (
id INTEGER PRIMARY KEY AUTOINCREMENT,
request_id INTEGER,
user_id INTEGER,
action TEXT,
timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (request_id) REFERENCES service_requests (id)
)
''')
# Таблица вложений
cursor.execute('''
CREATE TABLE IF NOT EXISTS attachments (
id INTEGER PRIMARY KEY AUTOINCREMENT,
request_id INTEGER,
filename TEXT,
filepath TEXT,
uploaded_by INTEGER,
upload_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (request_id) REFERENCES service_requests (id)
)
''')
# Таблица отчетов
cursor.execute('''
CREATE TABLE IF NOT EXISTS reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
request_id INTEGER,
master_id INTEGER,
work_description TEXT,
parts_used TEXT,
time_spent REAL,
created_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (request_id) REFERENCES service_requests (id)
)
''')
# Таблица заказов запчастей
cursor.execute('''
CREATE TABLE IF NOT EXISTS part_orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
request_id INTEGER,
part_name TEXT,
quantity INTEGER,
status TEXT DEFAULT 'Заказан',
ordered_by INTEGER,
order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (request_id) REFERENCES service_requests (id)
)
''')
# Создаем тестовых пользователей
self.create_test_users()
self.conn.commit()
def create_test_users(self):
cursor = self.conn.cursor()
test_users = [
('client1', '123', 'client', 'Иван Иванов', '+79161234567'),
('operator1', '123', 'operator', 'Петр Петров', '+79167654321'),
('master1', '123', 'master', 'Сергей Сергеев', '+79169998877'),
('admin1', '123', 'admin', 'Администратор Системы', '+79160001122')
]
for user in test_users:
try:
cursor.execute(
'INSERT INTO users (username, password, role, full_name, phone) VALUES (?, ?, ?, ?, ?)',
user
)
except sqlite3.IntegrityError:
pass # Пользователь уже существует
self.conn.commit()
class ServiceRequestApp(QMainWindow):
def __init__(self):
super().__init__()
self.db = DatabaseManager()
self.current_user = None
self.init_ui()
def init_ui(self):
self.setWindowTitle('Система учета заявок на ремонт оргтехники')
self.setGeometry(100, 100, 1200, 700)
# Центральный виджет
central_widget = QWidget()
self.setCentralWidget(central_widget)
# Основной layout
layout = QVBoxLayout(central_widget)
# Панель входа
self.login_widget = self.create_login_widget()
layout.addWidget(self.login_widget)
# Основной интерфейс (скрыт до входа)
self.main_tabs = QTabWidget()
self.main_tabs.setVisible(False)
layout.addWidget(self.main_tabs)
def create_login_widget(self):
widget = QWidget()
layout = QVBoxLayout(widget)
layout.addWidget(QLabel('Вход в систему'))
form_layout = QFormLayout()
self.username_input = QLineEdit()
self.password_input = QLineEdit()
self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
form_layout.addRow('Логин:', self.username_input)
form_layout.addRow('Пароль:', self.password_input)
layout.addLayout(form_layout)
login_btn = QPushButton('Войти')
login_btn.clicked.connect(self.login)
layout.addWidget(login_btn)
return widget
def login(self):
username = self.username_input.text()
password = self.password_input.text()
cursor = self.db.conn.cursor()
cursor.execute(
'SELECT * FROM users WHERE username = ? AND password = ?',
(username, password)
)
user = cursor.fetchone()
if user:
self.current_user = {
'id': user[0],
'username': user[1],
'role': user[3],
'full_name': user[4]
}
self.show_main_interface()
else:
QMessageBox.warning(self, 'Ошибка', 'Неверный логин или пароль')
def show_main_interface(self):
self.login_widget.setVisible(False)
self.main_tabs.setVisible(True)
# Очищаем предыдущие вкладки
self.main_tabs.clear()
role = self.current_user['role']
if role == 'client':
self.setup_client_interface()
elif role == 'operator':
self.setup_operator_interface()
elif role == 'master':
self.setup_master_interface()
elif role == 'admin':
self.setup_admin_interface()
def setup_client_interface(self):
# Вкладка создания заявки
create_tab = QWidget()
layout = QVBoxLayout(create_tab)
form_layout = QFormLayout()
self.client_name = QLineEdit(self.current_user['full_name'])
self.client_phone = QLineEdit()
self.equipment_type = QComboBox()
self.equipment_type.addItems(['Принтер', 'Копир', 'Сканер', 'МФУ', 'Компьютер'])
self.equipment_model = QLineEdit()
self.problem_description = QTextEdit()
form_layout.addRow('ФИО:', self.client_name)
form_layout.addRow('Телефон:', self.client_phone)
form_layout.addRow('Тип оборудования:', self.equipment_type)
form_layout.addRow('Модель:', self.equipment_model)
form_layout.addRow('Описание проблемы:', self.problem_description)
layout.addLayout(form_layout)
submit_btn = QPushButton('Создать заявку')
submit_btn.clicked.connect(self.create_service_request)
layout.addWidget(submit_btn)
self.main_tabs.addTab(create_tab, 'Новая заявка')
# Вкладка моих заявок
requests_tab = QWidget()
layout = QVBoxLayout(requests_tab)
self.client_requests_table = QTableWidget()
self.client_requests_table.setColumnCount(6)
self.client_requests_table.setHorizontalHeaderLabels([
'ID', 'Оборудование', 'Модель', 'Статус', 'Дата создания', 'Приоритет'
])
layout.addWidget(self.client_requests_table)
details_btn = QPushButton('Просмотреть детали')
details_btn.clicked.connect(self.show_request_details)
layout.addWidget(details_btn)
self.main_tabs.addTab(requests_tab, 'Мои заявки')
self.load_client_requests()
def setup_operator_interface(self):
# Вкладка всех заявок
requests_tab = QWidget()
layout = QVBoxLayout(requests_tab)
self.operator_requests_table = QTableWidget()
self.operator_requests_table.setColumnCount(8)
self.operator_requests_table.setHorizontalHeaderLabels([
'ID', 'Клиент', 'Оборудование', 'Модель', 'Статус', 'Приоритет', 'Дата', 'Оператор'
])
layout.addWidget(self.operator_requests_table)
# Панель управления заявкой
control_group = QGroupBox('Управление заявкой')
control_layout = QHBoxLayout(control_group)
self.status_combo = QComboBox()
self.status_combo.addItems(['Новая', 'В работе', 'Ожидает запчасти', 'Выполнена', 'Отменена'])
self.priority_combo = QComboBox()
self.priority_combo.addItems(['Низкий', 'Средний', 'Высокий', 'Критичный'])
self.type_combo = QComboBox()
self.type_combo.addItems(['Ремонт', 'Обслуживание', 'Консультация'])
self.observer_group = QLineEdit()
update_btn = QPushButton('Обновить заявку')
update_btn.clicked.connect(self.update_request_operator)
control_layout.addWidget(QLabel('Статус:'))
control_layout.addWidget(self.status_combo)
control_layout.addWidget(QLabel('Приоритет:'))
control_layout.addWidget(self.priority_combo)
control_layout.addWidget(QLabel('Тип:'))
control_layout.addWidget(self.type_combo)
control_layout.addWidget(QLabel('Группа наблюдателей:'))
control_layout.addWidget(self.observer_group)
control_layout.addWidget(update_btn)
layout.addWidget(control_group)
self.main_tabs.addTab(requests_tab, 'Все заявки')
# Вкладка архива
archive_tab = QWidget()
layout = QVBoxLayout(archive_tab)
search_layout = QHBoxLayout()
self.archive_search = QLineEdit()
self.archive_search.setPlaceholderText('Поиск в архиве...')
search_btn = QPushButton('Найти')
search_btn.clicked.connect(self.search_archive)
search_layout.addWidget(self.archive_search)
search_layout.addWidget(search_btn)
layout.addLayout(search_layout)
self.archive_table = QTableWidget()
self.archive_table.setColumnCount(8)
self.archive_table.setHorizontalHeaderLabels([
'ID', 'Клиент', 'Оборудование', 'Модель', 'Статус', 'Дата создания', 'Дата завершения', 'Мастер'
])
layout.addWidget(self.archive_table)
self.main_tabs.addTab(archive_tab, 'Архив')
self.load_operator_requests()
self.load_archive()
def setup_master_interface(self):
# Вкладка назначенных заявок
requests_tab = QWidget()
layout = QVBoxLayout(requests_tab)
self.master_requests_table = QTableWidget()
self.master_requests_table.setColumnCount(7)
self.master_requests_table.setHorizontalHeaderLabels([
'ID', 'Клиент', 'Оборудование', 'Модель', 'Статус', 'Приоритет', 'Дата'
])
layout.addWidget(self.master_requests_table)
# Панель управления для мастера
control_group = QGroupBox('Управление ремонтом')
control_layout = QVBoxLayout(control_group)
# Смена статуса
status_layout = QHBoxLayout()
status_layout.addWidget(QLabel('Статус:'))
self.master_status_combo = QComboBox()
self.master_status_combo.addItems(['В работе', 'Ожидает запчасти', 'Выполнена'])
status_layout.addWidget(self.master_status_combo)
update_status_btn = QPushButton('Обновить статус')
update_status_btn.clicked.connect(self.update_request_master)
status_layout.addWidget(update_status_btn)
control_layout.addLayout(status_layout)
# Заказ запчастей
parts_layout = QHBoxLayout()
parts_layout.addWidget(QLabel('Запчасть:'))
self.part_name = QLineEdit()
self.part_quantity = QLineEdit()
self.part_quantity.setText('1')
parts_layout.addWidget(self.part_name)
parts_layout.addWidget(QLabel('Количество:'))
parts_layout.addWidget(self.part_quantity)
order_parts_btn = QPushButton('Заказать запчасти')
order_parts_btn.clicked.connect(self.order_parts)
parts_layout.addWidget(order_parts_btn)
control_layout.addLayout(parts_layout)
# Прикрепление файлов
file_layout = QHBoxLayout()
attach_file_btn = QPushButton('Прикрепить файл')
attach_file_btn.clicked.connect(self.attach_file)
file_layout.addWidget(attach_file_btn)
control_layout.addLayout(file_layout)
# Создание отчета
report_layout = QHBoxLayout()
create_report_btn = QPushButton('Создать отчет')
create_report_btn.clicked.connect(self.create_report)
report_layout.addWidget(create_report_btn)
control_layout.addLayout(report_layout)
layout.addWidget(control_group)
self.main_tabs.addTab(requests_tab, 'Мои заявки')
self.load_master_requests()
def setup_admin_interface(self):
# Админский интерфейс будет похож на операторский с дополнительными функциями
self.setup_operator_interface()
# Добавляем вкладку управления пользователями
users_tab = QWidget()
layout = QVBoxLayout(users_tab)
self.users_table = QTableWidget()
self.users_table.setColumnCount(4)
self.users_table.setHorizontalHeaderLabels(['ID', 'Логин', 'ФИО', 'Роль'])
layout.addWidget(self.users_table)
add_user_btn = QPushButton('Добавить пользователя')
add_user_btn.clicked.connect(self.show_add_user_dialog)
layout.addWidget(add_user_btn)
self.main_tabs.addTab(users_tab, 'Пользователи')
self.load_users()
def create_service_request(self):
cursor = self.db.conn.cursor()
cursor.execute('''
INSERT INTO service_requests
(client_name, client_phone, equipment_type, equipment_model, problem_description)
VALUES (?, ?, ?, ?, ?)
''', (
self.client_name.text(),
self.client_phone.text(),
self.equipment_type.currentText(),
self.equipment_model.text(),
self.problem_description.toPlainText()
))
self.db.conn.commit()
QMessageBox.information(self, 'Успех', 'Заявка успешно создана!')
# Очищаем форму
self.client_phone.clear()
self.equipment_model.clear()
self.problem_description.clear()
def load_client_requests(self):
cursor = self.db.conn.cursor()
cursor.execute('''
SELECT id, equipment_type, equipment_model, status, created_date, priority
FROM service_requests
WHERE client_name = ?
ORDER BY created_date DESC
''', (self.current_user['full_name'],))
requests = cursor.fetchall()
self.client_requests_table.setRowCount(len(requests))
for row, request in enumerate(requests):
for col, value in enumerate(request):
self.client_requests_table.setItem(row, col, QTableWidgetItem(str(value)))
def load_operator_requests(self):
cursor = self.db.conn.cursor()
cursor.execute('''
SELECT id, client_name, equipment_type, equipment_model, status, priority, created_date, assigned_operator
FROM service_requests
ORDER BY created_date DESC
''')
requests = cursor.fetchall()
self.operator_requests_table.setRowCount(len(requests))
for row, request in enumerate(requests):
for col, value in enumerate(request):
self.operator_requests_table.setItem(row, col, QTableWidgetItem(str(value) if value is not None else ''))
def load_master_requests(self):
cursor = self.db.conn.cursor()
cursor.execute('''
SELECT id, client_name, equipment_type, equipment_model, status, priority, created_date
FROM service_requests
WHERE status != 'Выполнена' AND status != 'Отменена'
ORDER BY
CASE priority
WHEN 'Критичный' THEN 1
WHEN 'Высокий' THEN 2
WHEN 'Средний' THEN 3
WHEN 'Низкий' THEN 4
END,
created_date
''')
requests = cursor.fetchall()
self.master_requests_table.setRowCount(len(requests))
for row, request in enumerate(requests):
for col, value in enumerate(request):
self.master_requests_table.setItem(row, col, QTableWidgetItem(str(value)))
def load_archive(self):
cursor = self.db.conn.cursor()
cursor.execute('''
SELECT id, client_name, equipment_type, equipment_model, status, created_date, completed_date, assigned_master
FROM service_requests
WHERE status = 'Выполнена'
ORDER BY completed_date DESC
''')
requests = cursor.fetchall()
self.archive_table.setRowCount(len(requests))
for row, request in enumerate(requests):
for col, value in enumerate(request):
self.archive_table.setItem(row, col, QTableWidgetItem(str(value) if value is not None else ''))
def load_users(self):
cursor = self.db.conn.cursor()
cursor.execute('SELECT id, username, full_name, role FROM users')
users = cursor.fetchall()
self.users_table.setRowCount(len(users))
for row, user in enumerate(users):
for col, value in enumerate(user):
self.users_table.setItem(row, col, QTableWidgetItem(str(value)))
def show_request_details(self):
current_row = self.client_requests_table.currentRow()
if current_row >= 0:
request_id = self.client_requests_table.item(current_row, 0).text()
cursor = self.db.conn.cursor()
cursor.execute('SELECT * FROM service_requests WHERE id = ?', (request_id,))
request = cursor.fetchone()
if request:
details = f"""
ID: {request[0]}
Клиент: {request[1]}
Телефон: {request[2]}
Оборудование: {request[3]}
Модель: {request[4]}
Описание проблемы: {request[5]}
Статус: {request[6]}
Приоритет: {request[7]}
Тип: {request[8]}
Дата создания: {request[11]}
"""
QMessageBox.information(self, 'Детали заявки', details)
def update_request_operator(self):
current_row = self.operator_requests_table.currentRow()
if current_row >= 0:
request_id = self.operator_requests_table.item(current_row, 0).text()
cursor = self.db.conn.cursor()
cursor.execute('''
UPDATE service_requests
SET status = ?, priority = ?, request_type = ?, observer_group = ?, assigned_operator = ?
WHERE id = ?
''', (
self.status_combo.currentText(),
self.priority_combo.currentText(),
self.type_combo.currentText(),
self.observer_group.text(),
self.current_user['full_name'],
request_id
))
self.db.conn.commit()
self.load_operator_requests()
QMessageBox.information(self, 'Успех', 'Заявка обновлена!')
def update_request_master(self):
current_row = self.master_requests_table.currentRow()
if current_row >= 0:
request_id = self.master_requests_table.item(current_row, 0).text()
cursor = self.db.conn.cursor()
cursor.execute('''
UPDATE service_requests
SET status = ?, assigned_master = ?
WHERE id = ?
''', (
self.master_status_combo.currentText(),
self.current_user['full_name'],
request_id
))
self.db.conn.commit()
self.load_master_requests()
QMessageBox.information(self, 'Успех', 'Статус заявки обновлен!')
def order_parts(self):
current_row = self.master_requests_table.currentRow()
if current_row >= 0:
request_id = self.master_requests_table.item(current_row, 0).text()
cursor = self.db.conn.cursor()
cursor.execute('''
INSERT INTO part_orders (request_id, part_name, quantity, ordered_by)
VALUES (?, ?, ?, ?)
''', (
request_id,
self.part_name.text(),
int(self.part_quantity.text()),
self.current_user['id']
))
self.db.conn.commit()
# Обновляем статус заявки
cursor.execute('''
UPDATE service_requests
SET status = 'Ожидает запчасти'
WHERE id = ?
''', (request_id,))
self.db.conn.commit()
self.part_name.clear()
self.part_quantity.setText('1')
self.load_master_requests()
QMessageBox.information(self, 'Успех', 'Запчасти заказаны!')
def attach_file(self):
current_row = self.master_requests_table.currentRow()
if current_row >= 0:
request_id = self.master_requests_table.item(current_row, 0).text()
file_path, _ = QFileDialog.getOpenFileName(self, 'Выберите файл')
if file_path:
filename = os.path.basename(file_path)
cursor = self.db.conn.cursor()
cursor.execute('''
INSERT INTO attachments (request_id, filename, filepath, uploaded_by)
VALUES (?, ?, ?, ?)
''', (
request_id,
filename,
file_path,
self.current_user['id']
))
self.db.conn.commit()
QMessageBox.information(self, 'Успех', 'Файл прикреплен!')
def create_report(self):
current_row = self.master_requests_table.currentRow()
if current_row >= 0:
request_id = self.master_requests_table.item(current_row, 0).text()
# Диалог для ввода отчета
report_dialog = QDialog(self)
report_dialog.setWindowTitle('Создание отчета')
report_dialog.setModal(True)
layout = QVBoxLayout(report_dialog)
form_layout = QFormLayout()
work_description = QTextEdit()
parts_used = QLineEdit()
time_spent = QLineEdit()
form_layout.addRow('Описание работы:', work_description)
form_layout.addRow('Использованные запчасти:', parts_used)
form_layout.addRow('Затраченное время (часы):', time_spent)
layout.addLayout(form_layout)
buttons_layout = QHBoxLayout()
save_btn = QPushButton('Сохранить отчет')
cancel_btn = QPushButton('Отмена')
buttons_layout.addWidget(save_btn)
buttons_layout.addWidget(cancel_btn)
layout.addLayout(buttons_layout)
def save_report():
cursor = self.db.conn.cursor()
cursor.execute('''
INSERT INTO reports (request_id, master_id, work_description, parts_used, time_spent)
VALUES (?, ?, ?, ?, ?)
''', (
request_id,
self.current_user['id'],
work_description.toPlainText(),
parts_used.text(),
float(time_spent.text())
))
# Обновляем статус заявки на выполненную
cursor.execute('''
UPDATE service_requests
SET status = 'Выполнена', completed_date = CURRENT_TIMESTAMP
WHERE id = ?
''', (request_id,))
self.db.conn.commit()
report_dialog.accept()
self.load_master_requests()
QMessageBox.information(self, 'Успех', 'Отчет создан!')
save_btn.clicked.connect(save_report)
cancel_btn.clicked.connect(report_dialog.reject)
report_dialog.exec()
def search_archive(self):
search_text = self.archive_search.text()
cursor = self.db.conn.cursor()
if search_text:
cursor.execute('''
SELECT id, client_name, equipment_type, equipment_model, status, created_date, completed_date, assigned_master
FROM service_requests
WHERE status = 'Выполнена' AND
(client_name LIKE ? OR equipment_type LIKE ? OR equipment_model LIKE ?)
ORDER BY completed_date DESC
''', (f'%{search_text}%', f'%{search_text}%', f'%{search_text}%'))
else:
cursor.execute('''
SELECT id, client_name, equipment_type, equipment_model, status, created_date, completed_date, assigned_master
FROM service_requests
WHERE status = 'Выполнена'
ORDER BY completed_date DESC
''')
requests = cursor.fetchall()
self.archive_table.setRowCount(len(requests))
for row, request in enumerate(requests):
for col, value in enumerate(request):
self.archive_table.setItem(row, col, QTableWidgetItem(str(value) if value is not None else ''))
def show_add_user_dialog(self):
dialog = QDialog(self)
dialog.setWindowTitle('Добавить пользователя')
dialog.setModal(True)
layout = QVBoxLayout(dialog)
form_layout = QFormLayout()
username = QLineEdit()
password = QLineEdit()
password.setEchoMode(QLineEdit.EchoMode.Password)
full_name = QLineEdit()
phone = QLineEdit()
role = QComboBox()
role.addItems(['client', 'operator', 'master', 'admin'])
form_layout.addRow('Логин:', username)
form_layout.addRow('Пароль:', password)
form_layout.addRow('ФИО:', full_name)
form_layout.addRow('Телефон:', phone)
form_layout.addRow('Роль:', role)
layout.addLayout(form_layout)
buttons_layout = QHBoxLayout()
save_btn = QPushButton('Сохранить')
cancel_btn = QPushButton('Отмена')
buttons_layout.addWidget(save_btn)
buttons_layout.addWidget(cancel_btn)
layout.addLayout(buttons_layout)
def save_user():
cursor = self.db.conn.cursor()
try:
cursor.execute('''
INSERT INTO users (username, password, role, full_name, phone)
VALUES (?, ?, ?, ?, ?)
''', (
username.text(),
password.text(),
role.currentText(),
full_name.text(),
phone.text()
))
self.db.conn.commit()
dialog.accept()
self.load_users()
QMessageBox.information(self, 'Успех', 'Пользователь добавлен!')
except sqlite3.IntegrityError:
QMessageBox.warning(self, 'Ошибка', 'Пользователь с таким логином уже существует!')
save_btn.clicked.connect(save_user)
cancel_btn.clicked.connect(dialog.reject)
dialog.exec()
class Dialog(QDialog):
pass # Вспомогательный класс для диалогов
if __name__ == '__main__':
app = QApplication(sys.argv)
window = ServiceRequestApp()
window.show()
sys.exit(app.exec())

693
control2.py Normal file
View file

@ -0,0 +1,693 @@
import sys
import sqlite3
from datetime import datetime, date
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,
QHBoxLayout, QTabWidget, QTableWidget, QTableWidgetItem,
QPushButton, QLabel, QLineEdit, QComboBox, QDateEdit,
QTextEdit, QMessageBox, QHeaderView, QGroupBox,
QFormLayout, QSpinBox, QCheckBox, QTimeEdit)
from PyQt6.QtCore import Qt, QDate
from PyQt6.QtGui import QFont, QPalette, QColor
from PyQt6.QtCharts import QChart, QChartView, QPieSeries, QBarSeries, QBarSet, QBarCategoryAxis, QValueAxis
class FitnessApp(QMainWindow):
def __init__(self):
super().__init__()
self.initDB()
self.initUI()
def initDB(self):
"""Инициализация базы данных"""
self.conn = sqlite3.connect('fitness.db')
self.cursor = self.conn.cursor()
# Создание таблиц
self.create_tables()
# Заполнение тестовыми данными
self.insert_sample_data()
def create_tables(self):
"""Создание таблиц базы данных"""
tables = [
"""
CREATE TABLE IF NOT EXISTS Users (
userID INTEGER PRIMARY KEY,
fio TEXT NOT NULL,
phone TEXT,
email TEXT,
login TEXT UNIQUE,
password TEXT,
userType TEXT,
specialization TEXT,
birthDate DATE
)
""",
"""
CREATE TABLE IF NOT EXISTS Memberships (
membershipID INTEGER PRIMARY KEY,
clientID INTEGER,
membershipType TEXT,
startDate DATE,
endDate DATE,
visitsTotal INTEGER,
visitsUsed INTEGER,
zones TEXT,
membershipStatus TEXT,
cost REAL,
adminID INTEGER,
FOREIGN KEY (clientID) REFERENCES Users(userID),
FOREIGN KEY (adminID) REFERENCES Users(userID)
)
""",
"""
CREATE TABLE IF NOT EXISTS Visits (
visitID INTEGER PRIMARY KEY,
clientID INTEGER,
visitDate DATE,
checkInTime TIME,
checkOutTime TIME,
zone TEXT,
membershipID INTEGER,
FOREIGN KEY (clientID) REFERENCES Users(userID),
FOREIGN KEY (membershipID) REFERENCES Memberships(membershipID)
)
""",
"""
CREATE TABLE IF NOT EXISTS GroupClasses (
classID INTEGER PRIMARY KEY,
className TEXT,
trainerID INTEGER,
classDate DATE,
startTime TIME,
endTime TIME,
hall TEXT,
maxParticipants INTEGER,
enrolledParticipants INTEGER,
classStatus TEXT,
FOREIGN KEY (trainerID) REFERENCES Users(userID)
)
""",
"""
CREATE TABLE IF NOT EXISTS PersonalTraining (
trainingID INTEGER PRIMARY KEY,
clientID INTEGER,
trainerID INTEGER,
trainingDate DATE,
startTime TIME,
endTime TIME,
exercises TEXT,
notes TEXT,
progressMetrics TEXT,
FOREIGN KEY (clientID) REFERENCES Users(userID),
FOREIGN KEY (trainerID) REFERENCES Users(userID)
)
""",
"""
CREATE TABLE IF NOT EXISTS ClassRegistrations (
registrationID INTEGER PRIMARY KEY,
classID INTEGER,
clientID INTEGER,
registrationDate DATE,
status TEXT,
FOREIGN KEY (classID) REFERENCES GroupClasses(classID),
FOREIGN KEY (clientID) REFERENCES Users(userID)
)
""",
"""
CREATE TABLE IF NOT EXISTS EquipmentRequests (
requestID INTEGER PRIMARY KEY,
trainerID INTEGER,
equipment TEXT,
quantity INTEGER,
requestDate DATE,
status TEXT,
FOREIGN KEY (trainerID) REFERENCES Users(userID)
)
""",
"""
CREATE TABLE IF NOT EXISTS ShiftSwaps (
swapID INTEGER PRIMARY KEY,
trainerID1 INTEGER,
trainerID2 INTEGER,
shiftDate DATE,
status TEXT,
FOREIGN KEY (trainerID1) REFERENCES Users(userID),
FOREIGN KEY (trainerID2) REFERENCES Users(userID)
)
"""
]
for table in tables:
self.cursor.execute(table)
self.conn.commit()
def insert_sample_data(self):
"""Вставка тестовых данных"""
# Проверяем, есть ли уже данные
self.cursor.execute("SELECT COUNT(*) FROM Users")
if self.cursor.fetchone()[0] > 0:
return
users = [
(1, 'Сидорова Марина Петровна', '89219014567', 'director@fitness.ru', 'director1', 'pass1', 'Директор', '', '1980-05-15'),
(2, 'Романова Анна Сергеевна', '89210125678', 'admin1@fitness.ru', 'admin1', 'pass2', 'Администратор', '', '1992-08-22'),
(4, 'Яковлева Елена Викторовна', '89211236789', 'admin2@fitness.ru', 'admin2', 'pass3', 'Администратор', '', '1988-11-10'),
(7, 'Петров Дмитрий Александрович', '89212347890', 'petrov@fitness.ru', 'trainer1', 'pass4', 'Тренер', 'Силовые тренировки', '1985-03-18'),
(9, 'Смирнова Ольга Игоревна', '89213458901', 'smirnova@fitness.ru', 'trainer2', 'pass5', 'Тренер', 'Йога, Пилатес', '1990-07-25'),
(11, 'Козлов Сергей Николаевич', '89214569012', 'kozlov@fitness.ru', 'trainer3', 'pass6', 'Тренер', 'Плавание', '1987-12-05'),
(16, 'Федорова Екатерина Дмитриевна', '89161112236', 'fedorova@mail.ru', 'client1', 'pass7', 'Клиент', '', '1995-04-12'),
(21, 'Михайлов Алексей Владимирович', '89162223347', 'mikhailov@gmail.com', 'client2', 'pass8', 'Клиент', '', '1988-09-30'),
(26, 'Новикова Ирина Сергеевна', '89163334458', 'novikova@yandex.ru', 'client3', 'pass9', 'Клиент', '', '1992-06-18'),
(30, 'Соколов Игорь Петрович', '89164445569', 'sokolov@mail.ru', 'client4', 'pass10', 'Клиент', '', '1983-02-28'),
(34, 'Павлова Мария Александровна', '89165556670', 'pavlova@gmail.com', 'client5', 'pass11', 'Клиент', '', '1997-11-07')
]
memberships = [
(1, 16, 'Месячный безлимит', '2024-06-01', '2024-06-30', 999, 42, 'Зал, Бассейн, Групповые', 'Активен', 5000.00, 2),
(2, 21, '12 посещений', '2024-06-05', '2024-09-05', 12, 8, 'Зал', 'Активен', 4000.00, 2),
(3, 26, 'Годовой VIP', '2024-01-10', '2025-01-10', 999, 156, 'Все зоны', 'Активен', 45000.00, 4),
(4, 30, 'Разовое посещение', '2024-06-15', '2024-06-15', 1, 1, 'Зал', 'Завершен', 500.00, 2),
(5, 34, 'Квартальный', '2024-06-01', '2024-08-31', 999, 15, 'Зал, Групповые', 'Активен', 12000.00, 4)
]
visits = [
(1, 16, '2024-06-15', '08:30', '10:15', 'Тренажерный зал', 1),
(2, 21, '2024-06-15', '09:00', '10:30', 'Тренажерный зал', 2),
(3, 26, '2024-06-15', '07:00', '08:30', 'Бассейн', 3),
(4, 16, '2024-06-15', '18:00', '19:45', 'Групповое занятие', 1),
(5, 34, '2024-06-15', '19:00', '20:30', 'Групповое занятие', 5)
]
group_classes = [
(1, 'Йога для начинающих', 9, '2024-06-16', '10:00', '11:00', 'Зал 2', 15, 12, 'Запланировано'),
(2, 'Силовая аэробика', 7, '2024-06-16', '18:00', '19:00', 'Зал 1', 20, 18, 'Запланировано'),
(3, 'Пилатес', 9, '2024-06-17', '11:00', '12:00', 'Зал 2', 12, 12, 'Группа заполнена'),
(4, 'Аквааэробика', 11, '2024-06-17', '15:00', '16:00', 'Бассейн', 10, 7, 'Запланировано'),
(5, 'Бокс', 7, '2024-06-18', '19:00', '20:30', 'Зал 3', 8, 5, 'Запланировано')
]
personal_training = [
(1, 26, 7, '2024-06-14', '16:00', '17:00', 'Жим лежа, Приседания, Тяга блока', 'Хорошая техника', 'Жим 80кг x 8'),
(2, 16, 9, '2024-06-13', '10:00', '11:00', 'Асаны йоги, Растяжка', 'Улучшилась гибкость', ''),
(3, 21, 7, '2024-06-12', '14:00', '15:00', 'Становая тяга, Жим гантелей', 'Нужно работать над техникой', 'Становая 60кг x 6')
]
# Вставка данных
self.cursor.executemany("INSERT INTO Users VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", users)
self.cursor.executemany("INSERT INTO Memberships VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", memberships)
self.cursor.executemany("INSERT INTO Visits VALUES (?, ?, ?, ?, ?, ?, ?)", visits)
self.cursor.executemany("INSERT INTO GroupClasses VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", group_classes)
self.cursor.executemany("INSERT INTO PersonalTraining VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", personal_training)
self.conn.commit()
def initUI(self):
"""Инициализация пользовательского интерфейса"""
self.setWindowTitle('Фитнес-клуб - Система управления')
self.setGeometry(100, 100, 1200, 800)
# Центральный виджет с вкладками для разных ролей
self.tabs = QTabWidget()
# Вкладка для администратора
self.admin_tab = QWidget()
self.init_admin_tab()
self.tabs.addTab(self.admin_tab, "Администратор")
# Вкладка для тренера
self.trainer_tab = QWidget()
self.init_trainer_tab()
self.tabs.addTab(self.trainer_tab, "Тренер")
# Вкладка для директора
self.director_tab = QWidget()
self.init_director_tab()
self.tabs.addTab(self.director_tab, "Директор")
self.setCentralWidget(self.tabs)
def init_admin_tab(self):
"""Инициализация вкладки администратора"""
layout = QVBoxLayout()
# Группа управления расписанием
schedule_group = QGroupBox("Управление расписанием групповых занятий")
schedule_layout = QVBoxLayout()
# Таблица групповых занятий
self.classes_table = QTableWidget()
self.classes_table.setColumnCount(10)
self.classes_table.setHorizontalHeaderLabels([
'ID', 'Название', 'Тренер', 'Дата', 'Время начала',
'Время окончания', 'Зал', 'Макс. участников', 'Записано', 'Статус'
])
schedule_layout.addWidget(self.classes_table)
# Кнопки управления
btn_layout = QHBoxLayout()
self.add_class_btn = QPushButton("Добавить занятие")
self.edit_class_btn = QPushButton("Редактировать")
self.delete_class_btn = QPushButton("Удалить")
btn_layout.addWidget(self.add_class_btn)
btn_layout.addWidget(self.edit_class_btn)
btn_layout.addWidget(self.delete_class_btn)
schedule_layout.addLayout(btn_layout)
schedule_group.setLayout(schedule_layout)
layout.addWidget(schedule_group)
# Группа управления абонементами
membership_group = QGroupBox("Управление абонементами")
membership_layout = QVBoxLayout()
self.memberships_table = QTableWidget()
self.memberships_table.setColumnCount(8)
self.memberships_table.setHorizontalHeaderLabels([
'ID', 'Клиент', 'Тип', 'Начало', 'Окончание',
'Использовано/Всего', 'Статус', 'Стоимость'
])
membership_layout.addWidget(self.memberships_table)
# Кнопки для управления абонементами
membership_btn_layout = QHBoxLayout()
self.change_price_btn = QPushButton("Изменить стоимость")
self.freeze_membership_btn = QPushButton("Заморозить абонемент")
membership_btn_layout.addWidget(self.change_price_btn)
membership_btn_layout.addWidget(self.freeze_membership_btn)
membership_layout.addLayout(membership_btn_layout)
membership_group.setLayout(membership_layout)
layout.addWidget(membership_group)
# Группа статистики
stats_group = QGroupBox("Статистика и отчетность")
stats_layout = QHBoxLayout()
# Левая часть - форма для фильтров
stats_form = QFormLayout()
self.stats_start_date = QDateEdit()
self.stats_end_date = QDateEdit()
self.stats_start_date.setDate(QDate.currentDate().addMonths(-1))
self.stats_end_date.setDate(QDate.currentDate())
stats_form.addRow("С:", self.stats_start_date)
stats_form.addRow("По:", self.stats_end_date)
self.generate_stats_btn = QPushButton("Сформировать отчет")
stats_form.addRow(self.generate_stats_btn)
stats_layout.addLayout(stats_form)
# Правая часть - диаграмма
self.stats_chart = QChartView()
stats_layout.addWidget(self.stats_chart)
stats_group.setLayout(stats_layout)
layout.addWidget(stats_group)
# Загрузка данных
self.load_classes_data()
self.load_memberships_data()
# Подключение сигналов
self.add_class_btn.clicked.connect(self.add_class)
self.generate_stats_btn.clicked.connect(self.generate_stats)
self.admin_tab.setLayout(layout)
def init_trainer_tab(self):
"""Инициализация вкладки тренера"""
layout = QVBoxLayout()
# Группа программ тренировок
programs_group = QGroupBox("Индивидуальные программы тренировок")
programs_layout = QVBoxLayout()
self.programs_table = QTableWidget()
self.programs_table.setColumnCount(6)
self.programs_table.setHorizontalHeaderLabels([
'ID', 'Клиент', 'Дата', 'Упражнения', 'Заметки', 'Прогресс'
])
programs_layout.addWidget(self.programs_table)
programs_btn_layout = QHBoxLayout()
self.add_program_btn = QPushButton("Добавить программу")
self.edit_program_btn = QPushButton("Редактировать")
programs_btn_layout.addWidget(self.add_program_btn)
programs_btn_layout.addWidget(self.edit_program_btn)
programs_layout.addLayout(programs_btn_layout)
programs_group.setLayout(programs_layout)
layout.addWidget(programs_group)
# Группа базы упражнений
exercises_group = QGroupBox("База упражнений")
exercises_layout = QVBoxLayout()
self.exercises_table = QTableWidget()
self.exercises_table.setColumnCount(3)
self.exercises_table.setHorizontalHeaderLabels(['ID', 'Название', 'Группа мышц'])
exercises_layout.addWidget(self.exercises_table)
exercises_btn_layout = QHBoxLayout()
self.add_exercise_btn = QPushButton("Добавить упражнение")
exercises_btn_layout.addWidget(self.add_exercise_btn)
exercises_layout.addLayout(exercises_btn_layout)
exercises_group.setLayout(exercises_layout)
layout.addWidget(exercises_group)
# Группа запросов оборудования
equipment_group = QGroupBox("Запросы оборудования")
equipment_layout = QVBoxLayout()
self.equipment_table = QTableWidget()
self.equipment_table.setColumnCount(5)
self.equipment_table.setHorizontalHeaderLabels([
'ID', 'Оборудование', 'Количество', 'Дата запроса', 'Статус'
])
equipment_layout.addWidget(self.equipment_table)
equipment_btn_layout = QHBoxLayout()
self.request_equipment_btn = QPushButton("Запросить оборудование")
equipment_btn_layout.addWidget(self.request_equipment_btn)
equipment_layout.addLayout(equipment_btn_layout)
equipment_group.setLayout(equipment_layout)
layout.addWidget(equipment_group)
# Загрузка данных
self.load_programs_data()
self.load_equipment_data()
self.trainer_tab.setLayout(layout)
def init_director_tab(self):
"""Инициализация вкладки директора"""
layout = QVBoxLayout()
# Общая статистика
overall_stats_group = QGroupBox("Общая статистика клуба")
overall_layout = QHBoxLayout()
# Левая часть - ключевые показатели
metrics_layout = QFormLayout()
self.total_members_label = QLabel("0")
self.active_members_label = QLabel("0")
self.monthly_revenue_label = QLabel("0 руб.")
self.attendance_rate_label = QLabel("0%")
metrics_layout.addRow("Всего клиентов:", self.total_members_label)
metrics_layout.addRow("Активных абонементов:", self.active_members_label)
metrics_layout.addRow("Доход за месяц:", self.monthly_revenue_label)
metrics_layout.addRow("Посещаемость:", self.attendance_rate_label)
overall_layout.addLayout(metrics_layout)
# Правая часть - диаграмма доходов
self.revenue_chart = QChartView()
overall_layout.addWidget(self.revenue_chart)
overall_stats_group.setLayout(overall_layout)
layout.addWidget(overall_stats_group)
# Эффективность тренеров
trainers_group = QGroupBox("Эффективность тренеров")
trainers_layout = QVBoxLayout()
self.trainers_table = QTableWidget()
self.trainers_table.setColumnCount(6)
self.trainers_table.setHorizontalHeaderLabels([
'Тренер', 'Групповые занятия', 'Персональные тренировки',
'Средняя оценка', 'Доход', 'Бонусы'
])
trainers_layout.addWidget(self.trainers_table)
trainers_group.setLayout(trainers_layout)
layout.addWidget(trainers_group)
# Финансовые показатели
finance_group = QGroupBox("Финансовые показатели")
finance_layout = QVBoxLayout()
self.finance_table = QTableWidget()
self.finance_table.setColumnCount(4)
self.finance_table.setHorizontalHeaderLabels([
'Период', 'Доход', 'Расходы', 'Прибыль'
])
finance_layout.addWidget(self.finance_table)
finance_group.setLayout(finance_layout)
layout.addWidget(finance_group)
# Загрузка данных
self.load_director_data()
self.director_tab.setLayout(layout)
def load_classes_data(self):
"""Загрузка данных о групповых занятиях"""
self.cursor.execute("""
SELECT gc.classID, gc.className, u.fio, gc.classDate, gc.startTime,
gc.endTime, gc.hall, gc.maxParticipants, gc.enrolledParticipants, gc.classStatus
FROM GroupClasses gc
LEFT JOIN Users u ON gc.trainerID = u.userID
ORDER BY gc.classDate, gc.startTime
""")
classes = self.cursor.fetchall()
self.classes_table.setRowCount(len(classes))
for row, class_data in enumerate(classes):
for col, data in enumerate(class_data):
self.classes_table.setItem(row, col, QTableWidgetItem(str(data)))
def load_memberships_data(self):
"""Загрузка данных об абонементах"""
self.cursor.execute("""
SELECT m.membershipID, u.fio, m.membershipType, m.startDate, m.endDate,
m.visitsUsed || '/' || m.visitsTotal, m.membershipStatus, m.cost
FROM Memberships m
JOIN Users u ON m.clientID = u.userID
ORDER BY m.endDate
""")
memberships = self.cursor.fetchall()
self.memberships_table.setRowCount(len(memberships))
for row, membership_data in enumerate(memberships):
for col, data in enumerate(membership_data):
self.memberships_table.setItem(row, col, QTableWidgetItem(str(data)))
def load_programs_data(self):
"""Загрузка данных о программах тренировок"""
self.cursor.execute("""
SELECT pt.trainingID, u.fio, pt.trainingDate, pt.exercises, pt.notes, pt.progressMetrics
FROM PersonalTraining pt
JOIN Users u ON pt.clientID = u.userID
ORDER BY pt.trainingDate DESC
""")
programs = self.cursor.fetchall()
self.programs_table.setRowCount(len(programs))
for row, program_data in enumerate(programs):
for col, data in enumerate(program_data):
self.programs_table.setItem(row, col, QTableWidgetItem(str(data)))
def load_equipment_data(self):
"""Загрузка данных о запросах оборудования"""
self.cursor.execute("""
SELECT requestID, equipment, quantity, requestDate, status
FROM EquipmentRequests
ORDER BY requestDate DESC
""")
equipment = self.cursor.fetchall()
self.equipment_table.setRowCount(len(equipment))
for row, equipment_data in enumerate(equipment):
for col, data in enumerate(equipment_data):
self.equipment_table.setItem(row, col, QTableWidgetItem(str(data)))
def load_director_data(self):
"""Загрузка данных для директора"""
# Общая статистика
self.cursor.execute("SELECT COUNT(*) FROM Users WHERE userType = 'Клиент'")
total_clients = self.cursor.fetchone()[0]
self.total_members_label.setText(str(total_clients))
self.cursor.execute("SELECT COUNT(*) FROM Memberships WHERE membershipStatus = 'Активен'")
active_memberships = self.cursor.fetchone()[0]
self.active_members_label.setText(str(active_memberships))
self.cursor.execute("""
SELECT SUM(cost) FROM Memberships
WHERE strftime('%Y-%m', startDate) = strftime('%Y-%m', 'now')
""")
monthly_revenue = self.cursor.fetchone()[0] or 0
self.monthly_revenue_label.setText(f"{monthly_revenue:.2f} руб.")
# Диаграмма доходов
self.cursor.execute("""
SELECT membershipType, SUM(cost)
FROM Memberships
WHERE strftime('%Y', startDate) = strftime('%Y', 'now')
GROUP BY membershipType
""")
revenue_data = self.cursor.fetchall()
series = QPieSeries()
for membership_type, revenue in revenue_data:
series.append(membership_type, revenue)
chart = QChart()
chart.addSeries(series)
chart.setTitle("Доходы по типам абонементов")
chart.legend().setVisible(True)
chart.legend().setAlignment(Qt.AlignmentFlag.AlignBottom)
self.revenue_chart.setChart(chart)
# Данные по тренерам
self.cursor.execute("""
SELECT u.fio,
COUNT(DISTINCT gc.classID) as group_classes,
COUNT(DISTINCT pt.trainingID) as personal_trainings,
'4.5' as avg_rating,
SUM(m.cost * 0.1) as revenue,
COUNT(DISTINCT pt.trainingID) * 100 as bonuses
FROM Users u
LEFT JOIN GroupClasses gc ON u.userID = gc.trainerID
LEFT JOIN PersonalTraining pt ON u.userID = pt.trainerID
LEFT JOIN Memberships m ON pt.clientID = m.clientID
WHERE u.userType = 'Тренер'
GROUP BY u.userID, u.fio
""")
trainers = self.cursor.fetchall()
self.trainers_table.setRowCount(len(trainers))
for row, trainer_data in enumerate(trainers):
for col, data in enumerate(trainer_data):
self.trainers_table.setItem(row, col, QTableWidgetItem(str(data)))
def add_class(self):
"""Добавление нового группового занятия"""
dialog = AddClassDialog(self)
if dialog.exec():
class_data = dialog.get_data()
try:
self.cursor.execute("""
INSERT INTO GroupClasses (className, trainerID, classDate, startTime, endTime, hall, maxParticipants, enrolledParticipants, classStatus)
VALUES (?, ?, ?, ?, ?, ?, ?, 0, 'Запланировано')
""", class_data)
self.conn.commit()
self.load_classes_data()
QMessageBox.information(self, "Успех", "Занятие успешно добавлено!")
except Exception as e:
QMessageBox.critical(self, "Ошибка", f"Не удалось добавить занятие: {str(e)}")
def generate_stats(self):
"""Генерация статистики посещаемости"""
start_date = self.stats_start_date.date().toString("yyyy-MM-dd")
end_date = self.stats_end_date.date().toString("yyyy-MM-dd")
self.cursor.execute("""
SELECT zone, COUNT(*) as visits
FROM Visits
WHERE visitDate BETWEEN ? AND ?
GROUP BY zone
""", (start_date, end_date))
zone_stats = self.cursor.fetchall()
series = QBarSeries()
bar_set = QBarSet("Посещения по зонам")
categories = []
visits = []
for zone, count in zone_stats:
categories.append(zone)
visits.append(count)
bar_set.append(visits)
series.append(bar_set)
chart = QChart()
chart.addSeries(series)
chart.setTitle(f"Посещаемость по зонам ({start_date} - {end_date})")
axis_x = QBarCategoryAxis()
axis_x.append(categories)
chart.addAxis(axis_x, Qt.AlignmentFlag.AlignBottom)
series.attachAxis(axis_x)
axis_y = QValueAxis()
chart.addAxis(axis_y, Qt.AlignmentFlag.AlignLeft)
series.attachAxis(axis_y)
self.stats_chart.setChart(chart)
class AddClassDialog(QMessageBox):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("Добавить групповое занятие")
self.setModal(True)
self.class_name = QLineEdit()
self.trainer = QComboBox()
self.class_date = QDateEdit()
self.start_time = QTimeEdit()
self.end_time = QTimeEdit()
self.hall = QComboBox()
self.max_participants = QSpinBox()
self.class_date.setDate(QDate.currentDate())
self.start_time.setTime(QTime.currentTime())
self.end_time.setTime(QTime.currentTime().addSecs(3600))
self.max_participants.setRange(1, 100)
# Заполнение комбобоксов
parent.cursor.execute("SELECT userID, fio FROM Users WHERE userType = 'Тренер'")
trainers = parent.cursor.fetchall()
for trainer_id, fio in trainers:
self.trainer.addItem(fio, trainer_id)
self.hall.addItems(['Зал 1', 'Зал 2', 'Зал 3', 'Бассейн'])
layout = QFormLayout()
layout.addRow("Название:", self.class_name)
layout.addRow("Тренер:", self.trainer)
layout.addRow("Дата:", self.class_date)
layout.addRow("Время начала:", self.start_time)
layout.addRow("Время окончания:", self.end_time)
layout.addRow("Зал:", self.hall)
layout.addRow("Макс. участников:", self.max_participants)
widget = QWidget()
widget.setLayout(layout)
self.layout().addWidget(widget, 0, 0, 1, self.layout().columnCount())
self.addButton(QPushButton("Добавить"), QMessageBox.ButtonRole.AcceptRole)
self.addButton(QPushButton("Отмена"), QMessageBox.ButtonRole.RejectRole)
def get_data(self):
"""Получение данных из формы"""
return (
self.class_name.text(),
self.trainer.currentData(),
self.class_date.date().toString("yyyy-MM-dd"),
self.start_time.time().toString("hh:mm"),
self.end_time.time().toString("hh:mm"),
self.hall.currentText(),
self.max_participants.value()
)
if __name__ == '__main__':
app = QApplication(sys.argv)
# Установка стиля
app.setStyle('Fusion')
window = FitnessApp()
window.show()
sys.exit(app.exec())

BIN
fitness.db Normal file

Binary file not shown.

BIN
service_requests.db Normal file

Binary file not shown.