feat: Kontakt-/Stammdaten je Organisation (organizations)

Neue Spalten kontakt_name, adresse, telefon, kontakt_email, notizen -
bewusst nur einfache Kontaktdaten, keine Richtlinien-/Sicherheitsfelder
(Network Profile/Secret Reference bleiben laut ADR-0001 weiterhin
unspezifiziert, eigenständiges Thema). Bestehender PATCH-Endpoint
(/api/v1/organizations/{id}) wird nur breiter, keine neue Route.

fetch_organizations() (Liste, fuer den Admin-Bereich) und
fetch_organization() (Einzelabruf, fuer Self-Service) beide erweitert,
damit intern und im Kundenportal dieselben Daten sichtbar sind.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Thomas Stallinger 2026-08-20 07:39:50 +02:00
parent e5b7081955
commit 34e5254984
2 changed files with 74 additions and 9 deletions

67
app.py
View File

@ -90,6 +90,11 @@ class CreateOrganizationRequest(BaseModel):
class UpdateOrganizationRequest(BaseModel):
name: str
kontakt_name: str | None = None
adresse: str | None = None
telefon: str | None = None
kontakt_email: str | None = None
notizen: str | None = None
class CreateMerkmalRequest(BaseModel):
@ -1604,22 +1609,42 @@ def archive_device(device_id: str) -> bool:
)
return cur.fetchone() is not None
ORGANIZATION_KONTAKTFELDER = ("kontakt_name", "adresse", "telefon", "kontakt_email", "notizen")
def fetch_organizations():
with get_database_connection() as conn:
with conn.cursor() as cur:
cur.execute(
"SELECT id, name, created_at FROM organizations ORDER BY name"
"""
SELECT id, name, created_at, kontakt_name, adresse, telefon, kontakt_email, notizen
FROM organizations ORDER BY name
"""
)
return [
{"id": str(org_id), "name": name, "created_at": created_at.isoformat()}
for org_id, name, created_at in cur.fetchall()
{
"id": str(org_id),
"name": name,
"created_at": created_at.isoformat(),
"kontakt_name": kontakt_name,
"adresse": adresse,
"telefon": telefon,
"kontakt_email": kontakt_email,
"notizen": notizen,
}
for (
org_id, name, created_at,
kontakt_name, adresse, telefon, kontakt_email, notizen,
) in cur.fetchall()
]
def fetch_organization(organization_id: str):
with get_database_connection() as conn:
with conn.cursor() as cur:
cur.execute(
"SELECT id, name, created_at FROM organizations WHERE id = %s",
"""
SELECT id, name, created_at, kontakt_name, adresse, telefon, kontakt_email, notizen
FROM organizations WHERE id = %s
""",
(organization_id,),
)
row = cur.fetchone()
@ -1627,7 +1652,16 @@ def fetch_organization(organization_id: str):
if row is None:
return None
return {"id": str(row[0]), "name": row[1], "created_at": row[2].isoformat()}
return {
"id": str(row[0]),
"name": row[1],
"created_at": row[2].isoformat(),
"kontakt_name": row[3],
"adresse": row[4],
"telefon": row[5],
"kontakt_email": row[6],
"notizen": row[7],
}
def create_organization(name: str):
organization_id = uuid4()
@ -1652,12 +1686,26 @@ def create_organization(name: str):
return {"id": str(organization_id), "name": name}
def update_organization(organization_id: str, name: str):
def update_organization(organization_id: str, name: str, kontaktfelder: dict):
with get_database_connection() as conn:
with conn.cursor() as cur:
cur.execute(
"UPDATE organizations SET name = %s WHERE id = %s RETURNING id, name",
(name, organization_id),
"""
UPDATE organizations
SET name = %s, kontakt_name = %s, adresse = %s, telefon = %s,
kontakt_email = %s, notizen = %s
WHERE id = %s
RETURNING id, name
""",
(
name,
kontaktfelder.get("kontakt_name"),
kontaktfelder.get("adresse"),
kontaktfelder.get("telefon"),
kontaktfelder.get("kontakt_email"),
kontaktfelder.get("notizen"),
organization_id,
),
)
row = cur.fetchone()
@ -2691,7 +2739,8 @@ def update_organization_endpoint(
"message": "Fehlendes oder ungültiges Service-Token.",
}
organization = update_organization(organization_id, payload.name)
kontaktfelder = {feld: getattr(payload, feld) for feld in ORGANIZATION_KONTAKTFELDER}
organization = update_organization(organization_id, payload.name, kontaktfelder)
if organization is None:
return {

View File

@ -0,0 +1,16 @@
BEGIN;
-- Kontakt-/Stammdaten je Organisation (Ansprechpartner, Adresse, Telefon,
-- Kontakt-E-Mail, Notizen) - bislang hatte organizations ausser dem Namen
-- keine Felder. Bewusst nur einfache Stammdaten, keine Richtlinien-/
-- Sicherheitsfelder (Network Profile/Secret Reference bleiben laut
-- ADR-0001/09-data-model-v1.md weiterhin unspezifiziert, eigenstaendiges
-- Thema). Alle Spalten nullable - kein Pflichtfeld, bestehende und neue
-- Organisationen starten leer.
ALTER TABLE organizations ADD COLUMN kontakt_name TEXT;
ALTER TABLE organizations ADD COLUMN adresse TEXT;
ALTER TABLE organizations ADD COLUMN telefon TEXT;
ALTER TABLE organizations ADD COLUMN kontakt_email TEXT;
ALTER TABLE organizations ADD COLUMN notizen TEXT;
COMMIT;