Benutzer Bearbeitung hinzugefügt

This commit is contained in:
Erik Thiele
2026-05-26 16:52:08 +02:00
parent df98b6d57f
commit 0913f69c70
10 changed files with 4894 additions and 20 deletions

91
app.py
View File

@@ -12,7 +12,7 @@ from werkzeug.security import check_password_hash, generate_password_hash
app = Flask(__name__)
app.config["SECRET_KEY"] = "dev-secret-key"
APP_VERSION = "2.1.0"
APP_VERSION = "2.2.0"
DATABASE = Path(__file__).with_name("inventory.db")
LOGFILE = Path(__file__).with_name("inventory.log")
@@ -46,7 +46,8 @@ INPUT_PLACEHOLDERS = {
}
IMPORT_ACTIONS = {"import", "ausgabe", "assign"}
IMPORT_HEADER = ["user", "typ", "kennung", "aktion"]
IMPORT_HEADER_4 = ["user", "typ", "kennung", "aktion"]
IMPORT_HEADER_5 = ["vorname", "nachname", "typ", "kennung", "aktion"]
def get_db() -> sqlite3.Connection:
@@ -261,7 +262,7 @@ def normalize_asset_type(value: str) -> str | None:
def is_import_header(parts: list[str]) -> bool:
normalized = [part.strip().lower() for part in parts]
return normalized == IMPORT_HEADER
return normalized == IMPORT_HEADER_4 or normalized == IMPORT_HEADER_5
def get_transaction_for_print(transaction_id: int) -> sqlite3.Row | None:
@@ -477,11 +478,14 @@ def import_data() -> str:
parts = [part.strip() for part in row.split(";")]
if is_import_header(parts):
continue
if len(parts) != 4:
errors.append(f"Zeile {index}: ungueltig. Erwartet wird: User;Typ;Kennung;Aktion")
if len(parts) == 4:
full_name, raw_asset_type, asset_code, raw_action = parts
elif len(parts) == 5:
first_name, last_name, raw_asset_type, asset_code, raw_action = parts
full_name = f"{first_name} {last_name}"
else:
errors.append(f"Zeile {index}: ungueltig. Erwartet wird: User;Typ;Kennung;Aktion oder Vorname;Nachname;Typ;Kennung;Aktion")
continue
full_name, raw_asset_type, asset_code, raw_action = parts
asset_type = normalize_asset_type(raw_asset_type)
action = raw_action.strip().lower()
@@ -654,7 +658,7 @@ def index() -> str:
"""
params = (like_value, like_value, like_value, like_value, like_value)
user_query += " ORDER BY full_name COLLATE NOCASE"
user_query += " ORDER BY SUBSTR(full_name, INSTR(full_name, ' ') + 1) COLLATE NOCASE, full_name COLLATE NOCASE"
users = db.execute(user_query, params).fetchall()
stats = db.execute(
@@ -701,14 +705,16 @@ def index() -> str:
@login_required
def create_user() -> str:
if request.method == "POST":
full_name = request.form.get("full_name", "").strip()
first_name = request.form.get("first_name", "").strip()
last_name = request.form.get("last_name", "").strip()
email = request.form.get("email", "").strip() or None
department = request.form.get("department", "").strip() or None
if not full_name:
flash("Bitte einen Namen eingeben.")
if not first_name or not last_name:
flash("Bitte Vor- und Nachname eingeben.")
return redirect(url_for("create_user"))
full_name = f"{first_name} {last_name}"
db = get_db()
db.execute(
"INSERT INTO users (full_name, email, department) VALUES (?, ?, ?)",
@@ -721,6 +727,65 @@ def create_user() -> str:
return render_template("create_user.html")
@app.route("/users/<int:user_id>/edit", methods=["GET", "POST"])
@login_required
def edit_user(user_id: int) -> str:
db = get_db()
user = db.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone()
if user is None:
flash("User wurde nicht gefunden.")
return redirect(url_for("index"))
if request.method == "POST":
first_name = request.form.get("first_name", "").strip()
last_name = request.form.get("last_name", "").strip()
email = request.form.get("email", "").strip() or None
department = request.form.get("department", "").strip() or None
if not first_name or not last_name:
flash("Bitte Vor- und Nachname eingeben.")
return redirect(url_for("edit_user", user_id=user_id))
full_name = f"{first_name} {last_name}"
db.execute(
"UPDATE users SET full_name = ?, email = ?, department = ? WHERE id = ?",
(full_name, email, department, user_id),
)
db.commit()
flash("User wurde aktualisiert.")
return redirect(url_for("index"))
parts = user["full_name"].rsplit(" ", 1)
first_name = parts[0] if len(parts) > 1 else ""
last_name = parts[1] if len(parts) > 1 else parts[0]
return render_template(
"edit_user.html",
user=user,
first_name=first_name,
last_name=last_name,
)
@app.route("/users/<int:user_id>/delete", methods=["POST"])
@login_required
def delete_user(user_id: int) -> str:
db = get_db()
user = db.execute("SELECT * FROM users WHERE id = ?", (user_id,)).fetchone()
if user is None:
flash("User wurde nicht gefunden.")
return redirect(url_for("index"))
if user["chip_code"] or user["parking_card_code"] or user["pool_vehicle_code"]:
flash("Der User hat noch aktive Medien. Bitte zuerst alle Medien zuruecknehmen.")
return redirect(url_for("edit_user", user_id=user_id))
db.execute("DELETE FROM transactions WHERE user_id = ?", (user_id,))
db.execute("DELETE FROM users WHERE id = ?", (user_id,))
db.commit()
flash(f"User '{user['full_name']}' wurde geloescht.")
return redirect(url_for("index"))
@app.route("/assign", methods=["GET", "POST"])
@login_required
def assign_asset() -> str:
@@ -785,7 +850,7 @@ def assign_asset() -> str:
flash("Ausgabe wurde gespeichert.")
return redirect(url_for("print_transaction", transaction_id=transaction_id))
users = db.execute("SELECT id, full_name FROM users ORDER BY full_name COLLATE NOCASE").fetchall()
users = db.execute("SELECT id, full_name FROM users ORDER BY SUBSTR(full_name, INSTR(full_name, ' ') + 1) COLLATE NOCASE, full_name COLLATE NOCASE").fetchall()
return render_template(
"assign_asset.html",
users=users,
@@ -852,7 +917,7 @@ def return_asset() -> str:
flash("Rueckgabe wurde gespeichert.")
return redirect(url_for("print_transaction", transaction_id=transaction_id))
users = db.execute("SELECT id, full_name FROM users ORDER BY full_name COLLATE NOCASE").fetchall()
users = db.execute("SELECT id, full_name FROM users ORDER BY SUBSTR(full_name, INSTR(full_name, ' ') + 1) COLLATE NOCASE, full_name COLLATE NOCASE").fetchall()
return render_template(
"return_asset.html",
users=users,