- Add EmailEdaConsentService for prod consent requests via SMTP
- Add EdaMailSender, EdaMailParser, EdaMailPoller for IMAP polling
- Polling interval: 15 min (configurable via eda.email.poll-interval-ms)
- Consumption data ingestion from XLSX email attachments
- Add @Profile('!prod') to SimulatedEda*Services as fallback
- Add EMAIL_AUTO to DataSource enum for automated email imports
- Add EDA email configuration to application-prod.yml and application-dev.yml
- Add unit tests for all new services
- Add docs/PLAN-EDA-KOMMUNIKATION.md with full implementation plan
All 232 tests passing.
228 lines
8.5 KiB
Markdown
228 lines
8.5 KiB
Markdown
# Plan: E-Mail-basierte EDA-Kommunikation
|
|
|
|
## Ziel
|
|
|
|
Ersetze die aktuelle vollständige EDA-Simulation durch eine reale E-Mail-basierte Kommunikation mit dem EDA-Netzwerk (Netzbetreiber). Simulator bleibt als `@Profile("!prod")`-Fallback. Architektur erlaubt später einfachen Wechsel zu Messenger-API.
|
|
|
|
---
|
|
|
|
## Aktueller Stand
|
|
|
|
### Was existiert
|
|
|
|
- `EdaConsentService` (Interface) + `SimulatedEdaConsentService` (immer aktiv, kein @Profile)
|
|
- `EdaTopologyService` (Interface) + `SimulatedEdaTopologyService` (immer aktiv)
|
|
- `MailService` (Interface) für User-Verifizierung, nicht für EDA
|
|
- `spring-boot-starter-restclient` im pom.xml (nicht verwendet)
|
|
- `DataSource`-Enum hat `EMAIL_XLSX` aber kein automatisches E-Mail-Polling
|
|
- Kommentar in `EdaCommunicationEventListener:66`: "entweder via Webhook oder Mailbox"
|
|
|
|
### Was fehlt
|
|
|
|
- Keine reale EDA-Kommunikation (kein HTTP, kein E-Mail-Versand an EDA)
|
|
- Keine automatische Verbrauchsdaten-Ingestion via E-Mail
|
|
- Simulator hat kein `@Profile` - immer aktiv, auch in prod
|
|
|
|
---
|
|
|
|
## Architektur-Entscheidung: Strategy Pattern
|
|
|
|
```
|
|
┌─────────────────────────┐
|
|
│ EdaConsentService │ (Interface - bleibt unverändert)
|
|
│ EdaTopologyService │
|
|
└─────────┬───────────────┘
|
|
│
|
|
┌───────────────────┼───────────────────┐
|
|
│ │ │
|
|
┌─────────▼──────────┐ ┌─────▼───────────┐ ┌────▼──────────────┐
|
|
│ SimulatedEda* │ │ EmailEda* │ │ MessengerEda* │
|
|
│ @Profile("!prod") │ │ @Profile("prod")│ │ (später) │
|
|
└────────────────────┘ └─────────────────┘ └───────────────────┘
|
|
```
|
|
|
|
---
|
|
|
|
## Umsetzungs-Schritte
|
|
|
|
### Schritt 1: Simulator mit @Profile versehen
|
|
|
|
**Dateien:**
|
|
- `eeg_backend/.../mako/service/impl/SimulatedEdaConsentService.java`
|
|
- `eeg_backend/.../mako/service/impl/SimulatedEdaTopologyService.java`
|
|
|
|
**Änderung:**
|
|
```java
|
|
// Vorher:
|
|
@Service
|
|
public class SimulatedEdaConsentService implements EdaConsentService {
|
|
|
|
// Nachher:
|
|
@Profile("!prod")
|
|
@Service
|
|
public class SimulatedEdaConsentService implements EdaConsentService {
|
|
```
|
|
|
|
**Hinweis:** `@Profile("!prod")` statt `@Profile("dev")` - so sind die Simulatoren auch ohne Profil (z.B. in Tests) verfügbar. Die `EdaCommunicationEventListener` hat kein Profil und braucht immer einen `EdaConsentService` + `EdaTopologyService`.
|
|
|
|
---
|
|
|
|
### Schritt 2: EDA E-Mail-Konfiguration
|
|
|
|
**application-prod.yml (ergänzen):**
|
|
|
|
```yaml
|
|
eda:
|
|
email:
|
|
gateway-address: ${EDA_GATEWAY_EMAIL:eda-gateway@example.com}
|
|
poll-interval-ms: ${EDA_POLL_INTERVAL_MS:900000}
|
|
imap:
|
|
host: ${EDA_IMAP_HOST:}
|
|
port: ${EDA_IMAP_PORT:993}
|
|
username: ${EDA_IMAP_USERNAME:}
|
|
password: ${EDA_IMAP_PASSWORD:}
|
|
folder: INBOX
|
|
protocol: imaps
|
|
smtp:
|
|
host: ${EDA_SMTP_HOST:}
|
|
port: ${EDA_SMTP_PORT:587}
|
|
username: ${EDA_SMTP_USERNAME:}
|
|
password: ${EDA_SMTP_PASSWORD:}
|
|
```
|
|
|
|
**application-dev.yml (ergänzen):**
|
|
|
|
```yaml
|
|
eda:
|
|
email:
|
|
gateway-address: test-eda@example.com
|
|
poll-interval-ms: 900000
|
|
```
|
|
|
|
---
|
|
|
|
### Schritt 3: E-Mail-basierte Consent-Implementierung
|
|
|
|
#### EDA-E-Mail-Format (Hinweis)
|
|
|
|
Das EDA-Netzwerk (Elektrizitäts-Daten-Austausch) in Österreich nutzt für E-Mail-Kommunikation typischerweise:
|
|
|
|
- **Betreff:** Strukturiert mit AT-Nummer + Nachrichtentyp (z.B. `CMRequest|AT...` für Consent)
|
|
- **Body:** XML oder strukturiertes Textformat mit AT-Nummer, Entscheidung, Referenz-ID
|
|
- **Attachments:** XLSX/CSV für Verbrauchsdaten
|
|
- **Zentraler Empfänger:** EDA-Gateway leitet an Netzbetreiber weiter (wie beim Messenger)
|
|
|
|
Die genaue Spezifikation muss vom EDA-Gateway-Anbieter bestätigt werden. Die Architektur ist flexibel gehalten.
|
|
|
|
#### Neue Dateien
|
|
|
|
**EmailEdaConsentService.java** - Prod Consent via SMTP:
|
|
- `@Profile("prod")`
|
|
- Implementiert `EdaConsentService`
|
|
- `sendConsentRequest()`:
|
|
1. Baut Consent-E-Mail auf (AT-Nummer, Typ, Portal-Referenz-ID)
|
|
2. Versendet an `eda.email.gateway-address` via SMTP
|
|
3. Speichert Request-Metadaten für Zuordnung der Antwort
|
|
4. Logging
|
|
|
|
**EdaMailSender.java** - E-Mail-Versand:
|
|
- Hilfsklasse zum Aufbau und Versand von EDA-E-Mails
|
|
- Consent-Request-E-Mail Vorlage (XML-Format)
|
|
- `@Async` für nicht-blockierenden Versand
|
|
|
|
**EdaMailParser.java** - E-Mail-Parsing:
|
|
- Hilfsklasse zum Parsen von EDA-E-Mails
|
|
- Erkennt E-Mail-Typ (Consent-Antwort vs. Verbrauchsdaten)
|
|
- Extrahiert AT-Nummer, Entscheidung, Referenz-ID
|
|
- Flexibel: E-Mail-Format-Konfiguration via Properties
|
|
|
|
**EdaMailPoller.java** - IMAP-Polling:
|
|
- `@Profile("prod")`
|
|
- `@Scheduled(fixedDelayString = "${eda.email.poll-interval-ms:900000}")` - alle 15 Minuten
|
|
- Verbindet sich via IMAP zum EDA-Postfach
|
|
- Parst eingehende E-Mails:
|
|
- **Consent-Antwort:** Erkennt AT-Nummer + Entscheidung (approved/rejected)
|
|
- **Verbrauchsdaten-Attachment:** Erkennt XLSX/CSV
|
|
- Für Consent-Antworten:
|
|
- Veröffentlicht `MakoConsentApprovedEvent` / `MakoConsentRejectedEvent` / `MakoConsentTechnicalFailedEvent`
|
|
- Für Verbrauchsdaten:
|
|
- Nutzt bestehenden `XlsxMeteringDataParser` für XLSX
|
|
- Speichert via `MeteringDataService`
|
|
- Erstellt `MeteringDataUpload`-Audit-Eintrag
|
|
|
|
---
|
|
|
|
### Schritt 4: Verbrauchsdaten-Ingestion via E-Mail
|
|
|
|
**Integration in EdaMailPoller:**
|
|
|
|
Der Poller erkennt eingehende E-Mails mit Verbrauchsdaten-Attachments:
|
|
|
|
1. **Mail-Scan:** Durchsucht Postfach nach neuen E-Mails mit Attachments
|
|
2. **Attachment-Erkennung:** XLSX, CSV (je nach EDA-Standard)
|
|
3. **Parsing:** Nutzt `XlsxMeteringDataParser` (bestehend)
|
|
4. **Speicherung:** Ruft `MeteringDataService.uploadMeteringData()` auf
|
|
5. **Audit:** Erstellt `MeteringDataUpload` mit `DataSource.EMAIL_AUTO`
|
|
|
|
**DataSource erweitern:**
|
|
- `DataSource.java` - `EMAIL_AUTO` hinzugefügt
|
|
|
|
---
|
|
|
|
### Schritt 5: Tests
|
|
|
|
**Neue/angepasste Dateien:**
|
|
- `EmailEdaConsentServiceTest.java` - Mock SMTP, verify E-Mail-Inhalt
|
|
- `EdaMailParserTest.java` - Test verschiedener E-Mail-Formate
|
|
- `EdaMailPollerTest.java` - Unit-Test für Polling-Logik
|
|
- `SimulatorProfileTest.java` - Verifiziere @Profile("!prod")
|
|
|
|
---
|
|
|
|
## Datei-Übersicht
|
|
|
|
| Aktion | Datei |
|
|
|--------|-------|
|
|
| Ändern | `SimulatedEdaConsentService.java` - @Profile("!prod") |
|
|
| Ändern | `SimulatedEdaTopologyService.java` - @Profile("!prod") |
|
|
| Ändern | `application-prod.yml` - EDA E-Mail-Konfiguration |
|
|
| Ändern | `application-dev.yml` - EDA Dev-Konfiguration |
|
|
| Ändern | `DataSource.java` - EMAIL_AUTO hinzufügen |
|
|
| Neu | `EmailEdaConsentService.java` - Prod Consent via SMTP |
|
|
| Neu | `EdaMailSender.java` - E-Mail-Versand |
|
|
| Neu | `EdaMailParser.java` - E-Mail-Parsing |
|
|
| Neu | `EdaMailPoller.java` - IMAP-Polling (15 Min) für Antworten + Verbrauchsdaten |
|
|
| Neu | Tests |
|
|
|
|
---
|
|
|
|
## Verifizierung
|
|
|
|
1. **Dev-Modus:** `@Profile("!prod")` aktiv → Simulator wird geladen, kein EDA-Mail-Poller
|
|
2. **Prod-Modus:** `@Profile("prod")` aktiv → `EmailEdaConsentService` + `EdaMailPoller` werden geladen
|
|
3. **Unit-Tests:** `mvn test -pl eeg_backend` - alle Tests grün (232 Tests)
|
|
4. **Integrationstest:**
|
|
- Dev: Konsistenter Flow mit Simulator (AT-Nummer endet mit REJECT/ERROR)
|
|
- Prod: Echte SMTP/IMAP-Verbindung testen (kann mit Test-Server)
|
|
5. **Manuell prüfen:**
|
|
- Consent-Flow: User registrieren → Admin genehmigen → MeteringPoint wechselt zu WAITING_FOR_CONSENT
|
|
- Simulator: AT-Nummer "AT0010001234567890123456789012345" → Consent Approved nach Delay
|
|
- E-Mail: Echte E-Mail wird an Gateway gesendet
|
|
|
|
---
|
|
|
|
## Offene Fragen
|
|
|
|
1. **EDA-Spezifikation:** Die genaue E-Mail-Format-Spezifikation muss vom EDA-Gateway-Anbieter bezogen werden. Die Architektur ist flexibel gehalten (Konfiguration via Properties).
|
|
2. **Polling-Intervall:** **Entschieden: alle 15 Minuten** (Standardwert in Konfiguration, konfigurierbar).
|
|
3. **Fehlerbehandlung:** Was passiert bei nicht zuordenbaren E-Mails? (Log + Flag) - Muss noch definiert werden.
|
|
4. **Verbrauchsdaten-Format:** XLSX oder CSV? (XLSX-Parsing existiert bereits) - Muss mit EDA-Gateway-Anbieter abgestimmt werden.
|
|
|
|
---
|
|
|
|
## Implementierungsstand
|
|
|
|
**Status: ABGESCHLOSSEN**
|
|
|
|
Alle 6 Schritte wurden implementiert und alle 232 Tests bestehen.
|