Empfehlungen

This commit is contained in:
Bernhard Kolb 2026-04-17 14:46:53 +02:00
parent 470a8b1881
commit 87b44885b7
4 changed files with 147 additions and 0 deletions

15
app.py
View File

@ -55,6 +55,7 @@ from db import (
get_pdf_recommendation_topics, get_pdf_recommendation_topics,
get_random_ansprechpartner_for_thema, get_random_ansprechpartner_for_thema,
create_empfehlung, create_empfehlung,
get_all_empfehlungen,
) )
from permissions import admin_required, login_required from permissions import admin_required, login_required
from tools import create_assessment_chart, generate_activation_token, send_mail, verify_activation_token, generate_pdf_from_html from tools import create_assessment_chart, generate_activation_token, send_mail, verify_activation_token, generate_pdf_from_html
@ -900,6 +901,20 @@ def admin_question_edit_for_thema(thema_id, frage_id):
min_questions=8, min_questions=8,
) )
@app.route("/admin/empfehlungen")
@admin_required
def admin_empfehlungen():
empfehlungen = get_all_empfehlungen()
themen = get_all_themen()
ansprechpartner = get_all_ansprechpartner()
return render_template(
"admin/empfehlungen.html",
empfehlungen=empfehlungen,
themen=themen,
ansprechpartner=ansprechpartner,
)
@app.errorhandler(401) @app.errorhandler(401)
def unauthorized_error(error): def unauthorized_error(error):
return render_template("401.html"), 401 return render_template("401.html"), 401

23
db.py
View File

@ -805,4 +805,27 @@ def get_pdf_recommendation_topics(assessment_id, branche_id):
ORDER BY t.id ORDER BY t.id
""", """,
(assessment_id, branche_id), (assessment_id, branche_id),
)
def get_all_empfehlungen():
return fetch_all(
"""
SELECT
e.id,
e.datetime,
a.id AS ansprechpartner_id,
a.name AS ansprechpartner_name,
t.id AS thema_id,
t.titel AS thema_titel,
b.id AS user_id,
b.name AS user_name
FROM empfehlung e
JOIN ansprechpartner a
ON a.id = e.ansprechpartner_id
JOIN thema t
ON t.id = e.thema_id
JOIN benutzer b
ON b.id = e.user_id
ORDER BY a.name ASC, e.datetime DESC
"""
) )

View File

@ -0,0 +1,104 @@
{% extends "base.html" %}
{% block content %}
<div class="content-card">
<div class="page-header">
<h1>Empfehlungen</h1>
</div>
<div class="filter-bar">
<div class="form-group filter-item">
<label for="filter-ansprechpartner">Ansprechpartner</label>
<select id="filter-ansprechpartner">
<option value="">Alle Ansprechpartner</option>
{% for ap in ansprechpartner %}
<option value="{{ ap.name|lower }}">{{ ap.name }}</option>
{% endfor %}
</select>
</div>
<div class="form-group filter-item">
<label for="filter-thema">Thema</label>
<select id="filter-thema">
<option value="">Alle Themen</option>
{% for thema in themen %}
<option value="{{ thema.titel|lower }}">{{ thema.titel }}</option>
{% endfor %}
</select>
</div>
</div>
<div id="empfehlung-groups">
{% for ap in ansprechpartner %}
{% set group_items = empfehlungen | selectattr("ansprechpartner_id", "equalto", ap.id) | list %}
{% if group_items %}
<div class="question-group empfehlung-group" data-ansprechpartner="{{ ap.name|lower }}">
<div class="question-group-header">
<div>
<h2>{{ ap.name }}</h2>
<p class="muted">Empfehlungen: {{ group_items|length }}</p>
</div>
</div>
<div class="question-list">
{% for item in group_items %}
<div class="question-item empfehlung-item"
data-ansprechpartner="{{ item.ansprechpartner_name|lower }}"
data-thema="{{ item.thema_titel|lower }}">
<div class="question-item-main">
<div class="question-text">
<strong>Ansprechpartner:</strong> {{ item.ansprechpartner_name }}<br>
<strong>Thema:</strong> {{ item.thema_titel }}<br>
<strong>User:</strong> {{ item.user_name }}<br>
<strong>Datum:</strong> {{ item.datetime.strftime('%d.%m.%Y %H:%M') if item.datetime else '-' }}
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function () {
const apFilter = document.getElementById("filter-ansprechpartner");
const themaFilter = document.getElementById("filter-thema");
const groups = document.querySelectorAll(".empfehlung-group");
function applyFilters() {
const selectedAp = apFilter.value.trim().toLowerCase();
const selectedThema = themaFilter.value.trim().toLowerCase();
groups.forEach(group => {
const items = group.querySelectorAll(".empfehlung-item");
let visibleCount = 0;
items.forEach(item => {
const itemAp = item.dataset.ansprechpartner || "";
const itemThema = item.dataset.thema || "";
const apMatch = !selectedAp || itemAp === selectedAp;
const themaMatch = !selectedThema || itemThema.includes(selectedThema);
const visible = apMatch && themaMatch;
item.style.display = visible ? "" : "none";
if (visible) {
visibleCount++;
}
});
group.style.display = visibleCount > 0 ? "" : "none";
});
}
apFilter.addEventListener("change", applyFilters);
themaFilter.addEventListener("change", applyFilters);
applyFilters();
});
</script>
{% endblock %}

View File

@ -31,6 +31,11 @@
<h2>Branchen</h2> <h2>Branchen</h2>
<p>Branchen anlegen, bearbeiten und Themen zuordnen.</p> <p>Branchen anlegen, bearbeiten und Themen zuordnen.</p>
</a> </a>
<a class="topic-box" href="{{ url_for('admin_empfehlungen') }}">
<h2>Empfehlungen</h2>
<p>Empfehlungen nach Ansprechpartner und Thema auswerten.</p>
</a>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}