DasUnternehmen/db.py
2026-04-13 22:58:43 +02:00

808 lines
17 KiB
Python

from contextlib import contextmanager
import psycopg2
import psycopg2.extras
from config import Config
def get_connection():
return psycopg2.connect(
host=Config.DB_HOST,
dbname=Config.DB_NAME,
user=Config.DB_USER,
password=Config.DB_PASSWORD,
port=Config.DB_PORT,
cursor_factory=psycopg2.extras.RealDictCursor,
)
@contextmanager
def get_cursor(commit=False):
conn = get_connection()
cur = conn.cursor()
try:
yield cur
if commit:
conn.commit()
except Exception:
conn.rollback()
raise
finally:
cur.close()
conn.close()
def fetch_one(query, params=None):
with get_cursor() as cur:
cur.execute(query, params or ())
return cur.fetchone()
def fetch_all(query, params=None):
with get_cursor() as cur:
cur.execute(query, params or ())
return cur.fetchall()
def execute(query, params=None):
with get_cursor(commit=True) as cur:
cur.execute(query, params or ())
def execute_returning(query, params=None):
with get_cursor(commit=True) as cur:
cur.execute(query, params or ())
return cur.fetchone()
###############
# Benutzer
###############
def get_user_by_id(user_id):
return fetch_one(
"""
SELECT id, name, email, passwort_hash, is_active, last_login
FROM benutzer
WHERE id = %s
""",
(user_id,),
)
def get_user_by_email(email):
return fetch_one(
"""
SELECT id, name, email, passwort_hash, is_active, last_login
FROM benutzer
WHERE email = %s
""",
(email,),
)
def get_all_users():
return fetch_all(
"""
SELECT id, name, email, last_login, is_active
FROM benutzer
ORDER BY name, email
"""
)
def create_user(name, email, password_hash, is_active=False):
return execute_returning(
"""
INSERT INTO benutzer (name, email, passwort_hash, is_active)
VALUES (%s, %s, %s, %s)
RETURNING id
""",
(name, email, password_hash, is_active),
)
def activate_user_by_email(email):
execute(
"""
UPDATE benutzer
SET is_active = TRUE
WHERE email = %s
""",
(email,),
)
def update_user_password(user_id, password_hash):
execute(
"""
UPDATE benutzer
SET passwort_hash = %s
WHERE id = %s
""",
(password_hash, user_id),
)
def update_user_last_login(user_id):
execute(
"""
UPDATE benutzer
SET last_login = NOW()
WHERE id = %s
""",
(user_id,),
)
def log_access(user_id):
execute(
"""
INSERT INTO accesslog (user_id)
VALUES (%s)
""",
(user_id,),
)
def get_user_groups(user_id):
rows = fetch_all(
"""
SELECT g.gruppenname
FROM benutzer_gruppen bg
JOIN gruppen g ON g.id = bg.gruppen_id
WHERE bg.benutzer_id = %s
ORDER BY g.gruppenname
""",
(user_id,),
)
return [row["gruppenname"] for row in rows]
###############
# Themen
###############
def get_all_themen():
return fetch_all(
"""
SELECT id, kurztitel, titel, infotext, zusatztext
FROM thema
ORDER BY id
"""
)
def get_thema_by_id(thema_id):
return fetch_one(
"""
SELECT id, kurztitel, titel, infotext, zusatztext
FROM thema
WHERE id = %s
""",
(thema_id,),
)
def get_next_thema_id(current_thema_id):
row = fetch_one(
"""
SELECT id
FROM thema
WHERE id > %s
ORDER BY id
LIMIT 1
""",
(current_thema_id,),
)
return row["id"] if row else None
def get_all_ansprechpartner():
return fetch_all(
"""
SELECT id, name, email, infotext
FROM ansprechpartner
ORDER BY name ASC
"""
)
def get_all_contacts():
return fetch_all(
"""
SELECT id, name, email, infotext
FROM ansprechpartner
ORDER BY name ASC
"""
)
def get_thema_ansprechpartner(thema_id):
return fetch_all(
"""
SELECT a.id, a.name, a.email, a.infotext
FROM ansprechpartner a
JOIN themaansprechpartner ta ON ta.ansprechpartner_id = a.id
WHERE ta.thema_id = %s
ORDER BY a.name ASC
""",
(thema_id,),
)
def get_ansprechpartner_ids_for_thema(thema_id):
rows = fetch_all(
"""
SELECT ansprechpartner_id
FROM themaansprechpartner
WHERE thema_id = %s
""",
(thema_id,),
)
return [row["ansprechpartner_id"] for row in rows]
def create_thema(kurztitel, titel, infotext, zusatztext, ansprechpartner_ids, branche_ids=None):
if branche_ids is None:
branche_ids = []
row = execute_returning(
"""
INSERT INTO thema (kurztitel, titel, infotext, zusatztext)
VALUES (%s, %s, %s, %s)
RETURNING id
""",
(kurztitel, titel, infotext, zusatztext),
)
thema_id = row["id"]
for ap_id in ansprechpartner_ids:
execute(
"""
INSERT INTO themaansprechpartner (thema_id, ansprechpartner_id)
VALUES (%s, %s)
""",
(thema_id, ap_id),
)
for branche_id in branche_ids:
execute(
"""
INSERT INTO branchenthemen (branche_id, thema_id)
VALUES (%s, %s)
""",
(branche_id, thema_id),
)
return thema_id
def update_thema(thema_id, kurztitel, titel, infotext, zusatztext, ansprechpartner_ids, branche_ids=None):
if branche_ids is None:
branche_ids = []
execute(
"""
UPDATE thema
SET kurztitel = %s,
titel = %s,
infotext = %s,
zusatztext = %s
WHERE id = %s
""",
(kurztitel, titel, infotext, zusatztext, thema_id),
)
execute(
"""
DELETE FROM themaansprechpartner
WHERE thema_id = %s
""",
(thema_id,),
)
for ap_id in ansprechpartner_ids:
execute(
"""
INSERT INTO themaansprechpartner (thema_id, ansprechpartner_id)
VALUES (%s, %s)
""",
(thema_id, ap_id),
)
execute(
"""
DELETE FROM branchenthemen
WHERE thema_id = %s
""",
(thema_id,),
)
for branche_id in branche_ids:
execute(
"""
INSERT INTO branchenthemen (branche_id, thema_id)
VALUES (%s, %s)
""",
(branche_id, thema_id),
)
def delete_thema(thema_id):
execute("DELETE FROM themaansprechpartner WHERE thema_id = %s", (thema_id,))
execute("DELETE FROM fragen WHERE thema_id = %s", (thema_id,))
execute("DELETE FROM thema WHERE id = %s", (thema_id,))
###############
# Fragen
###############
def get_thema_questions(thema_id):
return fetch_all(
"""
SELECT id, thema_id, text
FROM fragen
WHERE thema_id = %s
ORDER BY id
""",
(thema_id,),
)
def get_all_questions_with_thema():
return fetch_all(
"""
SELECT
f.id,
f.text,
f.thema_id,
t.id AS thema_sort_id,
t.kurztitel,
t.titel,
COALESCE(STRING_AGG(b.branchenname, ' | '), '') AS branchen
FROM fragen f
JOIN thema t
ON t.id = f.thema_id
LEFT JOIN branchenthemen bt
ON bt.thema_id = t.id
LEFT JOIN branche b
ON b.id = bt.branche_id
GROUP BY
f.id,
f.text,
f.thema_id,
t.id,
t.kurztitel,
t.titel
ORDER BY t.id, f.id
"""
)
###############
# Assessment
###############
def create_assessment(user_id):
row = execute_returning(
"""
INSERT INTO assessment (user_id)
VALUES (%s)
RETURNING id
""",
(user_id,),
)
return row["id"]
def save_assessment_answer(assessment_id, thema_id, frage_id, antwort):
execute(
"""
INSERT INTO assessmentanswer (assessmentid, thema_id, frage_id, antwort)
VALUES (%s, %s, %s, %s)
ON CONFLICT (assessmentid, frage_id)
DO UPDATE SET antwort = EXCLUDED.antwort
""",
(assessment_id, thema_id, frage_id, antwort),
)
def get_assessment_result_rows(assessment_id, branche_id):
return fetch_all(
"""
SELECT
t.id,
t.kurztitel,
t.titel,
COUNT(*) FILTER (WHERE aa.antwort = TRUE) AS ja_anzahl
FROM thema t
JOIN branchenthemen bt
ON bt.thema_id = t.id
LEFT JOIN assessmentanswer aa
ON aa.thema_id = t.id
AND aa.assessmentid = %s
WHERE bt.branche_id = %s
GROUP BY t.id, t.kurztitel, t.titel
ORDER BY t.id
""",
(assessment_id, branche_id),
)
############
# Ansprechpartner
############
def get_ansprechpartner_by_id(ansprechpartner_id):
return fetch_one(
"""
SELECT id, name, email, infotext
FROM ansprechpartner
WHERE id = %s
""",
(ansprechpartner_id,),
)
def create_ansprechpartner(name, email, infotext):
row = execute_returning(
"""
INSERT INTO ansprechpartner (name, email, infotext)
VALUES (%s, %s, %s)
RETURNING id
""",
(name, email, infotext),
)
return row["id"]
def update_ansprechpartner(ansprechpartner_id, name, email, infotext):
execute(
"""
UPDATE ansprechpartner
SET name = %s,
email = %s,
infotext = %s
WHERE id = %s
""",
(name, email, infotext, ansprechpartner_id),
)
def delete_ansprechpartner(ansprechpartner_id):
execute(
"""
DELETE FROM themaansprechpartner
WHERE ansprechpartner_id = %s
""",
(ansprechpartner_id,),
)
execute(
"""
DELETE FROM ansprechpartner
WHERE id = %s
""",
(ansprechpartner_id,),
)
###############
# Fragen
###############
def get_question_by_id(frage_id):
return fetch_one(
"""
SELECT id, thema_id, text
FROM fragen
WHERE id = %s
""",
(frage_id,),
)
def create_question(thema_id, text):
return execute_returning(
"""
INSERT INTO fragen (thema_id, text)
VALUES (%s, %s)
RETURNING id
""",
(thema_id, text),
)
def update_question(frage_id, thema_id, text):
execute(
"""
UPDATE fragen
SET thema_id = %s,
text = %s
WHERE id = %s
""",
(thema_id, text, frage_id),
)
def delete_question(frage_id):
execute(
"DELETE FROM fragen WHERE id = %s",
(frage_id,),
)
##########
# usermanagement
##########
def activate_user(user_id):
execute(
"""
UPDATE benutzer
SET is_active = TRUE
WHERE id = %s
""",
(user_id,),
)
def delete_user(user_id, current_user_id=None):
if current_user_id is not None and int(user_id) == int(current_user_id):
raise ValueError("Der aktuell angemeldete Benutzer kann nicht gelöscht werden.")
execute(
"""
DELETE FROM benutzer
WHERE id = %s
""",
(user_id,),
)
###############
# Branchen
###############
def get_all_branchen():
return fetch_all(
"""
SELECT id, branchenname
FROM branche
ORDER BY branchenname ASC
"""
)
def get_branche_by_id(branche_id):
return fetch_one(
"""
SELECT id, branchenname
FROM branche
WHERE id = %s
""",
(branche_id,),
)
def get_thema_ids_for_branche(branche_id):
rows = fetch_all(
"""
SELECT thema_id
FROM branchenthemen
WHERE branche_id = %s
""",
(branche_id,),
)
return [row["thema_id"] for row in rows]
def create_branche(branchenname, thema_ids):
row = execute_returning(
"""
INSERT INTO branche (branchenname)
VALUES (%s)
RETURNING id
""",
(branchenname,),
)
branche_id = row["id"]
for thema_id in thema_ids:
execute(
"""
INSERT INTO branchenthemen (branche_id, thema_id)
VALUES (%s, %s)
""",
(branche_id, thema_id),
)
return branche_id
def update_branche(branche_id, branchenname, thema_ids):
execute(
"""
UPDATE branche
SET branchenname = %s
WHERE id = %s
""",
(branchenname, branche_id),
)
execute(
"""
DELETE FROM branchenthemen
WHERE branche_id = %s
""",
(branche_id,),
)
for thema_id in thema_ids:
execute(
"""
INSERT INTO branchenthemen (branche_id, thema_id)
VALUES (%s, %s)
""",
(branche_id, thema_id),
)
def delete_branche(branche_id):
execute(
"""
DELETE FROM branchenthemen
WHERE branche_id = %s
""",
(branche_id,),
)
execute(
"""
DELETE FROM branche
WHERE id = %s
""",
(branche_id,),
)
def get_branche_ids_for_thema(thema_id):
rows = fetch_all(
"""
SELECT branche_id
FROM branchenthemen
WHERE thema_id = %s
""",
(thema_id,),
)
return [row["branche_id"] for row in rows]
def update_thema_branchen(thema_id, branche_ids):
execute(
"""
DELETE FROM branchenthemen
WHERE thema_id = %s
""",
(thema_id,),
)
for branche_id in branche_ids:
execute(
"""
INSERT INTO branchenthemen (branche_id, thema_id)
VALUES (%s, %s)
""",
(branche_id, thema_id),
)
def get_all_branchen():
return fetch_all(
"""
SELECT id, branchenname
FROM branche
ORDER BY branchenname ASC
"""
)
def get_themen_for_branche(branche_id):
return fetch_all(
"""
SELECT t.id, t.kurztitel, t.titel, t.infotext, t.zusatztext
FROM thema t
JOIN branchenthemen bt ON bt.thema_id = t.id
WHERE bt.branche_id = %s
ORDER BY t.id
""",
(branche_id,),
)
def get_next_thema_id_for_branche(current_thema_id, branche_id):
row = fetch_one(
"""
SELECT t.id
FROM thema t
JOIN branchenthemen bt ON bt.thema_id = t.id
WHERE bt.branche_id = %s
AND t.id > %s
ORDER BY t.id
LIMIT 1
""",
(branche_id, current_thema_id),
)
return row["id"] if row else None
def get_thema_for_branche(thema_id, branche_id):
return fetch_one(
"""
SELECT t.id, t.kurztitel, t.titel, t.infotext, t.zusatztext
FROM thema t
JOIN branchenthemen bt ON bt.thema_id = t.id
WHERE t.id = %s
AND bt.branche_id = %s
""",
(thema_id, branche_id),
)
def get_question_count_for_thema(thema_id):
row = fetch_one(
"""
SELECT COUNT(*) AS anzahl
FROM fragen
WHERE thema_id = %s
""",
(thema_id,),
)
return int(row["anzahl"]) if row else 0
def get_all_themen_with_question_count():
return fetch_all(
"""
SELECT
t.id,
t.kurztitel,
t.titel,
t.infotext,
t.zusatztext,
COUNT(f.id) AS fragen_anzahl
FROM thema t
LEFT JOIN fragen f ON f.thema_id = t.id
GROUP BY t.id, t.kurztitel, t.titel, t.infotext, t.zusatztext
ORDER BY t.id
"""
)
def get_random_ansprechpartner_for_thema(thema_id):
return fetch_one(
"""
SELECT a.id, a.name, a.email, a.infotext
FROM ansprechpartner a
JOIN themaansprechpartner ta ON ta.ansprechpartner_id = a.id
WHERE ta.thema_id = %s
ORDER BY RANDOM()
LIMIT 1
""",
(thema_id,),
)
def create_empfehlung(user_id, thema_id, ansprechpartner_id):
return execute_returning(
"""
INSERT INTO empfehlung (user_id, thema_id, ansprechpartner_id)
VALUES (%s, %s, %s)
RETURNING id
""",
(user_id, thema_id, ansprechpartner_id),
)
def get_pdf_recommendation_topics(assessment_id, branche_id):
return fetch_all(
"""
SELECT
t.id,
t.titel,
t.zusatztext,
COUNT(*) FILTER (WHERE aa.antwort = TRUE) AS ja_anzahl
FROM thema t
JOIN branchenthemen bt
ON bt.thema_id = t.id
LEFT JOIN assessmentanswer aa
ON aa.thema_id = t.id
AND aa.assessmentid = %s
WHERE bt.branche_id = %s
GROUP BY t.id, t.titel, t.zusatztext
HAVING COUNT(*) FILTER (WHERE aa.antwort = TRUE) < 7
ORDER BY t.id
""",
(assessment_id, branche_id),
)