update deps, change config to restore changes, color overdue red in main, in loan color based on state

This commit is contained in:
2025-01-13 11:14:27 +01:00
parent 148adb937d
commit daf8d87b9d
10 changed files with 1085 additions and 40 deletions

View File

@@ -148,10 +148,37 @@ class Config:
raise KeyError(f"Option {keys[0]} not found in configuration")
else:
self._config[key] = value
def get_changes(self, other):
# compare self to other, return changes
changes = {}
for key in self._config:
if self._config[key] != other[key]:
changes[key] = self._config[key]
return changes
if __name__ == "__main__":
cfg = Config("config/settings.yaml")
#print(cfg.database.path)
cfg.database.path = "nopathhere"
#print(cfg.database.path)
cfg.save()
#cfg.updateValue("database.path", "Test")
other = {
"institution_name": "Test",
"default_loan_duration": 7,
"inactive_user_deletion": 365,
"database": {
"path": "./database",
"name": "library.db",
"backupLocation": "./backup",
"do_backup": True,
},
"report": {"generate_report": True, "path": "./report", "report_day": 0},
"shortcuts": [
{"name": "Rueckgabemodus", "default": "F5", "current": "F5"},
{"name": "Nutzer", "default": "F6", "current": "F6"},
{"name": "Hilfe", "default": "F1", "current": "F1"},
{"name": "Bericht_erstellen", "default": "F7", "current": "F7"},
{"name": "Ausleihhistorie", "default": "F8", "current": "F8"},
],
"advanced_refresh": False,
"catalogue": True,
"debug": True,
"documentation": True,
}
print(cfg.get_changes(other))

View File

@@ -1,4 +1,4 @@
from src.ui.main_ui import launch
if __name__ == "__main__":
launch("--debug")
launch()

View File

@@ -5,11 +5,22 @@ description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"beautifulsoup4>=4.12.3",
"loguru>=0.7.3",
"mkdocs>=1.6.1",
"mkdocs-material>=9.5.49",
"mkdocs-material-extensions>=1.3.1",
"omegaconf>=2.3.0",
"prettytable>=3.12.0",
"pyqt6>=6.8.0",
"pyramid>=2.0.2",
"python-dotenv>=1.0.1",
"requests>=2.32.3",
]
[dependency-groups]
dev = [
"bump-my-version>=0.29.0",
"icecream>=2.1.4",
"nuitka>=2.5.9",
]

View File

@@ -12,7 +12,7 @@ docport = 6543
config = Config("config/settings.yaml")
_config = config
_config = Config("config/settings.yaml")._config
# Store original values that might be overridden by CLI
@@ -46,13 +46,6 @@ if changes_made:
config.save()
def restore_config():
global _config
config._config = _config
config.save()
log.info("Restored configuration")
atexit.register(restore_config)
log = logger
log.remove()
log.add("logs/application.log", rotation="1 week", compression="zip")
@@ -69,3 +62,13 @@ if config.debug:
log.add(
sys.stderr,
)
def restore_config():
log.debug("Restoring configuration")
print("Changes made: ", changes_made)
if not changes_made:
return
config._config = _config
config.save()
log.info("Restored configuration, changed values: {config.get_changes(_config)}")

View File

@@ -2,3 +2,4 @@ __help__ = "This package contains the logic of the application."
from .database import Database
from .catalogue import Catalogue
from .backup import Backup
from .documentation_thread import DocumentationThread

View File

@@ -29,7 +29,7 @@ class Database:
os.makedirs(config.database.backupLocation)
#if main path does not exist, try to create it. if that fails, use the backuplocation
log.debug("Checking Database Path", self.db_path)
log.debug("Checking Database Path {}", self.db_path)
self.checkDatabaseStatus()
def handle_folder_reachability(self, original_path, backup_path):
@@ -219,14 +219,14 @@ class Database:
for res in result:
if res[0] == user_id:
user = User(userid=res[1], username=res[2], email=res[3], id=res[0])
dbg(f"Returning User {user}")
log.debug(f"Returning User {user}")
log.info(f"Returning User {user}")
return user
else:
for res in result:
if res[1] == user_id:
user = User(userid=res[1], username=res[2], email=res[3], id=res[0])
dbg(f"Returning User {user}")
log.debug(f"Returning User {user}")
log.info(f"Returning User {user}")
return user
raise ValueError(f"User {user_id} not found")
@@ -245,7 +245,7 @@ class Database:
return user
def updateUser(self, username, user_id, usermail):
log.debug(f"Updating User {userno}, {username}, {usermail}")
log.debug(f"Updating User {user_id}, {username}, {usermail}")
conn = self.connect()
cursor = conn.cursor()
cursor.execute(
@@ -260,7 +260,7 @@ class Database:
cursor = conn.cursor()
cursor.execute(query)
conn.commit()
dbg(f"Setting User {userid} to active on {date}")
log.debug(f"Setting User {userid} to active on {date}")
def renameInactiveUsers(self):
lastYear = QtCore.QDate.currentDate().addDays(int(f"-{config.delete_inactive_user_duration}")).toString("yyyy-MM-dd")
@@ -294,7 +294,7 @@ class Database:
self.close_connection(conn)
def getActiveLoans(self, userid):
dbg("id", str(userid))
log.debug("id", str(userid))
conn = self.connect()
cursor = conn.cursor()
try:
@@ -404,7 +404,7 @@ class Database:
)
return res
def getAllMedia(self, user_id):
def getAllMedia(self, user_id) -> list[Book]:
# get all books that have the user id in the loans table
query = f"SELECT * FROM loans WHERE user_id = '{user_id}'"
conn = self.connect()
@@ -487,7 +487,7 @@ class Database:
cursor = conn.cursor()
cursor.execute(query)
result = cursor.fetchone()
dbg("Result", response=result)
log.debug(f"Result: {result}")
self.close_connection(conn)
if result is not None:
return result[0]

View File

@@ -2,8 +2,10 @@ import sys
import atexit
import datetime
import webbrowser
from src import config, __email__, docport, log
from src.logic import Database, Catalogue, Backup
from PyQt6 import QtCore, QtWidgets
from omegaconf import OmegaConf
from src import config, __email__, docport, log, restore_config
from src.logic import Database, Catalogue, Backup, DocumentationThread
from src.utils import stringToDate, Icon
from src.utils.createReport import generate_report
from src.schemas import Book
@@ -16,9 +18,7 @@ from .settings import Settings
from .newBook import NewBook
from .loans import LoanWindow
from .reportUi import ReportUi
from PyQt6 import QtCore, QtWidgets
from omegaconf import OmegaConf
from src.logic.documentation_thread import DocumentationThread
backup = Backup()
cat = Catalogue()
@@ -327,6 +327,12 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
retdate = self.db.selectClosestReturnDate(self.activeUser.id)
if retdate:
date = stringToDate(retdate).toString("dd.MM.yyyy")
today = QtCore.QDate.currentDate().toString("yyyy-MM-dd")
# if retdate is in past, set nextReturnDate color to red
if retdate < today:
self.nextReturnDate.setStyleSheet("color: red")
else:
self.nextReturnDate.setStyleSheet("color: black")
self.nextReturnDate.setText(date)
self.nextReturnDate.show()
self.label_7.show()
@@ -516,13 +522,16 @@ class MainUI(QtWidgets.QMainWindow, Ui_MainWindow):
dialog.setText(message)
dialog.exec()
def exit_handler():
log.info("Exiting, creating backup")
log.info(
"Exiting, creating backup, renaming inactive users, creating report if day matches"
)
restore_config()
app = QtWidgets.QApplication(sys.argv)
#print(backup.backup)
# generate report if monday
if datetime.datetime.now().weekday() == config.report.report_day:
log.info("Generating Report")
generate_report()
log.info("Generated Report")
Database().renameInactiveUsers()
if config.database.do_backup:
state = backup.createBackup()
@@ -550,11 +559,35 @@ def exit_handler():
dialog.setWindowTitle("Backup nicht möglich")
dialog.setText("Backup konnte nicht erstellt werden\nGrund: {}".format(reason))
dialog.exec()
log.info("Exiting")
sys.exit()
def launch(*argv):
options = sys.argv
if argv:
options += [arg for arg in argv]
options = [arg for arg in options if arg.startswith("--")]
options += [arg for arg in options if arg.startswith("--")]
# add options to sys.argv
# print(options)
# print("Launching Main UI")
QtCore.QLocale().setDefault(
QtCore.QLocale(QtCore.QLocale.Language.German, QtCore.QLocale.Country.Germany)
)
SYSTEM_LANGUAGE = QtCore.QLocale().system().name()
# Load base QT translations from the normal place
app = QtWidgets.QApplication([])
main_ui = MainUI()
# translate ui to system language
if SYSTEM_LANGUAGE:
translator = QtCore.QTranslator()
# do not use ascii encoding
translator.load(f"qt_{SYSTEM_LANGUAGE}", "translations")
translator.load("app.qm", "translations")
app.installTranslator(translator)
atexit.register(exit_handler)
sys.exit(app.exec())
# sys.exit(app.exec())
#print("Launching Main UI")
#print(options)
QtCore.QLocale().setDefault(QtCore.QLocale(QtCore.QLocale.Language.German, QtCore.QLocale.Country.Germany))

View File

@@ -2,9 +2,10 @@ from .sources.Ui_main_userData import Ui_MainWindow
from PyQt6 import QtCore, QtGui, QtWidgets
from src import log
from src.logic import Database
from src.schemas import User
from src.schemas import User, Book
from .extendLoan import ExtendLoan
from src.utils import stringToDate, Icon
import datetime
TABLETOFIELDTRANSLATE = {
"Titel": "title",
@@ -65,6 +66,18 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
self.show()
def check_book(self, book: Book):
today = QtCore.QDate.currentDate().toString("yyyy-MM-dd")
returnDate = stringToDate(book.loan_to).toString("yyyy-MM-dd")
returned = book.returned
if returned == 1:
return "returned"
else:
if returnDate < today:
return "overdue"
else:
return "ok"
def userDelete(self):
self.db.deleteUser(self.user_id)
dialog = QtWidgets.QMessageBox()
@@ -212,6 +225,22 @@ class UserUI(QtWidgets.QMainWindow, Ui_MainWindow):
else stringToDate(book.returned_date).toString("dd.MM.yyyy")
),
)
match self.check_book(book):
case "overdue":
for i in range(6):
self.UserMediaTable.item(0, i).setBackground(
QtGui.QColor(255, 0, 0, 100)
)
case "ok":
for i in range(6):
self.UserMediaTable.item(0, i).setBackground(
QtGui.QColor(105, 255, 51, 100)
)
case "returned":
for i in range(6):
self.UserMediaTable.item(0, i).setBackground(
QtGui.QColor(102, 153, 153, 100)
)
def launch():

View File

@@ -49,11 +49,6 @@ def generate_report():
loan_action_date,
]
)
# #print(table)
# # wruitng the table to a file
# with open("report.txt", "w", encoding="utf-8") as f:
# f.write(str(table))
tsv_table = table.get_csv_string().replace(",", "\t")
# write the file
with open(report_path, "w", encoding="utf-8") as f:

950
uv.lock generated

File diff suppressed because it is too large Load Diff