wiki/mandates/pek/datenmodell/README.md
ValueOn AG 15f0e51bd0 pek
2025-10-24 21:42:47 +02:00

9.6 KiB

Architektur-Planungs-App - Datenmodell

Übersicht

Dieses Repository enthält das vollständige Datenmodell für eine Schweizer Architektur-Planungs-Applikation zur Verwaltung von Bauprojekten, Parzellen, Dokumenten und regulatorischen Informationen.

📁 Dateien

1. DATENMODELL_DOKUMENTATION.md

Umfassende Dokumentation mit:

  • Detaillierte Beschreibung aller Entitäten
  • Beziehungsdiagramme
  • Implementierungshinweise
  • Use Cases
  • Best Practices
  • Offene Fragen

Empfohlene Lesereihenfolge: Zuerst diese Datei lesen!

2. datenmodell.mermaid

Visuelles ER-Diagramm zur Darstellung der Entitäten und Beziehungen.

Verwendung:

# In Visual Studio Code mit Mermaid Extension
# Oder online: https://mermaid.live/

# Datei öffnen und als Diagramm anzeigen

3. datenmodell-schema.json

JSON Schema Definition im JSON Schema Draft-07 Format.

Verwendung:

  • API-Dokumentation mit Swagger/OpenAPI
  • Validierung von JSON-Payloads
  • Code-Generierung für verschiedene Sprachen
# JSON Schema validieren
npm install -g ajv-cli
ajv validate -s datenmodell-schema.json -d beispiel-daten.json

4. models.py

Python SQLAlchemy Implementation mit PostGIS-Unterstützung.

Verwendung:

# Installation
pip install sqlalchemy geoalchemy2 psycopg2-binary --break-system-packages

# Datenbank erstellen
python models.py

# In eigener Anwendung verwenden
from models import Projekt, Parzelle, Dokument

Tech Stack:

  • Python 3.10+
  • SQLAlchemy 2.0+
  • PostgreSQL 15+ mit PostGIS 3.4+
  • GeoAlchemy2

5. schema.prisma

Prisma Schema für TypeScript/JavaScript Backend.

Verwendung:

# Installation
npm install prisma @prisma/client

# Datenbank migrieren
npx prisma migrate dev --name init

# Prisma Client generieren
npx prisma generate

# Prisma Studio öffnen
npx prisma studio

Tech Stack:

  • Node.js 18+
  • Prisma 5+
  • PostgreSQL 15+ mit PostGIS

6. migration_001_initial_schema.sql

SQL-Migrationsskript für direkte PostgreSQL-Verwendung.

Verwendung:

# PostgreSQL Datenbank erstellen
createdb architektur_app

# Migration ausführen
psql -d architektur_app -f migration_001_initial_schema.sql

# Verbinden und testen
psql architektur_app
\dt  # Tabellen anzeigen

🚀 Quick Start

Option 1: Python mit SQLAlchemy

# 1. PostgreSQL mit PostGIS aufsetzen
docker run --name postgis -e POSTGRES_PASSWORD=postgres -p 5432:5432 -d postgis/postgis:15-3.4

# 2. Dependencies installieren
pip install sqlalchemy geoalchemy2 psycopg2-binary --break-system-packages

# 3. Models verwenden
python models.py

Option 2: TypeScript mit Prisma

# 1. Projekt initialisieren
npm init -y
npm install prisma @prisma/client

# 2. Prisma konfigurieren
cp schema.prisma prisma/schema.prisma

# 3. Database URL setzen
echo "DATABASE_URL=\"postgresql://user:password@localhost:5432/architektur_app\"" > .env

# 4. Migration ausführen
npx prisma migrate dev --name init

Option 3: Direkt mit SQL

# 1. Datenbank erstellen
createdb architektur_app

# 2. Migration ausführen
psql -d architektur_app -f migration_001_initial_schema.sql

# 3. Daten einfügen und abfragen
psql architektur_app

📊 Datenmodell-Struktur

Kern-Entitäten

PROJEKT (Bauprojekt)
├── Perimeter (Parzellen)
├── Dokumente (Bauherrschaft & Planung)
├── Baulinie (geografisch)
└── Kontext-Informationen

PARZELLE (Grundstück)
├── Geografischer Kontext (Land, Kanton, Gemeinde)
├── Bauliche Parameter (AZ, BZ, Vollgeschosse, etc.)
├── Schutzzonen
├── Nachbarparzellen
└── Dokumente & Kontext

DOKUMENT (Datei oder URL)
├── Versionierung
├── Tags
└── Format

Administrative Hierarchie:
LAND → KANTON → GEMEINDE

Geografische Daten

Das Modell verwendet das Schweizer Landessystem LV95 (EPSG:2056):

  • Ostwert (X): 2'480'000 - 2'840'000
  • Nordwert (Y): 1'070'000 - 1'300'000
  • Höhe (Z): Meter über Meer

🗺️ Koordinatensystem

Alle geografischen Daten verwenden LV95 (Swiss LV95 / EPSG:2056).

Beispiel-Koordinaten (Zürich Hauptbahnhof):

X (Ost):  2'683'140
Y (Nord): 1'247'850
Z (Höhe):     408 m ü. M.

🔍 Wichtige Entscheidungen

1. Polymorphe Beziehungen

Das Kontext-Objekt kann zu verschiedenen Entitäten gehören (Projekt, Parzelle, Land, Kanton, Gemeinde). Dies ermöglicht flexible Erweiterungen ohne Schema-Änderungen.

2. Array-Felder

  • statusProzess: Ein Projekt kann mehrere Status gleichzeitig haben
  • tags: Dokumente können mehrere Tags haben
  • parzellenNummern: Parzellen können mehrere offizielle Nummern haben

3. Selbstreferenzierende Beziehungen

Parzellen referenzieren sich gegenseitig als Nachbarn (n:m Beziehung).

4. Versionierung

Dokumente haben eine versionsbezeichnung für manuelle Versionskontrolle.

5. Drei-wertiger Zustand

JaNein Enum erlaubt "", "Ja", "Nein" für unbekannte Zustände.

📋 Anwendungsfälle

UC1: Neues Projekt erstellen

# Python Beispiel
projekt = Projekt(
    label="Neubau Mehrfamilienhaus",
    status_prozess=[StatusProzess.EINGANG]
)
projekt.perimeter.append(parzelle_1)
session.add(projekt)
session.commit()

UC2: Bebaubarkeit prüfen

-- SQL Beispiel
SELECT 
    p.label,
    p.bauzone,
    p.az,
    p.bz,
    p.vollgeschoss_zahl,
    p.gebaeudehoehe_max,
    ST_Area(p.geo_umfang) as flaeche_m2
FROM v_parzelle_vollstaendig p
WHERE p.id = 'UUID';

UC3: Nachbaranalyse

// TypeScript/Prisma Beispiel
const parzelle = await prisma.parzelle.findUnique({
  where: { id: parzelleId },
  include: {
    nachbarEigentuemer_von: {
      include: { nachbar: true }
    }
  }
});

🎯 Best Practices

Geometrie-Handling

# PostGIS: Parzelle mit Polygon erstellen
from geoalchemy2.shape import from_shape
from shapely.geometry import Polygon

polygon = Polygon([
    (2683140, 1247850),
    (2683200, 1247850),
    (2683200, 1247900),
    (2683140, 1247900),
    (2683140, 1247850)
])

parzelle.geo_umfang = from_shape(polygon, srid=2056)

Kontext-Informationen

# Flexibles Hinzufügen von Kontextinformationen
kontext = Kontext(
    thema="Dienstbarkeiten",
    inhalt="Wegrecht zugunsten Parzelle 1235 entlang Ostgrenze, eingetragen am 15.03.2020",
    parzelle_id=parzelle.id
)

Dokumenten-Management

# Dokument mit Tags
dokument = Dokument(
    label="Zonenplan Gemeinde Zürich",
    versionsbezeichnung="2024-v1",
    typ=DokumentTyp.DATEI,
    format="PDF",
    dokument_referenz="/storage/docs/zonenplan-zh-2024.pdf",
    tags=[TagTyp.ZONENPLAN, TagTyp.BZO]
)

🔐 Sicherheit

Zu beachten:

  • Eigentümerdaten sind personenbezogene Daten (DSGVO/DSG)
  • Dokumente benötigen Zugriffskontrolle
  • Audit-Logging für Änderungen empfohlen
  • Geometriedaten sollten validiert werden

Empfohlene Maßnahmen:

-- Audit-Log Tabelle hinzufügen
CREATE TABLE audit_log (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    table_name VARCHAR(100) NOT NULL,
    record_id UUID NOT NULL,
    action VARCHAR(20) NOT NULL,
    changed_by UUID NOT NULL,
    changed_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    old_values JSONB,
    new_values JSONB
);

📈 Performance-Optimierung

Indices sind bereits erstellt für:

  • Geografische Suchen (GIST Index auf Geometrien)
  • Array-Suchen (GIN Index auf Arrays)
  • Foreign Key Joins

Zusätzliche Optimierungen:

-- Materialized View für häufige Reports
CREATE MATERIALIZED VIEW mv_projekt_statistik AS
SELECT 
    k.label as kanton,
    COUNT(DISTINCT pr.id) as anzahl_projekte,
    COUNT(DISTINCT pa.id) as anzahl_parzellen,
    SUM(ST_Area(pa.geo_umfang)) as gesamtflaeche_m2
FROM projekt pr
JOIN projekt_parzelle pp ON pr.id = pp.projekt_id
JOIN parzelle pa ON pp.parzelle_id = pa.id
JOIN kanton k ON pa.kanton_id = k.id
GROUP BY k.label;

-- Refresh periodisch
REFRESH MATERIALIZED VIEW mv_projekt_statistik;

🧪 Testing

Unit Tests

# pytest Beispiel
def test_parzelle_creation():
    parzelle = Parzelle(
        label="Test Parzelle",
        parzellen_nummern=["1234"],
        az=1.5,
        bz=0.4
    )
    assert parzelle.label == "Test Parzelle"
    assert parzelle.az == 1.5

Integration Tests

// Jest Beispiel
describe('Projekt API', () => {
  it('should create projekt with parzellen', async () => {
    const projekt = await createProjekt({
      label: 'Test Projekt',
      perimeter: [parzelle1.id, parzelle2.id]
    });
    expect(projekt.perimeter).toHaveLength(2);
  });
});

📚 Weitere Ressourcen

🤝 Nächste Schritte

  1. Validierung: Review mit Architekten und Fachexperten
  2. API-Design: RESTful oder GraphQL API implementieren
  3. Frontend-Prototyp: Kartenansicht mit Leaflet/MapLibre
  4. GIS-Integration: Anbindung an Swisstopo-APIs
  5. Workflow-Engine: Statusübergänge und Genehmigungen
  6. Benutzer-Management: Rollen und Berechtigungen

📞 Support

Bei Fragen zum Datenmodell:

  • Öffne ein Issue im Repository
  • Konsultiere die DATENMODELL_DOKUMENTATION.md
  • Prüfe die Beispiel-Implementierungen in models.py oder schema.prisma

📝 License

[Lizenz hier einfügen]


Version: 1.0
Letzte Aktualisierung: 2025-10-24
Koordinatensystem: LV95 (EPSG:2056)
Datenbank: PostgreSQL 15+ mit PostGIS 3.4+