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())