# Schritt 2: Interface erstellen [← Zurück: Datenmodell erstellen](02-datamodels.md) | [Weiter: Feature-Logik implementieren →](04-feature-logic.md) ## Übersicht: Was sind Interfaces? **Interfaces** sind aktive Klassen, die den **Datenbankzugriff** implementieren. Sie unterscheiden sich von **Datamodels** (die nur die Datenstruktur definieren): | **Aspekt** | **Datamodels** | **Interfaces** | |------------|----------------|----------------| | **Zweck** | Definiert **WAS** (Datenstruktur) | Implementiert **WIE** (Datenzugriff) | | **Inhalt** | Pydantic-Modelle mit Feldern und Validierung | Klassen mit CRUD-Methoden (`create`, `get`, `update`, `delete`) | | **Beispiel** | `class Projekt(BaseModel): ...` | `def createProjekt(...) -> Projekt: ...` | | **Aktivität** | Passiv (nur Struktur) | Aktiv (führt Operationen aus) | **Analogie:** - **Datamodel** = Bauplan (beschreibt das Haus) - **Interface** = Bauunternehmer (baut das Haus) --- ## Struktur: Real Estate CRUD-Interface Da das Feature **stateless** arbeitet, benötigen wir nur **ein Interface** für CRUD-Operationen auf Real Estate-Entitäten: ### Real Estate-Datenmodelle → Real Estate CRUD-Interface **Datamodel:** `datamodelRealEstate.py` - `Projekt` - `Parzelle` - `Dokument` - `Kanton`, `Gemeinde`, `Land` - `GeoPolylinie`, `GeoPunkt` - `Kontext` - etc. **Interface:** `interfaceDbRealEstateObjects.py` - `RealEstateObjects` (Haupt-Interface) - `RealEstateAccess` (Zugriffskontrolle) - Methoden: `createProjekt()`, `getParzelle()`, `updateDokument()`, etc. **Hinweis:** Das Haupt-Interface enthält auch `executeQuery()` für direkte SQL-Queries (stateless) --- ## Warum nur ein Haupt-Interface? 1. **Stateless Design**: - Keine Session-Verwaltung notwendig - Direkte CRUD-Operationen auf Real Estate-Modellen 2. **Einfache Architektur**: - Ein Interface für alle CRUD-Operationen - Weniger Komplexität, bessere Wartbarkeit 3. **Query-Funktionalität**: - `executeQuery()` ist direkt im Haupt-Interface verfügbar - Für direkte SQL-Queries (stateless) - Keine Session-Management-Funktionen --- ## Zu erstellende Dateien ### Schritt 2a: Real Estate CRUD-Interface (ERFORDERLICH) **Zwei separate Dateien** (wie bei anderen Features): #### Datei 1: `modules/interfaces/interfaceDbRealEstateAccess.py` **Enthält:** - `RealEstateAccess` - Zugriffskontrolle für Real Estate-Entitäten - Methoden: `uam()`, `canModify()` **Zweck:** Prüft Zugriffsrechte und filtert Daten basierend auf Benutzerprivilegien #### Datei 2: `modules/interfaces/interfaceDbRealEstateObjects.py` **Enthält:** - `RealEstateObjects` - Haupt-Interface für CRUD-Operationen - `getInterface()` - Factory-Funktion - Nutzt `RealEstateAccess` aus der Access-Datei **Zweck:** Verwaltet Real Estate-Entitäten (Projekt, Parzelle, Dokument, etc.) **Nutzt:** - `datamodelRealEstate.py` (Projekt, Parzelle, Dokument, etc.) - `interfaceDbRealEstateAccess.py` (für Zugriffskontrolle) **Wann benötigt:** Für alle CRUD-Operationen auf Real Estate-Entitäten (z.B. Projekte erstellen/bearbeiten, Parzellen verwalten). Dies ist das Haupt-Interface für das Feature. --- ## Übersicht: Dateien und ihre Beziehungen ``` ┌─────────────────────────────────────────────────────────────┐ │ DATAMODELS (Struktur) │ ├─────────────────────────────────────────────────────────────┤ │ datamodelRealEstate.py │ │ ├── Projekt │ │ ├── Parzelle │ │ ├── Dokument │ │ ├── Kanton, Gemeinde, Land │ │ ├── GeoPolylinie, GeoPunkt │ │ ├── Kontext │ │ └── ... │ └─────────────────────────────────────────────────────────────┘ │ │ nutzt ▼ ┌─────────────────────────────────────────────────────────────┐ │ INTERFACES (Zugriff) │ ├─────────────────────────────────────────────────────────────┤ │ REAL ESTATE CRUD-INTERFACE (ERFORDERLICH) │ │ │ │ interfaceDbRealEstateAccess.py │ │ └── RealEstateAccess │ │ ├── uam() │ │ └── canModify() │ │ │ │ interfaceDbRealEstateObjects.py │ │ ├── RealEstateObjects │ │ │ ├── createProjekt() │ │ │ ├── getProjekt() │ │ │ ├── updateProjekt() │ │ │ ├── deleteProjekt() │ │ │ ├── createParzelle() │ │ │ ├── getParzelle() │ │ │ └── ... (CRUD für alle Entitäten) │ │ └── getInterface() │ │ └── nutzt RealEstateAccess │ │ │ │ │ │ HINWEIS: executeQuery() ist im Haupt-Interface verfügbar │ │ (kein separates Chat-Interface notwendig) │ └─────────────────────────────────────────────────────────────┘ ``` --- ## Interface-Struktur: Access vs. Objects Jedes Interface besteht aus **zwei Klassen**: ### 1. `*Access` Klasse (Zugriffskontrolle) **Zweck:** Prüft, wer was sehen/dürfen darf **Methoden:** - `uam()` - Filtert Daten basierend auf Benutzerprivilegien - `canModify()` - Prüft, ob Benutzer ändern darf **Beispiel:** `RealEstateAccess` ### 2. `*Objects` Klasse (Haupt-Interface) **Zweck:** Führt CRUD-Operationen aus **Methoden:** - `create*()` - Erstellt neue Einträge - `get*()` - Lädt einzelne Einträge nach ID - `get*()` (Plural) - Lädt Listen von Einträgen mit optionalen Filtern - `update*()` - Aktualisiert Einträge - `delete*()` - Löscht Einträge - `executeQuery()` - Führt direkte SQL-Queries aus (stateless) **Nutzt:** `*Access` für Zugriffskontrolle **Beispiel:** `RealEstateObjects` **Warum getrennt?** - Separation of Concerns: Zugriffskontrolle ist separate Verantwortlichkeit - Wiederverwendbarkeit: Access-Klasse kann von mehreren Interfaces genutzt werden - Testbarkeit: Zugriffskontrolle kann unabhängig getestet werden --- ## Implementierung: Real Estate CRUD-Interface Das Real Estate CRUD-Interface besteht aus **zwei separaten Dateien**, genau wie bei anderen Features (`interfaceDbAppObjects.py` + `interfaceDbAppAccess.py`). ### Datei 1: Access-Implementierung **Datei:** `modules/interfaces/interfaceDbRealEstateAccess.py` **Enthält:** - `RealEstateAccess` Klasse - Methoden: `uam()`, `canModify()` **Funktionalität:** - **`uam()`**: Filtert Datensätze basierend auf Benutzerprivilegien (SYSADMIN sieht alles, ADMIN sieht Mandat, User sieht nur eigene) - **`canModify()`**: Prüft, ob Benutzer Datensätze ändern/löschen darf - Fügt Zugriffskontroll-Attribute hinzu: `_hideView`, `_hideEdit`, `_hideDelete` --- ### Datei 2: Objects-Implementierung **Datei:** `modules/interfaces/interfaceDbRealEstateObjects.py` **Enthält:** - `RealEstateObjects` Klasse (Haupt-Interface) - `getInterface()` Factory-Funktion (Singleton-Pattern) **Datenbank-Konfiguration:** - Verwendet `DB_REALESTATE_*` Umgebungsvariablen (nicht `DB_APP_*`) - Variablen: `DB_REALESTATE_HOST`, `DB_REALESTATE_DATABASE`, `DB_REALESTATE_USER`, `DB_REALESTATE_PASSWORD_SECRET`, `DB_REALESTATE_PORT` **CRUD-Methoden für alle Entitäten:** - **Projekt**: `createProjekt()`, `getProjekt()`, `getProjekte()`, `updateProjekt()`, `deleteProjekt()` - **Parzelle**: `createParzelle()`, `getParzelle()`, `getParzellen()`, `updateParzelle()`, `deleteParzelle()` - **Dokument**: `createDokument()`, `getDokument()`, `getDokumente()`, `updateDokument()`, `deleteDokument()` - **Gemeinde**: `createGemeinde()`, `getGemeinde()`, `getGemeinden()`, `updateGemeinde()`, `deleteGemeinde()` - **Kanton**: `createKanton()`, `getKanton()`, `getKantone()`, `updateKanton()`, `deleteKanton()` - **Land**: `createLand()`, `getLand()`, `getLaender()`, `updateLand()`, `deleteLand()` **Zusätzliche Funktionalität:** - **List-Methoden**: Alle Entitäten haben `get*()` (Plural) Methoden für Listen mit optionalen Filtern - **Location-Resolution**: `getParzellen()` löst automatisch Gemeinde-Namen zu IDs auf - **Query-Ausführung**: `executeQuery()` für direkte SQL-Queries (stateless) - **Supporting Tables**: Automatische Erstellung von Land, Kanton, Gemeinde, Dokument Tabellen bei Initialisierung ## Wichtige Punkte: 1. **DatabaseConnector**: Nutzt `connectorDbPostgre.DatabaseConnector` für Datenbankzugriff 2. **Access Control**: `RealEstateAccess` implementiert Benutzer- und Mandaten-Filterung 3. **Singleton Pattern**: `getInterface()` erstellt pro User eine Instanz 4. **CRUD-Operationen**: `recordCreate`, `recordModify`, `recordDelete`, `getRecordset` vom Connector 5. **MandateId**: Wird automatisch gesetzt, wenn nicht vorhanden 6. **List-Methoden**: Alle Entitäten haben `get*()` (Plural) Methoden für Listen mit optionalen Filtern 7. **Location-Resolution**: Parzelle-Filter können Gemeinde-Namen enthalten, die automatisch zu IDs aufgelöst werden 8. **Query-Ausführung**: `executeQuery()` ist direkt im Haupt-Interface verfügbar (kein separates Chat-Interface notwendig) 9. **Datenbank-Initialisierung**: Unterstützende Tabellen (Land, Kanton, Gemeinde, Dokument) werden automatisch erstellt --- ## Query-Ausführung: executeQuery() Das Haupt-Interface `RealEstateObjects` enthält die Methode `executeQuery()` für direkte SQL-Queries. **Kein separates Chat-Interface ist notwendig.** ### Verwendung **Für CRUD-Operationen (EMPFOHLEN):** - Verwenden Sie die strukturierten CRUD-Methoden (`createProjekt()`, `getProjekte()`, etc.) - Vorteile: Validierung, Zugriffskontrolle, Typsicherheit, keine SQL-Injection-Risiken **Für komplexe SELECT-Queries (OPTIONAL):** - Verwenden Sie `executeQuery()` direkt im Haupt-Interface - **Warnung**: Nur für SELECT-Queries, immer Parameterisierung verwenden, Queries validieren ### Hinweise zur Query-Ausführung 1. **Stateless**: Keine Session-Management-Funktionen 2. **Nur für Queries**: Primär für SELECT-Queries gedacht 3. **Sicherheit**: Immer Parameterisierung verwenden 4. **Validierung**: Queries sollten validiert werden (z.B. nur SELECT erlauben) --- ## Zusammenfassung: Benötigte Dateien ### Erforderlich (für CRUD-Operationen): 1. ✅ `modules/datamodels/datamodelRealEstate.py` - Real Estate-Datenmodelle (Projekt, Parzelle, Dokument, etc.) 2. ✅ `modules/interfaces/interfaceDbRealEstateAccess.py` - Zugriffskontrolle für Real Estate-Entitäten (RealEstateAccess) 3. ✅ `modules/interfaces/interfaceDbRealEstateObjects.py` - Real Estate CRUD-Interface (RealEstateObjects) - Nutzt `interfaceDbRealEstateAccess.py` - Haupt-Interface für alle CRUD-Operationen ### Hinweis zu Query-Ausführung: 4. ✅ `executeQuery()` ist bereits im Haupt-Interface verfügbar - Kein separates Chat-Interface notwendig - Direkt in `RealEstateObjects` verfügbar - Stateless, keine Session-Management --- [← Zurück: Datenmodell erstellen](02-datamodels.md) | [Weiter: Feature-Logik implementieren →](04-feature-logic.md)