feat(workflow): Tages-Workflow-UI für Telefon-Akquise (Liste + Maske)

Server: neuer Endpunkt /xhr/workflow/list aggregiert pro Kontaktadresse
die letzte Gesprächsnotiz, das effektiv gültige Wiedervorlage-Datum
(jüngste Notiz mit Wert), den Erledigt-Status und eine priorisierte
Sortierung (überfällig → ohne Notizen → Rest). Filter: kunden_id, status
(offen/erledigt), wiedervorlage (heute/3tage/ueberfaellig/woche).
Sichtbarkeit wie kontaktadressen über projekt_users.

CallLog erfasst den Ersteller serverseitig (user_id, Migration _db_V01_14,
kein FK wegen separater Auth-DB); to_dict ergänzt mitarbeiter_name.
calllog_list unterstützt kontaktadresse_id als Filter.

Client: TagesWorkflowListe (Route /tagesworkflow, Filterleiste) und
TagesWorkflowMaske (Route /tagesworkflowkontakt, lesende Historie,
Notiz-Formular mit "Speichern und weiter"), Routes + Menüpunkt erster
Eintrag. berechneWiedervorlageDatum aus der Call_Log-Maske nach
models/tag.ts ausgelagert (gemeinsame Nutzung).

Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
gg committed 2026-09-24 18:56:23 +02:00
1 parent 981b28df03
commit c96ed6e97d
13 files changed
+1247 -44

No files matched your search

+35 -5
View File
@@ -27,6 +27,7 @@ from crm.model import projekt as projekte
from crm.model import projekt_user as projekt_users
from crm.model import kontaktadresse as kontaktadressen
from crm.model import call_log as call_logs
from crm.model import tages_workflow
from crm.model import tag as tags
print("crm-routes")
@@ -332,11 +333,15 @@ def kontaktadresse_delete():
@app.get("/xhr/calllog/list")
@authorisation_required([MITARBEITER, KUNDEN_MANAGER])
def calllog_list():
"""Liefert Gesprächsnotizen als Liste. Optional nach projekt_id gefiltert.
Für Nicht-SysAdmin/Nicht-AppAdmin nur Notizen sichtbarer Projekte."""
"""Liefert Gesprächsnotizen als Liste. Optional nach projekt_id und/oder
kontaktadresse_id gefiltert. Für Nicht-SysAdmin/Nicht-AppAdmin nur
Notizen sichtbarer Projekte."""
projekt_id = request.args.get("projekt_id", type=int)
kontaktadresse_id = request.args.get("kontaktadresse_id", type=int)
user_id = _get_visible_user_id()
result = [l.to_dict() for l in call_logs.get_call_logs(projekt_id, user_id)]
result = [l.to_dict() for l in call_logs.get_call_logs(
projekt_id, user_id, kontaktadresse_id
)]
return jsonify(result), 200
@@ -354,9 +359,10 @@ def calllog_get():
@app.post("/xhr/calllog/create")
@authorisation_required([KUNDEN_MANAGER])
def calllog_create():
"""Legt eine neue Gesprächsnotiz an. ID wird serverseitig vergeben."""
"""Legt eine neue Gesprächsnotiz an. ID wird serverseitig vergeben.
current_user.id wird als Ersteller (user_id) erfasst."""
_require_projekt_access(int(request.json["projekt_id"]))
call_log = call_logs.create_call_log(request.json)
call_log = call_logs.create_call_log(request.json, current_user.id)
return jsonify(call_log.to_dict()), 200
@@ -381,6 +387,30 @@ def calllog_delete():
return jsonify({}), 200
# --------------------------------------------------------------------------- #
# Tages-Workflow #
# --------------------------------------------------------------------------- #
@app.get("/xhr/workflow/list")
@authorisation_required([MITARBEITER, KUNDEN_MANAGER])
def workflow_list():
"""Tages-Workflow-Liste: Kontaktadressen mit letzter Notiz, Wiedervorlage
und dynamisch berechnetem Status. Optional gefiltert nach kunden_id,
status ('offen'/'erledigt') und wiedervorlage ('heute'/'3tage'/
'ueberfaellig'/'woche'). Für Nicht-SysAdmin/Nicht-AppAdmin nur
Kontaktadressen sichtbarer Projekte. Die Sortierung ist priorisiert:
überfällige Wiedervorlagen, dann Kontakte ohne Notizen, dann der Rest."""
user_id = _get_visible_user_id()
result = tages_workflow.get_tages_workflow_list(
user_id,
request.args.get("kunden_id", type=int),
request.args.get("status"),
request.args.get("wiedervorlage"),
)
return jsonify(result), 200
# --------------------------------------------------------------------------- #
# Tag (hierarchische Taxonomie) #
# --------------------------------------------------------------------------- #