customer cases soluttion architecture
This commit is contained in:
parent
d6f0b824bf
commit
c3e1eb74e8
10 changed files with 1528 additions and 989 deletions
|
|
@ -1,572 +0,0 @@
|
|||
<!-- status: plan -->
|
||||
<!-- started: 2026-04-16 -->
|
||||
<!-- component: gateway | ui-nyla | platform -->
|
||||
<!-- replaces: local/notes/demo-tue-use-cases-inputs-customers.md, c-work/1-plan/2026-04-demo2-merged-customer-trustee-plan.md, c-work/1-plan/2026-04-porta-ui-enhancements-team-meeting.md -->
|
||||
|
||||
# Konsolidierter Kundenwünsche-Plan — PORTA Umsetzung
|
||||
|
||||
> **Stand:** 16. April 2026 (aktualisiert mit PWG-Workshop-Ergebnissen)
|
||||
> **Zweck:** Einheitliche Übersicht aller Kundenwünsche, priorisiert und gegen die Codebase abgeglichen.
|
||||
> **Ersetzt:** `local/notes/demo-tue-use-cases-inputs-customers.md`, `c-work/1-plan/2026-04-demo2-merged-customer-trustee-plan.md`, `c-work/1-plan/2026-04-porta-ui-enhancements-team-meeting.md`
|
||||
|
||||
---
|
||||
|
||||
## Kunden-Übersicht
|
||||
|
||||
| Kunde | Branche | Kontakte | Hauptinteresse | Status |
|
||||
|-------|---------|----------|----------------|--------|
|
||||
| **Bling** | Treuhandbüro | KJS | Belegverarbeitung, Budget, Dashboards, Mandantenmanagement | Trial geplant |
|
||||
| **PWG** (Stiftung) | Immobilien/Wohnen (~300 Liegenschaften, 7–8 Pers.) | MB | **Pilot: Jahresmietzinsbestätigungen** (3'200/Jahr), Belegverarbeitung Abacus, CommCoach, Neutralisierung, Knowledge-Retrieval | Workshop 16.04.2026 ✅ — Pilot bestätigt, Versand Sommer 2026 |
|
||||
| **Quid / ServiceHunter** | SaaS/Dienstleistung | DC | KPI-Dashboard, Zeiterfassung, Prognosen, Konsolidierung | Follow-up geplant |
|
||||
|
||||
---
|
||||
|
||||
## Legende Codebase-Status
|
||||
|
||||
| Symbol | Bedeutung |
|
||||
|--------|-----------|
|
||||
| ✅ | Im Code vorhanden und funktional |
|
||||
| 🔧 | Grundstruktur vorhanden, Anpassung/Ergänzung nötig |
|
||||
| ❌ | Noch nicht umgesetzt |
|
||||
| ⏸️ | Bewusst zurückgestellt (wartet auf Input/Entscheid) |
|
||||
|
||||
---
|
||||
|
||||
## Teil 1: Feature-Anforderungen (Kunden-Use-Cases)
|
||||
|
||||
### 1.1 Automatisierte Belegverarbeitung & Spesenverwaltung
|
||||
|
||||
**Kunden:** Bling (Prio hoch), PWG, Quid (Spesen)
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.1.1 | Spesenbelege per Foto → automatische Klassifikation (Rechnung, Spesenbeleg, Bankauszug) | ✅ | `methodTrustee/actions/extractFromFiles.py` + `processDocuments.py` — Pipeline extrahiert, klassifiziert, verbucht |
|
||||
| 1.1.2 | SharePoint-Synchronisation (automatisch, z.B. täglich 22:00) | ✅ | `nodeDefinitions/sharepoint.py` — 6 Nodes; `automation2/scheduleCron.py` für Zeitsteuerung; System-Template "Treuhand: PDF-Klassifizierung & Trustee-Import" in `interfaceBootstrap.py` |
|
||||
| 1.1.3 | Automatische Kontierung basierend auf Kontoplan | ✅ | In `processDocuments.py` — AI-gestützte Kontierung gegen Feature-Daten (Kontoplan via Accounting-Bridge) |
|
||||
| 1.1.4 | Firmen-Mapping zu Kunden/Lieferanten | 🔧 | Grundstruktur in Accounting-Bridge; kein dediziertes Mapping-UI oder regelbasiertes Matching |
|
||||
| 1.1.5 | Optionales Tagging (z.B. "Fuel Station") | 🔧 | Tags auf Dokument-Ebene möglich; kein Beleg-spezifisches Tag-System |
|
||||
| 1.1.6 | Buchungsregeln für wiederkehrende Belege | ❌ | Kein regelbasiertes Booking-Template-System |
|
||||
| 1.1.7 | Vorsteuer automatisch hinterlegen und auslesen | 🔧 | Accounting-Connectors liefern Steuerdaten; automatische MWST-Zuordnung bei Belegverarbeitung nicht explizit |
|
||||
| 1.1.8 | Integration RunMyAccounts | ✅ | `accountingConnectorRma.py` |
|
||||
| 1.1.9 | Integration Bexio | ✅ | `accountingConnectorBexio.py` |
|
||||
| 1.1.10 | Integration Abacus | ✅ | `accountingConnectorAbacus.py` |
|
||||
| 1.1.11 | Integration Xero | ❌ | Kein `accountingConnectorXero.py` — kein Code vorhanden |
|
||||
| 1.1.12 | PDF/Excel/Word/Zip Verarbeitung | ✅ | Extraktoren vorhanden; UDM-Konzept in `0-ideas/unified-document-model.md` |
|
||||
|
||||
### 1.2 Budget / Soll-Ist-Vergleich
|
||||
|
||||
**Kunden:** Bling (Prio hoch), Quid (KPI-Kontext)
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.2.1 | Budget-Excel hochladen und gegen Live-Daten prüfen | 🔧 | Prompt-Template "Budget-Vergleich" in `mainTrustee.py` (Quick Action + Template Workflow); Frontend `TrusteeAnalyseView.tsx` hat Budget-Tab mit Upload; **aber kein Demo-Budget-Excel vorhanden** |
|
||||
| 1.2.2 | Vergleiche über Perioden (Q1 aktuell vs. Vorjahr vs. Budget) | ✅ | Im Prompt-Template als Anweisung an AI-Agent enthalten |
|
||||
| 1.2.3 | Automatische Diagramm-Erstellung | ✅ | Agent erzeugt Charts via `aggregateTable` + AI-Prompt |
|
||||
| 1.2.4 | Live-Daten via API (kein PDF-Export nötig) | ✅ | `refreshAccountingData` Action synct Live-Daten; API-basiert |
|
||||
| 1.2.5 | Caching konfigurierbar | ✅ | `_featureQueryCache` mit TTL 300s in `_featureSubAgentTools.py` |
|
||||
| 1.2.6 | Abweichungen mit Begründung | ✅ | Im Prompt-Template: Agent soll Abweichungen erklären |
|
||||
| 1.2.7 | Vorausschauende Prognosen | ✅ | Separates Prompt-Template "Prognose/Trend-Analyse" |
|
||||
|
||||
### 1.3 Cashflow-Rechnung
|
||||
|
||||
**Kunden:** Bling
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.3.1 | Plausibilisierung und Erstellung Cashflow-Rechnung | ✅ | Prompt-Template "Cashflow-Rechnung" in `mainTrustee.py` |
|
||||
| 1.3.2 | Nicht-relevante Positionen berücksichtigen | ✅ | Im Prompt-Template als Anweisung |
|
||||
| 1.3.3 | Warnungen bei kritischen Werten | ✅ | Im Prompt-Template |
|
||||
|
||||
### 1.4 Dashboard — Bilanz- & Erfolgsrechnungsanalyse
|
||||
|
||||
**Kunden:** Bling, Quid
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.4.1 | KPI-Dashboard (Bruttogewinn, ROI, Gewinn etc.) | ✅ | Prompt-Template "KPI-Dashboard" + Quick Action + `TrusteeAnalyseView.tsx` KPI-Tab |
|
||||
| 1.4.2 | Check hälftiger Kapitalverlust | ✅ | Im Jahresabschluss-Prompt enthalten |
|
||||
| 1.4.3 | Überschuldungs-Check | ✅ | Im Jahresabschluss-Prompt enthalten |
|
||||
| 1.4.4 | Durchschnittliche Zahlungsfrist | 🔧 | Nicht als dedizierter KPI; Agent kann es berechnen wenn Daten vorhanden |
|
||||
|
||||
### 1.5 Liquiditätsplanung
|
||||
|
||||
**Kunden:** Bling
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.5.1 | Liquiditätsplanung analog Budgetplanung | 🔧 | Kein dediziertes Prompt-Template; über Prognose-Template teilweise abdeckbar |
|
||||
| 1.5.2 | Automatische Erstellung aus Vergangenheit | 🔧 | Agent kann historische Daten analysieren; kein dedizierter Workflow |
|
||||
| 1.5.3 | Zusätzliche Inputs (z.B. ausserordentliche Dividende) | ❌ | Kein Mechanismus für manuelle Zusatz-Inputs in Prognose |
|
||||
|
||||
### 1.6 Gastro-Use-Case — Echtzeit-Rentabilitätsanalyse
|
||||
|
||||
**Kunden:** Bling (Prio hoch, bestes Beispiel für Kunden-Mehrwert)
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.6.1 | Integration Kassensystem + Lohndaten + Buchhaltung | ⏸️ | **Wartet auf Kevin-Input** — kein Connector für Kassensysteme/Virux |
|
||||
| 1.6.2 | Tagesumsatz vs. Personalkosten vs. Wareneinsatz | ⏸️ | Konzeptionell über generischen Data-Import möglich |
|
||||
|
||||
### 1.7 Abschlussunterstützung
|
||||
|
||||
**Kunden:** Bling, allgemein Treuhand
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.7.1 | Jahresabschluss-Checks | ✅ | Prompt-Template "Jahresabschluss prüfen" in `mainTrustee.py` |
|
||||
| 1.7.2 | Abgrenzungsbuchungen vorbereiten | 🔧 | Im Prompt adressiert; keine dedizierte Automation |
|
||||
| 1.7.3 | Bilanzkonti prüfen / Saldovalidierung | ✅ | Im Jahresabschluss-Prompt |
|
||||
| 1.7.4 | Vorjahresvergleiche | ✅ | In mehreren Prompt-Templates |
|
||||
|
||||
### 1.8 Zentrales Mandantenmanagement
|
||||
|
||||
**Kunden:** Bling (verschiedene Systeme über eine Schaltzentrale)
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.8.1 | Verschiedene Kunden auf verschiedenen Systemen verwalten | ✅ | Multi-Tenant-Plattform ist Kernarchitektur; `accountingRegistry.py` unterstützt verschiedene Connectors pro Mandant |
|
||||
| 1.8.2 | Ein Login, alle Mandanten | ✅ | Plattform-Feature: Mandantenwechsel im UI |
|
||||
| 1.8.3 | Strikte Datentrennung | ✅ | Mandantenisolation auf DB- und API-Ebene |
|
||||
|
||||
---
|
||||
|
||||
### 1.9 PWG — Stiftung für preisgünstiges Wohnen
|
||||
|
||||
**Kontext:** ~300 Liegenschaften, Team 7–8 Personen. IT-Leiter Markus Brütsch (seit 2+ Jahren). Neue Rolle "Organella" für Digitalisierung (Schnittstelle Technologie/Betrieb, kein IT-Hintergrund). PWG evaluiert AI-Lösungen offen, noch keine Entscheidung getroffen. Workshop 16.04.2026 durchgeführt.
|
||||
|
||||
**Pilotprojekt bestätigt:** Jahresmietzinsbestätigungen (siehe 1.9.9).
|
||||
|
||||
#### 1.9a Plattform-Features (bestehend)
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.9.1 | Automatisierte Belegverarbeitung mit Abacus | ✅ | `accountingConnectorAbacus.py` + Trustee-Pipeline |
|
||||
| 1.9.2 | Kommunikations-Coach für Mietergespräche | ✅ | `features/commcoach/` — komplett inkl. 10+ Personas |
|
||||
| 1.9.3 | Immobilien-Personas (Zahlungsrückstand, Nebenkosten, Einzug, Lärm) | ✅ | 4 PWG-Personas in `BUILTIN_PERSONAS` + Seeding |
|
||||
| 1.9.4 | KI-Arbeitsplatz mit Datenneutralisierung | ✅ | `features/neutralization/` — PII-Masking, Playground, Private-LLM; Daten-Residency Schweiz |
|
||||
| 1.9.5 | PWG-Agent (Stiftungsstil, öffentliche PDFs als Futter) | 🔧 | Knowledge-Base-Feature vorhanden; kein PWG-spezifisches Knowledge-Set (Geschäftsberichte, Vermietungsreglement, Führungshandbuch etc.) |
|
||||
| 1.9.6 | M365-Anbindung (SharePoint, Outlook, OneDrive, Teams) | ✅ | SharePoint-Nodes + Outlook-Methode in Workflows; nutzt nativen SharePoint-Index |
|
||||
| 1.9.7 | KI-Auswertung Abacus-Daten/Reports | ✅ | Über Trustee-Feature + `aggregateTable` + AI-Prompts; Read/Write via Abacus-API |
|
||||
| 1.9.8 | Grundstücksanalyse (öffentliche Daten: GIS, Maps, Grundbuch) | ❌ | Kein Connector/Workflow für öffentliche Geodaten |
|
||||
|
||||
#### 1.9b Neue Anforderungen aus Workshop 16.04.2026
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.9.9 | **Pilotprojekt: Jahresmietzinsbestätigungen** (ca. 700–800 Schreiben/Quartal, Versand Sommer 2026) | ❌ | Kein dedizierter Workflow — siehe Workflow-Design unten |
|
||||
| 1.9.10 | FileMaker-Integration (Portfolio, Liegenschaften, Erneuerungsplanung, Bauprojekte, Akquisition) | ❌ | Kein FileMaker-Connector; Datenmenge/-qualität muss geprüft werden |
|
||||
| 1.9.11 | Template-basierte Dokumentenerstellung (HTML-Templates → Word mit Corporate Design) | 🔧 | Code-Editor mit Claude vorhanden; kein Template-to-Word-Pipeline |
|
||||
| 1.9.12 | Notification-System (reagiert auf DB-Änderungen, Berichte per E-Mail, Workflow-Trigger) | 🔧 | E-Mail-Versand in Workflows vorhanden (`methodOutlook`); kein generisches DB-Change-Detection-System |
|
||||
| 1.9.13 | Information Retrieval über diverse Wissensquellen (Guidelines, Handbücher, SharePoint) | 🔧 | Knowledge-Base + SharePoint-Index vorhanden; kein PWG-spezifisches Datenset geladen |
|
||||
| 1.9.14 | Datenvalidierung als Erst-Schritt (welche Daten korrekt/aktuell?) | ❌ | Kein Daten-Audit-Workflow |
|
||||
| 1.9.15 | Compliance & Audit: vollständiges Tracking aller AI-Transaktionen | ✅ | `ComplianceAuditPage.tsx` + Gateway-Logging; jede Anfrage protokolliert |
|
||||
| 1.9.16 | Granulare Neutralisierungs-Kontrolle pro Datenquelle | ✅ | In Neutralisierungs-Feature konfigurierbar pro Source |
|
||||
|
||||
#### 1.9c Pilot-Workflow: Jahresmietzinsbestätigungen
|
||||
|
||||
**Business Case:** 4 × 800 Schreiben/Jahr = 3'200 Schreiben. Aktuell: Serienbrief → manueller Versand → Scan der Rückantworten → manuelle Verarbeitung. Ziel: AI-gestützte Verarbeitung der gescannten Rückantworten mit Antwortvorschlägen.
|
||||
|
||||
**Workflow-Design (6–7 Schritte, davon 1 mit AI):**
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ PWG Pilot: Jahresmietzinsbestätigungen │
|
||||
│ │
|
||||
│ Phase 1: Generierung (bestehend bei PWG) │
|
||||
│ ┌──────────────────────────────────────┐ │
|
||||
│ │ System generiert Serienbrief │ (PWG-internes System) │
|
||||
│ │ mit aktuellen Mietdaten │ │
|
||||
│ └──────────┬───────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ Phase 2: Versand & Rücklauf (manuell) │
|
||||
│ ┌──────────────────────────────────────┐ │
|
||||
│ │ Manueller Versand + Scan der │ │
|
||||
│ │ Rückantworten → SharePoint-Ordner │ │
|
||||
│ └──────────┬───────────────────────────┘ │
|
||||
│ ▼ │
|
||||
│ Phase 3: PowerOn-Workflow (automatisiert) │
|
||||
│ │
|
||||
│ Step 1: trigger.schedule (täglich oder on-demand) │
|
||||
│ ▼ │
|
||||
│ Step 2: sharepoint.listFiles (Scan-Ordner, neue Dokumente) │
|
||||
│ ▼ │
|
||||
│ Step 3: flow.loop (für jedes gescannte Dokument) │
|
||||
│ ▼ │
|
||||
│ Step 4: sharepoint.downloadFile + trustee.extractFromFiles │
|
||||
│ → OCR/Extraktion: Mietername, Adresse, Bestätigung, │
|
||||
│ Anmerkungen, Unterschrift ja/nein │
|
||||
│ ▼ │
|
||||
│ Step 5: ai.prompt ← EINZIGER AI-SCHRITT │
|
||||
│ → Gescannte Daten gegen Originaldaten prüfen │
|
||||
│ → Status klassifizieren (bestätigt / Abweichung / │
|
||||
│ fehlende Unterschrift / unleserlich) │
|
||||
│ → Antwortvorschlag generieren bei Abweichung │
|
||||
│ ▼ │
|
||||
│ Step 6: data.writeToTable (Ergebnis in Übersichtstabelle) │
|
||||
│ ▼ │
|
||||
│ Step 7: email.send (Zusammenfassung an Sachbearbeiter) │
|
||||
│ → Audit-Log für jeden Verarbeitungsschritt │
|
||||
└─────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**Benötigte Komponenten für den Pilot-Workflow:**
|
||||
|
||||
| # | Komponente | Codebase-Status | Was zu tun ist |
|
||||
|---|-----------|-----------------|----------------|
|
||||
| W1 | `trigger.schedule` oder `trigger.manual` | ✅ | Vorhanden in `nodeDefinitions/triggers.py` |
|
||||
| W2 | `sharepoint.listFiles` + `sharepoint.downloadFile` | ✅ | Vorhanden in `nodeDefinitions/sharepoint.py` |
|
||||
| W3 | `flow.loop` | ✅ | Vorhanden in `nodeDefinitions/flow.py` |
|
||||
| W4 | `trustee.extractFromFiles` (OCR/Extraktion gescannter Dokumente) | ✅ | Vorhanden; OCR für einseitige Scans unterstützt |
|
||||
| W5 | `ai.prompt` — Prompt-Template "Mietzinsbestätigung prüfen" | ❌ | **Neues Prompt-Template** nötig: Scan-Daten gegen Originaldaten abgleichen, Status klassifizieren, Antwortvorschlag generieren |
|
||||
| W6 | Ergebnis-Tabelle / Übersichtsliste (verarbeitete Bestätigungen) | 🔧 | `data`-Nodes existieren; kein dedizierter "Mietzinsbestätigungs-Report"-Output |
|
||||
| W7 | `email.send` (Zusammenfassung an Sachbearbeiter) | ✅ | Vorhanden via `methodOutlook` |
|
||||
| W8 | Abacus-Referenzdaten (Original-Mietzinsdaten für Abgleich) | 🔧 | Abacus-Connector vorhanden; Abfrage der Mietzins-Stammdaten muss konfiguriert werden |
|
||||
| W9 | Audit-Logging für gesamten Prozess | ✅ | Plattform-Feature: alle AI-Transaktionen geloggt |
|
||||
| W10 | Graph-Editor Workflow als Template speichern | ❌ | Workflow muss im Editor gebaut und als System-Template gespeichert werden |
|
||||
|
||||
**Voraussetzungen (Action Items aus Workshop):**
|
||||
|
||||
| # | Action Item | Verantwortlich | Status |
|
||||
|---|------------|----------------|--------|
|
||||
| AI1 | API-Zugang zu Abacus-Testmandant einrichten | Patrick Motsch | ❌ offen — Patrick koordiniert mit Abacus |
|
||||
| AI2 | PWG muss Zugriff auf Testmandant bestätigen | PWG (Markus) | ❌ offen |
|
||||
| AI3 | Preismodell bereitstellen (Grundgebühr/User/Monat + Token-Gebühr) | PowerOn | ❌ offen |
|
||||
| AI4 | Datenschutzanforderungen und Vertragsklauseln für Lieferanten prüfen | PWG | ❌ offen |
|
||||
| AI5 | Prozessschritte Pilot ausarbeiten und Kalkulation erstellen | PowerOn | 🔧 Workflow-Design in diesem Dokument; Kalkulation offen |
|
||||
| AI6 | FileMaker-Datenmenge und -qualität prüfen (potenzielle Integration) | PWG + PowerOn | ❌ offen |
|
||||
|
||||
---
|
||||
|
||||
### 1.10 Quid / ServiceHunter Use Cases
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 1.10.1 | KPI-Dashboard (Kundenmargen, ACV, Lifetime Value, Produktionsmarge) | 🔧 | Generisches KPI-Prompt-Template vorhanden; kundenspezifische KPIs brauchen Daten-Import |
|
||||
| 1.10.2 | Zeiterfassung & Support-Analyse (Zendesk-Verknüpfung) | ⏸️ | **Kein Zendesk-Connector** — bewusst CSV-Upload-Workaround |
|
||||
| 1.10.3 | Prognosen & Proaktive Steuerung | ✅ | Prognose-Prompt-Template vorhanden |
|
||||
| 1.10.4 | Konsolidierung international (CH, DE, UK) | ⏸️ | **Wartet auf Lars-Meeting** — hohe Komplexität |
|
||||
| 1.10.5 | Spesen-Automatisierung (SharePoint/Drive → verbuchen) | ✅ | SharePoint-Pipeline + Trustee-Import vorhanden |
|
||||
|
||||
---
|
||||
|
||||
## Teil 2: UI/UX-Anforderungen (aus Team-Meeting / Nutzertests)
|
||||
|
||||
### 2.1 AI-Workspace Usability
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 2.1.1 | Primäre Prompt-Zeile dominant sichtbar (kein "Wo tippe ich?") | 🔧 | `WorkspaceInput.tsx` funktional komplett; **Placeholder auf Englisch**, keine Hero-Eingabe, sekundäre Aktionen in einer Zeile |
|
||||
| 2.1.2 | Empty State im Chat (Orientierung für Erstnutzer) | ❌ | `ChatStream.tsx` zeigt blank area wenn `messages.length === 0` — **kein Welcome/Empty-State** |
|
||||
| 2.1.3 | "Neuer Chat" sichtbar ohne UDB-Sidebar | ❌ | Nur `+` in `ChatsTab` Toolbar; kein zentraler CTA |
|
||||
| 2.1.4 | Datei-Drop Entdeckbarkeit | 🔧 | Vollflächen-Drop existiert in `WorkspacePage.tsx`; kein dauerhafter Hinweis im leeren Chat |
|
||||
| 2.1.5 | DE-Placeholder und i18n | ❌ | Placeholder noch auf Englisch (`Type a message...`) |
|
||||
|
||||
### 2.2 Responsive Layout & Breakpoints
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 2.2.1 | Zwischen-Breakpoint (1025–1280px): Sidebars auto-einklappen | ❌ | `isMobile` nur bei `≤1024px`; schmale Desktop-Fenster → Mittelspalte zu schmal |
|
||||
| 2.2.2 | Visuelle Hierarchie Prompt (Schatten/Rand, minHeight) | ❌ | `WorkspaceInput.tsx` ohne besondere Hervorhebung |
|
||||
| 2.2.3 | Viewport-Testmatrix (1100/1200/1280/1440) | ❌ | Kein Test-Setup dafür |
|
||||
|
||||
### 2.3 Vertrauen & Marketing-UI
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 2.3.1 | Trust-Badges (Daten hosted in der Schweiz, Anbieter/Standort) | ❌ | Login: **kein** Hosting-Hinweis; keine `TrustFooter`/`TrustStrip` Komponente |
|
||||
| 2.3.2 | "Recommended by" Partner-Strip (Valion, PamoCreate, Swiss AI Association etc.) | ❌ | Keine Partner-Logos/Links |
|
||||
| 2.3.3 | Swiss ® am Logo | ❌ | Nur im Bildasset, nicht in UI sichtbar (Legal klären) |
|
||||
| 2.3.4 | Sicherheits-Banner in SourcesTab ("Verbindung ist read-only") | ❌ | `SourcesTab.tsx` ohne Info-Banner |
|
||||
|
||||
### 2.4 Billing & Pricing Auffindbarkeit
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 2.4.1 | Billing-Funktionalität (komplett) | ✅ | `BillingDataView.tsx` mit Tabs, Balance Cards, Transaktionen |
|
||||
| 2.4.2 | Einstieg Billing nach Login (Teaser/Banner) | ❌ | Kein Dashboard-Teaser; Zugang nur via Nav-Baum + User-Menü |
|
||||
| 2.4.3 | Balance im UserSection (neben Avatar) | ❌ | Nur Menü-Eintrag "Guthaben" |
|
||||
| 2.4.4 | Billing-Copy für Nicht-Admins | ❌ | Kein Hinweis "Frag deinen Admin" |
|
||||
|
||||
### 2.5 Onboarding & Erstnutzung
|
||||
|
||||
| # | Anforderung | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|-------------|-----------------|---------------------|
|
||||
| 2.5.1 | Connector-Onboarding ("sicher verbinden, nichts kaputt") | ❌ | Keine Microcopy in SourcesTab |
|
||||
| 2.5.2 | Progressive Offenlegung (weniger gleichzeitig auf Startscreens) | ❌ | Workspace zeigt alles parallel |
|
||||
|
||||
---
|
||||
|
||||
## Teil 3: Infrastruktur & Demo-Vorbereitung
|
||||
|
||||
### 3.1 Demo-Konfigurationen
|
||||
|
||||
| # | Item | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|------|-----------------|---------------------|
|
||||
| 3.1.1 | Demo-Config-Infrastruktur (Base + Admin API) | ✅ | `_baseDemoConfig.py`, `routeAdminDemoConfig.py` |
|
||||
| 3.1.2 | Referenz: `investorDemo2026.py` | ✅ | Vollständiges Muster mit Mandant, User, Features, Billing |
|
||||
| 3.1.3 | Demo-Mandant "Bling Demo" | ❌ | Kein `blingDemo2026.py` |
|
||||
| 3.1.4 | Demo-Mandant "PWG Demo" | ❌ | Kein `pwgDemo2026.py` |
|
||||
| 3.1.5 | Demo-Mandant "Quid Demo" | ❌ | Kein `quidDemo2026.py` |
|
||||
|
||||
### 3.2 Testdaten
|
||||
|
||||
| # | Item | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|------|-----------------|---------------------|
|
||||
| 3.2.1 | Fiktives Mieterdossier (Neutralisierung) | ✅ | `demoData/neutralizer/tenant-dossier.pdf` + Generator |
|
||||
| 3.2.2 | Knowledge-Base Demo-Dateien | ✅ | `demoData/knowledge-base/` — 4 Dateien |
|
||||
| 3.2.3 | Budget-Excel (Soll-Werte) | ❌ | Kein `.xlsx` im Repo |
|
||||
| 3.2.4 | Musterbelege (Rechnung, Spesen, Bank, Versicherung) | ❌ | Keine Demo-Belege |
|
||||
| 3.2.5 | Quid-Testdaten (CSV: Umsatz, Kunden, Support) | ❌ | Keine kundenspezifischen Testdaten |
|
||||
| 3.2.6 | Bling-Testdaten (Bexio-kompatibel) | ❌ | Keine Bexio-Testdaten |
|
||||
| 3.2.7 | PWG-Testdaten (Abacus-kompatibel) | ❌ | Keine Abacus-Testdaten |
|
||||
|
||||
### 3.3 Demo-Workflows & Skripte
|
||||
|
||||
| # | Item | Codebase-Status | Evidenz / Bemerkung |
|
||||
|---|------|-----------------|---------------------|
|
||||
| 3.3.1 | System-Template "Treuhand: PDF-Klassifizierung" | ✅ | In `interfaceBootstrap.py` |
|
||||
| 3.3.2 | Demo-Workflow (manual trigger → SharePoint → Trustee Pipeline) | ❌ | System-Template existiert, aber kein dedizierter Demo-Workflow |
|
||||
| 3.3.3 | Demo-Skript Bling | ❌ | |
|
||||
| 3.3.4 | Demo-Skript PWG | ❌ | |
|
||||
| 3.3.5 | Demo-Skript Quid | ❌ | |
|
||||
| 3.3.6 | Neutralisierungs-Demo-Flow (Schritt-für-Schritt) | ❌ | Kein Skript |
|
||||
|
||||
---
|
||||
|
||||
## Teil 4: Allgemeine Treuhand-Use-Cases (Prozessdokumentation)
|
||||
|
||||
Diese Use Cases stammen aus der allgemeinen Treuhand-Prozessdokumentation und sind für **alle** Kunden relevant.
|
||||
|
||||
### 4.1 Datenerfassung — Kleine Unternehmen
|
||||
|
||||
| # | Anforderung | Codebase-Status |
|
||||
|---|-------------|-----------------|
|
||||
| 4.1.1 | Belege sortieren & mit Banktransaktionen referenzieren | 🔧 — Belegverarbeitung vorhanden; kein Bank-Statement-Matching |
|
||||
| 4.1.2 | Import Banktransaktionen via Excel/CSV | 🔧 — File-Upload + Extraktion vorhanden; kein dedizierter Bank-Import |
|
||||
| 4.1.3 | Automatisierte Rückfragen an Kunden bei fehlenden Belegen | ❌ |
|
||||
|
||||
### 4.2 Lohnbuchhaltung
|
||||
|
||||
| # | Anforderung | Codebase-Status |
|
||||
|---|-------------|-----------------|
|
||||
| 4.2.1 | Überleitung Lohnaufwand (Fibu vs. Lohnbuchhaltung) | ❌ — Kein Lohn-Feature |
|
||||
| 4.2.2 | Nicht-lohnwirksame Buchungen identifizieren | ❌ |
|
||||
| 4.2.3 | Fehlende Lohnmeldungen erkennen | ❌ |
|
||||
|
||||
### 4.3 Steuererklärung
|
||||
|
||||
| # | Anforderung | Codebase-Status |
|
||||
|---|-------------|-----------------|
|
||||
| 4.3.1 | Belege nach Kategorien ordnen | 🔧 — Klassifikation vorhanden |
|
||||
| 4.3.2 | Steuererklärung erstellen | ❌ — Kein Steuer-Feature |
|
||||
| 4.3.3 | Vorjahresvergleich und Plausibilisierung | ✅ — In Analyse-Prompts |
|
||||
|
||||
### 4.4 Jahresabschluss (Mittlere/Grosse Unternehmen)
|
||||
|
||||
| # | Anforderung | Codebase-Status |
|
||||
|---|-------------|-----------------|
|
||||
| 4.4.1 | Banksalden abgleichen (Buchhaltung vs. Bank) | 🔧 — Konzeptionell via Agent; kein dedizierter Check |
|
||||
| 4.4.2 | PayPal, Revolut, ausländische Konten nachbuchen | ❌ |
|
||||
| 4.4.3 | Wertschriftendepot nachbuchen | ❌ |
|
||||
| 4.4.4 | Fehlerkonto-Transaktionen bereinigen | ❌ |
|
||||
| 4.4.5 | Kreditkartenkonto abstimmen | ❌ |
|
||||
| 4.4.6 | Zahlungsanbieter prüfen (Stripe, Amex) | ❌ |
|
||||
| 4.4.7 | Nebenbücher mit Fibu abstimmen | ❌ |
|
||||
| 4.4.8 | Skonto-Differenzen ausbuchen | ❌ |
|
||||
| 4.4.9 | Konzerninterne Abstimmung | ❌ |
|
||||
| 4.4.10 | Darlehenskonten abgleichen, Zinsen berechnen | ❌ |
|
||||
| 4.4.11 | Fremdwährungsbewertung gemäss ESTV | ❌ |
|
||||
| 4.4.12 | Eigenkapitalveränderungen mit HR abgleichen | ❌ |
|
||||
| 4.4.13 | Umsatz-/Aufwandsplausibilisierung | ✅ — Im Jahresabschluss-Prompt |
|
||||
| 4.4.14 | Rechnungsabgrenzungen (aktiv/passiv) | 🔧 — Im Prompt adressiert |
|
||||
| 4.4.15 | Abschreibungen erfassen | ❌ |
|
||||
| 4.4.16 | MWST-Jahresabstimmung | ❌ |
|
||||
| 4.4.17 | Steueraufwand-Rückstellungen berechnen | ❌ |
|
||||
| 4.4.18 | Bilanz und ER plausibilisieren | ✅ — Im Jahresabschluss-Prompt |
|
||||
| 4.4.19 | Analyse gesetzliche Bestimmungen (Kapitalverlust, Überschuldung) | ✅ — Im Jahresabschluss-Prompt |
|
||||
|
||||
### 4.5 Finanzielle Führung & Controlling
|
||||
|
||||
| # | Anforderung | Codebase-Status |
|
||||
|---|-------------|-----------------|
|
||||
| 4.5.1 | Businessplan → Absatzplanung → Ertragsplanung | ❌ |
|
||||
| 4.5.2 | Investitionsplan und Finanzplan | ❌ |
|
||||
| 4.5.3 | Budget mit Szenarien | 🔧 — Budget-Prompt vorhanden; Szenarien via Chat |
|
||||
| 4.5.4 | Soll/Ist-Vergleich mit Abweichungsanalyse | ✅ — Budget-Vergleich Prompt-Template |
|
||||
| 4.5.5 | Deckungsbeitragsrechnung | ❌ |
|
||||
| 4.5.6 | Projekt-Controlling | ❌ |
|
||||
| 4.5.7 | Benchmarkanalyse | ❌ |
|
||||
| 4.5.8 | KPI-Monitoring mit proaktiver Benachrichtigung | 🔧 — KPIs via Agent; kein proaktives Alert-System |
|
||||
|
||||
### 4.6 Revisionen
|
||||
|
||||
| # | Anforderung | Codebase-Status |
|
||||
|---|-------------|-----------------|
|
||||
| 4.6.1 | Ordentliche Revisionen unterstützen | ❌ — Kein Revisions-Feature |
|
||||
|
||||
### 4.7 Steueroptimierung & Simulationen
|
||||
|
||||
| # | Anforderung | Codebase-Status |
|
||||
|---|-------------|-----------------|
|
||||
| 4.7.1 | Jahresrechnung auf steuerliche Probleme prüfen | ❌ |
|
||||
| 4.7.2 | Simulationen (Lohn vs. Dividende, Umzug, 3. Säule, BVG) | ❌ |
|
||||
| 4.7.3 | MWST-Prüfung, VST-Korrekturen | ❌ |
|
||||
| 4.7.4 | Steuerausscheidungen auf verschiedene Kantone | ❌ |
|
||||
|
||||
### 4.8 Interdisziplinäre Themen
|
||||
|
||||
| # | Anforderung | Codebase-Status |
|
||||
|---|-------------|-----------------|
|
||||
| 4.8.1 | Umstrukturierungen | ❌ |
|
||||
| 4.8.2 | Steuer-/Vorsorgestrategien | ❌ |
|
||||
| 4.8.3 | Nachfolgeplanung | ❌ |
|
||||
| 4.8.4 | Unternehmensbewertungen | ❌ |
|
||||
|
||||
---
|
||||
|
||||
## Zusammenfassung: Status-Überblick
|
||||
|
||||
### Fertig (✅) — Kernplattform funktioniert
|
||||
|
||||
| Bereich | Was steht |
|
||||
|---------|-----------|
|
||||
| **Trustee Agent-Tools** | `refreshTrusteeData`, `aggregateTable`, Connection-Pooling, Result-Caching |
|
||||
| **Graph-Editor** | Trustee-Kategorie + 4 Nodes, SharePoint-Nodes, Flow-Nodes (Loop, If/Else, Switch, Merge) |
|
||||
| **Prompt-Templates** | 5 Analyse-Typen (Budget, KPI, Cashflow, Prognose, Jahresabschluss) als Quick Actions + Template Workflows |
|
||||
| **Accounting-Connectors** | Bexio, Abacus, RunMyAccounts |
|
||||
| **Belegverarbeitung** | Extraktion → Klassifikation → Kontierung → Sync (end-to-end) |
|
||||
| **CommCoach** | Feature komplett, 10+ Personas inkl. 4 Immobilien-Personas (PWG), Gamification, Seeding |
|
||||
| **Neutralisierung** | PII-Masking, Playground, Private-LLM, Mieterdossier-PDF |
|
||||
| **Multi-Tenancy** | Mandantenisolation, Datentrennung, Rollenwechsel |
|
||||
| **Billing** | BillingDataView, Balance, Transaktionen, useBilling |
|
||||
| **SharePoint-Integration** | 6 Workflow-Nodes + Automation |
|
||||
| **Demo-Infrastruktur** | Base-Config, Admin-API, Investor-Demo als Referenz |
|
||||
|
||||
### Teilweise (🔧) — Grundstruktur steht, Erweiterung nötig
|
||||
|
||||
| Bereich | Was fehlt |
|
||||
|---------|-----------|
|
||||
| Firmen-Mapping Kunden/Lieferanten | Regelbasiertes Matching-UI |
|
||||
| Beleg-Tagging | Beleg-spezifisches Tag-System |
|
||||
| Vorsteuer-Automatisierung | MWST-Zuordnung bei Belegverarbeitung |
|
||||
| Liquiditätsplanung | Dediziertes Prompt-Template |
|
||||
| Workspace-Prompt | DE-Placeholder, visuelle Hervorhebung |
|
||||
| Datei-Drop | Hinweis im Empty State |
|
||||
| Budget-Prompt | Demo-Excel-Datei fehlt |
|
||||
|
||||
### Offen (❌) — Noch zu bauen
|
||||
|
||||
#### Prio 0: PWG-Pilot (Versand Sommer 2026 — Deadline-gebunden)
|
||||
|
||||
| Item | Aufwand | Beschreibung |
|
||||
|------|---------|-------------|
|
||||
| Abacus-Testmandant API-Zugang | Extern | Patrick koordiniert mit Abacus; PWG muss Zugriff bestätigen |
|
||||
| Prompt-Template "Mietzinsbestätigung prüfen" | Mittel | Neues Template: Scan vs. Originaldaten, Status-Klassifikation, Antwortvorschlag |
|
||||
| Pilot-Workflow im Graph-Editor | Mittel | trigger → sharepoint.listFiles → loop → download → extract → ai.prompt → report → email |
|
||||
| Abacus-Mietzins-Stammdaten-Abfrage | Klein | Konfiguration im Abacus-Connector für Mietzins-Referenzdaten |
|
||||
| Demo-Mandant PWG | Mittel | `pwgDemo2026.py` — Trustee (Abacus), CommCoach, Neutralisierung, Workspace |
|
||||
| PWG Knowledge-Set | Klein | Öffentliche PDFs (Geschäftsberichte, Vermietungsreglement) in Knowledge-Base laden |
|
||||
| Preismodell / Kalkulation Pilot | Extern | Grundgebühr/User/Monat + Token-Gebühr; basierend auf 4×800 Schreiben/Jahr |
|
||||
|
||||
#### Prio 1: Demo-Blocker / Weitere Kunden-Demos
|
||||
|
||||
| Item | Aufwand | Beschreibung |
|
||||
|------|---------|-------------|
|
||||
| Demo-Mandant Bling | Mittel | `blingDemo2026.py` — Trustee (Bexio), Workspace, Graph-Editor |
|
||||
| Demo-Mandant Quid | Klein | `quidDemo2026.py` — Workspace, Graph-Editor, CSV-Upload |
|
||||
| Budget-Excel | Klein | Soll-Werte 2026 für Demo |
|
||||
| Musterbelege (PDFs) | Klein | 3–5 Belege (Rechnung, Spesen, Bank, Versicherung) |
|
||||
| Demo-Skripte | Klein | Schritt-für-Schritt pro Kunde |
|
||||
| Neutralisierungs-Demo-Flow | Klein | Dokumentation |
|
||||
| Demo-Workflow Graph-Editor (generisch) | Mittel | trigger.manual → SharePoint → Trustee Pipeline |
|
||||
|
||||
#### Prio 2: UI/UX-Verbesserungen (Erstnutzer-Hürde senken)
|
||||
|
||||
| Item | Aufwand | Beschreibung |
|
||||
|------|---------|-------------|
|
||||
| Empty State ChatStream | Klein | Titel, Bullets, "Neuer Chat" Button |
|
||||
| DE-Placeholder + i18n | Klein | `WorkspaceInput.tsx` |
|
||||
| "Neuer Chat" CTA in Mitte | Klein | `WorkspacePage.tsx` |
|
||||
| Zwischen-Breakpoint (1025–1280px) | Mittel | Sidebar-Auto-Collapse |
|
||||
| Trust-Strip/Footer (Login, Landing) | Mittel | Hosting Schweiz, Partner-Logos (Legal nötig) |
|
||||
| Billing-Teaser nach Login | Klein | Link oder Banner |
|
||||
| Connector-Onboarding Copy | Klein | Sicherheits-Banner in SourcesTab |
|
||||
| Balance im UserSection | Klein | Zahl neben Avatar |
|
||||
|
||||
#### Prio 3: Feature-Erweiterungen (Roadmap)
|
||||
|
||||
| Item | Aufwand | Beschreibung |
|
||||
|------|---------|-------------|
|
||||
| Xero-Connector | Gross | Neuer Accounting-Connector |
|
||||
| FileMaker-Connector (PWG) | Gross | Portfolio, Liegenschaften, Erneuerungsplanung; Datenmenge/-qualität erst prüfen |
|
||||
| Buchungsregeln für wiederkehrende Belege | Mittel | Regel-Engine |
|
||||
| Liquiditätsplanungs-Template | Klein | Neues Prompt-Template |
|
||||
| KPI-Monitoring mit Alerts | Gross | Proaktives Benachrichtigungssystem |
|
||||
| Template-basierte Dokumentenerstellung (HTML → Word) | Mittel | Erneuerungsstrategien, Corporate Design |
|
||||
| DB-Change-Detection / Notification-Trigger | Mittel | Reagiert auf Datenbank-Änderungen, triggert Workflows |
|
||||
| Datenvalidierungs-Workflow | Klein | Erst-Audit: welche Daten korrekt/aktuell |
|
||||
|
||||
#### Prio 4: Zurückgestellt (wartet auf externen Input)
|
||||
|
||||
| Item | Wartet auf | Kunde |
|
||||
|------|-----------|-------|
|
||||
| Gastro-Echtzeit-Integration | Kevin (Bling) soll UC ausformulieren | Bling |
|
||||
| Zendesk-Connector | Bewusst CSV-Workaround | Quid |
|
||||
| Regelbasierte Konsolidierung | Lars-Meeting | Quid |
|
||||
| Grundstücksanalyse (GIS etc.) | Kundenpräzisierung | PWG |
|
||||
| FileMaker-Integration (PWG) | Datenmenge/-qualität prüfen (PWG + PowerOn) | PWG |
|
||||
| PWG Datenschutz-/Vertragsklauseln | PWG prüft intern (genossenschaftliche Struktur) | PWG |
|
||||
|
||||
#### Langfristig: Allgemeine Treuhand-Automatisierung
|
||||
|
||||
Die Use Cases aus Teil 4 (Lohnbuchhaltung, Steuererklärung, detaillierter Jahresabschluss, Revisionen, Steueroptimierung, interdisziplinäre Themen) sind **konzeptionell dokumentiert** aber noch **nicht in der Codebase**. Diese bilden die Langfrist-Roadmap und werden schrittweise über AI-Prompt-Templates und dedizierte Workflows umgesetzt, sobald die Kern-Use-Cases bei den ersten Kunden validiert sind.
|
||||
|
||||
---
|
||||
|
||||
## Entscheidungen
|
||||
|
||||
| Datum | Entscheidung | Begründung |
|
||||
|-------|-------------|------------|
|
||||
| 2026-04-07 | Prompt-Templates als Code in `mainTrustee.py` | Wartbar und versioniert statt externe Dateien |
|
||||
| 2026-04-07 | `refreshTrusteeData` als separate Action | Separation of Concerns: Sync = schreibend, Query = lesend |
|
||||
| 2026-04-07 | DB-Connection-Pooling statt Connection-per-Call | Grösster Performance-Hebel (~200ms pro Connection) |
|
||||
| 2026-04-09 | Quid ohne Zendesk-Connector — CSV-Upload | Gleicher Analyse-Mehrwert, viel weniger Aufwand |
|
||||
| 2026-04-09 | Gastro-UC und Konsolidierung auf Prio 4 | Warten auf Kunden-Input |
|
||||
| 2026-04-09 | CommCoach-Personas als schnellster Wow-Effekt für PWG | Feature gebaut, nur Persona-Definitionen nötig |
|
||||
| 2026-04-07 | UI-Enhancements: Fokus Erstnutzer-Hürde | Ohne klare Userführung springen Kunden ab |
|
||||
| 2026-04-07 | Trust-Badges: kein ISO, sondern "Daten in CH" | Konkreter Nutzen > abstraktes Zertifikat |
|
||||
| 2026-04-16 | PWG-Pilot = Jahresmietzinsbestätigungen als erster Produktiv-UC | Konkreter, messbarer Business Case (4×800 Schreiben); Deadline Sommer 2026 |
|
||||
| 2026-04-16 | Workflow-Philosophie PWG: erst manuell testen, dann automatisieren | Agent wird aus manuell getesteten Prozessen erstellt; Workflows für wiederkehrende Aufgaben |
|
||||
| 2026-04-16 | FileMaker-Integration auf Prio 4 | Datenmenge/-qualität muss erst geprüft werden; kein Blocker für Pilot |
|
||||
| 2026-04-16 | Abacus-Testmandant als Voraussetzung für Pilot | Patrick koordiniert API-Zugang direkt mit Abacus |
|
||||
|
||||
---
|
||||
|
||||
## Betroffene Module
|
||||
|
||||
- **Gateway:** `features/trustee/` (Prompts, Quick Actions, Connectors), `features/commcoach/` (Personas), `features/neutralization/` (Demo-Config), `features/graphicalEditor/` (Nodes), `serviceCenter/services/serviceAgent/` (Tools, Caching), `demoConfigs/` (neue Configs), `workflows/methods/methodTrustee/` (Actions), `demoData/` (Testdaten)
|
||||
- **Frontend Nyla:** `WorkspacePage.tsx` (Layout, Breakpoints, Empty State), `WorkspaceInput.tsx` (Prompt, i18n), `ChatStream.tsx` (Empty State), `Login.tsx` (Trust-UI), `UserSection.tsx` (Balance), `SourcesTab.tsx` (Onboarding-Copy), `BillingDataView.tsx` (Discovery)
|
||||
- **DB-Migration:** Nein
|
||||
- **Platform/Wiki:** Nach Release `b-reference/` aktualisieren
|
||||
|
||||
## Links
|
||||
|
||||
- PWG Workshop-Inputs (16.04.2026): `pamocreate/projects/poweron/customer-pwg/20260415-inputs-pwg.txt`
|
||||
- Originale Kunden-Inputs: `local/notes/demo-tue-use-cases-inputs-customers.md`
|
||||
- Merged Demo-Plan (ersetzt): `c-work/1-plan/2026-04-demo2-merged-customer-trustee-plan.md`
|
||||
- UI-Enhancements Plan (ersetzt): `c-work/1-plan/2026-04-porta-ui-enhancements-team-meeting.md`
|
||||
- Investor-Demo (Referenz): `platform-core/modules/demoConfigs/investorDemo2026.py`
|
||||
- Frontend-Referenz: `b-reference/ui-nyla/architecture.md`
|
||||
- Trustee Main (Prompts): `platform-core/modules/features/trustee/mainTrustee.py`
|
||||
- CommCoach Personas: `platform-core/modules/features/commcoach/serviceCommcoachPersonas.py`
|
||||
- Neutralisierung: `platform-core/modules/features/neutralization/`
|
||||
- Graph-Editor Nodes: `platform-core/modules/features/graphicalEditor/nodeDefinitions/`
|
||||
- Demo-Daten: `platform-core/demoData/`
|
||||
- UDM-Konzept: `c-work/0-ideas/unified-document-model.md`
|
||||
|
||||
## Abschluss
|
||||
|
||||
- [ ] Quell-Dokumente als "superseded by this document" markieren
|
||||
- [ ] b-reference/ aktualisiert nach Umsetzung
|
||||
- [ ] TOPICS.md aktualisiert
|
||||
- [ ] Dieses Dokument → `1-plan/` verschieben wenn Umsetzung startet
|
||||
291
c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md
Normal file
291
c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
<!-- status: idea -->
|
||||
<!-- started: 2026-06-04 -->
|
||||
<!-- component: gateway | ui-nyla | platform -->
|
||||
|
||||
# Architektur: Vom Kundenbedürfnis zur Lösung — generische Workflow-/Solution-Schicht
|
||||
|
||||
> **Ebene:** App-/Plattform-Architektur (eine Stufe über den Feature-/Connector-Plänen).
|
||||
> **Frage, die wir lösen:** Wie erfüllt PORTA *jedes* wiederkehrende Kundenbedürfnis **ohne kundenspezifischen Code** — als konfigurierte Komposition vorhandener Bausteine?
|
||||
|
||||
## Vision: Konfigurierte Use Cases statt geschriebener Applikationen
|
||||
|
||||
Der eigentliche Paradigmenwechsel hinter diesem Plan:
|
||||
|
||||
**Klassische Software ist von gestern.** Bisher löst man ein Geschäftsproblem, indem jemand eine Applikation *schreibt* — pro Problem, pro Kunde, in Wochen/Monaten. Die Software ist das Asset; jede Anpassung kostet Engineering.
|
||||
|
||||
**Wir drehen das um: wir *konfigurieren* komplexe Use Cases, statt Applikationen zu schreiben.** Genau das, was eine AI heute schon tut, wenn sie assistiert: Du beschreibst eine *Absicht*, das System *komponiert* vorhandene Fähigkeiten (Tools, Daten, Logik) zu einem Ergebnis — niemand baut dafür eine App. Diese Architektur ist dieses Prinzip, **produktisiert**:
|
||||
|
||||
| AI-Assistenz (heute, z. B. Cursor) | PORTA Solution-Schicht |
|
||||
|---|---|
|
||||
| Du beschreibst die Absicht | Business-User beschreibt den Use Case (L4) |
|
||||
| AI plant die Schritte | Workflow-Agent komponiert den Graph (L2/L3) |
|
||||
| AI nutzt Tools (lesen, schreiben, ausführen) | Graph nutzt Actions/Connectors (L1) |
|
||||
| Ergebnis: einmalig, im Chat | Ergebnis: **dauerhaft** — konfiguriert, geplant, governt, mandantenfähig, dem Kunden gehörend |
|
||||
|
||||
**Was das für Kunden bedeutet — «next level»:**
|
||||
- **Massgeschneidert ohne Massanzug-Kosten:** der exakte Fall (Plings 5 Stores, ihre Konten-Ranges) ohne bespoke Entwicklung.
|
||||
- **Tage statt Monate**, Self-Service statt Vendor-Backlog.
|
||||
- **Grenzkosten eines neuen Use Cases → nahe null:** Konfiguration, nicht Code.
|
||||
|
||||
**Zu Ende gedacht (ehrlich, kein Hype):**
|
||||
- Es verschwindet *nicht* alle Software. Die **Bausteine** (Connectors, Actions, Engine) und einige **tiefe Features** (eigenes Datenmodell/UI, z. B. `lawyer`) bleiben klassisch geschriebene Software. Der Wechsel passiert in der **Mitte**: die vielen massgeschneiderten Einzellösungen, die man bisher pro Kunde gebaut hat, werden zu **Konfiguration**. Engineering wandert nach **unten** (haltbare, wiederverwendbare Primitive) und nach **oben** (AI-gestützte Konfiguration) — und verschwindet aus der teuren Mitte. Das ist exakt die Feature-vs-Solution-Grenze.
|
||||
- **Vertrauen ist Voraussetzung, kein Nachgedanke.** Wenn AI/Konfiguration komponiert, braucht es Leitplanken — typisierte Actions, Neutralisierung, Review-vor-Aktivierung, Testlauf ohne Versand. Im Treuhand-/Finanzkontext ist das Pflicht. PORTA hat diese Leitplanken bereits — das macht «konfigurieren statt coden» hier *seriös* möglich.
|
||||
- **Der Moat** ist nicht ein einzelnes Feature, sondern die **Toolbox + Kompositions-Engine + die AI, die Absicht → Komposition** übersetzt.
|
||||
|
||||
**In einem Satz:** PORTA verkauft künftig nicht «eine App», sondern die **Fähigkeit, jeden wiederkehrenden Geschäfts-Use-Case zu konfigurieren** — der konfigurierte Use Case ist das Asset, nicht der handgeschriebene Code.
|
||||
|
||||
## Beschreibung und Kontext
|
||||
|
||||
Viele Kunden (v. a. im Feature **Trustee**) haben **dasselbe Grundmuster** an Bedürfnissen. Die Kern-Logik:
|
||||
|
||||
> Ein Kunde hat kein «Workflow-Problem», sondern ein **Bedürfnis**. Dieses Bedürfnis lässt sich als **Use Case** formulieren, daraus wird — AI-gestützt — ein **Workflow** aus vorhandenen Bausteinen komponiert, **einmal konfiguriert**, **getriggert** (manuell oder per Zeitplan) und dessen **Ergebnis angesehen**. Drumherum braucht es eine **Verwaltung**, mit der ein Business-User genau das selbst tut — ohne dass wir pro Kunde Code schreiben.
|
||||
|
||||
Konkrete Bedürfnisse, immer dieselbe Logik:
|
||||
- Zwei Systeme synchronisieren, einmal einstellen, täglich um 06:00 via Scheduler (Solution S1, → `0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`).
|
||||
- **Monatsreporting über mehrere Buchhaltungen** (Pling «Kaffee-Klatsch»): am 15. des Monats aus 5 RMA-Buchhaltungen konsolidieren, 6 PDF-Reports erzeugen, **rollenbasiert** per Mail verteilen (Solution S2, → `0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`; Spec: `pamocreate/projects/poweron/customer-pling/20-spezifikation/20260522-workflow-spec-kaffee-klatsch.md` + Anhang).
|
||||
- Gescannte Jahresmietzinsbestätigungen verarbeiten + Antwortvorschläge (PWG-Pilot, Solution S3, → `0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`).
|
||||
- Mandatsvorbereitung + Dashboards (Feature, → `0-ideas/2026-06-CustomerCases-step3-features-plan.md`, B1).
|
||||
|
||||
**Beobachtung:** Alle vier Beispiele sind **Instanzen desselben Musters**: ein Bedürfnis wird durch eine **Komposition vorhandener Bausteine** (Connectors, Actions/Nodes, AI, Neutralisierung, Dashboards) erfüllt — nicht durch neuen, kundenspezifischen Code. Die Bausteine existieren bereits (Action Library, Graphical Editor, Scheduler, Templates, Connectors, Toolbox). **Was fehlt, ist die Schicht darüber:** eine generische, **kundentaugliche** Oberfläche, mit der ein Business-User (kein Techniker) eigene Workflows **anlegen lässt (AI), konfiguriert, testet, ausführt, ansieht und verwaltet**.
|
||||
|
||||
Business-Treiber:
|
||||
- Skaliert ohne Engineering pro Kunde/Workflow (das eigentliche Plattform-Versprechen).
|
||||
- Verwandelt jedes Kunden-«Bedürfnis» in ein Self-Service-Produkt → kürzeres Onboarding, höhere Marge.
|
||||
- Macht die bereits gebauten Bausteine endlich für Endkunden zugänglich (heute nur über den technischen Editor).
|
||||
|
||||
## Fokus und kritische Details
|
||||
|
||||
- **Das Problem ist NICHT «noch ein Feature», sondern eine fehlende Produkt-Schicht.** Wir bauen kein viertes Buchhaltungs-Detail, sondern die generische **Lifecycle-Verwaltung** für kundeneigene Workflows.
|
||||
- **Trennung Baustein ↔ Kundenlogik ist Plattform-Gesetz** (gilt schon für Connectors): Bausteine = Code; konkrete Kundenlösung = **Daten** (Graph + Settings + Trigger + Output-Bindung).
|
||||
- **«Settings in den Notes» ist die falsche Abkürzung.** Einstellungen in Freitext-Notes abzulegen ist verlockend, aber ein Hack. Architektonisch braucht es ein **strukturiertes, validiertes Settings-Modell** pro Workflow (typisiert, versioniert).
|
||||
- **Feature vs. Solution — die wichtigste Grenze.** Nicht jedes Bedürfnis rechtfertigt ein Code-Feature (wie `lawyer`). Default ist eine **konfigurierte Solution** (Template + Settings). Ein Code-Feature nur, wenn eigene Datenmodelle / tiefe opinionated UI / Domänenlogik nötig sind, die der Graph nicht ausdrücken kann (siehe Entscheidungstabelle).
|
||||
- **Zwei Personas, zwei Oberflächen:** Der **Graphical Editor** bleibt das technische Authoring-Tool (n8n-Stil). Neu kommt eine **Business-Oberfläche** (Lösungen verwalten), die den Graph *kapselt*. Sie ist die Antwort auf «wo stelle ich meine Sachen ein?».
|
||||
- **Fragile/relevante Stellen:** `AutoWorkflow/AutoVersion/AutoRun` (Greenfield-DB `poweron_graphicaleditor`), Scheduler (`mainScheduler.py`), Template-Scopes (`user|instance|mandate|system`), Action-Catalog (`/api/automation2/catalog`), Workflow-Agent-Toolbox (`workflow`-Tools: `addNode`, `bindNodeParameter`, …). Wir bauen **auf** diesen, nicht daneben.
|
||||
|
||||
## Ziel und Nicht-Ziele
|
||||
|
||||
- **Ziel:** Ein generisches **Solution-Konzept** definieren: «konfigurierte, getriggerte, kundentaugliche Verpackung eines Workflows», mit Settings-Schema, Trigger-Policy und Output-/Dashboard-Bindung — als **Daten pro Feature-Instanz**.
|
||||
- **Ziel:** Eine **kundenseitige Verwaltungs-Oberfläche** (Lifecycle: anlegen → konfigurieren → testen → aktivieren → ausführen → ansehen → verwalten), zuerst im Feature Trustee, dann feature-übergreifend wiederverwendbar.
|
||||
- **Ziel:** **AI-gestützte Erzeugung** «Use Case → Workflow» über den bestehenden Workflow-Agent.
|
||||
- **Ziel:** Ein **Use-Case-Katalog** (kuratierte System-Templates) als Startpunkt für die häufigsten Bedürfnisse.
|
||||
- **Ziel:** Architektur so, dass die vier Beispiele sauber als Spezialfälle abbildbar sind (Validierung unten).
|
||||
- **Explizit NICHT:** kundenspezifischer Code pro Workflow.
|
||||
- **Explizit NICHT:** den Graphical Editor ersetzen — wir kapseln ihn.
|
||||
- **Explizit NICHT:** Settings in Notes/Freitext.
|
||||
- **Explizit NICHT (jetzt):** Marktplatz/Sharing zwischen Mandanten, Billing-Redesign — später.
|
||||
|
||||
## Das wiederkehrende Muster (Kern der Architektur)
|
||||
|
||||
Jedes Kundenbedürfnis hat dieselbe Form:
|
||||
|
||||
```
|
||||
BEDÜRFNIS ──(als Use Case formuliert)──► WORKFLOW (Komposition von Bausteinen)
|
||||
│
|
||||
┌───────────────┬───────────────┬────┴────────┬──────────────┐
|
||||
SETTINGS TRIGGER DATENQUELLEN AI/LOGIK OUTPUT/VIEW
|
||||
(einmal einst.) (manuell/Zeit/ (Connectors; (Nodes/ (Dashboard/
|
||||
Event/Form) eigener Plan) Agent) Report/Mail/Tabelle)
|
||||
```
|
||||
|
||||
Beispiele auf dieselbe Form gebracht:
|
||||
|
||||
| Bedürfnis | Trigger | Bausteine (Nodes) | Settings | Output |
|
||||
|---|---|---|---|---|
|
||||
| 2 Systeme synchronisieren | `trigger.schedule` 06:00 | source-connector → `mapAccounts` → target-connector | Quelle/Ziel, Mapping | Sync-Log/Status |
|
||||
| **Monatsreporting 5 Buchhaltungen (Pling)** | `trigger.schedule` 15./06:00 + `trigger.manual` (rollen-beschränkt) | `loop`(5 Instanzen) → `refreshAccountingData` → `queryData`(Salden akt.+VJ) → `data.consolidate` → `ai.generateDocument`×6 → `rbac.queryUsersByRole` → `outlook.send` → `file.create` | Perioden, Konten-Ranges, Empfänger-Rollen, Cron, Branding | 6 PDFs + Mails + Lauf-Protokoll |
|
||||
| Mietzinsbestätigungen (PWG) | `trigger.schedule` | `sharepoint.listFiles` → `loop` → `extractFromFiles` → `ai.prompt` → `data.write` → `email.send` | Ordner, Abacus-Mandant, Empfänger | Übersichtstabelle + Mail |
|
||||
| Matter Preparation (Lawyer) | `trigger.manual/form` | `lawyer.prepareMatter` (Agent über Quellen) | Lookback, Quellen | Briefing + Dashboards |
|
||||
|
||||
→ **90 % des Kundenwerts ist Komposition, nicht Code.** Die Bausteine sind da. Die **Verpackung + Verwaltung** fehlt.
|
||||
|
||||
### Was der Pling-Fall zusätzlich schärft
|
||||
|
||||
Der Pling-«Kaffee-Klatsch»-Fall (vollständig spezifiziert inkl. Graph, Configs, Build-Items) zeigt zwei Verfeinerungen, die das Schema bestätigen statt es zu brechen:
|
||||
|
||||
1. **Eine Solution kann über mehrere Feature-Instanzen fan-out-en.** Ein Mandant hat hier **5 Trustee-Instanzen** (1 pro Store); die Solution läuft per `flow.loop` über alle. → Solution-**Scope** ist nicht zwingend «1 Instanz», sondern «ein Set von Instanzen eines Mandanten». Das Settings-Modell muss eine Instanz-Auswahl tragen.
|
||||
2. **Die «Kundenspezifika» sind durchweg Daten — die Lücken sind generische Bausteine.** Was Pling besonders macht (5 Stores, Konten-Ranges 3000–3999/6000–6299/5000–5099, Empfänger, Cron), ist **Settings**. Was im Code fehlt, sind **zwei generische Plattform-Bausteine**, kein Kunden-Code:
|
||||
- `rbac.queryUsersByRole` — **rollenbasierte Empfänger-Auflösung** (Verteiler aus Trustee-Rollen statt gepflegter Listen). Wiederverwendbar für jedes Report-/Notification-Bedürfnis.
|
||||
- **Trigger-Zugriffskontrolle** (`accessControl.requiredRoles` im `triggerExecutor`) — damit nur z. B. `trustee-admin` den manuellen Lauf auslösen darf.
|
||||
|
||||
Genau diese Trennung ist die Architektur-These: *Kundenspezifika → Settings/Graph (Daten); was fehlt → generische L1/L2-Bausteine.*
|
||||
|
||||
Weitere wiederverwendbare Muster aus dem Fall: **Konsolidierung** mehrerer Instanzen (`data.consolidate` sumByKey), **selektive Neutralisierung** (nur Namen/Beschreibungen pseudonymisiert, Zahlen/Konten lesbar), **Teil-Resultat-Toleranz** (unvollständige Buchhaltung → durchlaufen mit Markierung, steuerbar per Settings-Flag `stopOnIncomplete`), **Archivierung** der Outputs als `TrusteeDocument`.
|
||||
|
||||
## Schichten-Modell (Zielarchitektur)
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────────────────────────────────────────┐
|
||||
│ L4 SOLUTION SURFACE (kundentaugliche UX, pro Feature-Seite) NEU │
|
||||
│ «Lösungen»: Katalog · Anlegen(AI) · Settings · Test · Runs · View │
|
||||
├───────────────────────────────────────────────────────────────────────────┤
|
||||
│ L3 SOLUTION DEFINITION (Use Case → konfigurierter Workflow) NEU │
|
||||
│ Solution = Template/Version + Settings-Schema + Trigger-Policy + Output │
|
||||
│ Use-Case-Katalog · AI-Generierung · strukturierte Settings (kein Notes) │
|
||||
├───────────────────────────────────────────────────────────────────────────┤
|
||||
│ L2 COMPOSITION (Graph) VORHANDEN │
|
||||
│ AutoWorkflow/Version/Run · Graphical Editor · Templates (scopes) │
|
||||
├───────────────────────────────────────────────────────────────────────────┤
|
||||
│ L1 PLATTFORM-TOOLBOX (Bausteine) VORHANDEN │
|
||||
│ Connectors/Datenquellen · Action Library (Methods/Actions=Nodes) · │
|
||||
│ AI/Agent+Toolbox · Neutralisierung · Knowledge/RAG · Scheduler · │
|
||||
│ Dashboards-Primitive · RBAC · Multi-Tenancy │
|
||||
└───────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**L1/L2 existieren** (siehe `b-reference/platform-core/workflow.md`, `automation.md`). **L3/L4 sind neu** und der eigentliche Gegenstand dieses Dokuments.
|
||||
|
||||
### L3 — Solution Definition (das neue Kern-Konzept)
|
||||
|
||||
Eine **Solution** ist die kundentaugliche Verpackung eines Workflows:
|
||||
|
||||
| Bestandteil | Inhalt | Baut auf |
|
||||
|---|---|---|
|
||||
| **Workflow-Bindung** | Referenz auf `AutoWorkflow` + `PUBLISHED` `AutoVersion` | vorhanden |
|
||||
| **Settings-Schema** | typisierte, validierte Parameter, die der Kunde einstellen darf (z. B. «SharePoint-Ordner», «Empfänger», «Periode», «Konten-Mapping») | `FrontendType`/Typed-Action-System, `trigger.form`-Schema |
|
||||
| **Settings-Werte** | konkrete Belegung pro Solution (inkl. **Instanz-Auswahl** bei Multi-Instanz-Fan-out, z. B. Pling 5 Stores) | neu (Record) |
|
||||
| **Trigger-Policy** | manuell / Zeitplan / Event / Form, inkl. **Zugriffskontrolle** (welche Rolle darf manuell auslösen) | Scheduler + Trigger-Nodes (+ `accessControl`) |
|
||||
| **Output-/View-Bindung** | was der Kunde nach dem Lauf sieht — `kind: file \| table \| summary` (Dashboard später); siehe «Output-Bindung — Empfehlung» | `file.create`/Datenraum, FormGenerator/Data-Tables, `AutoRun`/`AutoStepLog` |
|
||||
| **Katalog-Herkunft** | aus Use-Case-Template instanziiert ODER per AI generiert | System-Templates + Workflow-Agent |
|
||||
|
||||
**Designentscheidung (bestätigt 2026-06-04):** Solution **nicht** als grosse neue Parallel-Welt bauen, sondern als **dünne Erweiterung** auf `AutoWorkflow` (Settings-Schema + Presentation-Binding + «is customer-facing»-Flag) plus einen **Settings-Record**. Das hält eine einzige Workflow-Wahrheit (Scheduler, Runs, Versioning greifen unverändert).
|
||||
|
||||
**Settings statt Notes:** Das Settings-Schema wird aus dem Graphen abgeleitet (Trigger-Form / als «exposed» markierte Node-Parameter) und/oder kuratiert. Validierung + Verschlüsselung (für Secrets) wie bei Connector-Configs. Das ist die saubere, wartbare Alternative zu Einstellungen in Freitext-Notes.
|
||||
|
||||
### L4 — Solution Surface (kundentaugliche UX)
|
||||
|
||||
Eine **Seite pro Feature** (Start: Trustee), Name «**Lösungen**», mit dem Lifecycle:
|
||||
|
||||
```
|
||||
[Katalog/Neu] [Meine Lösungen] [Detail einer Lösung]
|
||||
├─ Use-Case wählen ├─ Liste (aktiv/inaktiv) ├─ Settings (Formular)
|
||||
├─ oder beschreiben (AI) ├─ Status letzter Lauf ├─ Test / Probelauf
|
||||
└─ → erzeugt Workflow ├─ nächster geplanter Lauf ├─ Aktivieren + Zeitplan
|
||||
└─ Run-Historie ├─ Run-Trace (lesbar)
|
||||
├─ Output/Dashboard
|
||||
└─ «Im Editor öffnen» (Advanced)
|
||||
```
|
||||
|
||||
- **UI-Struktur (Antwort auf Frage 1):** **Eine** Seite «Lösungen» pro Feature — *kein* Seiten-Wildwuchs und keine Aufblähung der technischen Automation-UI. Diese eine Seite hat **Unteransichten** (Liste · Katalog/Neu · Detail) und das **Detail hat Tabs**: *Einstellungen · Testlauf · Läufe · Ausgabe*.
|
||||
- Business-User bleibt in L4; «Im Editor öffnen» ist die **Escape-Hatch** nach L2 für Power-User/uns.
|
||||
- Wiederverwendung: Run-Historie/Trace existiert (`AutoRun`/`AutoStepLog`, SSE `runs/{runId}/stream`); wir rendern es nur **kundentauglich** statt technisch.
|
||||
- Verknüpfung zum Datenquellen-Plan: «Datenquellen» (Connectors) ist eine Schwester-Seite; «Lösungen» nutzt die dort konfigurierten Quellen.
|
||||
|
||||
### AI: Use Case → Workflow
|
||||
|
||||
Der bestehende **Workflow-Agent** (Toolbox `workflow`: `readWorkflowGraph`, `addNode`, `bindNodeParameter`, `listUpstreamPaths`, …) ist bereits der Mechanismus, um aus einer Beschreibung einen Graphen zu bauen/ändern. L3 stellt ihm:
|
||||
1. den **Use-Case-Text** des Kunden,
|
||||
2. den **Action-Catalog** (verfügbare Bausteine, `/api/automation2/catalog`),
|
||||
3. die **konfigurierten Datenquellen** der Instanz,
|
||||
bereit und lässt ihn einen Graphen erzeugen → als Draft-Version speichern → der Kunde konfiguriert nur noch die Settings. Kuratierte **System-Templates** decken die häufigsten Fälle deterministisch ab (kein AI-Risiko); AI nur für Neues/Abweichendes, **mit Review-/Freigabe-Schritt vor Aktivierung**.
|
||||
|
||||
## Feature vs. Solution — die Architektur-Entscheidung
|
||||
|
||||
| Kriterium | → **Solution** (Daten/Config) | → **Feature** (Code) |
|
||||
|---|---|---|
|
||||
| Eigene Datenmodelle nötig? | nein (nutzt bestehende) | ja (z. B. `LawyerMatter`) |
|
||||
| Tiefe, opinionated UI? | nein (generische Solution-UX) | ja (z. B. Matter-Preparation-View) |
|
||||
| Aus Bausteinen komponierbar? | ja | nein (Domänenlogik) |
|
||||
| Time-to-value | Tage | Wochen |
|
||||
| Beispiel | SelectLine→RMA-Sync, Monatsbericht, PWG-Pilot | `lawyer`, `commcoach`, `trustee` selbst |
|
||||
|
||||
**Leitsatz:** *Solution-first.* Ein Code-Feature wird nur gebaut, wenn die Solution-Schicht es nachweislich nicht trägt. So bleibt die Plattform schlank und die «keine Kundenlogik im Code»-Regel real.
|
||||
|
||||
## Validierung an den Beispielen
|
||||
|
||||
| Beispiel | Abbildung in dieser Architektur |
|
||||
|---|---|
|
||||
| **Umsystem-Integration** (SelectLine→RMA) | L1: SelectLine/RMA-Connectors · L2: Import-Graph · L3: Solution «Systeme synchronisieren» (Settings: Quelle/Ziel/Mapping/Zeitplan) · L4: erscheint unter «Lösungen» neben «Datenquellen» |
|
||||
| **Pling Kaffee-Klatsch** (Monatsreporting) | L1: 5× RMA-Connector, Outlook, `data.consolidate`, `ai.generateDocument` · L2: Fan-out-Graph (`loop` über 5 Instanzen, Konsolidierung, 2 Report-Loops, Verteilung) · L3: Solution mit Settings (5 Instanzen, Konten-Ranges, Cron, Empfänger-Rollen, `stopOnIncomplete`) + Output (6 PDFs, archiviert) · L4: «Jetzt ausführen» (rollen-beschränkt), Run-Historie, Status. **Deckt 2 generische Bausteinlücken auf** (`rbac.queryUsersByRole`, Trigger-`accessControl`) — kein Kunden-Code. |
|
||||
| **PWG-Pilot** (Mietzinsbestätigungen) | L1: SharePoint/Abacus/Email/extract/ai · L2: 7-Schritt-Graph · L3: Solution mit Settings (Ordner, Mandant, Empfänger) + Output-Tabelle · L4: Test/Aktivieren/Run-Historie |
|
||||
| **Lawyer-Feature** | Mischfall: **Feature** (eigene Modelle + opinionated UI) **plus** Solutions darin (Matter-Prep, Dashboard-Refresh). Bestätigt die Feature-vs-Solution-Grenze. |
|
||||
|
||||
→ Alle vier passen ohne Architektur-Bruch. Das Muster trägt. Der Pling-Fall ist der **stärkste Beleg**: vollständig spezifiziert, ~2 Wochen Build, fast ausschliesslich vorhandene Bausteine — und die einzigen Code-Lücken sind **generisch**, nicht kundenspezifisch.
|
||||
|
||||
## Betroffene Module (Skizze)
|
||||
|
||||
- **Gateway:**
|
||||
- `features/graphicalEditor/` — `AutoWorkflow` um Settings-Schema + Presentation-Binding + `customerFacing`-Flag erweitern; Settings-Record-Modell. **DB-Migration: ja (Greenfield, additiv).**
|
||||
- `workflows/scheduler/mainScheduler.py` — unverändert nutzbar (Trigger-Policy mappt auf bestehende Schedule-Logik).
|
||||
- `interfaces/interfaceBootstrap.py` — Use-Case-Katalog als System-Templates.
|
||||
- `serviceCenter/services/serviceAgent/` (Toolbox `workflow`) — Use-Case→Graph-Generierung; ggf. Prompt/Guardrails ergänzen.
|
||||
- Solution-Routes (CRUD Settings, Test-Run, Activate) — dünn über bestehende Editor-/Run-Routes.
|
||||
- **Generische Bausteine aus dem Pling-Fall** (wiederverwendbar, kein Kunden-Code): neue Action `rbac.queryUsersByRole` (rollenbasierte Empfänger-Auflösung) und `triggerExecutor`-Erweiterung um `accessControl.requiredRoles` (Rollen-Check beim manuellen Trigger).
|
||||
- **Testlauf-Modus:** run-level `testMode` im Run-Context; kommunikations-/seiteneffekt-Actions (Mail/Outlook/Teams/Webhook) prüfen das Flag und unterdrücken den ausgehenden Versand (loggen «würde senden an …»). Reports/Dateien werden trotzdem erzeugt (siehe Frage 7).
|
||||
- Solution-Scope: Settings müssen ein **Set von Feature-Instanzen** referenzieren können (Multi-Instanz-Fan-out, z. B. 5 Stores).
|
||||
- **Frontend (ui-nyla):**
|
||||
- Neue generische **`SolutionsView`** (Katalog · Liste · Detail mit Settings-Formular · Test · Runs · Output), als Feature-Seite registriert (analog `FeatureView.tsx` VIEW_COMPONENTS + UI-Areas in `main<Feature>.py`).
|
||||
- Settings-Formular-Renderer aus dem Settings-Schema (FrontendType-getrieben).
|
||||
- **DB-Migration:** ja (additiv auf Greenfield-DB).
|
||||
- **Andere:** RBAC (neue UI-Area, customer-facing Rollen), Neutralisierung (unverändert über Services), Billing (Run-Volumen).
|
||||
|
||||
## Entscheidungen (Vorschläge — zu bestätigen)
|
||||
|
||||
| Datum | Entscheidung | Begründung |
|
||||
|-------|-------------|------------|
|
||||
| 2026-06-04 | Neue **Solution-Schicht (L3/L4)** statt neues Feature pro Bedürfnis | Skaliert ohne Code pro Kunde |
|
||||
| 2026-06-04 | Solution = **dünne Erweiterung von `AutoWorkflow`** + Settings-Record (keine Parallel-Welt) | Eine Workflow-Wahrheit; Scheduler/Runs/Versioning unverändert |
|
||||
| 2026-06-04 | **Strukturierte Settings** statt Notes | Validierbar, versioniert, sicher (Secrets) |
|
||||
| 2026-06-04 | **Solution-first**, Feature nur bei eigenem Datenmodell/Tiefe | «keine Kundenlogik im Code» real halten |
|
||||
| 2026-06-04 | Start im Feature **Trustee**, Schicht aber **feature-übergreifend** designen | breiteste Wiederverwendung |
|
||||
| 2026-06-04 | Solution-Scope = **Set von Feature-Instanzen** (nicht nur eine) | Pling-Fan-out (5 Stores) bricht sonst das Modell |
|
||||
| 2026-06-04 | Rollenbasierte Verteilung als **generischer Baustein** (`rbac.queryUsersByRole`) | aus Pling abgeleitet, wiederverwendbar für jedes Report-/Notification-Bedürfnis |
|
||||
| 2026-06-04 | UI = **eine «Lösungen»-Seite pro Feature** mit Unteransichten (Liste/Detail) + Tabs im Detail | kein Seiten-Wildwuchs; Technik-UI bleibt unangetastet (Frage 1) |
|
||||
| 2026-06-04 | Settings-Schema **automatisch abgeleitet** (aus `trigger.form`/exposed Params) | minimaler Pflegeaufwand; Overrides später (Frage 2) |
|
||||
| 2026-06-04 | **AI-Generierung ja** — Templates deterministisch, AI nur für Neues + Review vor Aktivierung | Geschwindigkeit ohne Kontrollverlust (Frage 3) |
|
||||
| 2026-06-04 | RBAC: **bestehende Feature-Rollen** nutzen, keine neuen customer-facing Rollen | weniger Komplexität; konsistent zu Feature (Frage 5) |
|
||||
| 2026-06-04 | Naming: **«Lösungen»** (engl. *Solutions*) | bestätigt (Frage 6) |
|
||||
| 2026-06-04 | Testlauf = **realer Lauf mit `testMode`** (Kommunikation unterdrückt, Artefakte erzeugt) | echtes Verhalten testen, ohne ungewollte Mails (Frage 7) |
|
||||
| 2026-06-04 | Output-Bindung **gestuft** (`file`/`table`/`summary` jetzt, `dashboard` später) | nutzt Vorhandenes; keine BI-Engine bauen (Frage 4 — Detail offen) |
|
||||
|
||||
## Beantwortete Fragen (Entscheid 2026-06-04)
|
||||
|
||||
1. **Daten-Heimat:** ✅ **`AutoWorkflow` erweitern** (kein eigenes Solution-Modell).
|
||||
*UI-Konsequenz (deine Frage):* Die Backend-Erweiterung berührt die technische Automation-UI (Graphical Editor / Ops) **nicht** — es entstehen **nicht** «viele Automation-Seiten». Stattdessen **eine** neue kundentaugliche Seite **«Lösungen» pro Feature**, die denselben `AutoWorkflow` nur anders *präsentiert*. Aufbau: **Liste** (aktiv/inaktiv, letzter/nächster Lauf) · **Katalog/Neu** (Vorlage oder AI) · **Detail mit Tabs** (*Einstellungen · Testlauf · Läufe · Ausgabe*). Also: **eine Seite pro Feature, Unteransichten + Tabs im Detail** — siehe Mockup.
|
||||
2. **Settings-Schema-Quelle:** ✅ **Automatisch abgeleitet** aus `trigger.form` + als «exposed» markierten Node-Parametern. (Kuratierte Overrides bei Bedarf später.)
|
||||
3. **AI-Generierung:** ✅ **Ja.** Katalog-Templates deterministisch; AI nur für Neues, mit Review-/Freigabe-Schritt vor Aktivierung.
|
||||
4. **Output/Dashboard:** ⚠️ **Richtung entschieden, Detail offen — Empfehlung im nächsten Abschnitt.**
|
||||
5. **RBAC:** ✅ **Bestehende Feature-Rollen** (z. B. `trustee-admin` anlegen/aktivieren/manuell starten; `trustee-*` ansehen). Keine neuen customer-facing Rollen.
|
||||
6. **Naming:** ✅ **«Lösungen»** (engl. *Solutions*).
|
||||
7. **Test/Probelauf:** ✅ **Realer Lauf, Kommunikation blockierbar.** Der Testlauf läuft echt (echte Daten/Bausteine), nur **ausgehende Kommunikation wird unterdrückt** via run-level **`testMode`**: Mail/Outlook/Teams/Webhook-Actions prüfen das Flag und senden nicht (loggen «würde senden an …»). Reports/Dateien entstehen trotzdem. Sauberer als ein vollständig isolierter Mock-Run.
|
||||
|
||||
## Output-Bindung — Empfehlung (Frage 4)
|
||||
|
||||
Der schwierigste Punkt, weil «Output» von «PDF im Mail-Anhang» bis «interaktives Dashboard» reicht. **Empfehlung: gestuft, kleinster tragfähiger Kern zuerst — keine generische Dashboard-Engine bauen.** Eine Solution deklariert eine `outputBinding` mit einem `kind`:
|
||||
|
||||
| `kind` | Was der Kunde sieht | Baut auf (vorhanden) | deckt ab |
|
||||
|---|---|---|---|
|
||||
| `file` | Liste erzeugter Dokumente (PDF/XLSX), Öffnen/Download | `file.create` → `TrusteeDocument` / Datenraum | Pling, SelectLine-Log |
|
||||
| `table` | Ergebnis-Tabelle (sortier-/filterbar) | FormGenerator / Data-Tables (`queryData`) | PWG-Übersicht |
|
||||
| `summary` | Status/Kennzahlen + Lauf-Protokoll | `AutoRun`/`AutoStepLog` (Run-Trace) | jeder Sync/Lauf |
|
||||
| `none` | nur Lauf-Status | — | reine Mail-Workflows |
|
||||
|
||||
- **Jetzt bauen:** `file`, `table`, `summary` — alle nutzen Vorhandenes, kein neuer Renderer-Stack. Deckt alle vier Cases ab.
|
||||
- **Später:** Rich-Dashboards über die **bestehende AI-Report-/Canvas-Pipeline** wiederverwenden (`kind: dashboard`), nicht neu erfinden.
|
||||
- **Abgrenzung (wichtig):** Braucht ein Kunde eine **tiefe, opinionated Dashboard-UI**, ist das das Signal für ein **Feature** (Code), nicht für eine Solution. Die Output-Bindung bleibt bewusst schlank — sie *zeigt* Ergebnisse, sie ist keine BI-Engine.
|
||||
- **Detail beim Bauen (offen):** genaues `outputBinding`-Schema (wie referenzieren wir das Artefakt — Run-Output-Key vs. Document-Query) und ob `table`-Spalten frei konfigurierbar sind oder aus dem Node-Output abgeleitet werden. *Vorschlag:* aus Node-Output ableiten (konsistent zu Frage 2).
|
||||
|
||||
## Meine Gedanken / Empfehlung
|
||||
|
||||
- **Das ist kein Feature, das ist *die* Produktisierung der Plattform.** Bisher ist PORTA ein Werkzeugkasten mit zwei Enden (technischer Editor + Ops-Dashboard). Die fehlende Mitte — eine kundentaugliche **Solution-Schicht** — ist der Hebel, der aus «wir bauen pro Kunde» ein skalierendes SaaS macht.
|
||||
- **Nichts Neues erfinden, verpacken.** Alle Bausteine (Graph, Templates, Scheduler, Agent, Connectors) sind da. Der Aufwand liegt in **L3 (Settings/Trigger/Output als Daten)** und **L4 (eine gute, einfache UX)** — nicht in neuer Engine.
|
||||
- **Die wichtigste Disziplin ist die Feature-vs-Solution-Grenze.** Ohne sie bauen wir wieder pro Kunde ein Feature (siehe die Klassifikationstabelle im `CustomerCases-step3-solutions-plan`). Mit ihr wird der Default «konfigurieren statt coden».
|
||||
- **Settings strukturieren, nicht in Notes.** Das ist die kleine Entscheidung mit grosser Wirkung: sie macht Solutions wartbar, sicher und versionierbar.
|
||||
- **Pling als idealer erster realer Beleg.** Der Fall ist bereits voll spezifiziert (~2 Wochen Build) und braucht nur zwei *generische* Ergänzungen (`rbac.queryUsersByRole`, Trigger-`accessControl`). Er beweist die These am konkreten Geld-Use-Case und liefert nebenbei wiederverwendbare Bausteine.
|
||||
- **Inkrementeller erster Schnitt:** (1) `AutoWorkflow` um Settings-Schema + `customerFacing` + Instanz-Set erweitern; (2) 1–2 kuratierte System-Templates (z. B. «Systeme synchronisieren» und «Periodisches Reporting» aus Pling); (3) minimale `SolutionsView` (Liste + Settings + Test + Aktivieren + Run-Historie) im Trustee. Damit ist das Muster end-to-end belegt — demonstrierbar am SelectLine→RMA- **und** am Pling-Fall.
|
||||
- **Verhältnis zu den anderen Plänen:** Der Umsystem-/Datenquellen-Plan liefert **L1-Connectors**; dieser Plan liefert **L3/L4**. Lawyer ist ein **Feature**, das L1–L4 konsumiert. Drei Pläne, eine Architektur.
|
||||
|
||||
## Links
|
||||
|
||||
- Beispiel Reporting/Fan-out (Pling): `pamocreate/projects/poweron/customer-pling/20-spezifikation/20260522-workflow-spec-kaffee-klatsch.md` (+ `-anhang.md`)
|
||||
- Umsetzungsplan Solutions (alle konfigurierten Use Cases): `c-work/0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`
|
||||
- Umsetzungsplan Features & Bausteine (der Code dahinter): `c-work/0-ideas/2026-06-CustomerCases-step3-features-plan.md`
|
||||
- Kommunikation: Product Summary `c-work/0-ideas/2026-06-CustomerCases-step2-communication-product-summary.md` (+ `.pdf`), Mockup `c-work/0-ideas/2026-06-CustomerCases-step2-communication-mockup.html`
|
||||
- Bausteine: `b-reference/platform-core/workflow.md`, `b-reference/platform-core/automation.md`
|
||||
- Datenquellen-Trennung: `b-reference/platform/unified-data-bar.md`
|
||||
|
||||
## Abschluss
|
||||
|
||||
- [x] Offene Fragen beantwortet (Entscheid 2026-06-04); Detail Output-Bindung beim Bauen
|
||||
- [ ] Bei Annahme → Plan-Dokument in `c-work/1-plan/` (erster Schnitt, Trustee)
|
||||
- [ ] `b-reference/` Kanon-Seite «Solutions / Customer Workflows» nach Umsetzung
|
||||
- [ ] `TOPICS.md` Eintrag
|
||||
|
|
@ -0,0 +1,762 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>PORTA · Lösungen (Solution-Schicht Mockup)</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=DM+Sans:opsz,wght@9..40,400;9..40,500;9..40,600;9..40,700&display=swap" rel="stylesheet" />
|
||||
<style>
|
||||
:root {
|
||||
--color-bg: #F8F9FA;
|
||||
--bg-primary: #ffffff;
|
||||
--bg-secondary: #F7FAFC;
|
||||
--bg-dark: #EDF2F7;
|
||||
--surface-color: #F7FAFC;
|
||||
--text-primary: #1A202C;
|
||||
--text-secondary: #4A5568;
|
||||
--text-tertiary: #718096;
|
||||
--border-color: #E2E8F0;
|
||||
--border-dark: #CBD5E0;
|
||||
--primary-color: #4A6FA5;
|
||||
--primary-color-dark: #3D5D8A;
|
||||
--primary-light: rgba(74, 111, 165, 0.1);
|
||||
--primary-color-light: rgba(74, 111, 165, 0.15);
|
||||
--success: #38A169;
|
||||
--success-bg: #C6F6D5;
|
||||
--warning: #D69E2E;
|
||||
--warning-bg: #FAF089;
|
||||
--error: #C53030;
|
||||
--error-bg: #FED7D7;
|
||||
--gray: #718096;
|
||||
--radius-lg: 10px;
|
||||
--radius-md: 8px;
|
||||
--radius-sm: 6px;
|
||||
--font: "DM Sans", system-ui, -apple-system, sans-serif;
|
||||
}
|
||||
* { box-sizing: border-box; }
|
||||
html, body { margin: 0; padding: 0; height: 100%; }
|
||||
body {
|
||||
font-family: var(--font);
|
||||
background: var(--bg-primary);
|
||||
color: var(--text-primary);
|
||||
font-size: 14px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
/* ===== App shell ===== */
|
||||
.app { display: flex; height: 100vh; overflow: hidden; }
|
||||
.sidebar {
|
||||
width: 280px; min-width: 280px; height: 100%;
|
||||
background: var(--surface-color);
|
||||
border-right: 1px solid var(--border-color);
|
||||
display: flex; flex-direction: column;
|
||||
}
|
||||
.logo {
|
||||
display: flex; align-items: center; gap: 8px;
|
||||
padding: 20px 18px; border-bottom: 1px solid var(--border-color);
|
||||
font-size: 22px; font-weight: 700; letter-spacing: -0.02em;
|
||||
}
|
||||
.logo .dot { width: 28px; height: 28px; border-radius: 8px; background: linear-gradient(135deg, var(--primary-color), var(--primary-color-dark)); display:flex; align-items:center; justify-content:center; color:#fff; font-size:15px; }
|
||||
.logo .pow { color: var(--text-primary); }
|
||||
.logo .on { color: var(--primary-color); }
|
||||
.nav { flex: 1; overflow-y: auto; padding: 12px 10px; }
|
||||
.nav .group { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-tertiary); padding: 14px 10px 6px; }
|
||||
.nav a {
|
||||
display: flex; align-items: center; gap: 10px;
|
||||
padding: 9px 12px; border-radius: var(--radius-sm);
|
||||
color: var(--text-secondary); text-decoration: none; font-weight: 500;
|
||||
margin: 1px 0; cursor: pointer; font-size: 13.5px;
|
||||
}
|
||||
.nav a:hover { background: rgba(0,0,0,0.03); color: var(--text-primary); }
|
||||
.nav a.active { background: var(--primary-light); color: var(--primary-color-dark); font-weight: 600; }
|
||||
.nav a .ic { width: 18px; text-align: center; opacity: 0.85; }
|
||||
.nav .sub { padding-left: 14px; border-left: 1px solid var(--border-color); margin-left: 16px; }
|
||||
.userbox { padding: 14px; border-top: 1px solid var(--border-color); display: flex; align-items: center; gap: 10px; }
|
||||
.avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--primary-color); color: #fff; display:flex; align-items:center; justify-content:center; font-weight:600; font-size:13px; }
|
||||
.userbox .meta { line-height: 1.2; }
|
||||
.userbox .nm { font-weight: 600; font-size: 13px; }
|
||||
.userbox .rl { font-size: 11px; color: var(--text-tertiary); }
|
||||
|
||||
/* ===== Main ===== */
|
||||
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; overflow: hidden; }
|
||||
.topbar {
|
||||
height: 56px; flex-shrink: 0; border-bottom: 1px solid var(--border-color);
|
||||
display: flex; align-items: center; justify-content: space-between; padding: 0 24px;
|
||||
background: var(--bg-primary);
|
||||
}
|
||||
.crumb { font-size: 13px; color: var(--text-tertiary); }
|
||||
.crumb b { color: var(--text-primary); font-weight: 600; }
|
||||
.topbar .right { display: flex; align-items: center; gap: 14px; color: var(--text-tertiary); font-size: 13px; }
|
||||
.content { flex: 1; overflow-y: auto; padding: 24px 28px; background: var(--bg-primary); }
|
||||
.wrap { max-width: 1180px; margin: 0 auto; }
|
||||
|
||||
/* ===== Page header ===== */
|
||||
.pagehead { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 22px; }
|
||||
.pagehead h1 { margin: 0 0 4px; font-size: 23px; font-weight: 700; letter-spacing: -0.01em; }
|
||||
.pagehead p { margin: 0; color: var(--text-secondary); font-size: 13.5px; max-width: 640px; }
|
||||
|
||||
/* ===== Buttons ===== */
|
||||
.btn { display: inline-flex; align-items: center; gap: 8px; border: none; border-radius: var(--radius-sm); font-family: var(--font); font-weight: 500; font-size: 14px; padding: 8px 18px; cursor: pointer; transition: all .18s cubic-bezier(.4,0,.2,1); letter-spacing: .01em; white-space: nowrap; }
|
||||
.btn-primary { background: linear-gradient(180deg, var(--primary-color), var(--primary-color-dark)); color: #fff; box-shadow: 0 1px 2px rgba(0,0,0,.12), inset 0 1px 0 rgba(255,255,255,.12); }
|
||||
.btn-primary:hover { transform: translateY(-1px); box-shadow: 0 2px 6px rgba(0,0,0,.16); }
|
||||
.btn-secondary { background: #fff; color: var(--text-secondary); border: 1px solid var(--border-color); box-shadow: 0 1px 2px rgba(0,0,0,.06); }
|
||||
.btn-secondary:hover { background: var(--gray); color: #fff; border-color: var(--gray); }
|
||||
.btn-success { background: linear-gradient(180deg, var(--success), #2F855A); color: #fff; }
|
||||
.btn-success:hover { transform: translateY(-1px); }
|
||||
.btn-ghost { background: transparent; color: var(--primary-color); border: 1px solid transparent; }
|
||||
.btn-ghost:hover { background: var(--primary-light); }
|
||||
.btn-sm { padding: 6px 13px; font-size: 12.5px; }
|
||||
.btn[disabled] { opacity: .5; cursor: not-allowed; }
|
||||
|
||||
/* ===== Cards / list ===== */
|
||||
.toolbar { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
|
||||
.search { flex: 1; max-width: 320px; position: relative; }
|
||||
.search input { width: 100%; padding: 8px 12px 8px 32px; border: 1px solid var(--border-color); border-radius: var(--radius-sm); font-family: var(--font); font-size: 13.5px; background: #fff; }
|
||||
.search .ic { position: absolute; left: 10px; top: 50%; transform: translateY(-50%); color: var(--text-tertiary); }
|
||||
.seg { display: inline-flex; border: 1px solid var(--border-color); border-radius: var(--radius-sm); overflow: hidden; }
|
||||
.seg button { border: none; background: #fff; padding: 7px 14px; font-family: var(--font); font-size: 13px; color: var(--text-secondary); cursor: pointer; }
|
||||
.seg button.on { background: var(--primary-light); color: var(--primary-color-dark); font-weight: 600; }
|
||||
.seg button + button { border-left: 1px solid var(--border-color); }
|
||||
|
||||
.sol-list { display: grid; gap: 12px; }
|
||||
.sol-card {
|
||||
border: 1px solid var(--border-color); border-radius: var(--radius-md); background: #fff;
|
||||
padding: 16px 18px; display: grid; grid-template-columns: 42px 1fr auto; gap: 14px; align-items: center;
|
||||
cursor: pointer; transition: all .15s ease;
|
||||
}
|
||||
.sol-card:hover { border-color: var(--border-dark); box-shadow: 0 4px 14px rgba(0,0,0,.06); transform: translateY(-1px); }
|
||||
.sol-ic { width: 42px; height: 42px; border-radius: var(--radius-md); display: flex; align-items: center; justify-content: center; font-size: 20px; background: var(--primary-light); }
|
||||
.sol-main .nm { font-weight: 600; font-size: 15px; margin-bottom: 3px; }
|
||||
.sol-main .ds { color: var(--text-secondary); font-size: 13px; }
|
||||
.sol-meta { display: flex; flex-direction: column; align-items: flex-end; gap: 6px; text-align: right; }
|
||||
.sol-meta .line { font-size: 12px; color: var(--text-tertiary); }
|
||||
.sol-meta .line b { color: var(--text-secondary); font-weight: 600; }
|
||||
|
||||
.badge { display: inline-flex; align-items: center; gap: 5px; font-size: 11.5px; font-weight: 600; padding: 3px 9px; border-radius: 999px; }
|
||||
.badge .d { width: 7px; height: 7px; border-radius: 50%; }
|
||||
.b-active { background: var(--success-bg); color: #22643f; }
|
||||
.b-active .d { background: var(--success); }
|
||||
.b-inactive { background: #EDF2F7; color: var(--text-secondary); }
|
||||
.b-inactive .d { background: var(--gray); }
|
||||
.b-error { background: var(--error-bg); color: #822; }
|
||||
.b-error .d { background: var(--error); }
|
||||
.b-running { background: var(--primary-light); color: var(--primary-color-dark); }
|
||||
.b-running .d { background: var(--primary-color); animation: pulse 1.2s infinite; }
|
||||
.b-warn { background: #FEFCBF; color: #744210; }
|
||||
.b-warn .d { background: var(--warning); }
|
||||
@keyframes pulse { 0%,100%{opacity:1;} 50%{opacity:.3;} }
|
||||
|
||||
/* ===== Detail ===== */
|
||||
.backlink { display: inline-flex; align-items: center; gap: 6px; color: var(--text-secondary); font-size: 13px; cursor: pointer; margin-bottom: 14px; background:none; border:none; font-family:var(--font); padding:0;}
|
||||
.backlink:hover { color: var(--primary-color); }
|
||||
.detail-head { display: flex; align-items: flex-start; gap: 16px; margin-bottom: 18px; }
|
||||
.detail-head .sol-ic { width: 52px; height: 52px; font-size: 25px; }
|
||||
.detail-head h1 { margin: 0 0 5px; font-size: 21px; }
|
||||
.detail-head .sub { color: var(--text-secondary); font-size: 13px; }
|
||||
.detail-actions { margin-left: auto; display: flex; gap: 8px; align-items: center; }
|
||||
|
||||
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border-color); margin-bottom: 22px; }
|
||||
.tabs button { border: none; background: none; font-family: var(--font); font-size: 14px; font-weight: 500; color: var(--text-secondary); padding: 11px 16px; cursor: pointer; border-bottom: 2px solid transparent; margin-bottom: -1px; }
|
||||
.tabs button:hover { color: var(--text-primary); }
|
||||
.tabs button.on { color: var(--primary-color-dark); border-bottom-color: var(--primary-color); font-weight: 600; }
|
||||
|
||||
.tabpane { display: none; }
|
||||
.tabpane.on { display: block; animation: fade .2s ease; }
|
||||
@keyframes fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
|
||||
|
||||
.grid2 { display: grid; grid-template-columns: 1fr 320px; gap: 22px; align-items: start; }
|
||||
@media (max-width: 900px){ .grid2 { grid-template-columns: 1fr; } }
|
||||
|
||||
.card { border: 1px solid var(--border-color); border-radius: var(--radius-md); background: #fff; overflow: hidden; }
|
||||
.card-h { padding: 13px 16px; border-bottom: 1px solid var(--border-color); font-weight: 600; font-size: 14px; background: var(--bg-secondary); display:flex; align-items:center; justify-content:space-between; }
|
||||
.card-h .hint { font-weight: 500; font-size: 11.5px; color: var(--text-tertiary); }
|
||||
.card-b { padding: 16px; }
|
||||
|
||||
.field { margin-bottom: 16px; }
|
||||
.field:last-child { margin-bottom: 0; }
|
||||
.field label { display: block; font-weight: 600; font-size: 12.5px; margin-bottom: 6px; }
|
||||
.field .desc { font-size: 11.5px; color: var(--text-tertiary); margin: -3px 0 7px; }
|
||||
.field input[type=text], .field input[type=number], .field select, .field textarea {
|
||||
width: 100%; padding: 8px 11px; border: 1px solid var(--border-color); border-radius: var(--radius-sm);
|
||||
font-family: var(--font); font-size: 13.5px; background: #fff; color: var(--text-primary);
|
||||
}
|
||||
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--primary-color); box-shadow: 0 0 0 3px var(--primary-light); }
|
||||
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
||||
.chips { display: flex; flex-wrap: wrap; gap: 7px; }
|
||||
.chip { display: inline-flex; align-items: center; gap: 6px; background: var(--primary-light); color: var(--primary-color-dark); border-radius: 999px; padding: 5px 11px; font-size: 12.5px; font-weight: 500; }
|
||||
.chip .x { cursor: pointer; opacity: .6; }
|
||||
.chip.add { background: #fff; border: 1px dashed var(--border-dark); color: var(--text-secondary); cursor: pointer; }
|
||||
.toggle { display: inline-flex; align-items: center; gap: 9px; cursor: pointer; }
|
||||
.switch { width: 38px; height: 22px; border-radius: 999px; background: var(--success); position: relative; transition: background .2s; }
|
||||
.switch::after { content: ""; position: absolute; top: 2px; left: 18px; width: 18px; height: 18px; border-radius: 50%; background: #fff; transition: left .2s; box-shadow: 0 1px 2px rgba(0,0,0,.2); }
|
||||
.switch.off { background: var(--border-dark); }
|
||||
.switch.off::after { left: 2px; }
|
||||
|
||||
.sidecard .kv { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px dashed var(--border-color); font-size: 13px; }
|
||||
.sidecard .kv:last-child { border-bottom: none; }
|
||||
.sidecard .kv span { color: var(--text-tertiary); }
|
||||
.sidecard .kv b { font-weight: 600; }
|
||||
|
||||
table.runs { width: 100%; border-collapse: collapse; font-size: 13px; }
|
||||
table.runs th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-tertiary); padding: 9px 14px; border-bottom: 1px solid var(--border-color); background: var(--bg-secondary); }
|
||||
table.runs td { padding: 11px 14px; border-bottom: 1px solid var(--border-color); }
|
||||
table.runs tr:hover td { background: var(--bg-secondary); }
|
||||
table.runs tr:last-child td { border-bottom: none; }
|
||||
.mono { font-family: ui-monospace, "SF Mono", Menlo, monospace; font-size: 12px; color: var(--text-secondary); }
|
||||
|
||||
/* run trace steps */
|
||||
.trace { display: grid; gap: 8px; }
|
||||
.step { display: grid; grid-template-columns: 24px 1fr auto; gap: 11px; align-items: center; padding: 10px 13px; border: 1px solid var(--border-color); border-radius: var(--radius-sm); background: #fff; }
|
||||
.step .dotc { width: 24px; height: 24px; border-radius: 50%; display: flex; align-items: center; justify-content: center; font-size: 12px; color: #fff; }
|
||||
.step .nm { font-weight: 500; }
|
||||
.step .nm small { color: var(--text-tertiary); font-weight: 400; }
|
||||
.step .dur { font-size: 12px; color: var(--text-tertiary); }
|
||||
.ok { background: var(--success); }
|
||||
.warnc { background: var(--warning); }
|
||||
|
||||
/* output files */
|
||||
.files { display: grid; gap: 10px; }
|
||||
.file { display: grid; grid-template-columns: 38px 1fr auto; gap: 12px; align-items: center; padding: 11px 14px; border: 1px solid var(--border-color); border-radius: var(--radius-sm); background: #fff; }
|
||||
.file .pic { width: 38px; height: 38px; border-radius: var(--radius-sm); background: var(--error-bg); color: #9b2c2c; display: flex; align-items: center; justify-content: center; font-weight: 700; font-size: 11px; }
|
||||
.file .nm { font-weight: 500; }
|
||||
.file .mt { font-size: 12px; color: var(--text-tertiary); }
|
||||
|
||||
.graph-strip { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 14px; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: var(--radius-md); margin-top: 14px; }
|
||||
.gnode { background: #fff; border: 1px solid var(--border-dark); border-radius: var(--radius-sm); padding: 7px 11px; font-size: 12px; font-weight: 500; display: flex; align-items: center; gap: 6px; }
|
||||
.gnode .tag { font-size: 10px; background: var(--primary-light); color: var(--primary-color-dark); padding: 1px 6px; border-radius: 4px; font-weight: 600; }
|
||||
.garrow { color: var(--text-tertiary); }
|
||||
.gnode.ai { border-color: var(--primary-color); }
|
||||
|
||||
.note { display: flex; gap: 9px; padding: 11px 13px; border-radius: var(--radius-sm); font-size: 12.5px; line-height: 1.5; }
|
||||
.note-info { background: var(--primary-light); color: var(--primary-color-dark); }
|
||||
.note-warn { background: #FEFCBF; color: #744210; }
|
||||
|
||||
/* ===== Modal ===== */
|
||||
.overlay { position: fixed; inset: 0; background: rgba(26,32,44,.5); display: none; align-items: center; justify-content: center; z-index: 100; padding: 24px; }
|
||||
.overlay.on { display: flex; }
|
||||
.modal { background: #fff; border-radius: var(--radius-lg); width: 100%; max-width: 720px; max-height: 88vh; overflow: hidden; display: flex; flex-direction: column; box-shadow: 0 24px 60px rgba(0,0,0,.3); }
|
||||
.modal-h { padding: 18px 22px; border-bottom: 1px solid var(--border-color); display: flex; align-items: center; justify-content: space-between; }
|
||||
.modal-h h2 { margin: 0; font-size: 18px; }
|
||||
.modal-h .close { background: none; border: none; font-size: 22px; color: var(--text-tertiary); cursor: pointer; line-height: 1; }
|
||||
.modal-b { padding: 22px; overflow-y: auto; }
|
||||
.modal-f { padding: 16px 22px; border-top: 1px solid var(--border-color); display: flex; justify-content: flex-end; gap: 10px; }
|
||||
|
||||
.tmpl-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
|
||||
@media (max-width: 640px){ .tmpl-grid { grid-template-columns: 1fr; } }
|
||||
.tmpl { border: 1px solid var(--border-color); border-radius: var(--radius-md); padding: 14px; cursor: pointer; transition: all .15s; }
|
||||
.tmpl:hover, .tmpl.sel { border-color: var(--primary-color); background: var(--primary-light); }
|
||||
.tmpl .ti { font-size: 22px; margin-bottom: 8px; }
|
||||
.tmpl .tn { font-weight: 600; font-size: 14px; margin-bottom: 3px; }
|
||||
.tmpl .td { font-size: 12px; color: var(--text-secondary); }
|
||||
.divider { display: flex; align-items: center; gap: 12px; margin: 20px 0; color: var(--text-tertiary); font-size: 12px; }
|
||||
.divider::before, .divider::after { content: ""; flex: 1; height: 1px; background: var(--border-color); }
|
||||
|
||||
.toast { position: fixed; bottom: 24px; left: 50%; transform: translateX(-50%) translateY(20px); background: var(--text-primary); color: #fff; padding: 12px 20px; border-radius: var(--radius-md); font-size: 13.5px; font-weight: 500; box-shadow: 0 8px 24px rgba(0,0,0,.25); opacity: 0; transition: all .25s; z-index: 200; display: flex; align-items: center; gap: 9px; }
|
||||
.toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
|
||||
.toast .d { width: 8px; height: 8px; border-radius: 50%; background: var(--success); }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="app">
|
||||
<!-- Sidebar -->
|
||||
<aside class="sidebar">
|
||||
<div class="logo"><span class="dot">P</span><span><span class="pow">Power</span><span class="on">On</span></span></div>
|
||||
<nav class="nav">
|
||||
<div class="group">Plattform</div>
|
||||
<a><span class="ic">▦</span> Dashboard</a>
|
||||
<a><span class="ic">✦</span> Workspace</a>
|
||||
<div class="group">Feature · Trustee</div>
|
||||
<a><span class="ic">▤</span> Übersicht</a>
|
||||
<a><span class="ic">🧾</span> Belege</a>
|
||||
<a><span class="ic">📊</span> Buchhaltungssystem</a>
|
||||
<a><span class="ic">🔌</span> Datenquellen</a>
|
||||
<a class="active"><span class="ic">⚙</span> Lösungen</a>
|
||||
<div class="group">Administration</div>
|
||||
<a><span class="ic">👥</span> Benutzer & Rollen</a>
|
||||
<a><span class="ic">💳</span> Abrechnung</a>
|
||||
</nav>
|
||||
<div class="userbox">
|
||||
<div class="avatar">PB</div>
|
||||
<div class="meta"><div class="nm">Päde Bruderer</div><div class="rl">trustee-admin · Pling</div></div>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Main -->
|
||||
<div class="main">
|
||||
<div class="topbar">
|
||||
<div class="crumb">Trustee · <b id="crumb">Lösungen</b></div>
|
||||
<div class="right"><span>Kaffee-Klatsch Holding</span><span>·</span><span>◑ Hell</span></div>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="wrap">
|
||||
|
||||
<!-- ===================== VIEW: LIST ===================== -->
|
||||
<section id="viewList">
|
||||
<div class="pagehead">
|
||||
<div>
|
||||
<h1>Lösungen</h1>
|
||||
<p>Wiederkehrende Aufgaben als konfigurierte Workflows — einmal einstellen, automatisch laufen lassen, Ergebnisse ansehen. Kein Code nötig.</p>
|
||||
</div>
|
||||
<button class="btn btn-primary" onclick="openCatalog()"><span>+</span> Neue Lösung</button>
|
||||
</div>
|
||||
|
||||
<div class="toolbar">
|
||||
<div class="search"><span class="ic">⌕</span><input type="text" placeholder="Lösungen durchsuchen…" /></div>
|
||||
<div class="seg">
|
||||
<button class="on">Alle</button>
|
||||
<button>Aktiv</button>
|
||||
<button>Inaktiv</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sol-list" id="solList"></div>
|
||||
</section>
|
||||
|
||||
<!-- ===================== VIEW: DETAIL ===================== -->
|
||||
<section id="viewDetail" style="display:none;">
|
||||
<button class="backlink" onclick="showList()">← Zurück zu Lösungen</button>
|
||||
<div class="detail-head">
|
||||
<div class="sol-ic" id="dIcon">📊</div>
|
||||
<div>
|
||||
<h1 id="dName">—</h1>
|
||||
<div class="sub" id="dSub">—</div>
|
||||
</div>
|
||||
<div class="detail-actions">
|
||||
<button class="btn btn-secondary btn-sm" onclick="toast('Workflow im Graphical Editor geöffnet')">Im Editor öffnen</button>
|
||||
<button class="btn btn-success btn-sm" id="dRunBtn" onclick="runNow()">▶ Jetzt ausführen</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tabs">
|
||||
<button class="on" onclick="switchTab(event,'tEinst')">Einstellungen</button>
|
||||
<button onclick="switchTab(event,'tTest')">Testlauf</button>
|
||||
<button onclick="switchTab(event,'tRuns')">Läufe</button>
|
||||
<button onclick="switchTab(event,'tOut')">Ausgabe</button>
|
||||
</div>
|
||||
|
||||
<!-- TAB: Einstellungen -->
|
||||
<div class="tabpane on" id="tEinst">
|
||||
<div class="grid2">
|
||||
<div style="display:grid; gap:18px;">
|
||||
<div class="card">
|
||||
<div class="card-h">Konfiguration <span class="hint">aus settingsSchema generiert</span></div>
|
||||
<div class="card-b" id="settingsBody"></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-h">Trigger & Zeitplan</div>
|
||||
<div class="card-b" id="triggerBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:grid; gap:18px;">
|
||||
<div class="card sidecard">
|
||||
<div class="card-h">Status</div>
|
||||
<div class="card-b" id="statusBody"></div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-h">Workflow</div>
|
||||
<div class="card-b">
|
||||
<div style="font-size:12.5px; color:var(--text-secondary); margin-bottom:8px;">Diese Lösung kapselt einen Graphen aus vorhandenen Bausteinen:</div>
|
||||
<div id="graphStrip"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display:flex; justify-content:flex-end; gap:10px; margin-top:18px;">
|
||||
<button class="btn btn-secondary" onclick="showList()">Abbrechen</button>
|
||||
<button class="btn btn-primary" onclick="toast('Einstellungen gespeichert')">Speichern</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TAB: Testlauf -->
|
||||
<div class="tabpane" id="tTest">
|
||||
<div class="card">
|
||||
<div class="card-h">Probelauf (Dry-Run) <span class="hint">keine Mails, keine Seiteneffekte</span></div>
|
||||
<div class="card-b">
|
||||
<p style="margin-top:0; color:var(--text-secondary); font-size:13.5px;">Führt die Lösung mit den aktuellen Einstellungen testweise aus. Reports werden erzeugt und angezeigt, aber <b>nicht</b> versendet.</p>
|
||||
<button class="btn btn-primary" onclick="startTest()">▶ Testlauf starten</button>
|
||||
<div id="testTrace" style="margin-top:18px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TAB: Läufe -->
|
||||
<div class="tabpane" id="tRuns">
|
||||
<div class="card">
|
||||
<div class="card-h">Lauf-Historie</div>
|
||||
<table class="runs" id="runsTable"></table>
|
||||
</div>
|
||||
<div class="card" style="margin-top:18px;">
|
||||
<div class="card-h">Lauf-Trace <span class="hint">Lauf #1042 · 15.05.2026 06:00</span></div>
|
||||
<div class="card-b">
|
||||
<div class="trace" id="traceBody"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TAB: Ausgabe -->
|
||||
<div class="tabpane" id="tOut">
|
||||
<div class="card">
|
||||
<div class="card-h">Erzeugte Dokumente <span class="hint">archiviert im Mandanten-Datenraum</span></div>
|
||||
<div class="card-b"><div class="files" id="filesBody"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===================== MODAL: Katalog / Neu ===================== -->
|
||||
<div class="overlay" id="catalog">
|
||||
<div class="modal">
|
||||
<div class="modal-h">
|
||||
<h2>Neue Lösung anlegen</h2>
|
||||
<button class="close" onclick="closeCatalog()">×</button>
|
||||
</div>
|
||||
<div class="modal-b">
|
||||
<div style="font-weight:600; margin-bottom:12px; font-size:14px;">Aus Vorlage (Use-Case-Katalog)</div>
|
||||
<div class="tmpl-grid">
|
||||
<div class="tmpl" onclick="selTmpl(this)"><div class="ti">🔄</div><div class="tn">Systeme synchronisieren</div><div class="td">Quelle → Ziel, periodisch (z. B. SelectLine → RMA)</div></div>
|
||||
<div class="tmpl" onclick="selTmpl(this)"><div class="ti">📈</div><div class="tn">Periodisches Reporting</div><div class="td">Daten konsolidieren, PDF erzeugen, verteilen</div></div>
|
||||
<div class="tmpl" onclick="selTmpl(this)"><div class="ti">📥</div><div class="tn">Dokumente verarbeiten</div><div class="td">Dateien einlesen, KI-Auswertung, Antwort</div></div>
|
||||
<div class="tmpl" onclick="selTmpl(this)"><div class="ti">✉️</div><div class="tn">Benachrichtigung</div><div class="td">Bei Ereignis rollenbasiert mailen</div></div>
|
||||
</div>
|
||||
<div class="divider">oder mit KI beschreiben</div>
|
||||
<div class="field">
|
||||
<label>Beschreibe dein Bedürfnis — die KI baut den Workflow</label>
|
||||
<div class="desc">Der Workflow-Agent komponiert daraus einen Graphen aus vorhandenen Bausteinen. Du konfigurierst danach nur noch die Einstellungen.</div>
|
||||
<textarea rows="3" placeholder="z. B. «Schicke mir am 15. jedes Monats einen konsolidierten Bericht über alle 5 Store-Buchhaltungen und je einen Kennzahlen-Report an jeden Store-Manager.»"></textarea>
|
||||
</div>
|
||||
<div class="note note-info"><span>✦</span><span>Vorlagen werden deterministisch instanziiert (kein KI-Risiko). KI-Generierung erzeugt einen Entwurf, den du vor dem Aktivieren prüfst.</span></div>
|
||||
</div>
|
||||
<div class="modal-f">
|
||||
<button class="btn btn-secondary" onclick="closeCatalog()">Abbrechen</button>
|
||||
<button class="btn btn-primary" onclick="generateSolution()">✦ Lösung erstellen</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="toast" id="toast"><span class="d"></span><span id="toastMsg">Gespeichert</span></div>
|
||||
|
||||
<script>
|
||||
const solutions = {
|
||||
pling: {
|
||||
icon: "📊",
|
||||
name: "Monatsreporting Kaffee-Klatsch",
|
||||
sub: "Periodisches Reporting · 5 RMA-Buchhaltungen · aus Vorlage",
|
||||
status: "active",
|
||||
statusLabel: "Aktiv",
|
||||
lastRun: "15.05.2026 06:00 · erfolgreich",
|
||||
nextRun: "15.06.2026 06:00",
|
||||
restricted: true,
|
||||
kv: [
|
||||
["Status", '<span class="badge b-active"><span class="d"></span>Aktiv</span>'],
|
||||
["Letzter Lauf", "15.05.2026 · OK"],
|
||||
["Nächster Lauf", "15.06.2026 06:00"],
|
||||
["Läufe gesamt", "7"],
|
||||
["Erfolgsquote", "100%"],
|
||||
["Instanzen", "5 Stores"]
|
||||
],
|
||||
settings: `
|
||||
<div class="field">
|
||||
<label>Feature-Instanzen (Fan-out)</label>
|
||||
<div class="desc">Über welche Buchhaltungen läuft die Lösung — eine Solution, mehrere Instanzen.</div>
|
||||
<div class="chips">
|
||||
<span class="chip">Coffeeshop Zürich <span class="x">×</span></span>
|
||||
<span class="chip">Coffeeshop Bern <span class="x">×</span></span>
|
||||
<span class="chip">Coffeeshop Basel <span class="x">×</span></span>
|
||||
<span class="chip">Coffeeshop Luzern <span class="x">×</span></span>
|
||||
<span class="chip">Coffeeshop St. Gallen <span class="x">×</span></span>
|
||||
<span class="chip add">+ Instanz</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Berichts-Periode</label>
|
||||
<div class="row2">
|
||||
<select><option>Vormonat (Standard)</option><option>Year-to-date</option><option>Freie Periode</option></select>
|
||||
<input type="text" value="Mai 2026" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Konten-Bereiche</label>
|
||||
<div class="desc">Kundenspezifisch — als Settings, nicht im Code.</div>
|
||||
<div class="row2">
|
||||
<div><div style="font-size:11px;color:var(--text-tertiary);margin-bottom:4px;">Umsatz</div><input type="text" value="3000–3999"/></div>
|
||||
<div><div style="font-size:11px;color:var(--text-tertiary);margin-bottom:4px;">Warenkosten</div><input type="text" value="6000–6299"/></div>
|
||||
</div>
|
||||
<div class="row2" style="margin-top:10px;">
|
||||
<div><div style="font-size:11px;color:var(--text-tertiary);margin-bottom:4px;">Personalaufwand</div><input type="text" value="5000–5099"/></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Empfänger (rollenbasiert)</label>
|
||||
<div class="desc">Verteiler wird automatisch aus Trustee-Rollen aufgelöst — keine Listen pflegen (rbac.queryUsersByRole).</div>
|
||||
<div class="chips">
|
||||
<span class="chip">Holding-Bericht → trustee-accountant <span class="x">×</span></span>
|
||||
<span class="chip">Store-Kennzahlen → trustee-client <span class="x">×</span></span>
|
||||
<span class="chip">Lauf-Protokoll → trustee-admin <span class="x">×</span></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="toggle"><span class="switch off"></span> Bei unvollständiger Buchhaltung blockieren</label>
|
||||
<div class="desc">Aus = durchlaufen & im Bericht markieren (stopOnIncomplete: false). Ein = warten bis alle 5 fertig.</div>
|
||||
</div>`,
|
||||
trigger: `
|
||||
<div class="field">
|
||||
<label class="toggle"><span class="switch"></span> Geplant (Zeitplan)</label>
|
||||
<div class="desc" style="margin-left:48px;">Cron: <span class="mono">0 6 15 * *</span> · Europe/Zurich — am 15. um 06:00.</div>
|
||||
</div>
|
||||
<div class="row2">
|
||||
<div class="field"><label>Tag im Monat</label><input type="number" value="15"/></div>
|
||||
<div class="field"><label>Uhrzeit</label><input type="text" value="06:00"/></div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="toggle"><span class="switch"></span> Manueller Start erlaubt</label>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label>Wer darf manuell starten</label>
|
||||
<div class="desc">Zugriffskontrolle am Trigger (accessControl.requiredRoles).</div>
|
||||
<select><option>Nur trustee-admin</option><option>trustee-admin + trustee-accountant</option><option>Alle mit Zugriff</option></select>
|
||||
</div>`,
|
||||
graph: [
|
||||
["trigger", "Zeitplan / Manuell"],
|
||||
["loop", "5 Instanzen"],
|
||||
["trustee", "Salden holen"],
|
||||
["data", "Konsolidieren"],
|
||||
["ai", "6 PDFs erzeugen", true],
|
||||
["rbac", "Empfänger auflösen"],
|
||||
["outlook", "Versenden"]
|
||||
],
|
||||
runs: [
|
||||
["#1042", "15.05.2026 06:00", "Zeitplan", "active", "Erfolgreich", "2m 14s", "6 PDFs · 8 Mails"],
|
||||
["#1041", "15.04.2026 06:00", "Zeitplan", "warn", "Mit Hinweis", "2m 41s", "1 BuHa unvollständig"],
|
||||
["#1038", "15.03.2026 06:00", "Zeitplan", "active", "Erfolgreich", "2m 02s", "6 PDFs · 8 Mails"],
|
||||
["#1031", "21.02.2026 14:22", "Manuell · Päde", "active", "Erfolgreich", "2m 10s", "Ad-hoc YTD"]
|
||||
],
|
||||
trace: [
|
||||
["ok", "trigger.scheduled", "Cron 0 6 15 * *", "0.1s"],
|
||||
["ok", "flow.loop · 5 Instanzen", "parallel, concurrency 5", "1.2s"],
|
||||
["ok", "trustee.refreshAccountingData", "5/5 Buchhaltungen gesynct", "44s"],
|
||||
["ok", "trustee.queryData · Salden", "akt. + Vorjahr", "9s"],
|
||||
["ok", "data.consolidate", "sumByKey → HoldingFigures", "0.6s"],
|
||||
["ok", "ai.generateDocument · Holding", "1 PDF, neutralisiert", "31s"],
|
||||
["ok", "ai.generateDocument · Store-KPI ×5", "5 PDFs", "26s"],
|
||||
["ok", "rbac.queryUsersByRole", "8 Empfänger aufgelöst", "0.4s"],
|
||||
["ok", "outlook.send", "8 Mails versendet", "3s"]
|
||||
],
|
||||
files: [
|
||||
["Monatsbericht Holding Mai 2026", "PDF · 412 KB · Holding-Instanz", "PDF"],
|
||||
["Kennzahlen Coffeeshop Zürich", "PDF · 88 KB · Store-Instanz", "PDF"],
|
||||
["Kennzahlen Coffeeshop Bern", "PDF · 86 KB · Store-Instanz", "PDF"],
|
||||
["Kennzahlen Coffeeshop Basel", "PDF · 87 KB · Store-Instanz", "PDF"],
|
||||
["Kennzahlen Coffeeshop Luzern", "PDF · 85 KB · Store-Instanz", "PDF"],
|
||||
["Kennzahlen Coffeeshop St. Gallen", "PDF · 84 KB · Store-Instanz", "PDF"]
|
||||
]
|
||||
},
|
||||
selectline: {
|
||||
icon: "🔄",
|
||||
name: "SelectLine → RMA Sync",
|
||||
sub: "Systeme synchronisieren · täglich · aus Vorlage",
|
||||
status: "active", statusLabel: "Aktiv",
|
||||
lastRun: "04.06.2026 06:00 · erfolgreich", nextRun: "05.06.2026 06:00",
|
||||
restricted: false,
|
||||
kv: [
|
||||
["Status", '<span class="badge b-active"><span class="d"></span>Aktiv</span>'],
|
||||
["Letzter Lauf", "04.06.2026 · OK"],
|
||||
["Nächster Lauf", "05.06.2026 06:00"],
|
||||
["Läufe gesamt", "63"],
|
||||
["Erfolgsquote", "98%"]
|
||||
],
|
||||
settings: `
|
||||
<div class="field"><label>Quell-System</label><select><option>SelectLine (API)</option></select></div>
|
||||
<div class="field"><label>Ziel-System</label><select><option>RunMyAccounts (RMA)</option></select></div>
|
||||
<div class="field">
|
||||
<label>Konten-Mapping</label>
|
||||
<div class="desc">Zuordnung Quell- zu Zielkonten — kundenspezifisch, als Settings.</div>
|
||||
<div class="chips"><span class="chip">1000 → 1020 <span class="x">×</span></span><span class="chip">3400 → 3000 <span class="x">×</span></span><span class="chip add">+ Mapping</span></div>
|
||||
</div>
|
||||
<div class="field"><label class="toggle"><span class="switch"></span> Duplikat-Prüfung aktiv</label></div>`,
|
||||
trigger: `
|
||||
<div class="field"><label class="toggle"><span class="switch"></span> Geplant (täglich)</label><div class="desc" style="margin-left:48px;">Cron <span class="mono">0 6 * * *</span> · Europe/Zurich</div></div>
|
||||
<div class="field"><label>Uhrzeit</label><input type="text" value="06:00"/></div>`,
|
||||
graph: [["trigger","Täglich 06:00"],["selectline","Rechnungen lesen"],["data","Mapping"],["rma","Buchen", true]],
|
||||
runs: [
|
||||
["#0631","04.06.2026 06:00","Zeitplan","active","Erfolgreich","48s","14 Rechnungen"],
|
||||
["#0630","03.06.2026 06:00","Zeitplan","active","Erfolgreich","51s","9 Rechnungen"],
|
||||
["#0629","02.06.2026 06:00","Zeitplan","error","Fehler","12s","API-Timeout SelectLine"]
|
||||
],
|
||||
trace: [
|
||||
["ok","trigger.scheduled","Cron 0 6 * * *","0.1s"],
|
||||
["ok","selectline.listInvoices","14 neue Rechnungen","6s"],
|
||||
["ok","data.mapAccounts","Mapping angewandt","0.3s"],
|
||||
["ok","rma.pushInvoice","14 gebucht, 0 Duplikate","41s"]
|
||||
],
|
||||
files: [["Sync-Protokoll 04.06.2026","CSV · 12 KB","CSV"]]
|
||||
},
|
||||
pwg: {
|
||||
icon: "📥",
|
||||
name: "Mietzins-Bestätigungen (PWG)",
|
||||
sub: "Dokumente verarbeiten · Pilot · per KI generiert",
|
||||
status: "inactive", statusLabel: "Inaktiv (Entwurf)",
|
||||
lastRun: "—", nextRun: "nicht aktiviert",
|
||||
restricted: false,
|
||||
kv: [
|
||||
["Status", '<span class="badge b-inactive"><span class="d"></span>Inaktiv</span>'],
|
||||
["Herkunft", "KI-Entwurf"],
|
||||
["Letzter Lauf", "—"],
|
||||
["Nächster Lauf", "nicht aktiviert"]
|
||||
],
|
||||
settings: `
|
||||
<div class="field"><label>SharePoint-Ordner</label><input type="text" value="/Mietzins/Eingang 2026"/></div>
|
||||
<div class="field"><label>Abacus-Mandant</label><select><option>PWG Immobilien AG</option></select></div>
|
||||
<div class="field"><label>Empfänger (Übersicht)</label><div class="chips"><span class="chip">trustee-accountant <span class="x">×</span></span><span class="chip add">+ Rolle</span></div></div>
|
||||
<div class="note note-warn"><span>⚠</span><span>KI-Entwurf — bitte Einstellungen prüfen und einen Testlauf machen, bevor du aktivierst.</span></div>`,
|
||||
trigger: `<div class="field"><label class="toggle"><span class="switch off"></span> Geplant</label><div class="desc" style="margin-left:48px;">Noch nicht aktiviert.</div></div>`,
|
||||
graph: [["trigger","Manuell"],["sharepoint","Dateien lesen"],["loop","pro Datei"],["ai","Extrahieren", true],["data","Schreiben"],["email","Antwort"]],
|
||||
runs: [],
|
||||
trace: [],
|
||||
files: []
|
||||
}
|
||||
};
|
||||
|
||||
const listOrder = ["pling","selectline","pwg"];
|
||||
|
||||
function _badge(s){
|
||||
const map = { active:["b-active","Aktiv"], inactive:["b-inactive","Inaktiv"], error:["b-error","Fehler"], warn:["b-warn","Hinweis"], running:["b-running","Läuft"] };
|
||||
const [cls,lbl] = map[s] || map.inactive;
|
||||
return `<span class="badge ${cls}"><span class="d"></span>${lbl}</span>`;
|
||||
}
|
||||
|
||||
function renderList(){
|
||||
const el = document.getElementById("solList");
|
||||
el.innerHTML = listOrder.map(id => {
|
||||
const s = solutions[id];
|
||||
return `<div class="sol-card" onclick="showDetail('${id}')">
|
||||
<div class="sol-ic">${s.icon}</div>
|
||||
<div class="sol-main">
|
||||
<div class="nm">${s.name}</div>
|
||||
<div class="ds">${s.sub}</div>
|
||||
</div>
|
||||
<div class="sol-meta">
|
||||
${_badge(s.status)}
|
||||
<div class="line">Letzter Lauf: <b>${s.lastRun}</b></div>
|
||||
<div class="line">Nächster: <b>${s.nextRun}</b></div>
|
||||
</div>
|
||||
</div>`;
|
||||
}).join("");
|
||||
}
|
||||
|
||||
let current = null;
|
||||
function showDetail(id){
|
||||
current = id;
|
||||
const s = solutions[id];
|
||||
document.getElementById("crumb").textContent = s.name;
|
||||
document.getElementById("dIcon").textContent = s.icon;
|
||||
document.getElementById("dName").textContent = s.name;
|
||||
document.getElementById("dSub").textContent = s.sub;
|
||||
document.getElementById("settingsBody").innerHTML = s.settings;
|
||||
document.getElementById("triggerBody").innerHTML = s.trigger;
|
||||
document.getElementById("statusBody").innerHTML = s.kv.map(([k,v]) => `<div class="kv"><span>${k}</span><b>${v}</b></div>`).join("");
|
||||
|
||||
document.getElementById("graphStrip").innerHTML = `<div class="graph-strip">` + s.graph.map((g,i) => {
|
||||
const arrow = i < s.graph.length-1 ? '<span class="garrow">→</span>' : '';
|
||||
return `<div class="gnode ${g[2]?'ai':''}"><span class="tag">${g[0]}</span>${g[1]}</div>${arrow}`;
|
||||
}).join("") + `</div>`;
|
||||
|
||||
// run button restriction
|
||||
const rb = document.getElementById("dRunBtn");
|
||||
if (s.restricted){ rb.title = "Nur trustee-admin"; }
|
||||
|
||||
// runs table
|
||||
const rt = document.getElementById("runsTable");
|
||||
if (s.runs.length){
|
||||
rt.innerHTML = `<thead><tr><th>Lauf</th><th>Zeitpunkt</th><th>Auslöser</th><th>Status</th><th>Dauer</th><th>Ergebnis</th></tr></thead><tbody>` +
|
||||
s.runs.map(r => `<tr><td class="mono">${r[0]}</td><td>${r[1]}</td><td>${r[2]}</td><td>${_badge(r[3])}</td><td>${r[5]}</td><td>${r[6]}</td></tr>`).join("") +
|
||||
`</tbody>`;
|
||||
} else {
|
||||
rt.innerHTML = `<tbody><tr><td style="padding:24px; text-align:center; color:var(--text-tertiary);">Noch keine Läufe — Lösung ist nicht aktiviert.</td></tr></tbody>`;
|
||||
}
|
||||
|
||||
// trace
|
||||
document.getElementById("traceBody").innerHTML = s.trace.length
|
||||
? s.trace.map(t => `<div class="step"><span class="dotc ${t[0]==='ok'?'ok':'warnc'}">${t[0]==='ok'?'✓':'!'}</span><span class="nm">${t[1]} <small>· ${t[2]}</small></span><span class="dur">${t[3]}</span></div>`).join("")
|
||||
: `<div style="color:var(--text-tertiary); font-size:13px;">Kein Lauf vorhanden.</div>`;
|
||||
|
||||
// files
|
||||
document.getElementById("filesBody").innerHTML = s.files.length
|
||||
? s.files.map(f => `<div class="file"><span class="pic">${f[2]}</span><div><div class="nm">${f[0]}</div><div class="mt">${f[1]}</div></div><button class="btn btn-ghost btn-sm" onclick="toast('Download (Mockup)')">Öffnen</button></div>`).join("")
|
||||
: `<div style="color:var(--text-tertiary); font-size:13px;">Noch keine Dokumente erzeugt.</div>`;
|
||||
|
||||
document.getElementById("viewList").style.display = "none";
|
||||
document.getElementById("viewDetail").style.display = "block";
|
||||
// reset to first tab
|
||||
document.querySelectorAll("#viewDetail .tabs button").forEach((b,i)=>b.classList.toggle("on",i===0));
|
||||
document.querySelectorAll("#viewDetail .tabpane").forEach((p,i)=>p.classList.toggle("on",p.id==="tEinst"));
|
||||
document.getElementById("testTrace").innerHTML = "";
|
||||
document.querySelector(".content").scrollTop = 0;
|
||||
}
|
||||
|
||||
function showList(){
|
||||
current = null;
|
||||
document.getElementById("crumb").textContent = "Lösungen";
|
||||
document.getElementById("viewDetail").style.display = "none";
|
||||
document.getElementById("viewList").style.display = "block";
|
||||
}
|
||||
|
||||
function switchTab(e, id){
|
||||
document.querySelectorAll("#viewDetail .tabs button").forEach(b=>b.classList.remove("on"));
|
||||
e.currentTarget.classList.add("on");
|
||||
document.querySelectorAll("#viewDetail .tabpane").forEach(p=>p.classList.toggle("on",p.id===id));
|
||||
}
|
||||
|
||||
function startTest(){
|
||||
const s = solutions[current];
|
||||
const box = document.getElementById("testTrace");
|
||||
box.innerHTML = `<div class="note note-info"><span>✦</span><span>Testlauf gestartet — Dry-Run, keine Mails werden versendet.</span></div><div class="trace" id="liveTrace" style="margin-top:12px;"></div>`;
|
||||
const lt = document.getElementById("liveTrace");
|
||||
const steps = s.trace.length ? s.trace : [["ok","workflow.run","Beispiel-Schritt","1s"]];
|
||||
let i = 0;
|
||||
(function next(){
|
||||
if (i >= steps.length){ toast("Testlauf erfolgreich · 6 Dokumente erzeugt (nicht versendet)"); return; }
|
||||
const t = steps[i];
|
||||
const div = document.createElement("div");
|
||||
div.className = "step";
|
||||
div.innerHTML = `<span class="dotc ${t[0]==='ok'?'ok':'warnc'}">${t[0]==='ok'?'✓':'!'}</span><span class="nm">${t[1]} <small>· ${t[2]}</small></span><span class="dur">${t[3]}</span>`;
|
||||
div.style.opacity = 0;
|
||||
lt.appendChild(div);
|
||||
requestAnimationFrame(()=>{ div.style.transition="opacity .25s"; div.style.opacity=1; });
|
||||
i++; setTimeout(next, 420);
|
||||
})();
|
||||
}
|
||||
|
||||
function runNow(){
|
||||
const s = solutions[current];
|
||||
if (s.restricted) toast("Lauf gestartet (Rolle trustee-admin bestätigt) ▶");
|
||||
else toast("Lauf gestartet ▶");
|
||||
}
|
||||
|
||||
// catalog modal
|
||||
function openCatalog(){ document.getElementById("catalog").classList.add("on"); }
|
||||
function closeCatalog(){ document.getElementById("catalog").classList.remove("on"); document.querySelectorAll(".tmpl").forEach(t=>t.classList.remove("sel")); }
|
||||
function selTmpl(el){ document.querySelectorAll(".tmpl").forEach(t=>t.classList.remove("sel")); el.classList.add("sel"); }
|
||||
function generateSolution(){ closeCatalog(); toast("✦ Workflow erstellt — jetzt Einstellungen konfigurieren"); showDetail("pling"); }
|
||||
|
||||
// toast
|
||||
let toastTimer;
|
||||
function toast(msg){
|
||||
const t = document.getElementById("toast");
|
||||
document.getElementById("toastMsg").textContent = msg;
|
||||
t.classList.add("show");
|
||||
clearTimeout(toastTimer);
|
||||
toastTimer = setTimeout(()=>t.classList.remove("show"), 2600);
|
||||
}
|
||||
|
||||
document.getElementById("catalog").addEventListener("click", e => { if (e.target.id === "catalog") closeCatalog(); });
|
||||
|
||||
renderList();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<!-- status: idea -->
|
||||
<!-- started: 2026-06-04 -->
|
||||
<!-- component: gateway | ui-nyla | platform -->
|
||||
|
||||
# Solution-Schicht — Product Summary
|
||||
|
||||
> **In einem Satz:** Wir verpacken den vorhandenen Workflow-Stack in eine **Solution-Schicht**, mit der ein Business-Kunde seine wiederkehrenden Aufgaben selbst **anlegt, einstellt, testet, startet und ansieht** — ohne Code pro Kunde.
|
||||
>
|
||||
> Volldokument: `2026-06-CustomerCases-step1-architecture.md` · Mockup: `2026-06-CustomerCases-step2-communication-mockup.html` · Umsetzung: `2026-06-CustomerCases-step3-solutions-plan.md` / `-step3-features-plan.md`
|
||||
|
||||
## Die Idee dahinter
|
||||
|
||||
**Klassische Software ist von gestern.** Statt pro Problem eine Applikation zu *schreiben*, **konfigurieren** wir komplexe Use Cases aus vorhandenen Bausteinen — genau das, was eine AI heute schon tut, wenn sie assistiert: Absicht beschreiben → System komponiert das Ergebnis.
|
||||
|
||||
Die Solution-Schicht **produktisiert** das: Der Kunde beschreibt seinen Use Case, der Workflow-Agent komponiert den Graph, das Ergebnis läuft **dauerhaft, geplant und governt**. Massgeschneidert ohne Massanzug-Kosten, Tage statt Monate, Self-Service statt Vendor-Backlog. **Grenzkosten eines neuen Use Cases → fast null.**
|
||||
|
||||
Ehrlich zu Ende gedacht: Es verschwindet nicht *alle* Software — die **Bausteine** und einige **tiefe Features** bleiben Code. Aber die vielen massgeschneiderten Einzellösungen, die man bisher pro Kunde gebaut hat, werden zu **Konfiguration**. Genau das ist «konfigurieren statt coden» — der Hebel, der Kunden aufs nächste Level bringt.
|
||||
|
||||
## Das SaaS-Asset: Solution vs. Feature
|
||||
|
||||
PORTA hat heute zwei Enden: den technischen **Workflow-Editor** und das **Ops-Dashboard**. Es fehlt die **Mitte** — die kundentaugliche Schicht. Genau das ist das Produkt-Asset:
|
||||
|
||||
- **Solution = konfigurierter Workflow (Daten).** Aus Bausteinen komponiert, vom Kunden per Settings eingestellt. Time-to-value: **Tage**. Skaliert **ohne** Engineering pro Kunde.
|
||||
- **Feature = Code.** Eigene Datenmodelle + tiefe, eigene UI (z. B. `lawyer`). Time-to-value: **Wochen**. Nur wo nötig.
|
||||
|
||||
**Leitsatz: Solution-first.** Ein Feature bauen wir nur, wenn die Solution-Schicht es nachweislich nicht trägt. So wird «konfigurieren statt coden» der Default — und das macht aus «wir bauen pro Kunde» ein skalierendes SaaS.
|
||||
|
||||
| | Solution (Daten) | Feature (Code) |
|
||||
|---|---|---|
|
||||
| Datenmodell | nutzt bestehende | eigenes |
|
||||
| UI | generische «Lösungen»-Seite | eigene, opinionated |
|
||||
| Erstellung | Settings + Graph | Engineering |
|
||||
| Beispiele | Pling-Reporting, SelectLine→RMA, PWG | lawyer, commcoach, trustee |
|
||||
|
||||
## Die vier Schichten
|
||||
|
||||
| | Schicht | Inhalt | Status |
|
||||
|---|---|---|---|
|
||||
| **L4** | Solution Surface | Kundentaugliche UX: «Lösungen»-Seite (Liste · Katalog/AI · Detail mit Tabs) | **NEU** |
|
||||
| **L3** | Solution Definition | Use Case → konfigurierter Workflow: Settings-Schema + Werte + Trigger + Output | **NEU** |
|
||||
| **L2** | Composition | Graph: AutoWorkflow/Version/Run, Editor, Templates | vorhanden |
|
||||
| **L1** | Plattform-Toolbox | Connectors, Actions/Nodes, AI, Neutralisierung, Scheduler, RBAC | vorhanden |
|
||||
|
||||
→ **Unsere Arbeit liegt in L3 + L4.** L1/L2 nutzen wir unverändert.
|
||||
|
||||
## Grundlage: die Kunden-Cases
|
||||
|
||||
Wir bauen aus realen Cases, nicht aus einer Idee. Sie sind die **Akzeptanzkriterien**: trägt der Entwurf den Fall, ist er richtig.
|
||||
|
||||
| Case | Bedürfnis | Settings (= Kundenspezifika, Daten) | Output |
|
||||
|---|---|---|---|
|
||||
| **Pling** (Leit-Case) | 5 Buchhaltungen → 6 PDFs, rollenbasiert mailen, monatlich | 5 Instanzen, Konten-Ranges, Cron, Empfänger-Rollen | 6 PDFs + Mails |
|
||||
| **SelectLine→RMA** | Rechnungen täglich ins RMA buchen | Quelle/Ziel, Mapping | Sync-Log |
|
||||
| **PWG** | Mietzins-Belege verarbeiten + Antwort | Ordner, Mandant, Empfänger | Tabelle + Mail |
|
||||
| **Lawyer** | Mandatsvorbereitung + Dashboards | — | = **Feature**, nicht Solution |
|
||||
|
||||
Was die Cases erzwingen: **Multi-Instanz-Fan-out** (Pling: 1 Solution über 5 Instanzen) und zwei **generische** Bausteine (`rbac.queryUsersByRole`, Trigger-`accessControl`) — wiederverwendbar, kein Kunden-Code.
|
||||
|
||||
## L3 — Datenmodell (kurz)
|
||||
|
||||
Solution = **dünne Erweiterung von `AutoWorkflow`** + Settings-Record (keine Parallel-Welt → Scheduler/Runs/Versioning greifen unverändert). Felder:
|
||||
|
||||
`workflowRef` · `settingsSchema` (auto aus `trigger.form`/exposed Params) · `settingsValues` (inkl. **Instanz-Set**) · `triggerPolicy` (+ `accessControl.requiredRoles`) · `outputBinding` (`file | table | summary`) · `customerFacing`.
|
||||
|
||||
## L4 — UI (kurz)
|
||||
|
||||
**Eine** «Lösungen»-Seite pro Feature (Start: Trustee) — kein Seiten-Wildwuchs:
|
||||
|
||||
- **Liste** (aktiv/inaktiv, letzter/nächster Lauf)
|
||||
- **Katalog/Neu** (Vorlage wählen oder per AI beschreiben)
|
||||
- **Detail** mit Tabs: **Einstellungen · Testlauf · Läufe · Ausgabe**
|
||||
|
||||
Settings-Formular wird aus dem `settingsSchema` gerendert (FrontendType). «Im Editor öffnen» bleibt die Escape-Hatch nach L2.
|
||||
|
||||
## Bauen — erster Schnitt
|
||||
|
||||
1. `AutoWorkflow` um `settingsSchema` + `customerFacing` + Instanz-Set erweitern (+ Settings-Record, Migration).
|
||||
2. 2 System-Templates: «Systeme synchronisieren» (SelectLine→RMA) + «Periodisches Reporting» (Pling).
|
||||
3. Generische `SolutionsView` im Trustee: Liste + Settings + Testlauf + Aktivieren + Läufe.
|
||||
4. Generische Bausteine: `rbac.queryUsersByRole`, Trigger-`accessControl`, run-level `testMode` (Kommunikation im Testlauf unterdrücken).
|
||||
|
||||
→ End-to-end belegt an **SelectLine→RMA** und **Pling**.
|
||||
Binary file not shown.
191
c-work/0-ideas/2026-06-CustomerCases-step3-features-plan.md
Normal file
191
c-work/0-ideas/2026-06-CustomerCases-step3-features-plan.md
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
<!-- status: plan -->
|
||||
<!-- started: 2026-06-04 -->
|
||||
<!-- component: gateway | ui-nyla | platform -->
|
||||
<!-- replaces: 2026-06-STEP2-lawyer-feature.md, 2026-06-STEP2-umsystem-integration-connectors-und-datenquellen-seiten.md (Code-Teile), 2026-06-STEP2-pm-consolidated-customer-requirements.md (Feature/Plattform-Teile) -->
|
||||
|
||||
# Plan: Features & Plattform-Bausteine — der Code hinter den Solutions
|
||||
|
||||
> **Baut auf:** `2026-06-CustomerCases-step1-architecture.md` (Schichten L1–L4, Feature-vs-Solution-Grenze).
|
||||
> **Schwester-Plan:** `2026-06-CustomerCases-step3-solutions-plan.md` (die konfigurierten Use Cases, die diesen Code konsumieren).
|
||||
> **Konsolidiert/ersetzt:** Lawyer-Feature-Plan + die Code-/Plattform-Teile aus Umsystem-Integration und konsolidiertem Kundenwünsche-Plan.
|
||||
|
||||
## Beschreibung und Kontext
|
||||
|
||||
Ein **Feature** ist **Code**: eigenes Datenmodell und/oder tiefe, opinionated UI / Domänenlogik, die ein Graph nicht ausdrücken kann (step1-architecture, Entscheidungsmatrix). Dazu zählen auch die **Plattform-Bausteine**, die die Solutions erst möglich machen — sie sind generischer Code (L1/L2/L3/L4), **ohne Kundennamen**.
|
||||
|
||||
Dieser Plan bündelt allen **Code**, der zu bauen ist, in zwei Teilen:
|
||||
|
||||
- **Teil A — Plattform-Enabler:** die Solution-Schicht selbst (L3/L4), generische Workflow-Bausteine, Connectors, das «Datenquelle = Seite»-Muster. Voraussetzung für *alle* Solutions.
|
||||
- **Teil B — Vertikale Code-Features:** Module mit eigenem Datenmodell/UI (`lawyer`), bestehende Features (`commcoach`, `trustee`, `neutralization`) und ihre Erweiterungen.
|
||||
|
||||
**Leitsatz (step1-architecture):** Solution-first. Code bauen wir nur, wenn (a) es ein generischer Baustein ist, den viele Solutions teilen, oder (b) der Use Case nachweislich nicht als Solution trägt.
|
||||
|
||||
## Fokus und kritische Details
|
||||
|
||||
- **Generisch, nie kundenspezifisch.** Connectors = reine API-Adapter (Auth + Lesen/Schreiben + Mapping auf kanonische Modelle), keine Geschäftsregeln, keine Kundennamen. Kundenlogik lebt als Solution (Daten).
|
||||
- **Eine Workflow-Wahrheit.** Die Solution-Schicht ist eine **dünne Erweiterung von `AutoWorkflow`** + Settings-Record, keine Parallel-Welt → Scheduler/Runs/Versioning unverändert.
|
||||
- **Source vs. Target** ist die wichtigste neue Connector-Achse (macht aus dem Push-Framework ein bidirektionales Integrations-Framework).
|
||||
- **RBAC strikt feature-instance-scoped**, nicht mit Mandate-Rollen vermischen (`.cursor/rules/rbac-role-separation.mdc`).
|
||||
- **Neutralisierung + Private LLM** zwingend für jeden LLM-Pfad mit Personendaten (Trustee, Lawyer/Berufsgeheimnis StGB 321).
|
||||
- **YAGNI bei Connector-Abstraktion:** beim bestehenden `BaseAccountingConnector` bleiben und nur die **Source-Rolle** ergänzen; das generische «Capability-Mixin»-Framework erst ziehen, wenn die zweite Kategorie (Saläre) real wird.
|
||||
|
||||
## Teil A — Plattform-Enabler (macht Solutions möglich)
|
||||
|
||||
### A1 — Solution-Schicht (L3/L4)
|
||||
|
||||
- **`AutoWorkflow` erweitern** um `settingsSchema`, `outputBinding`, `customerFacing`-Flag, **Instanz-Set** (Multi-Instanz-Fan-out). **DB-Migration: ja (Greenfield, additiv).**
|
||||
- **Settings-Record-Modell** (`settingsValues` pro Solution/Instanz; Secrets verschlüsselt wie Connector-Configs).
|
||||
- **`settingsSchema` automatisch ableiten** aus `trigger.form` + als «exposed» markierten Node-Params (kuratierte Overrides später).
|
||||
- **Solution-Routes** (dünn über bestehende Editor-/Run-Routes): CRUD Settings, Test-Run, Activate/Deactivate.
|
||||
- **`SolutionsView`** (ui-nyla): generische «Lösungen»-Seite pro Feature — Liste · Katalog/Neu · Detail mit Tabs (Einstellungen · Testlauf · Läufe · Ausgabe). Settings-Formular aus `settingsSchema` (FrontendType-getrieben). Registriert wie andere Views (`FeatureView.tsx` + UI-Areas in `main<Feature>.py`).
|
||||
- **Use-Case-Katalog** als System-Templates (`interfaces/interfaceBootstrap.py`).
|
||||
- **AI: Use Case → Workflow** über bestehenden Workflow-Agent (Toolbox `workflow`), Draft + Review vor Aktivierung.
|
||||
- **Output-Renderer** für `outputBinding.kind` = `file` (Datenraum/`TrusteeDocument`), `table` (FormGenerator/Data-Tables), `summary` (`AutoRun`/`AutoStepLog`). `dashboard` später (AI-Report/Canvas-Pipeline).
|
||||
|
||||
### A2 — Generische Workflow-Bausteine (Nodes/Actions)
|
||||
|
||||
| Baustein | Zweck | Status |
|
||||
|---|---|---|
|
||||
| `rbac.queryUsersByRole` | rollenbasierte Empfänger-Auflösung (Verteiler aus Feature-Rollen statt Listen) | **neu** |
|
||||
| Trigger-`accessControl.requiredRoles` (in `triggerExecutor`) | nur erlaubte Rolle darf manuell auslösen | **neu** |
|
||||
| run-level `testMode` | Testlauf real, Kommunikations-/Seiteneffekt-Nodes (Mail/Outlook/Teams/Webhook) unterdrücken Versand (loggen «würde senden …») | **neu** |
|
||||
| `integration.fetchFromSource` / `integration.mapAccounts` / `integration.pushToTarget` | system-agnostischer Source→Target-Import (Quelle/Ziel = Config) | **neu** |
|
||||
| `data.consolidate` (sumByKey) | Aggregation mehrerer Instanzen (Pling Holding-Konsolidierung) | prüfen/ggf. neu |
|
||||
| `data.writeToTable` / Tabellen-Output | Ergebnistabellen (PWG-Übersicht) | prüfen/ggf. neu |
|
||||
| `trigger.event` / DB-Change-Detection | ereignisgetriggerte Solutions (Notification) | **neu (Roadmap)** |
|
||||
|
||||
Alle erscheinen über den Editor-Adapter (`graphicalEditor/nodeDefinitions/`) als Bausteine.
|
||||
|
||||
### A3 — Connectors (L1, generische API-Adapter)
|
||||
|
||||
- **SelectLine-Connector** (Quelle): `accountingConnectorSelectline.py`, implementiert `BaseAccountingConnector`, Auto-Discovery via `accountingRegistry.py`. Methoden: `testConnection`, `getChartOfAccounts`, `getCustomers`/`getVendors`, Lese-Seite für Belege (`getOutgoingInvoices`, Default `[]` in Base). Config: `baseUrl`, `username`, `password` (secret), optional `mandant`.
|
||||
- **`TrusteeAccountingConfig.role`** (`source` | `target`) → mehrere Connector-Configs pro Instanz (eine Quelle + ein Ziel); `getActiveConfig`/`_resolveConnectorAndConfig` um `role` filtern. Optional `connectorCategory` (`accounting` | `payroll` | `invoicing`). **DB-Migration: ja.**
|
||||
- **Kanonisches `Invoice`-Modell** prüfen/ergänzen (falls RMA als AR-Rechnung statt GL-Buchung).
|
||||
- **Source-Pfad in `accountingBridge.py`** additiv (Push-Pfad unverändert).
|
||||
- **Roadmap-Connectors** (generisch, je 1 Datei + Config): Xero (1.1.11), FileMaker (PWG 1.9.10), Kassensystem/Gastro (1.6, wartet auf Input), Lohn/Swissdec (4.2), Bank-Statement-Import (4.1.2). Je neuer Connector schaltet neue Solutions frei, ohne Architekturänderung.
|
||||
|
||||
### A4 — «Datenquelle = Seite» (generische Connector-UI)
|
||||
|
||||
- `TrusteeAccountingSettingsView` → generische **`IntegrationSettingsView`** (`category`-Prop): Verbindungen (Connector + Rolle Quelle/Ziel + Credentials + Test), Datenfluss/Import, Daten-Spiegel.
|
||||
- Neue UI-Areas in `mainTrustee.py` (z. B. `ui.feature.trustee.payroll`) + Mapping in `FeatureView.tsx` → **gleiche** Komponente, andere `category`.
|
||||
- «Buchhaltungssystem» existiert; «Saläre»/«Fakturierung» als Folge-Kategorien (Platzhalter, nicht erste Umsetzung).
|
||||
|
||||
## Teil B — Vertikale Code-Features
|
||||
|
||||
### B1 — `lawyer` (Mandatsvorbereitung + Dashboards) — NEU
|
||||
|
||||
Echtes Feature (eigene Modelle + opinionated UI), das die Plattform-Bausteine bündelt; **konsumiert** die Solution-Schicht (Matter-Prep/Dashboard-Refresh als interne Solutions/Actions).
|
||||
|
||||
- **Datenmodell** (`datamodelLawyer.py`): `LawyerMatter`, `LawyerPreparation`, `LawyerDashboardSnapshot`, `LawyerKpi`, `LawyerSourceMap`. **Migration: ja.**
|
||||
- **Feature-Modul** `mainLawyer.py` + Template-Rollen `lawyer-admin` / `lawyer-user` / `lawyer-viewer` (feature-instance-scoped).
|
||||
- **Actions** (`methodLawyer/`): `lawyer.prepareMatter`, `lawyer.refreshDashboard`, `lawyer.queryData`.
|
||||
- **UI** (`ui-nyla/src/components/Lawyer/`): Dashboard-View (Tabs HR/Business/IT/Finance) + Matter-Preparation-View (opinionated, analog Workspace).
|
||||
- **Connectors:** DMS (SharePoint vorhanden, iManage neu?), E-Mail (Outlook/Exchange), KYC/AML, Konflikt-Check — als generische L1-Bausteine (Teil A3-Muster).
|
||||
- **Neutralisierung zwingend** (Berufsgeheimnis); Sprache UI primär Englisch (WW/Investor).
|
||||
- **Demo-Asset:** synthetic Matter `M-DEMO-001` für WW-Präsentation (statisches Briefing-JSON, Backend-frei).
|
||||
|
||||
> Begründung Feature statt Solution: eigene Datenmodelle (`LawyerMatter`…), tiefe opinionated UI (Matter-Preparation), Domänenlogik. Dashboards/Matter-Prep dürfen intern Solutions/Actions nutzen — das Feature ist der opinionated Rahmen.
|
||||
|
||||
### B2 — `commcoach` (bestehend)
|
||||
|
||||
- Feature komplett (10+ Personas inkl. 4 PWG-Immobilien-Personas, Gamification, Seeding). **Erweiterungen:** kundenspezifische Persona-Sets als Daten (z. B. PWG-Knowledge-Set). Kein Neubau.
|
||||
|
||||
### B3 — `trustee` (Core, bestehend) — Erweiterungen
|
||||
|
||||
- Engine + Accounting-Bridge + Pipeline (`extractFromFiles`/`processDocuments`/`syncToAccounting`) + Connectors (RMA/Bexio/Abacus) bestehen.
|
||||
- **Erweiterungen als Bausteine** (nicht als Kundenlogik): Firmen-/Lieferanten-Mapping-UI (1.1.4), Buchungsregeln-Engine (1.1.6), Vorsteuer-Automatik (1.1.7), Bank-Statement-Matching (4.1).
|
||||
- **Migration:** Analyse-Prompt-Templates (Budget/KPI/Cashflow/Prognose/Jahresabschluss) aus `mainTrustee.py` → kuratierte **Solution-Templates** (→ solutions-plan S5). Trustee bleibt Daten-/Connector-Heimat, die Analysen werden Solutions.
|
||||
|
||||
### B4 — Plattform-Features (bestehend, Querschnitt)
|
||||
|
||||
- `neutralization` (PII-Masking, Private-LLM, Compliance-Audit) — vorhanden; pro Solution/Feature nur konfigurieren.
|
||||
- Knowledge/RAG, Billing, Multi-Tenancy, Workspace — vorhanden.
|
||||
- **UI/UX-Härtung** (aus altem Kundenplan Teil 2, plattformweit, nicht Solution/Feature-spezifisch): Empty-State, DE-Placeholder/i18n, Zwischen-Breakpoint 1025–1280px, Trust-Strip, Billing-Discovery, Connector-Onboarding-Copy. → separate UX-Charge, hier nur referenziert.
|
||||
|
||||
## Feature-vs-Solution — Recap (Entscheidungsmatrix)
|
||||
|
||||
| Kriterium | → Solution (Daten) | → Feature (Code) |
|
||||
|---|---|---|
|
||||
| Eigenes Datenmodell? | nein | ja (`LawyerMatter`) |
|
||||
| Tiefe opinionated UI? | nein | ja (Matter-Preparation) |
|
||||
| Aus Bausteinen komponierbar? | ja | nein (Domänenlogik) |
|
||||
| Beispiel | SelectLine→RMA, Pling, PWG, Analysen | `lawyer`, `commcoach`, `trustee`-Core |
|
||||
|
||||
## Betroffene Module
|
||||
|
||||
- **Gateway (platform-core):**
|
||||
- `features/graphicalEditor/` — `AutoWorkflow`-Erweiterung + Settings-Record + Solution-Routes (A1). **Migration: ja.**
|
||||
- `workflows/methods/` + `graphicalEditor/nodeDefinitions/` — generische Nodes (A2).
|
||||
- `workflows/.../triggerExecutor` — `accessControl.requiredRoles` + `testMode` (A2).
|
||||
- `features/trustee/accounting/connectors/accountingConnectorSelectline.py` (neu), `accountingConnectorBase.py` (Source-Methode), `accountingBridge.py` (Source-Pfad), `datamodelFeatureTrustee.py` (`role` [+ `connectorCategory`]) — **Migration: ja** (A3).
|
||||
- `features/lawyer/` (neu, B1) — `mainLawyer.py`, `datamodelLawyer.py`, `methodLawyer/`, Routes. **Migration: ja.**
|
||||
- `interfaces/interfaceBootstrap.py` — Use-Case-Katalog/System-Templates (A1).
|
||||
- `serviceCenter/services/serviceAgent/` (Toolbox `workflow`) — Use-Case→Graph (A1).
|
||||
- **Frontend (ui-nyla):**
|
||||
- `SolutionsView` (A1), `IntegrationSettingsView` (A4), `Lawyer/`-Komponenten (B1), `FeatureView.tsx`-Registry + UI-Areas.
|
||||
- **DB-Migration:** ja (Solution-Schicht, `TrusteeAccountingConfig.role`, Lawyer-Modelle).
|
||||
- **Andere:** RBAC (neue UI-Areas, bestehende Feature-Rollen), Neutralisierung, Billing (Run-/Sync-Volumen).
|
||||
|
||||
## Entscheidungen
|
||||
|
||||
| Datum | Entscheidung | Begründung |
|
||||
|-------|-------------|------------|
|
||||
| 2026-06-04 | Plattform-Bausteine + Solution-Schicht als **generischer Code**, nie kundenspezifisch | macht alle Solutions möglich, hält «kein Kunden-Code» real |
|
||||
| 2026-06-04 | Connectors = reine Adapter; `source`/`target`-Rolle als neue Achse | bidirektionales Integrations-Framework, additive Erweiterung |
|
||||
| 2026-06-04 | `lawyer` bleibt **Feature** (eigene Modelle + opinionated UI), nutzt Solution-Schicht intern | Entscheidungsmatrix; Domänenlogik nicht als Graph abbildbar |
|
||||
| 2026-06-04 | Trustee-Analyse-Prompt-Templates → **Solution-Templates** migrieren | kundentauglich machen; Trustee bleibt Daten-/Connector-Heimat |
|
||||
| 2026-06-04 | Connector-Abstraktion erst bei zweiter Kategorie (Saläre) generalisieren | YAGNI |
|
||||
|
||||
## Umsetzungs-Checkliste
|
||||
|
||||
**Teil A (Enabler, zuerst):**
|
||||
- [ ] `AutoWorkflow`-Erweiterung (`settingsSchema`/`outputBinding`/`customerFacing`/Instanz-Set) + Settings-Record + Migration
|
||||
- [ ] Solution-Routes (CRUD/Test/Activate) + `SolutionsView` + Settings-Formular-Renderer
|
||||
- [ ] Output-Renderer `file`/`table`/`summary`
|
||||
- [ ] `rbac.queryUsersByRole`, Trigger-`accessControl`, run-level `testMode`
|
||||
- [ ] Integration-Nodes `fetchFromSource`/`mapAccounts`/`pushToTarget` + Editor-Adapter
|
||||
- [ ] `data.consolidate` / `data.writeToTable` prüfen/ergänzen
|
||||
- [ ] SelectLine-Connector + `TrusteeAccountingConfig.role` (+ optional `connectorCategory`) + Migration
|
||||
- [ ] kanonisches `Invoice`-Modell prüfen; Source-Pfad in `accountingBridge` (additiv)
|
||||
- [ ] `IntegrationSettingsView` (`category`) generalisieren
|
||||
- [ ] Use-Case-Katalog/System-Templates + Workflow-Agent-Pfad
|
||||
|
||||
**Teil B (Features):**
|
||||
- [ ] `lawyer`: Datenmodell (5 Modelle) + `mainLawyer.py` + 3 Actions + UI (Dashboard/Matter-Prep) + RBAC + Neutralisierung + Demo-Asset
|
||||
- [ ] `trustee`: Analyse-Templates → Solution-Templates; optional Mapping-UI/Buchungsregeln/Vorsteuer/Bank-Matching
|
||||
- [ ] `commcoach`: kundenspezifische Persona-/Knowledge-Sets als Daten
|
||||
- [ ] Roadmap-Connectors nach Bedarf (Xero, FileMaker, Lohn, Kassensystem, Bank-Import)
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
| # | Kriterium (Given-When-Then) | Prio |
|
||||
|---|---|---|
|
||||
| 1 | Given ein neues Umsystem, When ein Connector-File + Config ergänzt wird, Then ohne Änderung an Registry/Bridge/Editor verfügbar | must |
|
||||
| 2 | Given `testMode`, When eine Solution testweise läuft, Then erzeugt sie Artefakte, sendet aber keine Kommunikation | must |
|
||||
| 3 | Given `rbac.queryUsersByRole`, When mit Rollen-Set aufgerufen, Then dedupliziert die korrekten Empfänger (Pling-Verteiler) | must |
|
||||
| 4 | Given Anwalt mit `lawyer-user`, When Matter-Preparation getriggert, Then strukturiertes Briefing in <90s, PII vor LLM neutralisiert | must |
|
||||
| 5 | Given Mandate-Rolle ohne `lawyer-*`, When Lawyer-Feature geöffnet, Then Access Denied | must |
|
||||
| 6 | Given Solution-Schicht, When ein Kunde Settings ändert, Then ohne Code-Deploy wirksam | must |
|
||||
|
||||
## Offene Fragen
|
||||
|
||||
1. **Solution-Daten-Heimat:** `AutoWorkflow`-Erweiterung (empfohlen) — Settings-Record als eigenes Modell oder JSON-Feld?
|
||||
2. **`outputBinding`-Schema:** Artefakt-Referenz (Run-Output-Key vs. Document-Query); `table`-Spalten aus Node-Output ableiten?
|
||||
3. **SelectLine:** on-prem-Erreichbarkeit (VPN/Tunnel/Agent); Zielart RMA (AR vs. GL).
|
||||
4. **Lawyer-Connectors:** iManage/KYC/Konflikt-Check-APIs — welche mandantenspezifisch, welche generisch?
|
||||
5. **Connector-Generalisierung:** wann Capability-Mixins (`AccountingCapable`/`PayrollCapable`) ziehen?
|
||||
|
||||
## Links
|
||||
|
||||
- Architektur: `c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md`
|
||||
- Solutions: `c-work/0-ideas/2026-06-CustomerCases-step3-solutions-plan.md`
|
||||
- Bausteine: `b-reference/platform-core/workflow.md`, `b-reference/platform-core/automation.md`, `b-reference/platform-core/features/trustee.md`
|
||||
- RBAC/Neutralisierung: `b-reference/platform/rbac.md`, `b-reference/platform/neutralization.md`, `.cursor/rules/rbac-role-separation.mdc`
|
||||
- Lawyer-Kontext (WW): `pamocreate/projects/poweron/customer-walderwyss/`
|
||||
- Code: `platform-core/modules/features/trustee/accounting/` (Bridge/Base/Registry/Connectors), `features/graphicalEditor/`
|
||||
|
||||
## Abschluss
|
||||
|
||||
- [ ] Bei Annahme → Build in `c-work/2-build/` (Teil A vor Teil B)
|
||||
- [ ] `b-reference/` Kanon-Seiten: «Solutions / Customer Workflows», `features/lawyer.md`, Trustee «Source-Connectors»
|
||||
- [ ] `TOPICS.md` + `_CHANGELOG.md` pro Phase
|
||||
199
c-work/0-ideas/2026-06-CustomerCases-step3-solutions-plan.md
Normal file
199
c-work/0-ideas/2026-06-CustomerCases-step3-solutions-plan.md
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
<!-- status: plan -->
|
||||
<!-- started: 2026-06-04 -->
|
||||
<!-- component: gateway | ui-nyla | platform -->
|
||||
<!-- replaces: 2026-06-STEP2-umsystem-integration-connectors-und-datenquellen-seiten.md, 2026-06-STEP2-pm-consolidated-customer-requirements.md (Solution-Teile) -->
|
||||
|
||||
# Plan: Solutions — kundeneigene Workflows als Konfiguration (kein Code)
|
||||
|
||||
> **Baut auf:** `2026-06-CustomerCases-step1-architecture.md` (Schichten L1–L4, Feature-vs-Solution-Grenze).
|
||||
> **Schwester-Plan:** `2026-06-CustomerCases-step3-features-plan.md` (der Code dahinter: Solution-Schicht, generische Bausteine, Connectors, vertikale Features).
|
||||
> **Konsolidiert/ersetzt:** Umsystem-Integration-Plan + die Solution-tauglichen Use Cases aus dem konsolidierten Kundenwünsche-Plan.
|
||||
|
||||
## Beschreibung und Kontext
|
||||
|
||||
Eine **Solution** ist ein **konfigurierter Workflow** (Daten = Graph + Settings + Trigger + Output-Bindung), der ein wiederkehrendes Kundenbedürfnis erfüllt — **ohne kundenspezifischen Code**. Sie konsumiert die vorhandenen Plattform-Bausteine (L1 Toolbox, L2 Graph) und wird über die neue Solution-Schicht (L3/L4) angelegt, eingestellt, getestet, ausgeführt und angesehen.
|
||||
|
||||
Dieser Plan listet die **konkreten Kunden-Use-Cases, die als Solutions** umgesetzt werden. Der Code, den diese Solutions voraussetzen (Solution-Schicht selbst, generische Workflow-Bausteine, Connectors), steht im **features-plan** — eine Solution schreibt nie eigenen Code.
|
||||
|
||||
Business-Treiber: jeder Use Case wird zu Konfiguration statt Engineering → Time-to-value in Tagen, Onboarding ohne Entwicklungs-Backlog, Grenzkosten pro Use Case nahe null.
|
||||
|
||||
## Fokus und kritische Details
|
||||
|
||||
- **Solution = Daten, nie Code.** Konten-Mappings, Empfänger, Perioden, Ordnerpfade, Cron-Zeiten, Instanz-Auswahl = **Settings**. Tauchen Kundennamen oder `if kunde == X` im Code auf, ist die Solution falsch geschnitten.
|
||||
- **Multi-Instanz-Fan-out.** Eine Solution kann über ein **Set von Feature-Instanzen** laufen (Pling: 5 Stores). Das Settings-Modell trägt eine Instanz-Auswahl.
|
||||
- **Voraussetzung sind generische Bausteine, keine kundenspezifischen.** Wo ein Baustein fehlt (z. B. `rbac.queryUsersByRole`, ein SelectLine-Connector), wird er **generisch** im features-plan gebaut und hier nur referenziert.
|
||||
- **Neutralisierung** für jeden LLM-Pfad (Belege/Berichte mit Personendaten) — über das bestehende Gate, selektiv (Namen/Beschreibungen pseudonymisiert, Zahlen/Konten lesbar).
|
||||
- **Testlauf real, ohne Versand:** Solutions laufen im Test echt, nur Kommunikation wird via run-level `testMode` unterdrückt.
|
||||
|
||||
## Ziel und Nicht-Ziele
|
||||
|
||||
- **Ziel:** Die häufigsten Kundenbedürfnisse als **kuratierte Solution-Templates** + pro Mandant/Instanz konfigurierte Solutions abbilden.
|
||||
- **Ziel:** SelectLine→RMA und Pling-Reporting als erste produktive Solutions (Leit-Cases).
|
||||
- **Ziel:** Nachweis, dass dasselbe Muster Beleg-Import, Dokumentenverarbeitung und Finanz-Analysen trägt.
|
||||
- **Explizit NICHT:** kundenspezifischer Code pro Solution (→ features-plan baut nur Generisches).
|
||||
- **Explizit NICHT:** den Graphical Editor ersetzen — Solutions kapseln ihn; «Im Editor öffnen» bleibt Escape-Hatch.
|
||||
- **Explizit NICHT:** Use Cases, die ein eigenes Datenmodell / tiefe opinionated UI brauchen (→ das sind **Features**, siehe features-plan; z. B. `lawyer`).
|
||||
|
||||
## Klassifikation: was wird Solution, was Feature
|
||||
|
||||
| Use-Case-Quelle | Umsetzung | Begründung |
|
||||
|---|---|---|
|
||||
| SelectLine → RMA (Umsystem) | **Solution** «Systeme synchronisieren» | Komponierbar aus Connectors + Integration-Nodes; Kundenspezifika = Mapping/Settings |
|
||||
| Pling Kaffee-Klatsch (Monatsreporting) | **Solution** «Periodisches Reporting» | Fan-out + Konsolidierung + AI-Report + rollenbasierte Verteilung, alles Bausteine |
|
||||
| PWG Jahresmietzinsbestätigungen (1.9c) | **Solution** «Dokumente verarbeiten» | SharePoint→Extract→AI→Tabelle→Mail, 1 AI-Schritt |
|
||||
| Beleg-/Spesen-Import periodisch (1.1, 1.10.5) | **Solution** «Beleg-Import» | SharePoint/Drive→Trustee-Pipeline, Zeitplan |
|
||||
| Budget/Soll-Ist, KPI, Cashflow, Prognose, Jahresabschluss-Check, Liquidität (1.2–1.7, 4.x) | **Solution** «Finanz-Analyse & Reporting» | `queryData`→`ai.generate`→Output (Tabelle/Report); heute Prompt-Templates |
|
||||
| KPI-/Notification-Verteilung (1.9.12, 4.5.8) | **Solution** «Benachrichtigung/Report» | Trigger→Daten→Report→rollenbasierte Verteilung |
|
||||
| Lawyer (Mandatsvorbereitung + Dashboards) | **Feature** | Eigene Modelle (`LawyerMatter`…) + opinionated UI |
|
||||
| CommCoach, Neutralisierung, Trustee-Core | **Feature** (bestehend) | Domänenlogik/eigene UI/Engine |
|
||||
| Connectors (SelectLine, Xero, FileMaker, Lohn, Kassensystem) | **Feature/Plattform-Baustein** | Generischer Code (L1), kein Kunden-Code → features-plan |
|
||||
| Solution-Schicht, generische Nodes, `testMode` | **Feature/Plattform-Enabler** | Code, der Solutions erst möglich macht → features-plan |
|
||||
|
||||
## Solution-Katalog
|
||||
|
||||
Jede Solution = Template (kuratiert) → pro Instanz konfiguriert. Bausteine sind **vorhanden**, sofern nicht als «(neu → features-plan)» markiert.
|
||||
|
||||
### S1 — «Systeme synchronisieren» (Pilot: SelectLine → RMA)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Bedürfnis** | Rechnungen aus externem System (SelectLine) periodisch ins RMA buchen |
|
||||
| **Trigger** | `trigger.schedule` (z. B. täglich 06:00) oder `trigger.manual` |
|
||||
| **Bausteine (Graph)** | `integration.fetchFromSource` (SelectLine) → `integration.mapAccounts` → `integration.pushToTarget` (RMA, inkl. Beleg-Upload) *(Nodes + SelectLine-Connector neu → features-plan)* |
|
||||
| **Settings (L3)** | Quell-Connector + Credentials, Ziel-Connector, Konten-/Steuer-Mapping, Filter (nur Ausgangsrechnungen, «seit letztem Sync»), Zeitplan |
|
||||
| **Output (L4)** | `summary` — Sync-Log/Status (gebucht/übersprungen/Duplikate) |
|
||||
| **Dedup** | über bestehende AccountingBridge-Dedup-Logik |
|
||||
| **Kunden** | konkreter SelectLine-Kunde; Muster für jedes weitere Umsystem |
|
||||
| **Voraussetzungen (features-plan)** | SelectLine-Connector, `source`/`target`-Rolle auf Config, Integration-Nodes, ggf. kanonisches `Invoice`-Modell |
|
||||
|
||||
Zwei Kunden mit unterschiedlichem Kontenplan-Mapping = **zwei Solutions/Configs, ein Code**.
|
||||
|
||||
### S2 — «Periodisches Reporting» (Leit-Case: Pling Kaffee-Klatsch)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Bedürfnis** | Am 15./Monat aus 5 RMA-Buchhaltungen konsolidieren, 6 PDFs erzeugen, rollenbasiert mailen |
|
||||
| **Trigger** | `trigger.schedule` `0 6 15 * *` (Europe/Zurich) + `trigger.manual` (rollen-beschränkt) |
|
||||
| **Bausteine (Graph)** | `flow.loop`(5 Instanzen) → `trustee.refreshAccountingData` → `trustee.queryData` (Salden akt.+Vorjahr) → `data.consolidate` (sumByKey) → `ai.generateDocument`×6 (1 Holding + 5 Store) → `rbac.queryUsersByRole` → `outlook.send` → `file.create` (Archiv) |
|
||||
| **Settings (L3)** | **Instanz-Set** (5 Stores), Konten-Ranges (Umsatz 3000–3999, Warenkosten 6000–6299, Personal 5000–5099), Cron, Empfänger-**Rollen** (Holding→`trustee-accountant`/`trustee-viewer`, Store→`trustee-client`, Protokoll→`trustee-admin`), `stopOnIncomplete` |
|
||||
| **Output (L4)** | `file` — 6 PDFs, archiviert als `TrusteeDocument`; + `summary` Lauf-Protokoll |
|
||||
| **Sonderfall** | Buchhaltung am 15. nicht abgeschlossen → durchlaufen mit Markierung (Conditional nach refresh), steuerbar via `stopOnIncomplete` |
|
||||
| **Neutralisierung** | selektiv (Namen/Beschreibungen ja; Zahlen/Konten nein) |
|
||||
| **Voraussetzungen (features-plan)** | `rbac.queryUsersByRole`, Trigger-`accessControl.requiredRoles`, `data.consolidate` (prüfen), `testMode` |
|
||||
|
||||
Vollständig spezifiziert (High-Level + Anhang); ~2 Wochen Build → bester End-to-End-Beleg der Solution-Schicht.
|
||||
|
||||
### S3 — «Dokumente verarbeiten + Antwort» (PWG Jahresmietzinsbestätigungen, 1.9c)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Bedürfnis** | Gescannte Rücklauf-Bestätigungen (≈3'200/Jahr) prüfen, Status klassifizieren, Antwortvorschläge |
|
||||
| **Trigger** | `trigger.schedule` (täglich) oder `trigger.manual` |
|
||||
| **Bausteine (Graph)** | `sharepoint.listFiles` → `flow.loop` → `sharepoint.downloadFile` + `trustee.extractFromFiles` (OCR) → `ai.prompt` (Scan vs. Abacus-Originaldaten, Status, Antwortvorschlag) → `data.writeToTable` → `email.send` |
|
||||
| **Settings (L3)** | Scan-Ordner (SharePoint), Abacus-Mandant + Mietzins-Stammdaten-Abfrage, Empfänger (Sachbearbeiter), Prompt-Variante |
|
||||
| **Output (L4)** | `table` — Übersicht verarbeiteter Bestätigungen (bestätigt / Abweichung / fehlende Unterschrift / unleserlich) + Mail-Zusammenfassung |
|
||||
| **Kunden** | PWG (Pilot, Versand Sommer 2026, Deadline-gebunden) |
|
||||
| **Voraussetzungen (features-plan)** | Prompt-Template «Mietzinsbestätigung prüfen», Abacus-Stammdaten-Abfrage konfigurieren, `data.writeToTable`-Output-Renderer |
|
||||
|
||||
### S4 — «Beleg-Import» (periodische Spesen-/Belegverarbeitung; 1.1, 1.10.5)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Bedürfnis** | Belege/Spesen aus SharePoint/Drive periodisch klassifizieren, kontieren, verbuchen |
|
||||
| **Trigger** | `trigger.schedule` (z. B. täglich 22:00) |
|
||||
| **Bausteine (Graph)** | `sharepoint.listFiles` → `flow.loop` → `trustee.extractFromFiles` → `trustee.processDocuments` (Klassifikation + Kontierung) → `trustee.syncToAccounting` |
|
||||
| **Settings (L3)** | Quelle (Ordner), Ziel-Buchhaltung (RMA/Bexio/Abacus), Klassifikations-/Kontierungsoptionen, Zeitplan |
|
||||
| **Output (L4)** | `table` verarbeitete Belege + `summary` |
|
||||
| **Kunden** | Bling, PWG, Quid |
|
||||
| **Voraussetzungen** | bestehende Pipeline + System-Template existiert bereits; als Solution kapseln |
|
||||
|
||||
### S5 — «Finanz-Analyse & Reporting» (1.2–1.7, 4.x — heute Prompt-Templates)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Bedürfnis** | Budget/Soll-Ist, KPI-Dashboard, Cashflow, Prognose, Jahresabschluss-Checks, Liquidität |
|
||||
| **Trigger** | `trigger.manual` / `trigger.form` oder `trigger.schedule` (periodischer Report) |
|
||||
| **Bausteine (Graph)** | `trustee.refreshAccountingData` → `trustee.queryData`/`aggregateTable` → `ai.generateDocument`/`ai.prompt` → Output |
|
||||
| **Settings (L3)** | Periode(n), Vergleichsbasis (Vorjahr/Budget), optionaler Budget-Upload, KPI-Auswahl, Empfänger |
|
||||
| **Output (L4)** | `table` (KPIs), `file` (Report-PDF) oder `summary` |
|
||||
| **Kunden** | Bling, Quid, allgemein Treuhand |
|
||||
| **Voraussetzungen** | bestehende Analyse-Prompt-Templates als Solution-Templates verfügbar machen (Migration aus `mainTrustee.py` → kuratierte Templates) |
|
||||
|
||||
### S6 — «Benachrichtigung / Report-Verteilung» (1.9.12, 4.5.8)
|
||||
|
||||
| | |
|
||||
|---|---|
|
||||
| **Bedürfnis** | Bei Ereignis/Zeitplan Bericht erzeugen und rollenbasiert verteilen; KPI-Alerts |
|
||||
| **Trigger** | `trigger.schedule` / `trigger.event` (DB-Change → features-plan) |
|
||||
| **Bausteine (Graph)** | Daten lesen → `ai.generateDocument` (optional) → `rbac.queryUsersByRole` → `email.send`/`outlook.send` |
|
||||
| **Settings (L3)** | Auslöser/Schwellwerte, Empfänger-Rollen, Vorlage |
|
||||
| **Output (L4)** | `summary` + Mail |
|
||||
| **Voraussetzungen (features-plan)** | `rbac.queryUsersByRole`, optional `trigger.event`/DB-Change-Detection |
|
||||
|
||||
## Gemeinsames Settings-Muster (alle Solutions)
|
||||
|
||||
- **`settingsSchema`** automatisch aus `trigger.form` + exposed Node-Params abgeleitet (kuratierte Overrides später).
|
||||
- **`settingsValues`** inkl. **Instanz-Set** (Multi-Instanz-Fan-out).
|
||||
- **`triggerPolicy`** manuell/Zeitplan/Event/Form + `accessControl.requiredRoles` (bestehende Feature-Rollen).
|
||||
- **`outputBinding.kind`** = `file | table | summary` (Dashboard später).
|
||||
- **Lebenszyklus** in der «Lösungen»-Seite: Liste · Katalog/Neu (Vorlage oder AI) · Detail mit Tabs (Einstellungen · Testlauf · Läufe · Ausgabe).
|
||||
|
||||
## Betroffene Module
|
||||
|
||||
- **Daten/Config (kein Code pro Solution):** Solution-Definition + Settings-Record pro Feature-Instanz (Modell → features-plan), Workflow-Graph als Template/Version.
|
||||
- **Kuratierte System-Templates:** `interfaces/interfaceBootstrap.py` — «Systeme synchronisieren», «Periodisches Reporting», «Dokumente verarbeiten», «Beleg-Import», «Finanz-Analyse».
|
||||
- **Voraussetzungen (Code):** vollständig im **features-plan** (Solution-Schicht, generische Nodes, Connectors, `testMode`, `rbac.queryUsersByRole`).
|
||||
- **Demo:** je Solution ein Demo-Setup (Pling-/PWG-/Bling-Mandant) — verweist auf Demo-Items aus dem alten Kundenplan.
|
||||
|
||||
## Entscheidungen
|
||||
|
||||
| Datum | Entscheidung | Begründung |
|
||||
|-------|-------------|------------|
|
||||
| 2026-06-04 | Kunden-Use-Cases primär als **Solutions** (Config) statt Code | step1-architecture Solution-first; skaliert ohne Engineering pro Kunde |
|
||||
| 2026-06-04 | SelectLine→RMA und Pling als **erste produktive Solutions** | konkrete Geld-Cases, decken Sync- und Reporting-Muster ab |
|
||||
| 2026-06-04 | Analyse-Prompt-Templates (Budget/KPI/Cashflow/…) werden **Solution-Templates** | bisher Trustee-interne Quick Actions → kundentauglich als Solutions |
|
||||
| 2026-06-04 | Fehlende Bausteine werden **generisch** im features-plan gebaut, nie kundenspezifisch | «keine Kundenlogik im Code» |
|
||||
|
||||
## Umsetzungs-Checkliste
|
||||
|
||||
- [ ] Solution-Schicht + generische Bausteine verfügbar (→ features-plan: A1–A3)
|
||||
- [ ] System-Template «Systeme synchronisieren» + Demo SelectLine→RMA (S1)
|
||||
- [ ] System-Template «Periodisches Reporting» + Pling-Solution konfiguriert (S2)
|
||||
- [ ] System-Template «Dokumente verarbeiten» + PWG-Mietzins-Solution (S3) — Deadline Sommer 2026
|
||||
- [ ] «Beleg-Import» als Solution kapseln (S4)
|
||||
- [ ] Analyse-Templates → Solution-Templates migrieren (S5)
|
||||
- [ ] «Benachrichtigung/Report» (S6) inkl. rollenbasierte Verteilung
|
||||
- [ ] Pro Solution: Testlauf (`testMode`) grün, dann Aktivierung
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
| # | Kriterium (Given-When-Then) | Prio |
|
||||
|---|---|---|
|
||||
| 1 | Given konfigurierte S1, When der Sync läuft, Then erscheinen SelectLine-Rechnungen als Buchungen in RMA (kein Kunden-Code; zweiter Kunde = nur andere Settings) | must |
|
||||
| 2 | Given konfigurierte S2 (Pling), When der Monatslauf läuft, Then 6 PDFs erzeugt + rollenbasiert versendet + archiviert; manueller Start nur für `trustee-admin` | must |
|
||||
| 3 | Given S2 im Testlauf, When ausgeführt, Then Reports werden erzeugt aber **keine** Mails versendet (`testMode`) | must |
|
||||
| 4 | Given konfigurierte S3, When Scans eintreffen, Then Übersichtstabelle mit Status + Antwortvorschlägen + Mail | must |
|
||||
| 5 | Given eine Solution, When der Kunde Settings ändert, Then ohne Code-Deploy wirksam (Settings = Daten) | must |
|
||||
| 6 | Given ein neuer ähnlicher Use Case, When aus Template instanziiert, Then nur Settings nötig, kein Code | should |
|
||||
|
||||
## Offene Fragen
|
||||
|
||||
1. **S1 Erreichbarkeit:** SelectLine on-prem → Zugriffsweg (VPN/Tunnel/Agent)? Zielart RMA (AR-Rechnung vs. GL-Buchung)?
|
||||
2. **S5 Migration:** Wie viele der Analyse-Prompt-Templates werden 1:1 Solution-Templates vs. konsolidiert?
|
||||
3. **S2/S3 Output:** `outputBinding`-Detail (Artefakt-Referenz, `table`-Spalten aus Node-Output ableiten) — siehe step1-architecture «Output-Bindung».
|
||||
4. **Demo-Daten:** welche Mandanten/Testdaten zuerst (Pling, PWG, Bling)?
|
||||
|
||||
## Links
|
||||
|
||||
- Architektur: `c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md`
|
||||
- Product Summary: `c-work/0-ideas/2026-06-CustomerCases-step2-communication-product-summary.md` (+ `.pdf`)
|
||||
- Mockup: `c-work/0-ideas/2026-06-CustomerCases-step2-communication-mockup.html`
|
||||
- Features/Code: `c-work/0-ideas/2026-06-CustomerCases-step3-features-plan.md`
|
||||
- Pling-Spec: `pamocreate/projects/poweron/customer-pling/20-spezifikation/20260522-workflow-spec-kaffee-klatsch.md` (+ `-anhang.md`)
|
||||
- Bausteine: `b-reference/platform-core/workflow.md`, `b-reference/platform-core/automation.md`, `b-reference/platform-core/features/trustee.md`
|
||||
|
||||
## Abschluss
|
||||
|
||||
- [ ] Bei Annahme → Solution-Templates + erste Konfigurationen in `c-work/2-build/`
|
||||
- [ ] `b-reference/` Kanon-Seite «Solutions» nach Umsetzung
|
||||
- [ ] `_CHANGELOG.md`-Eintrag pro Solution
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
<!-- status: plan -->
|
||||
<!-- started: 2026-05-14 -->
|
||||
<!-- component: gateway | ui-nyla | platform -->
|
||||
|
||||
# Lawyer Feature (Mandatsvorbereitung + Dashboards)
|
||||
|
||||
## Beschreibung und Kontext
|
||||
|
||||
Im Sales-Meeting mit David Vasella (WalderWyss) am 13.05.2026 hat sich ein klares Bild ergeben: Anwaltskanzleien arbeiten mit grossen Mengen **nicht human-readable Daten** (PDFs, E-Mails, frühere Mandate, Konflikt-Checks, KYC/AML, Buchungen). Zwischen internen Prozessen und der Mandantsbesprechung entsteht ein Overhead, den **Copilot nicht löst**. Existierende Branchen-Tools (Harvey.ai ~500 USD p/m/user, Legora, ClientFlex) sind teuer und decken die Anforderungen nicht voll ab. WW hat **kein CRM**.
|
||||
|
||||
PORTA hat bereits alle Bausteine: Workspace, Knowledge/RAG, Konnektoren, Neutralisierung, Private LLM. Das `lawyer`-Feature bündelt diese Bausteine zu einem **opinionated UI für Anwälte**: ein Feature-Modul mit zwei Hauptseiten – **Dashboards** (HR / Business-Client / IT) und **Matter Preparation** (Mandatsvorbereitung in 5 Minuten).
|
||||
|
||||
Business-Treiber:
|
||||
- WW konkretes Sales-Asset (HTML-Präsentation und später Live-Demo).
|
||||
- Eigene Use Cases für Homepage (`www.poweron.swiss`) – Sales-Story «echtes Produkt».
|
||||
- Investor-Pitch (Founderful via Dominic + Philipp) braucht klare vertikale Geschichte.
|
||||
- Wiederverwendbar für jede Anwaltskanzlei und mit Anpassung für Treuhand/Audit/Steuerberatung.
|
||||
|
||||
## Fokus und kritische Details
|
||||
|
||||
- **Berufsgeheimnis (StGB Art. 321)** – Mandantsdaten dürfen den Mandanten-Tenant nicht verlassen. Neutralisierung + Private LLM **zwingend** für jeden Pfad, der LLM nutzt (`wiki/b-reference/platform/neutralization.md`).
|
||||
- RBAC korrekt: feature-instance roles, **NICHT** mit mandate roles vermischen (`.cursor/rules/rbac-role-separation.mdc`).
|
||||
- Daten kommen aus heterogenen Quellen: Document Management System (DMS), E-Mail-Archiv, Zeiterfassung, Buchhaltung, KYC/AML, Konflikt-Check-DB. Konnektor-Pflege ist der **harte Teil**, nicht das UI.
|
||||
- Mockup-Daten in der WW-Präsentation müssen klar als **synthetic** markiert sein.
|
||||
|
||||
## Ziel und Nicht-Ziele
|
||||
|
||||
- **Ziel:** Feature-Modul `lawyer` mit:
|
||||
- Dashboard-Seite mit Tabs pro Funktion (HR, Business/Client, IT, optional Finance).
|
||||
- Matter-Preparation-Seite: Anwalt definiert Kontext (Mandant, Matter, Meeting-Ziel, Datum), System aggregiert Quellen, AI-Agent generiert Briefing (Kerndaten, Risiken, Deadlines, offene Punkte, Agenda-Vorschlag).
|
||||
- **Ziel:** Wiederverwendung der bestehenden PORTA-Bausteine (Workspace, Knowledge, Konnektoren, Neutralisierung, Private LLM).
|
||||
- **Ziel:** Standard-Konnektoren für DMS (SharePoint, iManage), E-Mail (Outlook/Exchange), KYC-/Konflikt-Datenquellen, Buchhaltung (im ersten Schritt einer pro Kategorie).
|
||||
- **Explizit NICHT:** vollständiges Practice-Management-System ersetzen (kein Time-Tracking-Replacement, kein Billing-System).
|
||||
- **Explizit NICHT:** generische Vertragsanalyse / Drafting (das machen Harvey/Legora besser, wir sind komplementär).
|
||||
- **Explizit NICHT:** eigene KYC/AML-Datenquelle aufbauen – wir konsumieren bestehende.
|
||||
|
||||
## Betroffene Module
|
||||
|
||||
- Gateway:
|
||||
- Neues Feature-Modul `platform-core/modules/features/lawyer/` mit `mainLawyer.py`, `datamodelLawyer.py`, `interfaceLawyer.py`, `routeFeatureLawyer*.py`.
|
||||
- Workflow-Method `platform-core/modules/workflows/methods/methodLawyer/` für `lawyer.prepareMatter`, `lawyer.queryData`.
|
||||
- Konnektoren: prüfen, welche bestehen (`platform-core/modules/connectors/`), welche neu (DMS, KYC).
|
||||
- Frontend:
|
||||
- Neue Komponenten `ui-nyla/src/components/Lawyer/`.
|
||||
- Dashboard-View mit Tabs.
|
||||
- Matter-Preparation-View (analog Workspace, opinionated).
|
||||
- DB-Migration: ja – neue Tabellen `LawyerMatter`, `LawyerPreparation`, `LawyerDashboardSnapshot`, `LawyerKpi`.
|
||||
- Andere Komponenten: Knowledge/RAG (bestehend), Neutralisierung (bestehend), Private LLM (bestehend), Workspace-Agent-Tools (Erweiterung).
|
||||
|
||||
## Entscheidungen
|
||||
|
||||
| Datum | Entscheidung | Begründung |
|
||||
|-------|-------------|------------|
|
||||
| 2026-05-14 | Feature-Code `lawyer` (analog `trustee`, `realEstate`) | Konsistenz mit bestehenden Feature-Modulen |
|
||||
| 2026-05-14 | Template-Rollen `lawyer-admin`, `lawyer-user`, `lawyer-viewer` | RBAC-Regel: feature-instance roles, mandate-getrennt |
|
||||
| 2026-05-14 | Matter-Preparation nutzt bestehenden Workspace-Agent + neue opinionated Tool-Chain | Wiederverwendung statt Neubau |
|
||||
| 2026-05-14 | Dashboards starten als read-only Aggregations-Views auf Konnektor-Daten | Schneller Time-to-Demo, Schreibpfad später |
|
||||
| 2026-05-14 | Sprache UI primär Englisch | WW-Audience Management Board, Investor-tauglich; DE-Lokalisierung Phase 2 |
|
||||
|
||||
## Use Cases (User Stories)
|
||||
|
||||
### UC-1: Matter Preparation in 5 Minutes
|
||||
|
||||
**Given** ein Anwalt hat morgen ein Klienten-Meeting für Matter `M-2024-0042` (M&A-Transaktion).
|
||||
**When** er auf der Matter-Preparation-Seite den Matter und das Meeting-Ziel eingibt ("Statusbesprechung Due Diligence, offene Punkte"),
|
||||
**Then** sammelt das System innerhalb von ~60 Sekunden aus DMS (alle Dokumente zu M-2024-0042), E-Mails (letzte 30 Tage), Zeiterfassung (WIP + Deadlines), KYC/AML (Aktueller Status), Konflikt-Check.
|
||||
**And** generiert ein strukturiertes Briefing:
|
||||
- Kerndaten Mandant + Matter
|
||||
- Stand Due Diligence (Dokumente, offene Punkte)
|
||||
- Risiken & Deadlines
|
||||
- Offene Aktionen seit letzter Besprechung
|
||||
- Vorschlag Agenda
|
||||
- Quellenliste (jeder Punkt mit Link zur Quelle)
|
||||
**And** alle Mandantsdaten werden neutralisiert, bevor sie das LLM erreichen.
|
||||
|
||||
### UC-2: Partner-Dashboard
|
||||
|
||||
**Given** ein Partner möchte vor der Wochensitzung den Stand seines Teams sehen.
|
||||
**When** er die Dashboard-Seite öffnet,
|
||||
**Then** sieht er HR-KPIs (Billable Hours, Utilization, Realization) für sein Team, Top-3-Risk-Matters, AR Aging.
|
||||
**And** kann pro KPI in die Detailansicht drillen (Drilldown via Konnektor-Live-Query).
|
||||
|
||||
### UC-3: IT/Compliance-Dashboard
|
||||
|
||||
**Given** der IT-Leiter braucht für ein Audit-Meeting den Compliance-Status.
|
||||
**When** er den IT-Tab öffnet,
|
||||
**Then** sieht er Uptime, Security-Incidents (letzte 90 Tage), Patch-Status, KYC/AML-Backlog, Conflict-Check-SLAs.
|
||||
|
||||
## Datenmodell-Skizze
|
||||
|
||||
| Modell | Felder (Kern) | Kommentar |
|
||||
|--------|---------------|-----------|
|
||||
| `LawyerMatter` | id, featureInstanceId, mandateCode, clientName, matterType, openedAt, status, leadLawyerUserId | Mandate spiegeln, nicht zweimal halten |
|
||||
| `LawyerPreparation` | id, matterId, requestedBy, meetingGoal, createdAt, briefingJson, sourceRefs | Persistiert das generierte Briefing für Audit + Wiederverwendung |
|
||||
| `LawyerDashboardSnapshot` | id, featureInstanceId, dashboardType, periodStart, periodEnd, dataJson, generatedAt | Cache für Dashboard-Daten, Refresh periodisch |
|
||||
| `LawyerKpi` | id, featureInstanceId, kpiCode, label, formula, lastValue, lastValueAt, dashboardType | Konfigurierbare KPI-Definitionen pro Tenant |
|
||||
| `LawyerSourceMap` | id, featureInstanceId, sourceType, connectorRef, mappingJson | Welcher Konnektor liefert welche Daten in welche KPI |
|
||||
|
||||
## Actions (Workflow-Method)
|
||||
|
||||
| Action | Eingabe | Output | Zweck |
|
||||
|--------|---------|--------|-------|
|
||||
| `lawyer.prepareMatter` | featureInstanceId, matterId, meetingGoal, lookbackDays | LawyerPreparation (briefingJson + sourceRefs) | Sammelt aus Quellen, neutralisiert, generiert Briefing via Workspace-Agent |
|
||||
| `lawyer.refreshDashboard` | featureInstanceId, dashboardType, periodStart, periodEnd | LawyerDashboardSnapshot | Re-aggregiert KPI-Werte aus Konnektoren |
|
||||
| `lawyer.queryData` | featureInstanceId, freie Filter | ActionResult mit Query-Resultat | Read-only Zugriff für AI-Agent (analog `trustee.queryData`) |
|
||||
|
||||
## UI-Skizze
|
||||
|
||||
```
|
||||
/lawyer/<featureInstanceId>/
|
||||
├── dashboards/
|
||||
│ ├── hr (Tab)
|
||||
│ ├── business (Tab)
|
||||
│ ├── it (Tab)
|
||||
│ └── finance (Tab, optional)
|
||||
└── matter-preparation/
|
||||
├── <list of recent matters>
|
||||
└── <matterId>/
|
||||
├── briefing (generated)
|
||||
├── sources (drilldown)
|
||||
└── agenda-export (PDF/Markdown)
|
||||
```
|
||||
|
||||
## RBAC-Mapping
|
||||
|
||||
- Template-Rollen (Feature-Code `lawyer`, `mandateId=NULL`, `isSystemRole=False`):
|
||||
- `lawyer-admin` – Feature-Instance-Admin, Konnektor-Konfig, KPI-Definition.
|
||||
- `lawyer-user` – Anwalt, Matter-Preparation, Dashboard read.
|
||||
- `lawyer-viewer` – Read-only, z. B. Management Board.
|
||||
- Nutzung: `FeatureAccessRole` mit `featureCode=lawyer, featureInstanceId=<id>, mandateId=<id>, roleId=<>`.
|
||||
- Strikt getrennt von Mandate-Rollen (`admin`, `user`, `viewer`).
|
||||
|
||||
## Umsetzungs-Checkliste
|
||||
|
||||
- [ ] Datenmodell (`datamodelLawyer.py`) – 5 Modelle + PowerOnModel-Basis
|
||||
- [ ] Migration: Auto-Schema reicht? (analog `trustee`)
|
||||
- [ ] Feature-Modul (`mainLawyer.py`) inkl. Template-Rollen-Definition
|
||||
- [ ] Workflow-Method `methodLawyer/` mit 3 Actions
|
||||
- [ ] Konnektoren-Inventur: was haben wir, was fehlt
|
||||
- [ ] DMS-Konnektor (SharePoint vorhanden, iManage neu?)
|
||||
- [ ] E-Mail-Konnektor (Outlook/Exchange vorhanden?)
|
||||
- [ ] Zeiterfassung (mandantenabhängig, Anbindung über generisches Schema)
|
||||
- [ ] KYC/AML (extern, API-Anbindung mandantenspezifisch)
|
||||
- [ ] Konflikt-Check (intern WW-System – API klären)
|
||||
- [ ] Routes (`routeFeatureLawyer.py`)
|
||||
- [ ] Frontend-Komponenten (`Lawyer/Dashboard`, `Lawyer/MatterPreparation`)
|
||||
- [ ] RBAC: Template-Rollen registrieren (siehe `.cursor/rules/rbac-role-separation.mdc`)
|
||||
- [ ] Neutralisierung: `prepareMatter`-Action zwingend mit `PrivateLLM`-Pfad für sensitive Daten
|
||||
- [ ] Navigation (Gateway → Frontend) – Feature-Eintrag
|
||||
- [ ] Billing-Impact: prüfen (analog andere Features – pro Feature-Instance, Subscription-Capacity)
|
||||
- [ ] Mockup-Daten-Set (synthetic) für WW-Präsentation + Demo
|
||||
- [ ] Demo-Login-Mandant einrichten (für Live-Demo nach Präsentation)
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
| # | Kriterium (Given-When-Then) | Prio |
|
||||
|---|---------------------------|------|
|
||||
| 1 | Given Anwalt mit `lawyer-user`-Rolle, When er Matter-Preparation für offenen Matter triggert, Then erhält er in <90s strukturiertes Briefing mit ≥3 Quellen | must |
|
||||
| 2 | Given sensitive Mandantsdaten (Namen, Beträge), When `lawyer.prepareMatter` läuft, Then werden alle PII vor LLM-Call neutralisiert (Audit-Trail in Neutralization-Log) | must |
|
||||
| 3 | Given User mit `lawyer-viewer`, When er Dashboard öffnet, Then sieht er KPIs read-only ohne Schreib-Buttons | must |
|
||||
| 4 | Given User mit Mandate-Rolle `admin` aber ohne `lawyer-*`, When er Lawyer-Feature öffnet, Then Access Denied | must |
|
||||
| 5 | Given Dashboard-Konnektor offline, When `refreshDashboard` läuft, Then Snapshot zeigt Fehlerstatus, Frontend zeigt klare Meldung statt leerer Werte | should |
|
||||
| 6 | Given Briefing generiert, When Anwalt es exportiert, Then PDF/Markdown mit Quellenliste und «synthetic data» Wasserzeichen (im Demo-Mandanten) | should |
|
||||
|
||||
## Testplan
|
||||
|
||||
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|
||||
|----|----|-----|--------------|-----------|--------|
|
||||
| T1 | 1 | api | ja | platform-core/tests/test_lawyer_prepare_matter.py | pending |
|
||||
| T2 | 2 | integration | ja | platform-core/tests/test_lawyer_neutralization.py | pending |
|
||||
| T3 | 3,4 | api | ja | platform-core/tests/test_lawyer_rbac.py | pending |
|
||||
| T4 | 5 | integration | ja | platform-core/tests/test_lawyer_dashboard_refresh.py | pending |
|
||||
| T5 | 1,6 | e2e | manuell | – | pending |
|
||||
|
||||
## Demo-Asset Plan (für WW-Präsentation)
|
||||
|
||||
- Synthetic Matter `M-DEMO-001` (M&A) mit fiktiven Dokumenten, E-Mails, Zeiteinträgen.
|
||||
- Briefing-Output statisch generiert und in `30-presentation/src/data/matter-preparation.json` ablegen, damit die HTML-Präsentation **ohne Backend** funktioniert.
|
||||
- Wenn David Live-Demo will: gleichen Demo-Mandanten im PORTA-Demo-Tenant live verfügbar machen.
|
||||
|
||||
## Links
|
||||
|
||||
- WW-Kontext: `pamocreate/projects/poweron/customer-walderwyss/20-objectives/20260514-zusammenfassung-meeting-dv.md`
|
||||
- WW-Präsentation: `pamocreate/projects/poweron/customer-walderwyss/30-presentation/`
|
||||
- Bestehende Feature-Doku als Vorbild: `wiki/b-reference/platform-core/features/trustee.md`
|
||||
- Plattform-Bausteine: `wiki/b-reference/platform/neutralization.md`, `wiki/b-reference/platform/rbac.md`
|
||||
- PR: – (noch nicht)
|
||||
- Issue: – (noch nicht)
|
||||
|
||||
## Abschluss
|
||||
|
||||
- [ ] `b-reference/platform-core/features/lawyer.md` als neue Kanon-Seite anlegen
|
||||
- [ ] `TOPICS.md` Eintrag für Lawyer-Feature
|
||||
- [ ] Dieses Dokument → `2-build/` → `3-validate/` → `4-done/`
|
||||
- [ ] Eintrag in `c-work/_CHANGELOG.md` pro Phase
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
<!-- status: plan -->
|
||||
<!-- started: 2026-06-04 -->
|
||||
<!-- component: gateway | ui-nyla | platform -->
|
||||
|
||||
# Umsystem-Integration: generische Connectors + kundenspezifische Workflows + Datenquellen-Seiten
|
||||
|
||||
## Beschreibung und Kontext
|
||||
|
||||
Ein Kunde schreibt seine Rechnungen in einem externen System (**SelectLine**, REST-API vorhanden) und möchte, dass diese Rechnungen **ins RMA (Run My Accounts)** geladen werden. Die Frage des Kunden: «Kann PowerOn dafür einfach eine Schnittstelle machen?»
|
||||
|
||||
Der konkrete Fall ist ein Spezialfall eines generischen Musters: PowerOn soll **proprietäre Umsysteme** (ERP, Fakturierung, Lohn, …) anbinden. Wir haben die Logik dafür im Prinzip schon – im Feature **Trustee** sind Buchhaltungssysteme (ABACUS, Bexio, Banana, **RMA**) über das **AccountingBridge-Connector-Framework** angebunden (`platform-core/modules/features/trustee/accounting/`). RMA ist bereits ein vollwertiger Ziel-Connector (inkl. `pushBooking`, `pushInvoice`, Beleg-Upload).
|
||||
|
||||
**Kern-Architekturvorgabe (Auftrag):** Es soll **keine kundenspezifische Logik im Code** entstehen. Wir trennen sauber in:
|
||||
|
||||
1. **Generische Bausteine** (Code, wiederverwendbar, ohne Kundennamen): Connectors, kanonische Datenmodelle, generische Workflow-Nodes.
|
||||
2. **Kundenspezifische Logik** (als **Daten** = Workflow-Graph + Config, nicht als Code): die konkrete Verdrahtung «SelectLine → Mapping → RMA» pro Mandant/Instanz im Graphical Editor.
|
||||
|
||||
Business-Treiber:
|
||||
- Konkreter Kundenwunsch (Termin nächste Woche).
|
||||
- Wiederverwendbares Muster für jedes weitere Umsystem → Sales-Asset und skalierbare Onboarding-Story.
|
||||
- Vermeidung von Wartungs-Hölle durch `if kunde == X`-Code.
|
||||
|
||||
**Abgrenzung — NICHT als Personal Source einbinden.** Personal Sources (UDB-`DataSource`-Familie: SharePoint, Drive, Infomaniak) sind **user-privat** und für **unstrukturierte RAG-Daten** gedacht (`wiki/b-reference/platform/unified-data-bar.md`). Eine Debitorenrechnung von SelectLine nach RMA ist ein **transaktionaler Buchungs-Vorgang auf Mandant-/Feature-Ebene** mit Dedup, Sync-Audit und verschlüsselten Credentials pro Mandant. Das gehört in das **Trustee-Connector-Framework** (`featureInstanceId`-scoped), nicht in Personal Sources.
|
||||
|
||||
## Fokus und kritische Details
|
||||
|
||||
- **Trennung Baustein ↔ Kundenlogik ist das eigentliche Ziel.** Jede Versuchung, Kunden-/Systemspezifika fest zu verdrahten (Konten-Mappings, Filter, Belegart-Auswahl), muss in **Config/Workflow-Graph** wandern, nicht in den Connector.
|
||||
- **Connector = reiner API-Adapter.** Auth, Lesen/Schreiben von Ressourcen, Mapping zwischen nativem API-Format und kanonischem Modell. Keine Geschäftsregeln, keine Kundennamen, keine Konto-Zuordnungen.
|
||||
- **Richtung.** Bestehende AccountingBridge ist heute **push-orientiert** (lokale `TrusteePosition` → extern). SelectLine ist eine **Quelle** (lesen). Wir brauchen einen sauberen **Import-/Source-Pfad** und eine **Rolle** (`source` / `target`) auf der Config, weil eine Instanz künftig *eine Quelle* **und** *ein Ziel* hat.
|
||||
- **On-Prem-Erreichbarkeit (grösstes Risiko, extern abhängig).** Die SelectLine-API läuft typischerweise beim Kunden (Doku zeigt `http://localhost/...`). Unsere Cloud muss sie erreichen → VPN / Reverse-Tunnel / fester Endpoint / On-Site-Agent. Klärt Aufwand und Sicherheit.
|
||||
- **Datenschutz/Neutralisierung.** Rechnungen enthalten Personendaten. Pfade, die durch das LLM laufen (z. B. KI-gestütztes Konten-Mapping), müssen über das Neutralisierungs-Gate (`wiki/b-reference/platform/neutralization.md`).
|
||||
- **Fragile Stellen:** `accountingBridge.py` (Orchestrierung, Dedup, Sync-Records) ist heute auf Position→Push zugeschnitten; der Source-Pfad muss additiv ergänzt werden, ohne den bestehenden Push-Pfad zu brechen. `TrusteeAccountingConfig` erlaubt heute nur **eine aktive** Config pro Instanz (siehe `getActiveConfig`).
|
||||
|
||||
## Ziel und Nicht-Ziele
|
||||
|
||||
- **Ziel:** Generisches, plugin-basiertes **Umsystem-Connector-Framework** (Erweiterung des bestehenden AccountingBridge-Musters), mit dem ein neues System = **eine Connector-Datei + Config**, ohne Architekturänderung.
|
||||
- **Ziel:** **SelectLine-Connector** (Quelle): Login, Lesen von Ausgangsrechnungen (`Document`/`DocumentKind`), Kunden, Konten, Steuerschlüssel.
|
||||
- **Ziel:** **Source→Target-Import** als **generische Workflow-Nodes**, sodass «SelectLine → RMA» ein **Workflow-Graph** ist (kundenspezifisch als Daten), kein Code.
|
||||
- **Ziel:** **UI-Muster «Datenquelle = Seite»** im Feature Trustee: die Seite «Buchhaltungssystem» existiert; das Muster wird generisch, sodass weitere Kategorien (z. B. «Saläre», «Fakturierung») als eigene Seiten dazukommen können.
|
||||
- **Explizit NICHT:** kundenspezifische Logik im Code (`if kunde == …`).
|
||||
- **Explizit NICHT:** SelectLine als Personal Source.
|
||||
- **Explizit NICHT:** Aufbau eines eigenen ERP/Faktura-Systems – wir konsumieren/transferieren nur.
|
||||
- **Explizit NICHT (vorerst):** voll generisches «Integrations-Framework für alles». Wir bleiben im Trustee-Kontext und verallgemeinern erst, wenn die zweite Kategorie (Saläre) real wird (YAGNI – siehe «Meine Gedanken»).
|
||||
|
||||
## Architektur: generische Bausteine vs. kundenspezifische Logik
|
||||
|
||||
Vier Schichten. Schicht 1–3 sind **Code (generisch)**, Schicht 4 ist **Daten (kundenspezifisch)**.
|
||||
|
||||
```
|
||||
┌─ Schicht 4: WORKFLOW-GRAPH + CONFIG (Daten, pro Instanz, im Graphical Editor) ─┐
|
||||
│ "SelectLine → mappe Konto 1100→1100, Belegart=AR, seit lastSync → RMA (GL)" │
|
||||
│ Konto-Mappings · Filter · Zeitplan · Quelle/Ziel-Auswahl → KUNDENSPEZIFISCH │
|
||||
└─────────────────────────────────────────────────────────────────────────────────┘
|
||||
▲ konsumiert generische Nodes, enthält KEINEN Code
|
||||
┌─ Schicht 3: WORKFLOW-NODES (generische Typed Actions) ─────────────────────────┐
|
||||
│ source.fetchInvoices · transform.mapAccounts · target.pushBooking · attachDoc │
|
||||
└─────────────────────────────────────────────────────────────────────────────────┘
|
||||
▲ arbeiten ausschliesslich auf kanonischen Modellen
|
||||
┌─ Schicht 2: KANONISCHE MODELLE ─────────────────────────────────────────────────┐
|
||||
│ AccountingBooking / AccountingBookingLine / Invoice / Contact / Chart … │
|
||||
│ (bereits vorhanden in accountingConnectorBase.py) │
|
||||
└─────────────────────────────────────────────────────────────────────────────────┘
|
||||
▲ Connectors übersetzen natives API-Format ⇄ kanonisch
|
||||
┌─ Schicht 1: CONNECTORS (generische API-Adapter, plugin-discovery) ─────────────┐
|
||||
│ accountingConnectorRma.py · accountingConnectorSelectline.py · …bexio/abacus │
|
||||
│ nur Auth + Lesen/Schreiben + Mapping. KEINE Kundenlogik. │
|
||||
└─────────────────────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### Schicht 1 — Connectors (neu: SelectLine)
|
||||
|
||||
- Neue Datei `platform-core/modules/features/trustee/accounting/connectors/accountingConnectorSelectline.py`, implementiert `BaseAccountingConnector` (`accountingConnectorBase.py`). Auto-Discovery über `accountingRegistry.py` (Pattern `accountingConnector*.py`) → **keine Registrierungs-Änderung nötig**.
|
||||
- Methoden: `testConnection` (Login + GET), `getChartOfAccounts` (Konten), `getCustomers`/`getVendors`, und die Lese-Seite für Belege (siehe «Source-Capability» unten).
|
||||
- Config-Felder (`getRequiredConfigFields`): `baseUrl`, `username`, `password` (secret), optional `mandant`. Verschlüsselt wie alle Configs (`_decryptConfig`).
|
||||
- **Source-Capability:** Da die Base heute primär Push/Read-Journal kennt, ergänzen wir eine schlanke, optionale Lesemethode für Belege, z. B. `getOutgoingInvoices(config, dateFrom, sinceCursor) -> List[Invoice]` (Default `[]` in der Base; nur Source-Connectors überschreiben). Alternativ Wiederverwendung von `getJournalEntries` – Entscheidung siehe «Offene Fragen».
|
||||
|
||||
### Schicht 2 — kanonische Modelle (vorhanden)
|
||||
|
||||
`AccountingBooking`, `AccountingBookingLine`, `AccountingChart`, `SyncResult` etc. in `accountingConnectorBase.py`. Für reine Debitoren-Fakturen ggf. ein kanonisches `Invoice`-Modell ergänzen (Header + Lines + Kunde + Steuer), falls RMA als **AR-Rechnung** (offener Posten) statt GL-Buchung beschrieben werden soll.
|
||||
|
||||
### Schicht 3 — Workflow-Nodes (generisch, Typed Actions)
|
||||
|
||||
Analog zu den bestehenden Trustee-Actions (`trustee.extractFromFiles` → `processDocuments` → `syncToAccounting`). Neue, **system-agnostische** Nodes:
|
||||
|
||||
- `integration.fetchFromSource` — zieht Belege/Buchungen aus dem **konfigurierten Quell-Connector** (Quelle = Config, nicht hartcodiert) → kanonische Liste.
|
||||
- `integration.mapAccounts` — wendet eine **Mapping-Tabelle** (Config/Daten) auf Konten/Steuercodes an.
|
||||
- `integration.pushToTarget` — schreibt über den **konfigurierten Ziel-Connector** (`pushBooking`/`pushInvoice` + Beleg-Upload, bereits in RMA vorhanden).
|
||||
|
||||
Diese Nodes erscheinen über den Editor-Adapter (`graphicalEditor/nodeDefinitions/`) als Bausteine im Graphical Editor. Die Pipeline `trigger → fetchFromSource(SelectLine) → mapAccounts → pushToTarget(RMA)` ersetzt damit für strukturierte Quellen den KI-Extraktionsschritt (günstiger + zuverlässiger).
|
||||
|
||||
### Schicht 4 — Workflow-Graph + Config (kundenspezifisch, als Daten)
|
||||
|
||||
- Der konkrete Kundenfluss ist ein **Workflow-Template/Graph** pro Feature-Instanz (persistiert), gebaut im Graphical Editor. Konten-Mappings, Filter (nur Ausgangsrechnungen, nur «seit letztem Sync»), Buchungsart, Zeitplan = **Config-Datensätze**.
|
||||
- Ergebnis: zwei Kunden mit SelectLine→RMA, aber unterschiedlichem Kontenplan-Mapping = **zwei Graphen/Configs, ein Code**.
|
||||
|
||||
### Datenmodell-Änderung
|
||||
|
||||
`TrusteeAccountingConfig` um **`role`** (`source` | `target`) erweitern, sodass pro Instanz mehrere Connector-Configs koexistieren (eine Quelle + ein Ziel). `getActiveConfig` / `_resolveConnectorAndConfig` entsprechend um `role` filtern. Optional: `connectorCategory` (`accounting` | `payroll` | `invoicing`) für die UI-Seitenzuordnung.
|
||||
|
||||
## SelectLine-API – Befund (Kurz)
|
||||
|
||||
Geprüft anhand hilfe.selectline.ch und der Demo-API (demo.slmobile.de):
|
||||
|
||||
- REST, JSON/XML. Auth: `POST /Login` mit `{username,password}` → `AccessToken`/`LoginId`; danach Header `Authorization: LoginId <token>` (Session-Token, Re-Login bei Ablauf).
|
||||
- Relevante Ressourcen: **`Document` / `DocumentKind`** (Belegkette inkl. Ausgangsrechnungen), `Customers`/`Vendors` (Geschäftspartner), `Konten` + `Kontensalden`, `Journale`, `Offene Posten`, `Steuerschlüssel`, `Kostenrechnung`, `Bankassistent` (camt.053-Import).
|
||||
- Betriebsmodell: i. d. R. **on-premise** beim Kunden → Erreichbarkeit klären (Risiko oben).
|
||||
- Swagger-/OpenAPI-Beschreibung pro Installation herunterladbar → exaktes Beleg-Schema beim Kunden verifizieren.
|
||||
|
||||
## UI-Konzept: «Datenquelle = Seite»
|
||||
|
||||
Heute ist «Buchhaltungs-Einstellungen» eine eigene Seite im Trustee-Feature:
|
||||
- Registriert als UI-Object `ui.feature.trustee.settings` (`meta.area="settings"`, `admin_only`) in `mainTrustee.py`.
|
||||
- Gemappt auf `TrusteeAccountingSettingsView` in `ui-nyla/src/pages/FeatureView.tsx` (`VIEW_COMPONENTS.trustee.settings`).
|
||||
- Innen bereits Tabs: «Verbindungseinstellungen» + «Buchhaltungsdaten importieren» (Connector wählen → Credentials → Test → Import).
|
||||
|
||||
**Vorschlag:** dieses Muster zu einem **generischen «Datenquellen-Seiten»-Pattern** verallgemeinern – eine Seite pro **Kategorie** von Umsystem:
|
||||
|
||||
| Seite (UI-Area) | Kategorie | Connectors (Beispiele) | Kanonisches Modell |
|
||||
|---|---|---|---|
|
||||
| Buchhaltungssystem (existiert) | `accounting` | RMA, Bexio, Abacus, **SelectLine (Quelle)** | AccountingBooking |
|
||||
| **Saläre** (Idee) | `payroll` | SwissSalary, Abacus Lohn, Swissdec-konform | PayrollEntry (neu) |
|
||||
| Fakturierung (Idee) | `invoicing` | SelectLine, Bexio | Invoice |
|
||||
|
||||
Pro Seite identischer Aufbau (**eine generische React-Komponente, parametrisiert über `category`**):
|
||||
1. **Verbindungen** — Connectors der Kategorie listen, Rolle (Quelle/Ziel) wählen, Credentials, Test (wiederverwendet die bestehende `TrusteeAccountingSettingsView`-Mechanik, generalisiert).
|
||||
2. **Datenfluss/Import** — Workflow-Template wählen/starten (= Schicht-4-Graph), Zeitplan, Status/Audit.
|
||||
3. **Daten** — eingelesene Datensätze (read-only Spiegel).
|
||||
|
||||
Konkret:
|
||||
- Generische `IntegrationSettingsView` (aus `TrusteeAccountingSettingsView` extrahiert), die `category` als Prop bekommt.
|
||||
- Neue UI-Areas in `mainTrustee.py` (z. B. `ui.feature.trustee.payroll`) + Mapping in `FeatureView.tsx` → **gleiche** Komponente, andere `category`.
|
||||
- «Saläre» ist bewusst **nur ein Platzhalter-Beispiel**, um zu zeigen, dass das Muster skaliert; nicht Teil der ersten Umsetzung.
|
||||
|
||||
## Betroffene Module
|
||||
|
||||
- **Gateway (platform-core):**
|
||||
- `features/trustee/accounting/connectors/accountingConnectorSelectline.py` (neu).
|
||||
- `accounting/accountingConnectorBase.py` (optionale Source-Lesemethode, Default `[]`).
|
||||
- `accounting/accountingBridge.py` (additiver Import-/Source-Pfad; `role`-Auflösung).
|
||||
- `datamodelFeatureTrustee.py` (`TrusteeAccountingConfig.role` [+ optional `connectorCategory`]) → **DB-Migration: ja**.
|
||||
- `workflows/methods/methodTrustee/actions/` + `graphicalEditor/nodeDefinitions/` (generische Nodes `integration.fetchFromSource` / `mapAccounts` / `pushToTarget`).
|
||||
- `mainTrustee.py` (UI-Areas, RBAC-Objekte, Workflow-Templates).
|
||||
- **Frontend (ui-nyla):**
|
||||
- `TrusteeAccountingSettingsView` → generische `IntegrationSettingsView` (`category`-Prop).
|
||||
- `FeatureView.tsx` Registry + `mainTrustee` UI-Areas für weitere Seiten.
|
||||
- `trusteeApi.ts` (Connector-Listing nach Kategorie, Rolle source/target).
|
||||
- **DB-Migration:** ja (`role`, optional `connectorCategory`).
|
||||
- **Andere:** Neutralisierung (falls KI-Mapping), Audit/Billing (Sync-Volumen).
|
||||
|
||||
## Entscheidungen
|
||||
|
||||
| Datum | Entscheidung | Begründung |
|
||||
|-------|-------------|------------|
|
||||
| 2026-06-04 | Umsystem als Trustee-Connector, **nicht** als Personal Source | Transaktional, mandant-scoped, Dedup/Audit/verschlüsselte Credentials bereits in AccountingBridge |
|
||||
| 2026-06-04 | Kundenlogik als Workflow-Graph + Config, nicht im Code | Auftrag: keine kundenspezifische Logik im Code; nutzt bestehende Typed-Action-/Editor-Architektur |
|
||||
| 2026-06-04 | UI-Muster «Datenquelle = Seite» pro Kategorie, eine generische Komponente | Skaliert auf Saläre/Fakturierung ohne Copy-Paste |
|
||||
|
||||
## Umsetzungs-Checkliste
|
||||
|
||||
- [ ] DB: `TrusteeAccountingConfig.role` (+ optional `connectorCategory`) + Migration
|
||||
- [ ] Bridge: Source-Auflösung nach `role`, Import-Pfad (additiv, Push-Pfad unverändert)
|
||||
- [ ] Connector: `accountingConnectorSelectline.py` (Login/Test/Konten/Kunden/Belege lesen)
|
||||
- [ ] Kanonisch: `Invoice`-Modell prüfen/ergänzen (falls AR-Rechnung in RMA)
|
||||
- [ ] Workflow-Nodes: `integration.fetchFromSource` / `mapAccounts` / `pushToTarget` + Editor-Adapter
|
||||
- [ ] Workflow-Template «Source→Target Import» (parametrisierbar)
|
||||
- [ ] UI: `IntegrationSettingsView` generalisieren (`category`), Quelle/Ziel-Auswahl
|
||||
- [ ] RBAC / Permissions (neue UI-Areas, admin_only)
|
||||
- [ ] Neutralisierung betroffen? (nur falls KI-Mapping)
|
||||
- [ ] Navigation / Routing (UI-Areas + FeatureView-Registry)
|
||||
- [ ] Billing-Impact? (Sync-Läufe/Volumen)
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
| # | Kriterium (Given-When-Then) | Prio |
|
||||
|---|---------------------------|------|
|
||||
| 1 | Given konfigurierter SelectLine-Source + RMA-Target, When der Import-Workflow läuft, Then erscheinen die SelectLine-Ausgangsrechnungen als Buchungen in RMA (inkl. Beleg-Verlinkung) | must |
|
||||
| 2 | Given zwei Mandanten mit unterschiedlichem Konten-Mapping, When beide SelectLine→RMA nutzen, Then unterscheiden sie sich nur in Workflow-Graph/Config – **kein** kundenspezifischer Code | must |
|
||||
| 3 | Given ein neues Umsystem, When ein Connector-File + Config ergänzt wird, Then ist es ohne Änderung an Registry/Bridge/Editor verfügbar | must |
|
||||
| 4 | Given erneuter Import, When Belege bereits gebucht sind, Then werden sie über die bestehende Dedup-Logik nicht doppelt gebucht | must |
|
||||
| 5 | Given das UI-Muster, When eine neue Kategorie-Seite («Saläre») registriert wird, Then nutzt sie dieselbe generische Komponente | should |
|
||||
|
||||
## Testplan
|
||||
|
||||
| ID | AC | Art | Automatisiert | Repo-Pfad | Status |
|
||||
|----|----|-----|--------------|-----------|--------|
|
||||
| T1 | 1 | unit | ja | platform-core/tests/unit/features/trustee/test_accountingConnectorSelectline.py | pending |
|
||||
| T2 | 1,4 | integration | ja | platform-core/tests/integration/trustee/test_source_target_import_e2e.py | pending |
|
||||
| T3 | 3 | unit | ja | platform-core/tests/unit/.../test_adapter_validator.py (Editor-Node-Drift) | pending |
|
||||
| T4 | 2 | unit | ja | platform-core/tests/unit/.../test_integration_nodes.py (Mapping aus Config) | pending |
|
||||
|
||||
## Offene Fragen (für den Kundentermin)
|
||||
|
||||
1. **Erreichbarkeit:** Wo läuft die SelectLine-API (on-prem/Cloud)? Welcher Zugriffsweg (VPN/Tunnel/Agent)?
|
||||
2. **Zielart in RMA:** Debitoren-Rechnung (AR, offener Posten) **oder** GL-Buchung? → bestimmt `pushInvoice`-Ausbau vs. `pushBooking`.
|
||||
3. **Mapping:** Liefert SelectLine pro Rechnung Konto + Steuerschlüssel, oder Kontenplan-Mapping SelectLine→RMA nötig?
|
||||
4. **Beleg-PDF:** Rechnungs-PDF mit nach RMA (Beleg-Upload vorhanden)?
|
||||
5. **Delta/Frequenz:** On-demand, Zeitplan oder Event? Cursor = Belegnummer/Datum?
|
||||
6. **Alternative:** SelectLine `Bankassistent` (camt.053) – relevant oder nur Ausgangsrechnungen?
|
||||
|
||||
## Meine Gedanken / Empfehlungen
|
||||
|
||||
- **Saubere Trennung ist erreichbar, weil die Plattform sie schon vorlebt.** Trustee nutzt bereits Typed Actions + Graphical Editor + Templates. «Kundenlogik als Graph» ist kein neues Paradigma, sondern Anwendung des Bestehenden. Das ist der grösste Hebel gegen kundenspezifischen Code.
|
||||
- **Nicht zu früh über-generalisieren.** Ein einziges «BaseConnector für alles» mit Capability-Mixins (`AccountingCapable`, `PayrollCapable`) ist elegant, aber bevor «Saläre» real ist, würde ich beim bestehenden `BaseAccountingConnector` bleiben und nur die **Source-Rolle** ergänzen. Die Abstraktion ziehen wir, wenn die zweite Kategorie konkret wird – sonst bauen wir ein Framework für hypothetische Fälle (YAGNI).
|
||||
- **Namensgebung zur Abgrenzung:** «Personal Sources» = user-privat/RAG. Diese hier sind **«Umsystem-Anbindungen» / «Integrationen»** auf Mandant-Ebene. Klare Begriffe verhindern, dass die zwei Welten wieder vermischt werden.
|
||||
- **Source vs. Target ist die wichtigste neue Achse.** Sie macht aus dem heutigen Push-Framework ein bidirektionales Integrations-Framework und ist die Voraussetzung für «System A → PowerOn → System B» generell.
|
||||
- **«Saläre»-Seite** ist ein gutes nächstes Beispiel: Lohnsystem (Swissdec-konform) → Lohnbuchungen → Buchhaltung. Gleicher Mechanismus, neues kanonisches Modell `PayrollEntry`. Bestätigt, dass das Seiten-Muster trägt.
|
||||
- **Risiko bleibt extern:** On-Prem-Erreichbarkeit von SelectLine ist der kritische Pfad – das ist eher Infrastruktur/Netzwerk als Code. Im Kundentermin zuerst klären.
|
||||
|
||||
## Links
|
||||
|
||||
- Vorgelagerte Analyse (dieser Chat): SelectLine-API-Prüfung + erste Empfehlung
|
||||
- Referenz Trustee: `wiki/b-reference/platform-core/features/trustee.md`
|
||||
- Referenz UDB/Personal Sources: `wiki/b-reference/platform/unified-data-bar.md`
|
||||
- Code: `platform-core/modules/features/trustee/accounting/` (Bridge, Base, Registry, Connectors)
|
||||
- PR: —
|
||||
- Issue: —
|
||||
|
||||
## Abschluss
|
||||
|
||||
- [ ] b-reference/ aktualisiert (`features/trustee.md` Abschnitt «Source-Connectors / Integrationen»; ggf. neue `platform/integrations.md`)
|
||||
- [ ] TOPICS.md aktualisiert (neues Thema «Umsystem-Integrationen»)
|
||||
- [ ] Dieses Dokument → c-work/2-build/ (bei Umsetzungsbeginn), am Ende → z-archive/
|
||||
|
|
@ -14,6 +14,9 @@ Skip: reine Refactors, Formatting, Lint, Dep-Bumps, Test-only, Wiki-Tippfehler.
|
|||
|
||||
## 2026-06-04
|
||||
|
||||
- 2026-06-04 | docs | wiki | **CustomerCases-Doks auf einheitliche Naming-Convention umbenannt**: `2026-06-STEP*`-Dateien → `2026-06-CustomerCases-stepN-*` (step1=architecture, step2=communication [product-summary md/pdf + mockup html], step3=solutions-plan/features-plan). Alle Cross-Referenzen in den Dokumenten + Changelog-Pfade angepasst. (c-work: c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md u. a.)
|
||||
- 2026-06-04 | docs | wiki | **STEP2-Pläne neu strukturiert: Solutions vs. Features**: Die drei bisherigen STEP2-Docs (lawyer-feature, pm-consolidated-customer-requirements, umsystem-integration) durch zwei architektur-konforme Pläne ersetzt. `step3-solutions-plan.md` = alle konfigurierten Use Cases als Solutions (S1 SelectLine→RMA, S2 Pling-Reporting, S3 PWG-Mietzins, S4 Beleg-Import, S5 Finanz-Analysen, S6 Notification) mit Trigger/Bausteine/Settings/Output je Solution + Klassifikationstabelle. `step3-features-plan.md` = der Code dahinter (Teil A Plattform-Enabler: Solution-Schicht L3/L4, generische Nodes rbac.queryUsersByRole/testMode/integration.*, Connectors; Teil B vertikale Features: lawyer, commcoach, trustee-core). (c-work: c-work/0-ideas/2026-06-CustomerCases-step3-solutions-plan.md, 2026-06-CustomerCases-step3-features-plan.md)
|
||||
- 2026-06-04 | docs | wiki | **Konzept: Solution-Schicht (Customer Workflows) + Pling-Use-Case**: Architektur-Idee fuer generische L3/L4-Solution-Schicht ueber dem Workflow-Stack (Use Case → konfigurierter Workflow, kein Kunden-Code). Pling «Kaffee-Klatsch» Monatsreporting als staerkstes Validierungsbeispiel eingearbeitet (Multi-Instanz-Fan-out, rollenbasierte Verteilung). Plus generische Product-Summary und klickbares HTML-Mockup im ui-nyla-Look. (c-work: c-work/0-ideas/2026-06-CustomerCases-step1-architecture.md, 2026-06-CustomerCases-step2-communication-product-summary.md, 2026-06-CustomerCases-step2-communication-mockup.html)
|
||||
- 2026-06-04 | docs | wiki | **Plan: Umsystem-Integration (Connectors + Workflows + Datenquellen-Seiten)**: Arbeitsdokument fuer generische Umsystem-Anbindung (SelectLine→RMA als Pilot). Trennung generische Bausteine (Connectors/kanonische Modelle/Workflow-Nodes) vs. kundenspezifische Logik (Workflow-Graph + Config). UI-Muster «Datenquelle = Seite» pro Kategorie (Buchhaltung existiert, Saläre als Idee). (c-work: c-work/1-plan/2026-06-umsystem-integration-connectors-und-datenquellen-seiten.md)
|
||||
|
||||
## 2026-06-03
|
||||
|
|
|
|||
Loading…
Reference in a new issue