# 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:** ```bash # 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 ```bash # 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:** ```bash # 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:** ```bash # 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:** ```bash # 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 ```bash # 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 ```bash # 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 ```bash # 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 # 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 -- 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 // TypeScript/Prisma Beispiel const parzelle = await prisma.parzelle.findUnique({ where: { id: parzelleId }, include: { nachbarEigentuemer_von: { include: { nachbar: true } } } }); ``` ## 🎯 Best Practices ### Geometrie-Handling ```python # 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 ```python # 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 ```python # 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: ```sql -- 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: ```sql -- 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 ```python # 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 ```typescript // 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 - [PostGIS Dokumentation](https://postgis.net/docs/) - [SQLAlchemy ORM](https://docs.sqlalchemy.org/) - [Prisma Dokumentation](https://www.prisma.io/docs/) - [Swisstopo - Schweizer Koordinatensysteme](https://www.swisstopo.admin.ch/de/wissen-fakten/geodaesie-vermessung/bezugsrahmen/lokal/lv95.html) ## 🤝 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+