Server: CRM-Domain mit REST-API, Autorisierung und CLI
Neues crm-Paket mit Datenmodell, Geschäftslogik und REST-Endpunkten
für die Entität Kunde (/xhr/kunde/{list,get,create,update,delete}).
authorisation_required-Decorator: app-spezifische Rollenprüfung via
has_permission(appid, ...). SysAdmin systemweit, AppAdmin implizit in
seiner Anwendung, User (Mitarbeiter) als Basis-Rolle, Zusatz-Rollen
wie KundenManager additiv.
Flask CLI: init-db (Schema + Musterdaten + App-Rollen) und reset-db
(Bestätigung, behält SysAdmin).
config.ini: Neuer appid-Eintrag (KBPlusCRM), getrennt vom technischen
PROJEKTNAME. checkdb: appid aus config, Migration _db_V01_02 für
bestehende DBs.
Generated by Mistral Vibe.
Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
This commit is contained in:
1 parent
65f81a0ee8
commit
13eaaec9c1
12 files changed
+627
-8
No files matched your search
@@ -0,0 +1,91 @@
|
||||
"""
|
||||
Geschäftslogik für die Entität Kunde.
|
||||
|
||||
Diese Funktionen kapseln den DB-Zugriff und die fachlichen Validierungen.
|
||||
Aufgerufen werden sie aus crm/routes.py; die Autorisierungsprüfung erfolgt
|
||||
dort über den Decorator authorisation_required.
|
||||
|
||||
:author: Mistral Vibe <vibe@mistral.ai>
|
||||
:date: 2026-09-02
|
||||
:version: 1.0
|
||||
"""
|
||||
from db import dbapp
|
||||
from crm.model import Kunde
|
||||
|
||||
from auth.model.errors import ApplicationError, HtmlStatusCode
|
||||
|
||||
session = dbapp.session
|
||||
|
||||
|
||||
def get_kunden():
|
||||
"""
|
||||
Liefert alle Kunden, sortiert nach Name.
|
||||
"""
|
||||
return Kunde.query.order_by(Kunde.name).all()
|
||||
|
||||
|
||||
def get_kunde(kunde_id: int) -> Kunde:
|
||||
"""
|
||||
Liefert einen einzelnen Kunden anhand seiner ID.
|
||||
Wirft ApplicationError (404), falls der Kunde nicht existiert.
|
||||
"""
|
||||
kunde = Kunde.query.get(kunde_id)
|
||||
if kunde is None:
|
||||
raise ApplicationError(
|
||||
"Kunde mit der ID {} wurde nicht gefunden.".format(kunde_id),
|
||||
htmlstatus=HtmlStatusCode.Not_Found,
|
||||
)
|
||||
return kunde
|
||||
|
||||
|
||||
def create_kunde(data: dict) -> Kunde:
|
||||
"""
|
||||
Legt einen neuen Kunden an. Die vom Client übergebene ID wird ignoriert;
|
||||
die ID wird serverseitig per Auto-Increment vergeben.
|
||||
|
||||
- data: dict mit den Feldern name, strasse, plz, ort, land
|
||||
"""
|
||||
if not data.get("name") or not str(data["name"]).strip():
|
||||
raise ApplicationError(
|
||||
"Der Kundenname darf nicht leer sein.",
|
||||
htmlstatus=HtmlStatusCode.Bad_Request,
|
||||
)
|
||||
kunde = Kunde()
|
||||
kunde.name = data["name"].strip()
|
||||
kunde.strasse = data.get("strasse") or None
|
||||
kunde.plz = data.get("plz") or None
|
||||
kunde.ort = data.get("ort") or None
|
||||
kunde.land = data.get("land") or None
|
||||
session.add(kunde)
|
||||
session.commit()
|
||||
return kunde
|
||||
|
||||
|
||||
def update_kunde(data: dict) -> Kunde:
|
||||
"""
|
||||
Aktualisiert einen bestehenden Kunden. Die ID im data-Dict bestimmt den
|
||||
zu ändernden Datensatz.
|
||||
"""
|
||||
kunde = get_kunde(data["id"])
|
||||
if not data.get("name") or not str(data["name"]).strip():
|
||||
raise ApplicationError(
|
||||
"Der Kundenname darf nicht leer sein.",
|
||||
htmlstatus=HtmlStatusCode.Bad_Request,
|
||||
)
|
||||
kunde.name = data["name"].strip()
|
||||
kunde.strasse = data.get("strasse") or None
|
||||
kunde.plz = data.get("plz") or None
|
||||
kunde.ort = data.get("ort") or None
|
||||
kunde.land = data.get("land") or None
|
||||
session.commit()
|
||||
return kunde
|
||||
|
||||
|
||||
def delete_kunde(kunde_id: int):
|
||||
"""
|
||||
Löscht einen Kunden anhand seiner ID.
|
||||
Wirft ApplicationError (404), falls der Kunde nicht existiert.
|
||||
"""
|
||||
kunde = get_kunde(kunde_id)
|
||||
session.delete(kunde)
|
||||
session.commit()
|
||||
Reference in new issue
Block a user