From 69ecc2e1f2041098fa8d7065c164de4f13f78acb Mon Sep 17 00:00:00 2001 From: Bkolb Date: Fri, 3 Apr 2026 17:27:17 +0200 Subject: [PATCH] Dokumentenmanagement plus Checkliste --- app/flask-postgres/app/app.py | 193 +++++++++++++++++++++++++++++++++- 1 file changed, 192 insertions(+), 1 deletion(-) diff --git a/app/flask-postgres/app/app.py b/app/flask-postgres/app/app.py index 76c051a..dc0e5a0 100644 --- a/app/flask-postgres/app/app.py +++ b/app/flask-postgres/app/app.py @@ -15,6 +15,7 @@ from flask import ( abort, ) from werkzeug.security import check_password_hash, generate_password_hash +from werkzeug.utils import secure_filename from config import Config, COUNTRY_VAT_LABELS from db import get_connection, fetchone_dict, fetchall_dict @@ -25,6 +26,7 @@ from security import ( get_current_user, get_current_user_mandant_level, user_admin_required, + contentmanager_required ) from logging_config import setup_logging @@ -1070,4 +1072,193 @@ def course_page(course_id, page_number): course_id=course_id, page_number=page_number, **get_current_user() - ) \ No newline at end of file + ) + +@app.route("/dokumente") +@contentmanager_required +def dokumente(): + mandant_id = session.get("mandant_id") + mandant_level = session.get("mandant_level") + + allowed_levels = get_allowed_checklist_levels_for_mandant_level(mandant_level) + + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT + c.id, + c.level, + c.title, + c.short_description, + c.default_filename, + u.uploaded_at, + u.uploaded_by_user_id, + u.filesize, + u.stored_filename, + u.original_filename, + au.name AS uploaded_by_name + FROM certification_checklist c + LEFT JOIN mandant_checklist_upload u + ON u.checklist_item_id = c.id + AND u.mandant_id = %s + LEFT JOIN app_user au + ON au.id = u.uploaded_by_user_id + WHERE c.level = ANY(%s) + ORDER BY c.level, c.id + """, (mandant_id, allowed_levels)) + + items = fetchall_dict(cur) + + cur.close() + conn.close() + + return render_template( + "dokumente.html", + page_title="Dokumente", + active_page="dokumente", + items=items, + **get_current_user() + ) + +@app.route("/dokumente/upload/", methods=["POST"]) +@contentmanager_required +def dokument_upload(item_id): + mandant_id = session.get("mandant_id") + user_id = session.get("user_id") + + uploaded_file = request.files.get("file") + if not uploaded_file or uploaded_file.filename == "": + return redirect(url_for("dokumente")) + + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT id, default_filename + FROM certification_checklist + WHERE id = %s + """, (item_id,)) + item = fetchone_dict(cur) + + if not item: + cur.close() + conn.close() + abort(404) + + original_filename = secure_filename(uploaded_file.filename) + final_name_part = item["default_filename"] or original_filename + stored_filename = f"{item_id}-{secure_filename(final_name_part)}" + + mandant_dir = os.path.join("/files", str(mandant_id)) + os.makedirs(mandant_dir, exist_ok=True) + + full_path = os.path.join(mandant_dir, stored_filename) + uploaded_file.save(full_path) + + filesize = os.path.getsize(full_path) + + cur.execute(""" + SELECT stored_filename + FROM mandant_checklist_upload + WHERE mandant_id = %s + AND checklist_item_id = %s + """, (mandant_id, item_id)) + existing = cur.fetchone() + + if existing: + old_filename = existing[0] + old_path = os.path.join(mandant_dir, old_filename) + if os.path.exists(old_path) and old_filename != stored_filename: + os.remove(old_path) + + cur.execute(""" + UPDATE mandant_checklist_upload + SET uploaded_at = CURRENT_TIMESTAMP, + uploaded_by_user_id = %s, + filesize = %s, + stored_filename = %s, + original_filename = %s + WHERE mandant_id = %s + AND checklist_item_id = %s + """, (user_id, filesize, stored_filename, original_filename, mandant_id, item_id)) + else: + cur.execute(""" + INSERT INTO mandant_checklist_upload ( + mandant_id, + checklist_item_id, + uploaded_by_user_id, + filesize, + stored_filename, + original_filename + ) + VALUES (%s, %s, %s, %s, %s, %s) + """, (mandant_id, item_id, user_id, filesize, stored_filename, original_filename)) + + conn.commit() + cur.close() + conn.close() + + return redirect(url_for("dokumente")) + +@app.route("/dokumente/delete/", methods=["POST"]) +@contentmanager_required +def dokument_delete(item_id): + mandant_id = session.get("mandant_id") + mandant_dir = os.path.join("/files", str(mandant_id)) + + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT stored_filename + FROM mandant_checklist_upload + WHERE mandant_id = %s + AND checklist_item_id = %s + """, (mandant_id, item_id)) + row = cur.fetchone() + + if row: + stored_filename = row[0] + full_path = os.path.join(mandant_dir, stored_filename) + + if os.path.exists(full_path): + os.remove(full_path) + + cur.execute(""" + DELETE FROM mandant_checklist_upload + WHERE mandant_id = %s + AND checklist_item_id = %s + """, (mandant_id, item_id)) + conn.commit() + + cur.close() + conn.close() + + return redirect(url_for("dokumente")) + +@app.route("/dokumente/file/") +@contentmanager_required +def dokument_file(item_id): + mandant_id = session.get("mandant_id") + + conn = get_connection() + cur = conn.cursor() + + cur.execute(""" + SELECT stored_filename + FROM mandant_checklist_upload + WHERE mandant_id = %s + AND checklist_item_id = %s + """, (mandant_id, item_id)) + row = cur.fetchone() + + cur.close() + conn.close() + + if not row: + abort(404) + + stored_filename = row[0] + mandant_dir = os.path.join("/files", str(mandant_id)) + return send_from_directory(mandant_dir, stored_filename) \ No newline at end of file