feat(tags): Backend mit REST-API und Client-Anbindung fuer hierarchische Tags
- SQLAlchemy-Modell Tag mit Selbst-Referenz (parent_id), is_parent-Flag - DB-Migration V01.10 (idempotent via create_all) - Geschaeftslogik tag.py: CRUD, Hierarchie-Aufbau, kaskadierendes Loeschen, Zirkelbezug-Pruefung - REST-Endpunkte /xhr/tag/*: Lesen fuer Mitarbeiter, Schreiben fuer AppAdmin - Client-Modell tag.ts mit REST-Funktionen - Frontend tags.ts auf REST-API umgestellt, hartcodierte Daten entfernt, Loesch-Dialog mit kaskadierender Bestaetigung Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
1 parent
675d7775c1
commit
5abcb2d96c
6 files changed
+600
-648
No files matched your search
@@ -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 tag as tags
|
||||
|
||||
print("crm-routes")
|
||||
|
||||
@@ -380,4 +381,64 @@ def calllog_delete():
|
||||
return jsonify({}), 200
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Tag (hierarchische Taxonomie) #
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Tags sind nicht projektbezogen — die projektbezogene Sichtbarkeits-
|
||||
# Filterung entfaellt. Lesen: alle Mitarbeiter. Schreiben: nur AppAdmin/SysAdmin.
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
@app.get("/xhr/tag/list")
|
||||
@authorisation_required([MITARBEITER, KUNDEN_MANAGER])
|
||||
def tag_list():
|
||||
"""Liefert alle Tags als flache Liste. Optional nach parent_id gefiltert."""
|
||||
parent_id = request.args.get("parent_id", type=int)
|
||||
result = [t.to_dict() for t in tags.get_tags(parent_id)]
|
||||
return jsonify(result), 200
|
||||
|
||||
|
||||
@app.get("/xhr/tag/hierarchy")
|
||||
@authorisation_required([MITARBEITER, KUNDEN_MANAGER])
|
||||
def tag_hierarchy():
|
||||
"""Liefert die vollstaendige Tag-Hierarchie als verschachtelte Struktur."""
|
||||
result = tags.get_tag_hierarchy()
|
||||
return jsonify(result), 200
|
||||
|
||||
|
||||
@app.get("/xhr/tag/get")
|
||||
@authorisation_required([MITARBEITER, KUNDEN_MANAGER])
|
||||
def tag_get():
|
||||
"""Liefert einen einzelnen Tag anhand seiner ID (Query-Param id)."""
|
||||
tag = tags.get_tag(int(request.args.get("id")))
|
||||
return jsonify(tag.to_dict()), 200
|
||||
|
||||
|
||||
@app.post("/xhr/tag/create")
|
||||
# Leeres allowed_roles-Array: Nur AppAdmin/SysAdmin (vom Decorator
|
||||
# implizit ergaenzt). Tags sind eine globale Taxonomie — die Anlage
|
||||
# und Aenderung ist ausschliesslich den Administratoren vorbehalten.
|
||||
@authorisation_required([])
|
||||
def tag_create():
|
||||
"""Legt einen neuen Tag an. ID wird serverseitig vergeben."""
|
||||
tag = tags.create_tag(request.json)
|
||||
return jsonify(tag.to_dict()), 200
|
||||
|
||||
|
||||
@app.put("/xhr/tag/update")
|
||||
@authorisation_required([])
|
||||
def tag_update():
|
||||
"""Aktualisiert einen bestehenden Tag."""
|
||||
tag = tags.update_tag(request.json)
|
||||
return jsonify(tag.to_dict()), 200
|
||||
|
||||
|
||||
@app.delete("/xhr/tag/delete")
|
||||
@authorisation_required([])
|
||||
def tag_delete():
|
||||
"""Loescht einen Tag inkl. aller Nachfahren (kaskadierend) anhand seiner ID."""
|
||||
tags.delete_tag(int(request.args.get("id")))
|
||||
return jsonify({}), 200
|
||||
|
||||
|
||||
print("########## crm.routes importiert")
|
||||
Reference in new issue
Block a user