Files
LibrarySystem/src/ui/main_ui.py
2024-09-16 13:51:44 +02:00

469 lines
18 KiB
Python

import sys
import atexit
import datetime
from src import config
from src.logic import Database, Catalogue, Backup
from src.utils import stringToDate, Icon, Log
from src.utils import debugMessage as dbg
from src.utils.createReport import generate_report
from src.schemas import Book
from .sources.Ui_main_UserInterface import Ui_MainWindow
from .user import UserUI
from .createUser import CreateUser
from .multiUserInfo import MultiUserFound
from .newentry import NewEntry
from .settings import Settings
from .newBook import NewBook
from .loans import LoanWindow
from .reportUi import ReportUi
from PyQt6 import QtCore, QtWidgets
backup = Backup()
cat = Catalogue()
log = Log("main")
dbg(backup=config.database.do_backup, catalogue=config.catalogue)
class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
def __init__(self):
super(MainUI, self).__init__()
self.setupUi(self)
self.setWindowTitle(f"Handbibliotheksleihsystem {config.institution_name}")
self.setWindowIcon(Icon("main").icon)
self.label_7.hide()
self.nextReturnDate.hide()
# add default loan duration to current date
# hotkeys
self.actionRueckgabemodus.triggered.connect(self.changeMode)
self.actionNutzer.triggered.connect(self.showUser)
self.actionEinstellungen.triggered.connect(self.showSettings)
self.actionAusleihistorie.triggered.connect(self.showLoanHistory)
self.actionBericht_erstellen.triggered.connect(self.generateReport)
# Buttons
self.btn_show_lentmedia.clicked.connect(self.showUser)
self.btn_createNewUser.clicked.connect(self.createUser)
self.btn_createNewUser.setText("")
self.btn_createNewUser.setIcon(Icon("add_user").overwriteColor("#1E90FF"))
# LineEdits
self.input_userno.returnPressed.connect(
lambda: self.checkUser("user_id", self.input_userno.text())
)
self.input_username.returnPressed.connect(
lambda: self.checkUser("username", self.input_username.text())
)
self.input_file_ident.returnPressed.connect(self.handleLineInput)
self.input_userno.setMaxLength(40)
self.input_userno.textChanged.connect(
lambda: self.validateInput(self.input_userno.text(), "int")
)
self.input_username.setEnabled(False)
self.input_userno.setEnabled(False)
self.duedate.setEnabled(False)
# TableWidget
# set header size to be width/number of columns
self.mediaOverview.horizontalHeader().setSectionResizeMode(
QtWidgets.QHeaderView.ResizeMode.Stretch
)
self.input_file_ident.setFocus()
# self.userdata.textChanged.connect(lambda: self.mode.setText("Ausleihe"))
# variables
self.db = Database()
self.currentDate = QtCore.QDate.currentDate()
loanDate = self.currentDate.addDays(config.loan_duration)
self.activeUser = None
self.activeState = "Rückgabe"
self.duedate.setDate(loanDate)
# functions
self.activateReturnMode()
if backup.backup:
log.info("Backup enabled")
else:
log.warning("Backup disabled")
self.show()
def generateReport(self):
log.info("Generating Report")
report = ReportUi()
report.exec()
def showLoanHistory(self):
log.info("Showing Loan History")
self.loan = LoanWindow()
self.loan.show()
def validateInput(self, value, type):
lastchar = value[-1] if value else ""
# if lastchar is not of the type, remove it
if type == "int":
if not lastchar.isdigit():
self.input_userno.setText(value[:-1])
def showSettings(self):
log.info("Showing Settings")
settings = Settings()
settings.exec()
# reload settings
#print(config)
def changeMode(self):
log.info("Changing Mode")
dbg(f"Current mode: {self.activeState}")
self.input_username.clear()
stayReturn = False
if self.userdata.toPlainText() != "":
stayReturn = True
self.userdata.clear()
self.input_userno.clear()
self.btn_show_lentmedia.setText("")
self.input_file_ident.clear()
self.label_7.hide()
self.nextReturnDate.hide()
self.mediaOverview.setRowCount(0)
self.activeUser = None #! remove if last user should be kept
if self.activeState == "Rückgabe":
if stayReturn:
self.activateReturnMode()
else: self.activateLoanMode()
else:
self.activateReturnMode()
def activateLoanMode(self):
dbg("Activating Loan Mode")
self.input_username.setEnabled(True)
self.input_userno.setEnabled(True)
self.duedate.setEnabled(True)
self.input_userno.setFocus()
# set mode background color to blue with rounded edges
# self.mode.setFrameShape(QtWidgets.QFrame.Shape.StyledPanel)
self.mode.setStyleSheet("background-color: #1E90FF")
self.mode.setText("Ausleihe")
self.activeState = "Ausleihe"
if self.input_userno.text() == "" or self.input_username.text() == "":
self.input_file_ident.setEnabled(False)
self.input_file_ident.setPlaceholderText("Bitte zuerst Nutzerdaten eingeben")
else:
self.input_file_ident.setEnabled(True)
def activateReturnMode(self):
dbg("Activating Return Mode")
self.input_username.setEnabled(False)
self.input_userno.setEnabled(False)
# set mode background color to orange
self.mode.setStyleSheet("background-color: #FFA500")
self.duedate.setEnabled(False)
self.activeState = "Rückgabe"
self.mode.setText("Rückgabe")
self.input_file_ident.setEnabled(True)
self.input_file_ident.setPlaceholderText("Buchidentifikation eingeben")
def showUser(self):
log.info(f"Showing User {self.activeUser}")
if self.activeUser is None:
# create warning dialog
log.info("Showing no user selected warning")
dialog = QtWidgets.QMessageBox()
dialog.setWindowTitle("Kein Nutzer ausgewählt")
dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning)
dialog.setWindowIcon(Icon("warning").overwriteColor("#EA3323"))
dialog.setText("Kein Nutzer ausgewählt")
dialog.exec()
return
self.user_ui = UserUI(
self.activeUser
)
# self.user_ui.setFields("John Doe", "123456789", "test@mail.com")
self.user_ui.show()
def setUserData(self):
log.info("Setting User Data")
self.input_username.setText(str(self.activeUser.username))
self.input_userno.setText(str(self.activeUser.userid))
self.userdata.setText(self.activeUser.__repr__())
today = QtCore.QDate.currentDate().toString("yyyy-MM-dd")
self.db.setUserActiveDate(self.activeUser.userid, today)
# self.mode.setText("Ausleihe")
def createUser(self):
log.info("Creating User")
user = CreateUser(fieldname="id", data="")
user.exec()
userid = user.userid
print(userid)
if userid:
log.info(f"User created {userid}")
data = self.db.getUserBy("user_id", userid)
self.activeUser = data
# set user to active user
self.setUserData()
self.activateLoanMode()
self.input_file_ident.setFocus()
return
def checkUser(self, fieldname, data):
log.info(f"Checking User {fieldname}, {data}")
#print("Checking User", fieldname, data)
# set fieldname as key and data as variable
user = self.db.checkUserExists(fieldname, data)
if not user:
warning = QtWidgets.QMessageBox()
warning.setWindowTitle("Nutzer nicht gefunden")
warning.setIcon(QtWidgets.QMessageBox.Icon.Warning)
warning.setWindowIcon(Icon("warning").overwriteColor("#EA3323"))
warning.setText("Nutzer nicht gefunden, bitte erst anlegen")
warning.exec()
self.input_username.clear()
self.input_userno.clear()
return
else:
if len(user) > 1:
log.info("Multiple Users found")
multi = MultiUserFound(user)
multi.exec()
self.activeUser = multi.userdata
else:
#print("User found", user[0])
self.activeUser = user[0]
if self.activeUser is not None:
log.info(f"User found {self.activeUser}")
#print("User found", self.activeUser)
self.setUserData()
self.input_file_ident.setFocus()
self.mode.setText("Ausleihe")
#print(self.activeUser.__dict__)
loans = self.db.getActiveLoans(self.activeUser.id)
dbg(loans=loans)
self.btn_show_lentmedia.setText(loans)
retdate = self.db.selectClosestReturnDate(self.activeUser.id)
if retdate:
date = stringToDate(retdate).toString("dd.MM.yyyy")
self.nextReturnDate.setText(date)
self.nextReturnDate.show()
self.label_7.show()
self.input_file_ident.setEnabled(True)
self.input_file_ident.setPlaceholderText("Buchidentifikation eingeben")
self.input_file_ident.setFocus()
def moveToLine(self, line):
log.debug("Moving to Line", line)
line.setFocus()
def handleLineInput(self):
value = self.input_file_ident.text().strip()
log.debug(f"Handling Line Input {value}")
if self.mode.text() == "Rückgabe":
self.returnMedia(value)
else:
if not " " in value:
# create warning dialog
log.info("Invalid Input")
dialog = QtWidgets.QMessageBox()
dialog.setWindowTitle("Ungültige Eingabe")
dialog.setIcon(QtWidgets.QMessageBox.Icon.Warning)
dialog.setWindowIcon(Icon("warning").overwriteColor("#EA3323"))
dialog.setText(
"Die Eingabe enthält kein Leerzeichen\nBitte prüfen und erneut eingeben"
)
dialog.exec()
return
self.mediaAdd(value)
self.input_file_ident.setFocus()
def mediaAdd(self, identifier):
dbg("Adding Media", identifier = identifier)
self.input_file_ident.clear()
self.input_file_ident.setEnabled(False)
user_id = self.activeUser.id
media = Book(signature=identifier)
book_id = self.db.checkMediaExists(media)
dbg(f"Book ID: {book_id}, User ID: {user_id}", media=media)
if not book_id:
dbg("Book not found, searching catalogue")
if config.catalogue == True:
media = cat.get_book(identifier)
if not media:
self.setStatusTipMessage("Buch nicht gefunden")
self.input_file_ident.setEnabled(True)
return
book_id = self.db.insertMedia(media)
self.loanMedia(user_id, [book_id], media)
else:
newbook = NewBook()
newbook.exec()
if newbook.result() == 1:
media = newbook.book
book_id = self.db.insertMedia(media)
elif book_id:
if isinstance(book_id, list) and len(book_id) > 1:
#print("Multiple Books found")
# TODO: implement book selection dialog
return
else:
if isinstance(book_id, int):
book_id = [book_id]
# check if book is already loaned
loaned = self.db.checkLoanState(book_id[0])
if loaned:
#print("Book already loaned")
self.setStatusTipMessage("Buch bereits entliehen")
# dialog with yes no to create new entry
dialog = QtWidgets.QMessageBox()
dialog.setWindowTitle("Buch bereits entliehen")
dialog.setWindowIcon(Icon("duplicate").icon)
dialog.setText(
"Buch bereits entliehen, soll ein neues hinzugefügt werden?"
)
dialog.setStandardButtons(
QtWidgets.QMessageBox.StandardButton.Yes
| QtWidgets.QMessageBox.StandardButton.No
)
dialog.setDefaultButton(QtWidgets.QMessageBox.StandardButton.No)
dialog.exec()
result = dialog.result()
if result == QtWidgets.QMessageBox.StandardButton.No:
self.input_file_ident.setEnabled(True)
return
newentry = NewEntry([book_id[0]])
newentry.exec()
self.setStatusTipMessage("Neues Exemplar hinzugefügt")
#print(created_ids)
self.input_file_ident.setEnabled(True)
newentries = newentry.newIds
if newentries:
for entry in newentries:
book = self.db.getMedia(entry)
self.loanMedia(user_id, [entry], book)
dbg("inserted duplicated book into database")
return
else:
#print("Book not loaned, loaning now")
self.loanMedia(user_id, book_id)
def loanMedia(self, user_id, book_id):
self.db.insertLoan(
user_id,
book_id[0],
self.currentDate.toString("yyyy-MM-dd"),
self.duedate.date().toString("yyyy-MM-dd"),
)
media = self.db.getMedia(book_id[0])
#print(media)
self.mediaOverview.insertRow(0)
self.mediaOverview.setItem(0, 0, QtWidgets.QTableWidgetItem(media.signature))
self.mediaOverview.setItem(0, 1, QtWidgets.QTableWidgetItem(media.title))
self.mediaOverview.setItem(0, 2, QtWidgets.QTableWidgetItem("Entliehen"))
self.btn_show_lentmedia.setText(self.db.getActiveLoans(self.activeUser.id))
self.nextReturnDate.setText(
stringToDate(self.db.selectClosestReturnDate(self.activeUser.id)).toString(
"dd.MM.yyyy"
)
)
self.nextReturnDate.show()
self.label_7.show()
self.input_file_ident.setEnabled(True)
def returnMedia(self, identifier):
#print("Returning Media", identifier)
# get book id from database
# self.
identifier = Book(
isbn=identifier, title=identifier, signature=identifier, ppn=identifier
)
book_id = self.db.checkMediaExists(identifier)
#print(book_id)
if book_id:
# check if book is already loaned
loaned = self.db.checkLoanState(book_id[0])
if loaned:
#print("Book already loaned, returning now")
user = self.db.getUserByLoan(book_id[0])
# set userdata in lineedits
self.activeUser = user
self.setUserData()
book = self.db.returnMedia(
book_id[0], self.currentDate.toString("yyyy-MM-dd")
)
self.mediaOverview.insertRow(0)
self.mediaOverview.setItem(0, 0, QtWidgets.QTableWidgetItem(book.signature))
self.mediaOverview.setItem(0, 1, QtWidgets.QTableWidgetItem(book.title))
self.mediaOverview.setItem(
0, 2, QtWidgets.QTableWidgetItem("Zurückgegeben")
)
self.input_file_ident.clear()
self.btn_show_lentmedia.setText(
self.db.getActiveLoans(self.activeUser.id)
)
else:
#print("Book not loaned")
self.setStatusTipMessage("Buch nicht entliehen")
self.input_file_ident.clear()
else:
dbg("Book not found")
#print("Book not found")
#self.input_file_ident.setPlaceholderText(f"Buch {identifier} nicht gefunden")
def setStatusTipMessage(self, message):
dialog = QtWidgets.QMessageBox()
dialog.setWindowTitle("Information")
dialog.setIcon(QtWidgets.QMessageBox.Icon.Information)
dialog.setWindowIcon(Icon("error").overwriteColor("#EA3323"))
dialog.setText(message)
dialog.exec()
def exit_handler():
dbg("Exiting, creating backup")
app = QtWidgets.QApplication(sys.argv)
#print(backup.backup)
# generate report if monday
if datetime.datetime.now().weekday() == config.report.report_day:
generate_report()
dbg("Generated Report")
Database().renameInactiveUsers()
if config.database.do_backup:
state = backup.createBackup()
# create dialog to show state
if state == True:
return
else:
dialog = QtWidgets.QMessageBox()
# set icon
dialog.setWindowIcon(Icon("backup").icon)
dialog.setWindowTitle("Backup")
dialog.setText("Backup konnte nicht erstellt werden")
dialog.exec()
dbg("Exiting", backupstate=state)
else:
dialog = QtWidgets.QMessageBox()
# set icon
reason = "Unbekannter Grund"
if config.database.do_backup is False:
reason = "Backup deaktiviert"
if backup.backup is False:
reason = "Backuppfad nicht gefunden"
dialog.setWindowIcon(Icon("backup").icon)
dialog.setWindowTitle("Backup nicht möglich")
dialog.setText("Backup konnte nicht erstellt werden\nGrund: {}".format(reason))
dialog.exec()
def launch(*argv):
options = sys.argv
if argv:
options += [arg for arg in argv]
options = [arg for arg in options if arg.startswith("--")]
#print("Launching Main UI")
#print(options)
app = QtWidgets.QApplication([])
main_ui = MainUI()
atexit.register(exit_handler)
sys.exit(app.exec())
# sys.exit(app.exec())