Module database
Expand source code
import datetime
import os
import re
import sqlite3 as sql
import tempfile
from src.logic.log import MyLogger
#from icecream import ic
from typing import List, Tuple, Dict, Any, Optional, Union
from pathlib import Path
from omegaconf import OmegaConf
from src.backend.db import CREATE_TABLE_APPARAT, CREATE_TABLE_MESSAGES, CREATE_TABLE_MEDIA, CREATE_TABLE_APPKONTOS, CREATE_TABLE_FILES, CREATE_TABLE_PROF, CREATE_TABLE_USER, CREATE_TABLE_SUBJECTS
from src.logic.constants import SEMAP_MEDIA_ACCOUNTS
from src.logic.dataclass import ApparatData, BookData
from src.errors import NoResultError, AppPresentError
from src.utils import load_pickle, dump_pickle,create_blob
config = OmegaConf.load("config.yaml")
logger = MyLogger(__name__)
class Database:
"""
Initialize the database and create the tables if they do not exist.
"""
def __init__(self, db_path: str = None):
"""
Default constructor for the database class
Args:
db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None.
"""
if db_path is None:
self.db_path = config.database.path + config.database.name
self.db_path = self.db_path.replace("~", str(Path.home()))
else:
self.db_path = db_path
if self.get_db_contents() is None:
logger.log_critical("Database does not exist, creating tables")
self.create_tables()
def get_db_contents(self)->Union[List[Tuple], None]:
"""
Get the contents of the
Returns:
Union[List[Tuple], None]: _description_
"""
try:
with sql.connect(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM sqlite_master WHERE type='table'")
return cursor.fetchall()
except sql.OperationalError:
return None
def connect(self)->sql.Connection:
"""
Connect to the database
Returns:
sql.Connection: The active connection to the database
"""
return sql.connect(self.db_path)
def close_connection(self, conn: sql.Connection):
"""
closes the connection to the database
Args:
----
- conn (sql.Connection): the connection to be closed
"""
conn.close()
def create_tables(self):
"""
Create the tables in the database
"""
conn = self.connect()
cursor = conn.cursor()
cursor.execute(CREATE_TABLE_APPARAT)
cursor.execute(CREATE_TABLE_MESSAGES)
cursor.execute(CREATE_TABLE_MEDIA)
cursor.execute(CREATE_TABLE_APPKONTOS)
cursor.execute(CREATE_TABLE_FILES)
cursor.execute(CREATE_TABLE_PROF)
cursor.execute(CREATE_TABLE_USER)
cursor.execute(CREATE_TABLE_SUBJECTS)
conn.commit()
self.close_connection(conn)
def insertInto(self, query:str, params:Tuple) -> None:
"""
Insert sent data into the database
Args:
query (str): The query to be executed
params (Tuple): the parameters to be inserted into the database
"""
conn = self.connect()
cursor = conn.cursor()
logger.log_info(f"Inserting {params} into database with query {query}")
cursor.execute(query, params)
conn.commit()
self.close_connection(conn)
def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]:
"""
Query the Database for the sent query.
Args:
query (str): The query to be executed
args (Tuple, optional): The arguments for the query. Defaults to ().
one (bool, optional): Return the first result only. Defaults to False.
Returns:
Union[Typle|List[Tuple]]: Returns the result of the query
"""
conn = self.connect()
cursor = conn.cursor()
logger.log_info(f"Querying database with query {query}, args: {args}")
cursor.execute(query, args)
rv = cursor.fetchall()
conn.commit()
self.close_connection(conn)
return (rv[0] if rv else None) if one else rv
# Books
def addBookToDatabase(self, bookdata:BookData,app_id:str, prof_id:str):
"""
Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
Args:
bookdata (BookData): The metadata of the book to be added
app_id (str): The apparat id where the book should be added to
prof_id (str): The id of the professor where the book should be added to.
"""
conn = self.connect()
cursor = conn.cursor()
t_query = (
f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}"
)
# print(t_query)
result = cursor.execute(t_query).fetchall()
result = [load_pickle(i[0]) for i in result]
if bookdata in result:
print("Bookdata already in database")
# check if the book was deleted in the apparat
query = (
"SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?"
)
params = (app_id, prof_id, dump_pickle(bookdata))
result = cursor.execute(query, params).fetchone()
if result[0] == 1:
print("Book was deleted, updating bookdata")
query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?"
params = (app_id, prof_id, dump_pickle(bookdata))
cursor.execute(query, params)
conn.commit()
return
query = (
"INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)"
)
converted = dump_pickle(bookdata)
params = (converted, app_id, prof_id, 0)
cursor.execute(query, params)
conn.commit()
self.close_connection(conn)
def getBookIdBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->int:
"""
Get a book id based on the signature of the book.
Args:
app_id (str): The apparat id the book should be associated with
prof_id (str): The professor id the book should be associated with
signature (str): The signature of the book
Returns:
int: The id of the book
"""
result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
books = [(load_pickle(i[0]),i[1]) for i in result]
book = [i for i in books if i[0].signature == signature][0][1]
return book
def getBookBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->BookData:
"""
Get the book based on the signature of the book.
Args:
app_id (str): The apparat id the book should be associated with
prof_id (str): The professor id the book should be associated with
signature (str): The signature of the book
Returns:
BookData: The total metadata of the book wrapped in a BookData object
"""
result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id))
books = [load_pickle(i[0]) for i in result]
book = [i for i in books if i.signature == signature][0]
return book
def getLastBookId(self)->int:
"""
Get the last book id in the database
Returns:
int: ID of the last book in the database
"""
return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0]
def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]:
"""
Search a book in the database based on the sent data.
Args:
data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following:
- signature: The signature of the book
- title: The title of the book
Returns:
list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book
"""
rdata = self.query_db("SELECT * FROM media WHERE deleted=0")
#ic(rdata, len(rdata))
mode = 0
if len(data)== 1:
if "signature" in data.keys():
mode = 1
elif "title" in data.keys():
mode = 2
elif len(data) == 2:
mode = 3
else:
return None
ret = []
for book in rdata:
bookdata = load_pickle(book[1])
app_id = book[2]
prof_id = book[3]
if mode == 1:
if data["signature"] in bookdata.signature:
ret.append((bookdata,app_id,prof_id))
elif mode == 2:
if data["title"] in bookdata.title:
ret.append((bookdata,app_id,prof_id))
elif mode == 3:
if data["signature"] in bookdata.signature and data["title"] in bookdata.title:
ret.append((bookdata,app_id,prof_id))
#ic(ret)
return ret
def setAvailability(self, book_id:str, available:str):
"""
Set the availability of a book in the database
Args:
book_id (str): The id of the book
available (str): The availability of the book
"""
self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id))
def getBookId(self, bookdata:BookData, app_id, prof_id)->int:
"""
Get the id of a book based on the metadata of the book
Args:
bookdata (BookData): The wrapped metadata of the book
app_id (str): The apparat id the book should be associated with
prof_id (str): The professor id the book should be associated with
Returns:
int: ID of the book
"""
result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True)
return result[0]
def getBook(self,book_id:int)->BookData:
"""
Get the book based on the id in the database
Args:
book_id (int): The id of the book
Returns:
BookData: The metadata of the book wrapped in a BookData object
"""
return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0])
def getBooks(self, app_id, prof_id, deleted=0)->list[dict[int, BookData, int]]:
"""
Get the Books based on the apparat id and the professor id
Args:
app_id (str): The ID of the apparat
prof_id (str): The ID of the professor
deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0.
Returns:
list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book
"""
qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})")
ret_result = []
for result_a in qdata:
data = {"id": int, "bookdata": BookData, "available": int}
data["id"] = result_a[0]
data["bookdata"] = load_pickle(result_a[1])
data["available"] = result_a[2]
ret_result.append(data)
return ret_result
def updateBookdata(self, book_id, bookdata:BookData):
"""
Update the bookdata in the database
Args:
book_id (str): The id of the book
bookdata (BookData): The new metadata of the book
"""
self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id))
def deleteBook(self, book_id):
"""
Delete a book from the database
Args:
book_id (str): ID of the book
"""
self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,))
# File Interactions
def getBlob(self, filename, app_id):
"""
Get a blob from the database
Args:
filename (str): The name of the file
app_id (str): ID of the apparat
Returns:
bytes: The file stored in
"""
return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0]
def insertFile(self, file: list[dict], app_id: int, prof_id):
for f in file:
filename = f["name"]
path = f["path"]
filetyp = f["type"]
if path == "Database":
continue
blob = create_blob(path)
query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)"
self.query_db(query, (filename, blob, app_id, filetyp,prof_id))
def recreateFile(self, filename, app_id,filetype):
blob = self.getBlob(filename, app_id)
tempdir = config.database.tempdir
tempdir = tempdir.replace("~", str(Path.home()))
tempdir_path = Path(tempdir)
if not os.path.exists(tempdir_path):
os.mkdir(tempdir_path)
file = tempfile.NamedTemporaryFile(
delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}"
)
file.write(blob)
print("file created")
return file.name
def getFiles(self, app_id:int, prof_id:int)->list[tuple]:
return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id))
def getSemersters(self):
data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat")
return [i[0] for i in data]
def getSubjects(self):
return self.query_db("SELECT * FROM subjects")
# Messages
def addMessage(self, message:dict,user, appnr):
def __getUserId(user):
return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0]
user_id = __getUserId(user)
self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],appnr))
def getMessages(self, date:str):
def __get_user_name(user_id):
return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0]
messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,))
ret = [
{
"message": i[2],
"user": __get_user_name(i[4]),
"appnr": i[5],
"id": i[0]
}
for i in messages
]
return ret
def deleteMessage(self, message_id):
self.query_db("DELETE FROM messages WHERE id=?", (message_id,))
# Prof data
def getProfNameById(self, prof_id:int,add_title:bool=False):
prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True)
if add_title:
return f"{self.getTitleById(prof_id)}{prof[0]}"
else:
return prof[0]
def getTitleById(self, prof_id:int):
title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0]
return f"{title} " if title is not None else ""
def getProfByName(self, prof_name:str):
return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True)
def getProfId(self, prof_name:str):
"""
getProfId _summary_
:param prof_name: _description_
:type prof_name: str
:return: _description_
:rtype: _type_
"""
data = self.getProfByName(prof_name.replace(",", ""))
if data is None:
return None
else:
return data[0]
def getSpecificProfData(self, prof_id:int, fields:List[str]):
"""
getSpecificProfData _summary_
Args:
----
- prof_id (int): _description_
- fields (List[str]): _description_
Returns:
-------
- _type_: _description_
"""
query = "SELECT "
for field in fields:
query += f"{field},"
query = query[:-1]
query += " FROM prof WHERE id=?"
return self.query_db(query, (prof_id,), one=True)[0]
def getProfData(self, profname:str):
data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True)
return data
def createProf(self, prof_details:dict):
prof_title = prof_details["prof_title"]
prof_fname = prof_details["profname"].split(",")[1]
prof_fname = prof_fname.strip()
prof_lname = prof_details["profname"].split(",")[0]
prof_lname = prof_lname.strip()
prof_fullname = prof_details["profname"].replace(",", "")
prof_mail = prof_details["prof_mail"]
prof_tel = prof_details["prof_tel"]
params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname)
query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)"
self.insertInto(query=query, params=params)
def getProfs(self):
return self.query_db("SELECT * FROM prof")
# Apparat
def getAllAparats(self,deleted=0):
return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,))
def getApparatData(self, appnr, appname)->ApparatData:
result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True)
if result is None:
raise NoResultError("No result found")
apparat = ApparatData()
apparat.appname = result[1]
apparat.appnr = result[4]
apparat.dauerapp = True if result[7] == 1 else False
prof_data = self.getProfData(self.getProfNameById(result[2]))
apparat.profname = self.getProfNameById(result[2])
apparat.prof_mail = prof_data[0]
apparat.prof_tel = prof_data[1]
apparat.prof_title = prof_data[2]
apparat.app_fach = result[3]
apparat.erstellsemester = result[5]
apparat.semester = result[8]
apparat.deleted = result[9]
apparat.apparat_adis_id = result[11]
apparat.prof_adis_id = result[12]
return apparat
def getUnavailableApparatNumbers(self)->List[int]:
"""
getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers
Returns:
-------
- number(List[int]): a list of all currently used apparat numbers
"""
numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0")
numbers = [i[0] for i in numbers]
logger.log_info(f"Currently used apparat numbers: {numbers}")
return numbers
def setNewSemesterDate(self, appnr, newDate, dauerapp=False):
date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d")
if dauerapp:
self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,appnr))
else:
self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,appnr))
def getApparatId(self, apparat_name):
data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True)
if data is None:
return None
else:
return data[0]
def createApparat(self, apparat:ApparatData)->Optional[AppPresentError]|int:
prof_id = self.getProfId(apparat.profname)
app_id = self.getApparatId(apparat.appname)
if app_id:
return AppPresentError(app_id)
self.createProf(apparat.get_prof_details())
prof_id = self.getProfId(apparat.profname)
#ic(prof_id)
query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')"
logger.log_info(query)
self.query_db(query)
return self.getApparatId(apparat.appname)
def getApparatsByProf(self, prof_id:int)->list[tuple]:
return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,))
def getApparatsBySemester(self, semester:str)->dict:
data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,))
conn = self.connect()
cursor = conn.cursor()
c_tmp = []
for i in data:
c_tmp.append((i[0], self.getProfNameById(i[1])))
query = (
f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'"
)
result = cursor.execute(query).fetchall()
d_tmp = []
for i in result:
d_tmp.append((i[0], self.getProfNameById(i[1])))
# group the apparats by prof
c_ret = {}
for i in c_tmp:
if i[1] not in c_ret.keys():
c_ret[i[1]] = [i[0]]
else:
c_ret[i[1]].append(i[0])
d_ret = {}
for i in d_tmp:
if i[1] not in d_ret.keys():
d_ret[i[1]] = [i[0]]
else:
d_ret[i[1]].append(i[0])
self.close_connection(conn)
return {"created": c_ret, "deleted": d_ret}
def getApparatCountBySemester(self)->tuple[list[str],list[int]]:
conn = self.connect()
cursor = conn.cursor()
semesters = self.getSemersters()
created = []
deleted = []
for semester in semesters:
query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'"
result = cursor.execute(query).fetchone()
created.append(result[0])
query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'"
result = cursor.execute(query).fetchone()
deleted.append(result[0])
# store data in a tuple
ret = []
e_tuple = ()
for sem in semesters:
e_tuple = (
sem,
created[semesters.index(sem)],
deleted[semesters.index(sem)],
)
ret.append(e_tuple)
self.close_connection(conn)
return ret
def deleteApparat(self, appnr, semester):
self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,appnr))
def isEternal(self, id):
return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True)
def getApparatName(self, app_id, prof_id):
return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0]
def updateApparat(self, apparat_data:ApparatData):
query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?"
params = (
apparat_data.appname,
apparat_data.app_fach,
apparat_data.dauerapp,
self.getProfId(apparat_data.profname),
apparat_data.appnr,
)
self.query_db(query, params)
def checkApparatExists(self, apparat_name):
return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False
def checkApparatExistsById(self, apparat_id):
return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (apparat_id,), one=True) else False
# Statistics
def statistic_request(self, **kwargs: Any):
def __query(query):
conn = self.connect()
cursor = conn.cursor()
result = cursor.execute(query).fetchall()
for result_a in result:
orig_value = result_a
prof_name = self.getProfNameById(result_a[2])
# replace the prof_id with the prof_name
result_a = list(result_a)
result_a[2] = prof_name
result_a = tuple(result_a)
result[result.index(orig_value)] = result_a
self.close_connection(conn)
return result
if "deletable" in kwargs.keys():
query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')"
return __query(query)
if "dauer" in kwargs.keys():
kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0")
query = "SELECT * FROM semesterapparat WHERE "
for key, value in kwargs.items() if kwargs.items() is not None else {}:
print(key, value)
query += f"{key}='{value}' AND "
print(query)
# remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat
if "deletesemester" in kwargs.keys():
query = query.replace(
f"deletesemester='{kwargs['deletesemester']}' AND ", ""
)
if "endsemester" in kwargs.keys():
if "erstellsemester" in kwargs.keys():
query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "")
query = query.replace(
f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz"
)
else:
query = query.replace(
f"endsemester='{kwargs['endsemester']}' AND ", "xyz"
)
print("replaced")
query = query.replace(
"xyz",
f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ",
)
# remove all x="" parts from the query where x is a key in kwargs
query = query[:-5]
print(query)
return __query(query)
# Admin data
def getUser(self):
return self.query_db("SELECT * FROM user", one=True)
def getUsers(self):
return self.query_db("SELECT * FROM user")
def login(self, user, hashed_password):
salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
if salt is None:
return False
hashed_password = salt + hashed_password
password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0]
if password == hashed_password:
return True
else:
return False
def changePassword(self, user, new_password):
salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0]
new_password = salt + new_password
self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user))
def getRole(self, user):
return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0]
def getRoles(self):
return self.query_db("SELECT role FROM user")
def checkUsername(self, user):
data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True)
return True if data is not None else False
def createUser(self, user, password, role, salt):
"""Create a user based on passed data.
Args:
----
- username (str): Username to be used
- password (str): the salted password
- role (str): Role of the user
- salt (str): a random salt for the user
"""
self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt))
def deleteUser(self, user):
self.query_db("DELETE FROM user WHERE username=?", (user,))
def updateUser(self, username, data:dict[str, str]):
conn = self.connect()
cursor = conn.cursor()
query = "UPDATE user SET "
for key,value in data.items():
if key == "username":
continue
query += f"{key}='{value}',"
query = query[:-1]
query += " WHERE username=?"
params = (username,)
cursor.execute(query, params)
conn.commit()
self.close_connection(conn)
def getFacultyMember(self, name:str):
return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True)
def updateFacultyMember(self, data, oldlname, oldfname):
placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()])
query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname"
data["oldlname"] = oldlname
data["oldfname"] = oldfname
self.query_db(query, data)
def getFacultyMembers(self):
return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")
Classes
class Database (db_path: str = None)-
Initialize the database and create the tables if they do not exist.
Default constructor for the database class
Args
db_path:str, optional- Optional Path for testing / specific purposes. Defaults to None.
Expand source code
class Database: """ Initialize the database and create the tables if they do not exist. """ def __init__(self, db_path: str = None): """ Default constructor for the database class Args: db_path (str, optional): Optional Path for testing / specific purposes. Defaults to None. """ if db_path is None: self.db_path = config.database.path + config.database.name self.db_path = self.db_path.replace("~", str(Path.home())) else: self.db_path = db_path if self.get_db_contents() is None: logger.log_critical("Database does not exist, creating tables") self.create_tables() def get_db_contents(self)->Union[List[Tuple], None]: """ Get the contents of the Returns: Union[List[Tuple], None]: _description_ """ try: with sql.connect(self.db_path) as conn: cursor = conn.cursor() cursor.execute("SELECT * FROM sqlite_master WHERE type='table'") return cursor.fetchall() except sql.OperationalError: return None def connect(self)->sql.Connection: """ Connect to the database Returns: sql.Connection: The active connection to the database """ return sql.connect(self.db_path) def close_connection(self, conn: sql.Connection): """ closes the connection to the database Args: ---- - conn (sql.Connection): the connection to be closed """ conn.close() def create_tables(self): """ Create the tables in the database """ conn = self.connect() cursor = conn.cursor() cursor.execute(CREATE_TABLE_APPARAT) cursor.execute(CREATE_TABLE_MESSAGES) cursor.execute(CREATE_TABLE_MEDIA) cursor.execute(CREATE_TABLE_APPKONTOS) cursor.execute(CREATE_TABLE_FILES) cursor.execute(CREATE_TABLE_PROF) cursor.execute(CREATE_TABLE_USER) cursor.execute(CREATE_TABLE_SUBJECTS) conn.commit() self.close_connection(conn) def insertInto(self, query:str, params:Tuple) -> None: """ Insert sent data into the database Args: query (str): The query to be executed params (Tuple): the parameters to be inserted into the database """ conn = self.connect() cursor = conn.cursor() logger.log_info(f"Inserting {params} into database with query {query}") cursor.execute(query, params) conn.commit() self.close_connection(conn) def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]: """ Query the Database for the sent query. Args: query (str): The query to be executed args (Tuple, optional): The arguments for the query. Defaults to (). one (bool, optional): Return the first result only. Defaults to False. Returns: Union[Typle|List[Tuple]]: Returns the result of the query """ conn = self.connect() cursor = conn.cursor() logger.log_info(f"Querying database with query {query}, args: {args}") cursor.execute(query, args) rv = cursor.fetchall() conn.commit() self.close_connection(conn) return (rv[0] if rv else None) if one else rv # Books def addBookToDatabase(self, bookdata:BookData,app_id:str, prof_id:str): """ Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on. Args: bookdata (BookData): The metadata of the book to be added app_id (str): The apparat id where the book should be added to prof_id (str): The id of the professor where the book should be added to. """ conn = self.connect() cursor = conn.cursor() t_query = ( f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}" ) # print(t_query) result = cursor.execute(t_query).fetchall() result = [load_pickle(i[0]) for i in result] if bookdata in result: print("Bookdata already in database") # check if the book was deleted in the apparat query = ( "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?" ) params = (app_id, prof_id, dump_pickle(bookdata)) result = cursor.execute(query, params).fetchone() if result[0] == 1: print("Book was deleted, updating bookdata") query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?" params = (app_id, prof_id, dump_pickle(bookdata)) cursor.execute(query, params) conn.commit() return query = ( "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)" ) converted = dump_pickle(bookdata) params = (converted, app_id, prof_id, 0) cursor.execute(query, params) conn.commit() self.close_connection(conn) def getBookIdBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->int: """ Get a book id based on the signature of the book. Args: app_id (str): The apparat id the book should be associated with prof_id (str): The professor id the book should be associated with signature (str): The signature of the book Returns: int: The id of the book """ result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id)) books = [(load_pickle(i[0]),i[1]) for i in result] book = [i for i in books if i[0].signature == signature][0][1] return book def getBookBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->BookData: """ Get the book based on the signature of the book. Args: app_id (str): The apparat id the book should be associated with prof_id (str): The professor id the book should be associated with signature (str): The signature of the book Returns: BookData: The total metadata of the book wrapped in a BookData object """ result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id)) books = [load_pickle(i[0]) for i in result] book = [i for i in books if i.signature == signature][0] return book def getLastBookId(self)->int: """ Get the last book id in the database Returns: int: ID of the last book in the database """ return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0] def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]: """ Search a book in the database based on the sent data. Args: data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: - signature: The signature of the book - title: The title of the book Returns: list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book """ rdata = self.query_db("SELECT * FROM media WHERE deleted=0") #ic(rdata, len(rdata)) mode = 0 if len(data)== 1: if "signature" in data.keys(): mode = 1 elif "title" in data.keys(): mode = 2 elif len(data) == 2: mode = 3 else: return None ret = [] for book in rdata: bookdata = load_pickle(book[1]) app_id = book[2] prof_id = book[3] if mode == 1: if data["signature"] in bookdata.signature: ret.append((bookdata,app_id,prof_id)) elif mode == 2: if data["title"] in bookdata.title: ret.append((bookdata,app_id,prof_id)) elif mode == 3: if data["signature"] in bookdata.signature and data["title"] in bookdata.title: ret.append((bookdata,app_id,prof_id)) #ic(ret) return ret def setAvailability(self, book_id:str, available:str): """ Set the availability of a book in the database Args: book_id (str): The id of the book available (str): The availability of the book """ self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id)) def getBookId(self, bookdata:BookData, app_id, prof_id)->int: """ Get the id of a book based on the metadata of the book Args: bookdata (BookData): The wrapped metadata of the book app_id (str): The apparat id the book should be associated with prof_id (str): The professor id the book should be associated with Returns: int: ID of the book """ result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True) return result[0] def getBook(self,book_id:int)->BookData: """ Get the book based on the id in the database Args: book_id (int): The id of the book Returns: BookData: The metadata of the book wrapped in a BookData object """ return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0]) def getBooks(self, app_id, prof_id, deleted=0)->list[dict[int, BookData, int]]: """ Get the Books based on the apparat id and the professor id Args: app_id (str): The ID of the apparat prof_id (str): The ID of the professor deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0. Returns: list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book """ qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})") ret_result = [] for result_a in qdata: data = {"id": int, "bookdata": BookData, "available": int} data["id"] = result_a[0] data["bookdata"] = load_pickle(result_a[1]) data["available"] = result_a[2] ret_result.append(data) return ret_result def updateBookdata(self, book_id, bookdata:BookData): """ Update the bookdata in the database Args: book_id (str): The id of the book bookdata (BookData): The new metadata of the book """ self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id)) def deleteBook(self, book_id): """ Delete a book from the database Args: book_id (str): ID of the book """ self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,)) # File Interactions def getBlob(self, filename, app_id): """ Get a blob from the database Args: filename (str): The name of the file app_id (str): ID of the apparat Returns: bytes: The file stored in """ return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0] def insertFile(self, file: list[dict], app_id: int, prof_id): for f in file: filename = f["name"] path = f["path"] filetyp = f["type"] if path == "Database": continue blob = create_blob(path) query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)" self.query_db(query, (filename, blob, app_id, filetyp,prof_id)) def recreateFile(self, filename, app_id,filetype): blob = self.getBlob(filename, app_id) tempdir = config.database.tempdir tempdir = tempdir.replace("~", str(Path.home())) tempdir_path = Path(tempdir) if not os.path.exists(tempdir_path): os.mkdir(tempdir_path) file = tempfile.NamedTemporaryFile( delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}" ) file.write(blob) print("file created") return file.name def getFiles(self, app_id:int, prof_id:int)->list[tuple]: return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id)) def getSemersters(self): data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat") return [i[0] for i in data] def getSubjects(self): return self.query_db("SELECT * FROM subjects") # Messages def addMessage(self, message:dict,user, appnr): def __getUserId(user): return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0] user_id = __getUserId(user) self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],appnr)) def getMessages(self, date:str): def __get_user_name(user_id): return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0] messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,)) ret = [ { "message": i[2], "user": __get_user_name(i[4]), "appnr": i[5], "id": i[0] } for i in messages ] return ret def deleteMessage(self, message_id): self.query_db("DELETE FROM messages WHERE id=?", (message_id,)) # Prof data def getProfNameById(self, prof_id:int,add_title:bool=False): prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True) if add_title: return f"{self.getTitleById(prof_id)}{prof[0]}" else: return prof[0] def getTitleById(self, prof_id:int): title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0] return f"{title} " if title is not None else "" def getProfByName(self, prof_name:str): return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True) def getProfId(self, prof_name:str): """ getProfId _summary_ :param prof_name: _description_ :type prof_name: str :return: _description_ :rtype: _type_ """ data = self.getProfByName(prof_name.replace(",", "")) if data is None: return None else: return data[0] def getSpecificProfData(self, prof_id:int, fields:List[str]): """ getSpecificProfData _summary_ Args: ---- - prof_id (int): _description_ - fields (List[str]): _description_ Returns: ------- - _type_: _description_ """ query = "SELECT " for field in fields: query += f"{field}," query = query[:-1] query += " FROM prof WHERE id=?" return self.query_db(query, (prof_id,), one=True)[0] def getProfData(self, profname:str): data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True) return data def createProf(self, prof_details:dict): prof_title = prof_details["prof_title"] prof_fname = prof_details["profname"].split(",")[1] prof_fname = prof_fname.strip() prof_lname = prof_details["profname"].split(",")[0] prof_lname = prof_lname.strip() prof_fullname = prof_details["profname"].replace(",", "") prof_mail = prof_details["prof_mail"] prof_tel = prof_details["prof_tel"] params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname) query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)" self.insertInto(query=query, params=params) def getProfs(self): return self.query_db("SELECT * FROM prof") # Apparat def getAllAparats(self,deleted=0): return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,)) def getApparatData(self, appnr, appname)->ApparatData: result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True) if result is None: raise NoResultError("No result found") apparat = ApparatData() apparat.appname = result[1] apparat.appnr = result[4] apparat.dauerapp = True if result[7] == 1 else False prof_data = self.getProfData(self.getProfNameById(result[2])) apparat.profname = self.getProfNameById(result[2]) apparat.prof_mail = prof_data[0] apparat.prof_tel = prof_data[1] apparat.prof_title = prof_data[2] apparat.app_fach = result[3] apparat.erstellsemester = result[5] apparat.semester = result[8] apparat.deleted = result[9] apparat.apparat_adis_id = result[11] apparat.prof_adis_id = result[12] return apparat def getUnavailableApparatNumbers(self)->List[int]: """ getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers Returns: ------- - number(List[int]): a list of all currently used apparat numbers """ numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0") numbers = [i[0] for i in numbers] logger.log_info(f"Currently used apparat numbers: {numbers}") return numbers def setNewSemesterDate(self, appnr, newDate, dauerapp=False): date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d") if dauerapp: self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,appnr)) else: self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,appnr)) def getApparatId(self, apparat_name): data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) if data is None: return None else: return data[0] def createApparat(self, apparat:ApparatData)->Optional[AppPresentError]|int: prof_id = self.getProfId(apparat.profname) app_id = self.getApparatId(apparat.appname) if app_id: return AppPresentError(app_id) self.createProf(apparat.get_prof_details()) prof_id = self.getProfId(apparat.profname) #ic(prof_id) query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')" logger.log_info(query) self.query_db(query) return self.getApparatId(apparat.appname) def getApparatsByProf(self, prof_id:int)->list[tuple]: return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,)) def getApparatsBySemester(self, semester:str)->dict: data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,)) conn = self.connect() cursor = conn.cursor() c_tmp = [] for i in data: c_tmp.append((i[0], self.getProfNameById(i[1]))) query = ( f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'" ) result = cursor.execute(query).fetchall() d_tmp = [] for i in result: d_tmp.append((i[0], self.getProfNameById(i[1]))) # group the apparats by prof c_ret = {} for i in c_tmp: if i[1] not in c_ret.keys(): c_ret[i[1]] = [i[0]] else: c_ret[i[1]].append(i[0]) d_ret = {} for i in d_tmp: if i[1] not in d_ret.keys(): d_ret[i[1]] = [i[0]] else: d_ret[i[1]].append(i[0]) self.close_connection(conn) return {"created": c_ret, "deleted": d_ret} def getApparatCountBySemester(self)->tuple[list[str],list[int]]: conn = self.connect() cursor = conn.cursor() semesters = self.getSemersters() created = [] deleted = [] for semester in semesters: query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'" result = cursor.execute(query).fetchone() created.append(result[0]) query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'" result = cursor.execute(query).fetchone() deleted.append(result[0]) # store data in a tuple ret = [] e_tuple = () for sem in semesters: e_tuple = ( sem, created[semesters.index(sem)], deleted[semesters.index(sem)], ) ret.append(e_tuple) self.close_connection(conn) return ret def deleteApparat(self, appnr, semester): self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,appnr)) def isEternal(self, id): return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True) def getApparatName(self, app_id, prof_id): return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0] def updateApparat(self, apparat_data:ApparatData): query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?" params = ( apparat_data.appname, apparat_data.app_fach, apparat_data.dauerapp, self.getProfId(apparat_data.profname), apparat_data.appnr, ) self.query_db(query, params) def checkApparatExists(self, apparat_name): return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False def checkApparatExistsById(self, apparat_id): return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (apparat_id,), one=True) else False # Statistics def statistic_request(self, **kwargs: Any): def __query(query): conn = self.connect() cursor = conn.cursor() result = cursor.execute(query).fetchall() for result_a in result: orig_value = result_a prof_name = self.getProfNameById(result_a[2]) # replace the prof_id with the prof_name result_a = list(result_a) result_a[2] = prof_name result_a = tuple(result_a) result[result.index(orig_value)] = result_a self.close_connection(conn) return result if "deletable" in kwargs.keys(): query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')" return __query(query) if "dauer" in kwargs.keys(): kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0") query = "SELECT * FROM semesterapparat WHERE " for key, value in kwargs.items() if kwargs.items() is not None else {}: print(key, value) query += f"{key}='{value}' AND " print(query) # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat if "deletesemester" in kwargs.keys(): query = query.replace( f"deletesemester='{kwargs['deletesemester']}' AND ", "" ) if "endsemester" in kwargs.keys(): if "erstellsemester" in kwargs.keys(): query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "") query = query.replace( f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz" ) else: query = query.replace( f"endsemester='{kwargs['endsemester']}' AND ", "xyz" ) print("replaced") query = query.replace( "xyz", f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ", ) # remove all x="" parts from the query where x is a key in kwargs query = query[:-5] print(query) return __query(query) # Admin data def getUser(self): return self.query_db("SELECT * FROM user", one=True) def getUsers(self): return self.query_db("SELECT * FROM user") def login(self, user, hashed_password): salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0] if salt is None: return False hashed_password = salt + hashed_password password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0] if password == hashed_password: return True else: return False def changePassword(self, user, new_password): salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0] new_password = salt + new_password self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user)) def getRole(self, user): return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0] def getRoles(self): return self.query_db("SELECT role FROM user") def checkUsername(self, user): data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True) return True if data is not None else False def createUser(self, user, password, role, salt): """Create a user based on passed data. Args: ---- - username (str): Username to be used - password (str): the salted password - role (str): Role of the user - salt (str): a random salt for the user """ self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt)) def deleteUser(self, user): self.query_db("DELETE FROM user WHERE username=?", (user,)) def updateUser(self, username, data:dict[str, str]): conn = self.connect() cursor = conn.cursor() query = "UPDATE user SET " for key,value in data.items(): if key == "username": continue query += f"{key}='{value}'," query = query[:-1] query += " WHERE username=?" params = (username,) cursor.execute(query, params) conn.commit() self.close_connection(conn) def getFacultyMember(self, name:str): return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True) def updateFacultyMember(self, data, oldlname, oldfname): placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()]) query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname" data["oldlname"] = oldlname data["oldfname"] = oldfname self.query_db(query, data) def getFacultyMembers(self): return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof")Methods
def addBookToDatabase(self, bookdata: src.logic.dataclass.BookData, app_id: str, prof_id: str)-
Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on.
Args
bookdata:BookData- The metadata of the book to be added
app_id:str- The apparat id where the book should be added to
prof_id:str- The id of the professor where the book should be added to.
Expand source code
def addBookToDatabase(self, bookdata:BookData,app_id:str, prof_id:str): """ Add books to the database. Both app_id and prof_id are required to add the book to the database, as the app_id and prof_id are used to select the books later on. Args: bookdata (BookData): The metadata of the book to be added app_id (str): The apparat id where the book should be added to prof_id (str): The id of the professor where the book should be added to. """ conn = self.connect() cursor = conn.cursor() t_query = ( f"SELECT bookdata FROM media WHERE app_id={app_id} AND prof_id={prof_id}" ) # print(t_query) result = cursor.execute(t_query).fetchall() result = [load_pickle(i[0]) for i in result] if bookdata in result: print("Bookdata already in database") # check if the book was deleted in the apparat query = ( "SELECT deleted FROM media WHERE app_id=? AND prof_id=? AND bookdata=?" ) params = (app_id, prof_id, dump_pickle(bookdata)) result = cursor.execute(query, params).fetchone() if result[0] == 1: print("Book was deleted, updating bookdata") query = "UPDATE media SET deleted=0 WHERE app_id=? AND prof_id=? AND bookdata=?" params = (app_id, prof_id, dump_pickle(bookdata)) cursor.execute(query, params) conn.commit() return query = ( "INSERT INTO media (bookdata, app_id, prof_id,deleted) VALUES (?, ?, ?,?)" ) converted = dump_pickle(bookdata) params = (converted, app_id, prof_id, 0) cursor.execute(query, params) conn.commit() self.close_connection(conn) def addMessage(self, message: dict, user, appnr)-
Expand source code
def addMessage(self, message:dict,user, appnr): def __getUserId(user): return self.query_db("SELECT id FROM user WHERE username=?", (user,), one=True)[0] user_id = __getUserId(user) self.query_db("INSERT INTO messages (message, user_id, remind_at,appnr) VALUES (?,?,?,?)", (message["message"],user_id,message["remind_at"],appnr)) def changePassword(self, user, new_password)-
Expand source code
def changePassword(self, user, new_password): salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0] new_password = salt + new_password self.query_db("UPDATE user SET password=? WHERE username=?", (new_password,user)) def checkApparatExists(self, apparat_name)-
Expand source code
def checkApparatExists(self, apparat_name): return True if self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) else False def checkApparatExistsById(self, apparat_id)-
Expand source code
def checkApparatExistsById(self, apparat_id): return True if self.query_db("SELECT appnr FROM semesterapparat WHERE appnr=?", (apparat_id,), one=True) else False def checkUsername(self, user)-
Expand source code
def checkUsername(self, user): data = self.query_db("SELECT username FROM user WHERE username=?", (user,), one=True) return True if data is not None else False def close_connection(self, conn: sqlite3.Connection)-
closes the connection to the database
Args:
- conn (sql.Connection): the connection to be closedExpand source code
def close_connection(self, conn: sql.Connection): """ closes the connection to the database Args: ---- - conn (sql.Connection): the connection to be closed """ conn.close() def connect(self) ‑> sqlite3.Connection-
Connect to the database
Returns
sql.Connection- The active connection to the database
Expand source code
def connect(self)->sql.Connection: """ Connect to the database Returns: sql.Connection: The active connection to the database """ return sql.connect(self.db_path) def createApparat(self, apparat: src.logic.dataclass.ApparatData) ‑> Union[src.errors.DatabaseErrors.AppPresentError, ForwardRef(None), int]-
Expand source code
def createApparat(self, apparat:ApparatData)->Optional[AppPresentError]|int: prof_id = self.getProfId(apparat.profname) app_id = self.getApparatId(apparat.appname) if app_id: return AppPresentError(app_id) self.createProf(apparat.get_prof_details()) prof_id = self.getProfId(apparat.profname) #ic(prof_id) query = f"INSERT OR IGNORE INTO semesterapparat (appnr, name, erstellsemester, dauer, prof_id, fach,deletion_status,konto) VALUES ('{apparat.appnr}', '{apparat.appname}', '{apparat.semester}', '{apparat.dauerapp}', {prof_id}, '{apparat.app_fach}', '{0}', '{SEMAP_MEDIA_ACCOUNTS[apparat.appnr]}')" logger.log_info(query) self.query_db(query) return self.getApparatId(apparat.appname) def createProf(self, prof_details: dict)-
Expand source code
def createProf(self, prof_details:dict): prof_title = prof_details["prof_title"] prof_fname = prof_details["profname"].split(",")[1] prof_fname = prof_fname.strip() prof_lname = prof_details["profname"].split(",")[0] prof_lname = prof_lname.strip() prof_fullname = prof_details["profname"].replace(",", "") prof_mail = prof_details["prof_mail"] prof_tel = prof_details["prof_tel"] params = (prof_title, prof_fname, prof_lname, prof_mail, prof_tel, prof_fullname) query = "INSERT OR IGNORE INTO prof (titel, fname, lname, mail, telnr, fullname) VALUES (?, ?, ?, ?, ?, ?)" self.insertInto(query=query, params=params) def createUser(self, user, password, role, salt)-
Create a user based on passed data.
Args:
- username (str): Username to be used - password (str): the salted password - role (str): Role of the user - salt (str): a random salt for the userExpand source code
def createUser(self, user, password, role, salt): """Create a user based on passed data. Args: ---- - username (str): Username to be used - password (str): the salted password - role (str): Role of the user - salt (str): a random salt for the user """ self.query_db("INSERT OR IGNORE INTO user (username, password, role, salt) VALUES (?,?,?,?)", (user,password,role,salt)) def create_tables(self)-
Create the tables in the database
Expand source code
def create_tables(self): """ Create the tables in the database """ conn = self.connect() cursor = conn.cursor() cursor.execute(CREATE_TABLE_APPARAT) cursor.execute(CREATE_TABLE_MESSAGES) cursor.execute(CREATE_TABLE_MEDIA) cursor.execute(CREATE_TABLE_APPKONTOS) cursor.execute(CREATE_TABLE_FILES) cursor.execute(CREATE_TABLE_PROF) cursor.execute(CREATE_TABLE_USER) cursor.execute(CREATE_TABLE_SUBJECTS) conn.commit() self.close_connection(conn) def deleteApparat(self, appnr, semester)-
Expand source code
def deleteApparat(self, appnr, semester): self.query_db("UPDATE semesterapparat SET deletion_status=1, deleted_date=? WHERE appnr=?", (semester,appnr)) def deleteBook(self, book_id)-
Delete a book from the database
Args
book_id:str- ID of the book
Expand source code
def deleteBook(self, book_id): """ Delete a book from the database Args: book_id (str): ID of the book """ self.query_db("UPDATE media SET deleted=1 WHERE id=?", (book_id,)) def deleteMessage(self, message_id)-
Expand source code
def deleteMessage(self, message_id): self.query_db("DELETE FROM messages WHERE id=?", (message_id,)) def deleteUser(self, user)-
Expand source code
def deleteUser(self, user): self.query_db("DELETE FROM user WHERE username=?", (user,)) def getAllAparats(self, deleted=0)-
Expand source code
def getAllAparats(self,deleted=0): return self.query_db("SELECT * FROM semesterapparat WHERE deletion_status=?", (deleted,)) def getApparatCountBySemester(self) ‑> tuple[list[str], list[int]]-
Expand source code
def getApparatCountBySemester(self)->tuple[list[str],list[int]]: conn = self.connect() cursor = conn.cursor() semesters = self.getSemersters() created = [] deleted = [] for semester in semesters: query = f"SELECT COUNT(*) FROM semesterapparat WHERE erstellsemester='{semester}'" result = cursor.execute(query).fetchone() created.append(result[0]) query = f"SELECT COUNT(*) FROM semesterapparat WHERE deletion_status=1 AND deleted_date='{semester}'" result = cursor.execute(query).fetchone() deleted.append(result[0]) # store data in a tuple ret = [] e_tuple = () for sem in semesters: e_tuple = ( sem, created[semesters.index(sem)], deleted[semesters.index(sem)], ) ret.append(e_tuple) self.close_connection(conn) return ret def getApparatData(self, appnr, appname) ‑> src.logic.dataclass.ApparatData-
Expand source code
def getApparatData(self, appnr, appname)->ApparatData: result = self.query_db("SELECT * FROM semesterapparat WHERE appnr=? AND name=?", (appnr,appname), one=True) if result is None: raise NoResultError("No result found") apparat = ApparatData() apparat.appname = result[1] apparat.appnr = result[4] apparat.dauerapp = True if result[7] == 1 else False prof_data = self.getProfData(self.getProfNameById(result[2])) apparat.profname = self.getProfNameById(result[2]) apparat.prof_mail = prof_data[0] apparat.prof_tel = prof_data[1] apparat.prof_title = prof_data[2] apparat.app_fach = result[3] apparat.erstellsemester = result[5] apparat.semester = result[8] apparat.deleted = result[9] apparat.apparat_adis_id = result[11] apparat.prof_adis_id = result[12] return apparat def getApparatId(self, apparat_name)-
Expand source code
def getApparatId(self, apparat_name): data = self.query_db("SELECT appnr FROM semesterapparat WHERE name=?", (apparat_name,), one=True) if data is None: return None else: return data[0] def getApparatName(self, app_id, prof_id)-
Expand source code
def getApparatName(self, app_id, prof_id): return self.query_db("SELECT name FROM semesterapparat WHERE appnr=? AND prof_id=?", (app_id,prof_id), one=True)[0] def getApparatsByProf(self, prof_id: int) ‑> list[tuple]-
Expand source code
def getApparatsByProf(self, prof_id:int)->list[tuple]: return self.query_db("SELECT * FROM semesterapparat WHERE prof_id=?", (prof_id,)) def getApparatsBySemester(self, semester: str) ‑> dict-
Expand source code
def getApparatsBySemester(self, semester:str)->dict: data = self.query_db("SELECT name, prof_id FROM semesterapparat WHERE erstellsemester=?", (semester,)) conn = self.connect() cursor = conn.cursor() c_tmp = [] for i in data: c_tmp.append((i[0], self.getProfNameById(i[1]))) query = ( f"SELECT name,prof_id FROM semesterapparat WHERE deleted_date='{semester}'" ) result = cursor.execute(query).fetchall() d_tmp = [] for i in result: d_tmp.append((i[0], self.getProfNameById(i[1]))) # group the apparats by prof c_ret = {} for i in c_tmp: if i[1] not in c_ret.keys(): c_ret[i[1]] = [i[0]] else: c_ret[i[1]].append(i[0]) d_ret = {} for i in d_tmp: if i[1] not in d_ret.keys(): d_ret[i[1]] = [i[0]] else: d_ret[i[1]].append(i[0]) self.close_connection(conn) return {"created": c_ret, "deleted": d_ret} def getBlob(self, filename, app_id)-
Get a blob from the database
Args
filename:str- The name of the file
app_id:str- ID of the apparat
Returns
bytes- The file stored in
Expand source code
def getBlob(self, filename, app_id): """ Get a blob from the database Args: filename (str): The name of the file app_id (str): ID of the apparat Returns: bytes: The file stored in """ return self.query_db("SELECT fileblob FROM files WHERE filename=? AND app_id=?", (filename,app_id), one=True)[0] def getBook(self, book_id: int) ‑> src.logic.dataclass.BookData-
Get the book based on the id in the database
Args
book_id:int- The id of the book
Returns
BookData- The metadata of the book wrapped in a BookData object
Expand source code
def getBook(self,book_id:int)->BookData: """ Get the book based on the id in the database Args: book_id (int): The id of the book Returns: BookData: The metadata of the book wrapped in a BookData object """ return load_pickle(self.query_db("SELECT bookdata FROM media WHERE id=?", (book_id,), one=True)[0]) def getBookBasedOnSignature(self, app_id: str, prof_id: str, signature: str) ‑> src.logic.dataclass.BookData-
Get the book based on the signature of the book.
Args
app_id:str- The apparat id the book should be associated with
prof_id:str- The professor id the book should be associated with
signature:str- The signature of the book
Returns
BookData- The total metadata of the book wrapped in a BookData object
Expand source code
def getBookBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->BookData: """ Get the book based on the signature of the book. Args: app_id (str): The apparat id the book should be associated with prof_id (str): The professor id the book should be associated with signature (str): The signature of the book Returns: BookData: The total metadata of the book wrapped in a BookData object """ result = self.query_db("SELECT bookdata FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id)) books = [load_pickle(i[0]) for i in result] book = [i for i in books if i.signature == signature][0] return book def getBookId(self, bookdata: src.logic.dataclass.BookData, app_id, prof_id) ‑> int-
Get the id of a book based on the metadata of the book
Args
bookdata:BookData- The wrapped metadata of the book
app_id:str- The apparat id the book should be associated with
prof_id:str- The professor id the book should be associated with
Returns
int- ID of the book
Expand source code
def getBookId(self, bookdata:BookData, app_id, prof_id)->int: """ Get the id of a book based on the metadata of the book Args: bookdata (BookData): The wrapped metadata of the book app_id (str): The apparat id the book should be associated with prof_id (str): The professor id the book should be associated with Returns: int: ID of the book """ result = self.query_db("SELECT id FROM media WHERE bookdata=? AND app_id=? AND prof_id=?", (dump_pickle(bookdata),app_id,prof_id), one=True) return result[0] def getBookIdBasedOnSignature(self, app_id: str, prof_id: str, signature: str) ‑> int-
Get a book id based on the signature of the book.
Args
app_id:str- The apparat id the book should be associated with
prof_id:str- The professor id the book should be associated with
signature:str- The signature of the book
Returns
int- The id of the book
Expand source code
def getBookIdBasedOnSignature(self, app_id:str, prof_id:str,signature:str)->int: """ Get a book id based on the signature of the book. Args: app_id (str): The apparat id the book should be associated with prof_id (str): The professor id the book should be associated with signature (str): The signature of the book Returns: int: The id of the book """ result = self.query_db("SELECT bookdata, id FROM media WHERE app_id=? AND prof_id=?", (app_id,prof_id)) books = [(load_pickle(i[0]),i[1]) for i in result] book = [i for i in books if i[0].signature == signature][0][1] return book def getBooks(self, app_id, prof_id, deleted=0) ‑> list[dict[int, src.logic.dataclass.BookData, int]]-
Get the Books based on the apparat id and the professor id
Args
app_id:str- The ID of the apparat
prof_id:str- The ID of the professor
deleted:int, optional- The state of the book. Set to 1 to include deleted ones. Defaults to 0.
Returns
list[dict[int, BookData, int]]- A list of dictionaries containing the id, the metadata of the book and the availability of the book
Expand source code
def getBooks(self, app_id, prof_id, deleted=0)->list[dict[int, BookData, int]]: """ Get the Books based on the apparat id and the professor id Args: app_id (str): The ID of the apparat prof_id (str): The ID of the professor deleted (int, optional): The state of the book. Set to 1 to include deleted ones. Defaults to 0. Returns: list[dict[int, BookData, int]]: A list of dictionaries containing the id, the metadata of the book and the availability of the book """ qdata = self.query_db(f"SELECT id,bookdata,available FROM media WHERE (app_id={app_id} AND prof_id={prof_id}) AND (deleted={deleted if deleted == 0 else '1 OR deleted=0'})") ret_result = [] for result_a in qdata: data = {"id": int, "bookdata": BookData, "available": int} data["id"] = result_a[0] data["bookdata"] = load_pickle(result_a[1]) data["available"] = result_a[2] ret_result.append(data) return ret_result def getFacultyMember(self, name: str)-
Expand source code
def getFacultyMember(self, name:str): return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof WHERE fullname=?", (name,), one=True) def getFacultyMembers(self)-
Expand source code
def getFacultyMembers(self): return self.query_db("SELECT titel, fname,lname,mail,telnr,fullname FROM prof") def getFiles(self, app_id: int, prof_id: int) ‑> list[tuple]-
Expand source code
def getFiles(self, app_id:int, prof_id:int)->list[tuple]: return self.query_db("SELECT filename, filetyp FROM files WHERE app_id=? AND prof_id=?", (app_id,prof_id)) def getLastBookId(self) ‑> int-
Get the last book id in the database
Returns
int- ID of the last book in the database
Expand source code
def getLastBookId(self)->int: """ Get the last book id in the database Returns: int: ID of the last book in the database """ return self.query_db("SELECT id FROM media ORDER BY id DESC", one=True)[0] def getMessages(self, date: str)-
Expand source code
def getMessages(self, date:str): def __get_user_name(user_id): return self.query_db("SELECT username FROM user WHERE id=?", (user_id,), one=True)[0] messages = self.query_db("SELECT * FROM messages WHERE remind_at=?", (date,)) ret = [ { "message": i[2], "user": __get_user_name(i[4]), "appnr": i[5], "id": i[0] } for i in messages ] return ret def getProfByName(self, prof_name: str)-
Expand source code
def getProfByName(self, prof_name:str): return self.query_db("SELECT * FROM prof WHERE fullname=?", (prof_name,), one=True) def getProfData(self, profname: str)-
Expand source code
def getProfData(self, profname:str): data = self.query_db("SELECT mail, telnr, titel FROM prof WHERE fullname=?", (profname.replace(",",""),), one=True) return data def getProfId(self, prof_name: str)-
getProfId summary
:param prof_name: description :type prof_name: str :return: description :rtype: type
Expand source code
def getProfId(self, prof_name:str): """ getProfId _summary_ :param prof_name: _description_ :type prof_name: str :return: _description_ :rtype: _type_ """ data = self.getProfByName(prof_name.replace(",", "")) if data is None: return None else: return data[0] def getProfNameById(self, prof_id: int, add_title: bool = False)-
Expand source code
def getProfNameById(self, prof_id:int,add_title:bool=False): prof = self.query_db("SELECT fullname FROM prof WHERE id=?", (prof_id,), one=True) if add_title: return f"{self.getTitleById(prof_id)}{prof[0]}" else: return prof[0] def getProfs(self)-
Expand source code
def getProfs(self): return self.query_db("SELECT * FROM prof") def getRole(self, user)-
Expand source code
def getRole(self, user): return self.query_db("SELECT role FROM user WHERE username=?", (user,), one=True)[0] def getRoles(self)-
Expand source code
def getRoles(self): return self.query_db("SELECT role FROM user") def getSemersters(self)-
Expand source code
def getSemersters(self): data = self.query_db("SELECT DISTINCT erstellsemester FROM semesterapparat") return [i[0] for i in data] def getSpecificProfData(self, prof_id: int, fields: List[str])-
getSpecificProfData summary
Args:
- prof_id (int): _description_ - fields (List[str]): _description_Returns:
- _type_: _description_Expand source code
def getSpecificProfData(self, prof_id:int, fields:List[str]): """ getSpecificProfData _summary_ Args: ---- - prof_id (int): _description_ - fields (List[str]): _description_ Returns: ------- - _type_: _description_ """ query = "SELECT " for field in fields: query += f"{field}," query = query[:-1] query += " FROM prof WHERE id=?" return self.query_db(query, (prof_id,), one=True)[0] def getSubjects(self)-
Expand source code
def getSubjects(self): return self.query_db("SELECT * FROM subjects") def getTitleById(self, prof_id: int)-
Expand source code
def getTitleById(self, prof_id:int): title = self.query_db("SELECT titel FROM prof WHERE id=?", (prof_id,), one=True)[0] return f"{title} " if title is not None else "" -
getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers
Returns:
- number(List[int]): a list of all currently used apparat numbersExpand source code
def getUnavailableApparatNumbers(self)->List[int]: """ getUnavailableApparatNumbers returns a list of all currently used ApparatNumbers Returns: ------- - number(List[int]): a list of all currently used apparat numbers """ numbers = self.query_db("SELECT appnr FROM semesterapparat WHERE deletion_status=0") numbers = [i[0] for i in numbers] logger.log_info(f"Currently used apparat numbers: {numbers}") return numbers def getUser(self)-
Expand source code
def getUser(self): return self.query_db("SELECT * FROM user", one=True) def getUsers(self)-
Expand source code
def getUsers(self): return self.query_db("SELECT * FROM user") def get_db_contents(self) ‑> Optional[List[Tuple]]-
Get the contents of the
Returns
Union[List[Tuple], None]- description
Expand source code
def get_db_contents(self)->Union[List[Tuple], None]: """ Get the contents of the Returns: Union[List[Tuple], None]: _description_ """ try: with sql.connect(self.db_path) as conn: cursor = conn.cursor() cursor.execute("SELECT * FROM sqlite_master WHERE type='table'") return cursor.fetchall() except sql.OperationalError: return None def insertFile(self, file: list[dict], app_id: int, prof_id)-
Expand source code
def insertFile(self, file: list[dict], app_id: int, prof_id): for f in file: filename = f["name"] path = f["path"] filetyp = f["type"] if path == "Database": continue blob = create_blob(path) query = "INSERT OR IGNORE INTO files (filename, fileblob, app_id, filetyp,prof_id) VALUES (?, ?, ?, ?,?)" self.query_db(query, (filename, blob, app_id, filetyp,prof_id)) def insertInto(self, query: str, params: Tuple) ‑> None-
Insert sent data into the database
Args
query:str- The query to be executed
params:Tuple- the parameters to be inserted into the database
Expand source code
def insertInto(self, query:str, params:Tuple) -> None: """ Insert sent data into the database Args: query (str): The query to be executed params (Tuple): the parameters to be inserted into the database """ conn = self.connect() cursor = conn.cursor() logger.log_info(f"Inserting {params} into database with query {query}") cursor.execute(query, params) conn.commit() self.close_connection(conn) def isEternal(self, id)-
Expand source code
def isEternal(self, id): return self.query_db("SELECT dauer FROM semesterapparat WHERE appnr=?", (id,), one=True) def login(self, user, hashed_password)-
Expand source code
def login(self, user, hashed_password): salt = self.query_db("SELECT salt FROM user WHERE username=?", (user,), one=True)[0] if salt is None: return False hashed_password = salt + hashed_password password = self.query_db("SELECT password FROM user WHERE username=?", (user,), one=True)[0] if password == hashed_password: return True else: return False def query_db(self, query: str, args: Tuple = (), one: bool = False) ‑> Union[Tuple, List[Tuple]]-
Query the Database for the sent query.
Args
query:str- The query to be executed
args:Tuple, optional- The arguments for the query. Defaults to ().
one:bool, optional- Return the first result only. Defaults to False.
Returns
Union[Typle|List[Tuple]]: Returns the result of the query
Expand source code
def query_db(self, query: str, args: Tuple = (), one: bool = False)->Union[Tuple, List[Tuple]]: """ Query the Database for the sent query. Args: query (str): The query to be executed args (Tuple, optional): The arguments for the query. Defaults to (). one (bool, optional): Return the first result only. Defaults to False. Returns: Union[Typle|List[Tuple]]: Returns the result of the query """ conn = self.connect() cursor = conn.cursor() logger.log_info(f"Querying database with query {query}, args: {args}") cursor.execute(query, args) rv = cursor.fetchall() conn.commit() self.close_connection(conn) return (rv[0] if rv else None) if one else rv def recreateFile(self, filename, app_id, filetype)-
Expand source code
def recreateFile(self, filename, app_id,filetype): blob = self.getBlob(filename, app_id) tempdir = config.database.tempdir tempdir = tempdir.replace("~", str(Path.home())) tempdir_path = Path(tempdir) if not os.path.exists(tempdir_path): os.mkdir(tempdir_path) file = tempfile.NamedTemporaryFile( delete=False, dir=tempdir_path, mode="wb", suffix=f".{filetype}" ) file.write(blob) print("file created") return file.name def searchBook(self, data: dict[str, str]) ‑> list[tuple[src.logic.dataclass.BookData, int]]-
Search a book in the database based on the sent data.
Args
data:dict[str, str]- A dictionary containing the data to be searched for. The dictionary can contain the following:
- signature: The signature of the book
- title: The title of the book
Returns
list[tuple[BookData, int]]- A list of tuples containing the wrapped Metadata and the id of the book
Expand source code
def searchBook(self, data:dict[str, str])->list[tuple[BookData, int]]: """ Search a book in the database based on the sent data. Args: data (dict[str, str]): A dictionary containing the data to be searched for. The dictionary can contain the following: - signature: The signature of the book - title: The title of the book Returns: list[tuple[BookData, int]]: A list of tuples containing the wrapped Metadata and the id of the book """ rdata = self.query_db("SELECT * FROM media WHERE deleted=0") #ic(rdata, len(rdata)) mode = 0 if len(data)== 1: if "signature" in data.keys(): mode = 1 elif "title" in data.keys(): mode = 2 elif len(data) == 2: mode = 3 else: return None ret = [] for book in rdata: bookdata = load_pickle(book[1]) app_id = book[2] prof_id = book[3] if mode == 1: if data["signature"] in bookdata.signature: ret.append((bookdata,app_id,prof_id)) elif mode == 2: if data["title"] in bookdata.title: ret.append((bookdata,app_id,prof_id)) elif mode == 3: if data["signature"] in bookdata.signature and data["title"] in bookdata.title: ret.append((bookdata,app_id,prof_id)) #ic(ret) return ret def setAvailability(self, book_id: str, available: str)-
Set the availability of a book in the database
Args
book_id:str- The id of the book
available:str- The availability of the book
Expand source code
def setAvailability(self, book_id:str, available:str): """ Set the availability of a book in the database Args: book_id (str): The id of the book available (str): The availability of the book """ self.query_db("UPDATE media SET available=? WHERE id=?", (available,book_id)) def setNewSemesterDate(self, appnr, newDate, dauerapp=False)-
Expand source code
def setNewSemesterDate(self, appnr, newDate, dauerapp=False): date = datetime.datetime.strptime(newDate, "%d.%m.%Y").strftime("%Y-%m-%d") if dauerapp: self.query_db("UPDATE semesterapparat SET verlängerung_bis=?, dauerapp=? WHERE appnr=?", (date,dauerapp,appnr)) else: self.query_db("UPDATE semesterapparat SET endsemester=? WHERE appnr=?", (date,appnr)) def statistic_request(self, **kwargs: Any)-
Expand source code
def statistic_request(self, **kwargs: Any): def __query(query): conn = self.connect() cursor = conn.cursor() result = cursor.execute(query).fetchall() for result_a in result: orig_value = result_a prof_name = self.getProfNameById(result_a[2]) # replace the prof_id with the prof_name result_a = list(result_a) result_a[2] = prof_name result_a = tuple(result_a) result[result.index(orig_value)] = result_a self.close_connection(conn) return result if "deletable" in kwargs.keys(): query = f"SELECT * FROM semesterapparat WHERE deletion_status=0 AND dauer=0 AND (erstellsemester!='{kwargs['deletesemester']}' OR verlängerung_bis!='{kwargs['deletesemester']}')" return __query(query) if "dauer" in kwargs.keys(): kwargs["dauer"] = kwargs["dauer"].replace("Ja", "1").replace("Nein", "0") query = "SELECT * FROM semesterapparat WHERE " for key, value in kwargs.items() if kwargs.items() is not None else {}: print(key, value) query += f"{key}='{value}' AND " print(query) # remove deletesemester part from normal query, as this will be added to the database upon deleting the apparat if "deletesemester" in kwargs.keys(): query = query.replace( f"deletesemester='{kwargs['deletesemester']}' AND ", "" ) if "endsemester" in kwargs.keys(): if "erstellsemester" in kwargs.keys(): query = query.replace(f"endsemester='{kwargs['endsemester']}' AND ", "") query = query.replace( f"erstellsemester='{kwargs['erstellsemester']} AND ", "xyz" ) else: query = query.replace( f"endsemester='{kwargs['endsemester']}' AND ", "xyz" ) print("replaced") query = query.replace( "xyz", f"(erstellsemester='{kwargs['endsemester']}' OR verlängerung_bis='{kwargs['endsemester']}') AND ", ) # remove all x="" parts from the query where x is a key in kwargs query = query[:-5] print(query) return __query(query) def updateApparat(self, apparat_data: src.logic.dataclass.ApparatData)-
Expand source code
def updateApparat(self, apparat_data:ApparatData): query = f"UPDATE semesterapparat SET name = ?, fach = ?, dauer = ?, prof_id = ? WHERE appnr = ?" params = ( apparat_data.appname, apparat_data.app_fach, apparat_data.dauerapp, self.getProfId(apparat_data.profname), apparat_data.appnr, ) self.query_db(query, params) def updateBookdata(self, book_id, bookdata: src.logic.dataclass.BookData)-
Update the bookdata in the database
Args
book_id:str- The id of the book
bookdata:BookData- The new metadata of the book
Expand source code
def updateBookdata(self, book_id, bookdata:BookData): """ Update the bookdata in the database Args: book_id (str): The id of the book bookdata (BookData): The new metadata of the book """ self.query_db("UPDATE media SET bookdata=? WHERE id=?", (dump_pickle(bookdata),book_id)) def updateFacultyMember(self, data, oldlname, oldfname)-
Expand source code
def updateFacultyMember(self, data, oldlname, oldfname): placeholders = ", ".join([f"{i}=:{i} " for i in data.keys()]) query = f"UPDATE prof SET {placeholders} WHERE lname = :oldlname AND fname = :oldfname" data["oldlname"] = oldlname data["oldfname"] = oldfname self.query_db(query, data) def updateUser(self, username, data: dict[str, str])-
Expand source code
def updateUser(self, username, data:dict[str, str]): conn = self.connect() cursor = conn.cursor() query = "UPDATE user SET " for key,value in data.items(): if key == "username": continue query += f"{key}='{value}'," query = query[:-1] query += " WHERE username=?" params = (username,) cursor.execute(query, params) conn.commit() self.close_connection(conn)