diff --git a/TOPICS.md b/TOPICS.md index 847ca9f..84ff188 100644 --- a/TOPICS.md +++ b/TOPICS.md @@ -35,6 +35,7 @@ Lade immer zuerst diese Datei. Dann gezielt die passende(n) Referenz-Datei(en). | RBAC | b-reference/platform/rbac.md | 4-Stufen-Modell, Template-Rollen, Resolution, Datenmodell | | Datenbank-Architektur | b-reference/platform/database-architecture.md | Interface-Pattern, Connector, Auto-Init, DB-Liste | | Navigation | b-reference/platform/navigation.md | Menü-Struktur, Admin-Seiten, API | +| i18n / Mehrsprachigkeit | b-reference/gateway/architecture.md (Abschnitt i18n), d-guides/coding-conventions.md (Backend i18n), b-reference/frontend-nyla/architecture.md (Routing/i18n) | `t()`, `@i18nModel`, UiLanguageSet, TextMultilingual, AI-Uebersetzung, Boot-Sync | ## Aktive Arbeiten (c-work) @@ -43,6 +44,11 @@ Lade immer zuerst diese Datei. Dann gezielt die passende(n) Referenz-Datei(en). | Automation Unification | c-work/1-plan/2026-04-automation-unification.md | Refactoring v1/v2/Workspace | | Web Image Search | c-work/1-plan/2026-03-web-image-search.md | WEB_SEARCH_MEDIA Feature | | UI i18n / Sprachsets (done) | c-work/3-validate/2026-04-ui-i18n-dynamic-language-sets.md | Mehrsprachigkeit, `t()`, Sprachset-API, Admin-UI, AI-Übersetzung | +| Gateway i18n Unified | c-work/3-validate/2026-04 gateway-i18n-unified.md | `@i18nModel`, `t()` Backend, Boot-Sync, TextMultilingual dynamisch | +| Gateway i18n Phase 7 (done) | c-work/3-validate/2026-04-gateway-i18n-phase-7-implementation.md | RBAC-Keys (rbac.*) im xx-Set, `translate-field` API, FormGenerator KI-Button | +| Gateway Duplicate Class Names (done) | c-work/3-validate/2026-04-gateway-duplicate-class-names.md | TaskResult, AiResponse, TableData, Token Umbenennungen | +| Generic Graph Editor (Typed Nodes, done) | c-work/3-validate/2026-04-generic-graph-editor.md | Port-Typen, Extraktoren, FrontendType-Renderer, System-Variablen | +| i18n Static Text Elimination (Ph. 1–2 done) | c-work/2-build/2026-04-i18n-static-text-elimination.md | Gateway Feature+Nodes: Dicts → de-Keys; Ph. 3–5 offen | ## Prozess & Betrieb diff --git a/b-reference/frontend-nyla/architecture.md b/b-reference/frontend-nyla/architecture.md index 36e98ca..bdfe67d 100644 --- a/b-reference/frontend-nyla/architecture.md +++ b/b-reference/frontend-nyla/architecture.md @@ -1,5 +1,5 @@ - + # Frontend Nyla -- Architektur @@ -49,7 +49,8 @@ Ergänzend typische Root-Dateien und Bereiche im Repo: `main.tsx`, `App.tsx`, `a - **Geschützte Bereiche:** Route-Guards (z. B. `ProtectedRoute`) prüfen Authentifizierung; Redirect bei fehlender Session. - **Haupt-App:** Nach Login **`MainLayout.tsx`** mit **`MandateNavigation`** (Sidebar) und `` (React Router). - **Seiten-Mapping:** `pageRegistry.tsx` definiert `PAGE_REGISTRY` und `FEATURE_REGISTRY`; Seiten werden lazy geladen. `core/PageManager/` enthält ergänzende Infrastruktur (State Preservation, Lifecycle-Hooks). -- **i18n:** DB-backed via `LanguageContext` (`t()`-Hook). Sprachsets werden dynamisch via public API geladen (`GET /api/i18n/sets/{code}`). Key-Konvention: **Deutscher Klartext = Key**. Jeder neue/geänderte UI-Text MUSS mit `t('Deutscher Klartext')` getaggt werden. Variable Interpolation: `t('Text {var}', {var: 'Wert'})`. Fallback: Ziel-Set → `de`-Set → Key selbst. Keine statischen Locale-Files. +- **i18n:** DB-backed via `LanguageContext` (`t()`-Hook). Sprachsets werden dynamisch via public API geladen (`GET /api/i18n/sets/{code}`). Key-Konvention: **Deutscher Klartext = Key**. Jeder neue/geänderte UI-Text MUSS mit `t('Deutscher Klartext')` getaggt werden. Variable Interpolation: `t('Text {var}', {var: 'Wert'})`. Fallback: Ziel-Set → `de`-Set → Key selbst. Keine statischen Locale-Files. Das xx-Basisset enthaelt sowohl UI-Keys (context="ui") als auch Gateway-Keys (context="api.*", "table.*") — beide werden per AI uebersetzt. +- **TextMultilingual:** Felder vom Typ `TextMultilingual` rendern dynamisch Eingabefelder fuer alle verfuegbaren Sprachen (aus `availableLanguages`). Keine hardcodierten Sprach-Codes. Sprachcodes folgen ISO 639-1 (en, de, fr, it, …). - **Theme:** global über Context; API-Requests mit Auth-Header (Interceptor in zentralem API-Client). ## UI-Regeln @@ -72,7 +73,12 @@ Ergänzend typische Root-Dateien und Bereiche im Repo: `main.tsx`, `App.tsx`, `a | `auth/authConfig`, `authProvider`, `ProtectedRoute` | MSAL, geschützte Routen | | `contexts/*` | FileContext, PekContext, Toast, Workflow-Auswahl, etc. | | `components/FlowEditor/editor/Automation2FlowEditor.tsx` | Haupt-Editor-Komponente (3-Column-Layout, State-Management) | -| `components/FlowEditor/editor/FlowCanvas.tsx` | Custom Canvas mit Node-Rendering, Connections, Highlighting | +| `components/FlowEditor/editor/FlowCanvas.tsx` | Custom Canvas mit Node-Rendering, Connections, Highlighting; `CanvasNode` traegt `inputPorts`/`outputPorts` | +| `components/FlowEditor/nodes/frontendTypeRenderers/index.tsx` | `FRONTEND_TYPE_RENDERERS` Registry — generischer Renderer pro `FrontendType` statt pro Node-Typ | +| `components/FlowEditor/editor/NodeConfigPanel.tsx` | Generischer Config-Renderer via `FRONTEND_TYPE_RENDERERS` (kein `NODE_CONFIG_REGISTRY` mehr) | +| `components/FlowEditor/nodes/shared/graphUtils.ts` | `fromApiGraph`/`toApiGraph` serialisieren `inputPorts`/`outputPorts` auf `CanvasNode` | +| `components/FlowEditor/nodes/shared/DataPicker.tsx` | Schema-basierte Pfad-Aufloesung, Transit-Chain, System-Variablen-Sektion | +| `components/FlowEditor/context/Automation2DataFlowContext.tsx` | Stellt `portTypeCatalog` und `systemVariables` im Context bereit | | `components/FlowEditor/editor/RunTracingPanel.tsx` | SSE Live-Push + Canvas-Highlighting fuer Workflow-Runs | | `components/FlowEditor/editor/EditorChatPanel.tsx` | AI Chat mit Dateianhang (Drag&Drop) und Source-Picker | | `components/FlowEditor/editor/CanvasHeader.tsx` | Versioning, Template-Management, Workflow-Aktionen | @@ -80,7 +86,9 @@ Ergänzend typische Root-Dateien und Bereiche im Repo: `main.tsx`, `App.tsx`, `a | `pages/views/graphicalEditor/GraphicalEditorPage.tsx` | Feature-Seite mit KeepAlive, URL-basiertem Workflow-Loading | | `locales/index.ts`, `types.ts` | i18n: API-basiertes Language-Loading (DB-backed, keine statischen Files) | | `providers/language/LanguageContext.tsx` | `t()`-Hook mit `{variable}`-Interpolation, Fallback-Kette, `availableLanguages` | -| `pages/admin/AdminLanguagesPage.tsx` | Admin-Seite: Sprachset-Verwaltung (CRUD, AI-Übersetzung) | +| `components/FormGenerator/FormGeneratorForm/FormGeneratorForm.tsx` | Rendert `frontend_type: multilingual` (TextMultilingual) dynamisch nach `availableLanguages`; Button „In alle Sprachen uebersetzen“ (KI via `POST /api/i18n/translate-field`) | +| `pages/admin/AdminLanguagesPage.tsx` | Admin-Seite: Sprachset-Verwaltung (CRUD, AI-Übersetzung, UI/API-Key-Counts) | +| `pages/admin/AdminLanguagesKeepAlive.tsx` | KeepAlive-Wrapper: Sprach-Seite bleibt persistent bei Seitenwechsel | ## Regeln / Invarianten diff --git a/b-reference/gateway/architecture.md b/b-reference/gateway/architecture.md index 808fe06..6730c59 100644 --- a/b-reference/gateway/architecture.md +++ b/b-reference/gateway/architecture.md @@ -1,5 +1,5 @@ - + # Gateway -- Architektur @@ -25,7 +25,7 @@ Unter `gateway/modules/` (Kontext-Audit): | `security/` | RBAC (`rbac.py`, `rbacCatalog.py`), Root-Access | | `serviceCenter/` | Zentrale Service-Orchestrierung (Registry, Resolver, Kontext, Haupt-Services) | | `serviceHub/` | Service-Registry und Dependency Injection (u. a. `PublicService`-Wrapper) | -| `shared/` | Gemeinsame Utilities (attributeUtils, Konfiguration, Logging, …) | +| `shared/` | Gemeinsame Utilities (attributeUtils, i18nRegistry, Konfiguration, Logging, …) | | `system/` | System-Konfiguration, Feature-Discovery (`registry.py`: `loadFeatureMainModules`, `loadFeatureRouters`) | | `workflows/` | Workflow-Engine mit Methoden, Aktionen, Execution Engine und konsolidiertem Scheduler | @@ -96,10 +96,39 @@ Weitere Interface-Dateien im Ordner (z. B. Voice, Tickets, Messaging, Bootstrap) | `gateway/modules/shared/*` | Querschnitt: Konfiguration, Audit-Logging, Events, Utilities | | `gateway/modules/system/registry.py` | Feature-Discovery, Router-Laden, Katalog-Registrierung beim App-Start | | `gateway/modules/workflows/workflowManager.py` | Zentrale Workflow-Steuerung (Workspace/Chat Workflows) | -| `gateway/modules/workflows/automation2/executionEngine.py` | Graph-Execution-Engine (Graphical Editor) | +| `gateway/modules/workflows/automation2/executionEngine.py` | Graph-Execution-Engine: topoSort, Transit-Routing, `_normalizeToSchema` nach Execute, `flow.merge`-Wait, Resume-Schema-Validierung | | `gateway/modules/workflows/scheduler/mainScheduler.py` | Konsolidierter Workflow-Scheduler | | `gateway/modules/interfaces/interfaceBootstrap.py` | System-Bootstrap (Templates, Billing, Stripe) | +## i18n (Mehrsprachigkeit) + +Das Gateway nutzt dasselbe DB-basierte Sprachsystem wie das Frontend (`UiLanguageSet`). Alle UI-sichtbaren Texte (HTTPException-Details, Model-Labels, API-Messages) werden ueber `t()` getaggt und per AI uebersetzt. + +| Komponente | Datei | Zweck | +|------------|-------|-------| +| `i18nRegistry.py` | `modules/shared/` | `t()`, `@i18nModel` Decorator, `_REGISTRY`, `_CACHE`, `_setLanguage`, Boot-Sync | +| `attributeUtils.py` | `modules/shared/` | `getModelLabels()` / `getModelLabel()` lesen aus `i18nRegistry.MODEL_LABELS` | +| `routeI18n.py` | `modules/routes/` | Admin-API: Sprachset-CRUD, AI-Uebersetzung, xx-Sync | +| `app.py` | `gateway/` | Boot-Hooks (`_syncRegistryToDb`, `_loadCache`), Request-Middleware (`_setLanguage`) | + +**Boot-Reihenfolge:** +1. Module laden → `@i18nModel` Decorators + `t()`-Aufrufe registrieren Keys in `_REGISTRY` +2. `_syncRegistryToDb()`: + - Scannt Route-Dateien nach `routeApiMsg("…")` (api.* Keys) + - `_registerNavLabels()`: Navigation-Labels aus `NAVIGATION_SECTIONS` (nav.* Keys) + - `_registerFeatureUiLabels()`: `FEATURE_LABEL` und `UI_OBJECTS` Labels (nav.* Keys) + - `_registerRbacLabels()`: `DATA_OBJECTS`, `RESOURCE_OBJECTS`, `TEMPLATE_ROLES`, `QUICK_ACTIONS` Labels (rbac.data, rbac.resource, rbac.role, rbac.quickaction Keys) + - Merged Gateway-Keys ins xx-Basisset (UI-Keys bleiben erhalten) +3. `_loadCache()`: Laedt alle `UiLanguageSets` in den In-Memory-Cache (`_CACHE`) + +**Request-Flow:** Middleware setzt `_setLanguage(lang)` aus `Accept-Language` Header → `t("Key")` liefert Uebersetzung aus `_CACHE[lang]` (O(1) Dict-Lookup, kein DB-Call) + +**Context-Namensraeume:** `ui` (Frontend), `api.` (HTTPExceptions), `table.` (Model-Labels), `table..` (Feld-Labels), `nav` (Navigation/Feature-Labels), `rbac.data` / `rbac.resource` / `rbac.role` / `rbac.quickaction` (RBAC-Katalog) + +**Entries-Identitaet:** Ein Entry wird durch `(key, context)` eindeutig identifiziert — derselbe Text kann mit verschiedenen Contexts existieren (z.B. einmal als UI-Key, einmal als API-Key). + +**TextMultilingual-Uebersetzung:** `POST /api/i18n/translate-field` — On-Demand-KI-Uebersetzung fuer einzelne Texte in mehrere Zielsprachen (genutzt vom FormGenerator-Button „In alle Sprachen uebersetzen"). + ## Regeln / Invarianten - **Schichten:** Connectors sind anbieterspezifisch und ersetzbar; **Services hängen von Interfaces ab, nicht direkt von Connectors**. Geschäftslogik und Guardrails liegen in den Services. diff --git a/c-work/1-plan/2026-04-customer-demo-enablement.md b/c-work/1-plan/2026-04-customer-demo-enablement.md new file mode 100644 index 0000000..8cf1307 --- /dev/null +++ b/c-work/1-plan/2026-04-customer-demo-enablement.md @@ -0,0 +1,330 @@ + + + + +# Customer Demo Enablement — Bling, PWG, Quid/ServiceHunter + +## Beschreibung und Kontext + +Drei potenzielle Kunden haben konkrete Use Cases formuliert (siehe `local/notes/use-cases-inputs-customers.md`). Dieses Dokument analysiert alle Kundenwünsche gegen den **Ist-Zustand** der Plattform und definiert einen priorisierten Umsetzungsplan, der mit minimalem Aufwand maximale Demo-Abdeckung und produktive Nutzbarkeit liefert. + +**Kunden:** + +| Kunde | Branche | Hauptinteresse | Status | +|-------|---------|----------------|--------| +| **Bling** (Kevin, Julian, Silvan) | Treuhandbüro | Belegverarbeitung, Budget, Dashboards, Mandantenmanagement | Trial geplant | +| **PWG** (Markus Brütsch) | Stiftung (Immobilien/Wohnen, 200+ Liegenschaften) | Belegverarbeitung Abacus, KI-Arbeitsplatz, Coaching, Neutralisierung | Workshop 16.04.2026 | +| **Quid/ServiceHunter** (David Christen) | SaaS/Dienstleistung | KPI-Dashboard, Zeiterfassung, Prognosen, Konsolidierung | Follow-up geplant | + +**Business-Treiber:** Jeder Kunde erwartet eine funktionsfähige Demo seines Haupt-Use-Cases. Demos, die end-to-end durchlaufen, konvertieren zu Trials. Trials konvertieren zu zahlenden Kunden. + +**Abhängigkeiten:** +- PWG-Demo wird parallel in `c-work/1-plan/2026-04-trustee-tooling-and-demo-prep.md` vorbereitet (Trustee Agent-Tools, Graph-Editor Nodes, Performance) +- UI-Enhancements für Erstnutzer-Erlebnis in `c-work/1-plan/2026-04-porta-ui-enhancements-team-meeting.md` +- INT-Stabilität in `c-work/1-plan/2026-04-gateway-int-stability-and-bugfixes.md` + +**Risiko bei Nicht-Umsetzung:** Kunden sehen nur generische AI-Chat-Funktionalität statt branchenspezifische Lösungen. Differenzierung zu ChatGPT/Copilot nicht erlebbar. + +--- + +## Analyse: Kundenwünsche vs. Ist-Zustand + +### Legende + +| Symbol | Bedeutung | +|--------|-----------| +| ✅ | Vorhanden und demo-fähig | +| 🔧 | Teilweise vorhanden, Anpassung nötig | +| 🆕 | Muss neu gebaut werden | +| ⏳ | In Arbeit (andere Plandokumente) | +| ❌ | Nicht im Scope (zu komplex / kein ROI für Demo) | + +--- + +### Bling (Treuhandbüro) + +| # | Use Case | Status | Was existiert | Was fehlt | +|---|----------|--------|---------------|-----------| +| 1.1 | Belegverarbeitung & Spesen | ⏳ | Trustee-Feature mit `extractFromFiles`, `processDocuments`, `syncToAccounting`; SharePoint-Nodes im Graph-Editor; Abacus/Bexio/RMA-Connectors | Graph-Editor Demo-Workflow (in trustee-tooling-plan Phase 4); Bexio-spezifische Testdaten | +| 1.2 | Budget / Soll-Ist-Vergleich | 🔧 | Agent kann Dateien lesen (Excel), `aggregateTable` für Trustee-Daten, `createChart` Tool | **Fehlend:** Demo-Prompt + Budget-Excel; Agent braucht Anleitung zum Vergleich Soll vs. Ist über Kontennummern | +| 1.3 | Cashflow-Rechnung | 🔧 | Agent kann Trustee-Daten aggregieren und analysieren | **Fehlend:** Prompt-Template für Cashflow-Berechnung; Beispieldaten mit Bilanz + ER | +| 1.4 | Dashboard – Kennzahlen | 🔧 | Agent hat `createChart`, kann rechnen, kann Dateien schreiben | **Fehlend:** Prompt-Templates für Kennzahlen (ROI, Gewinn, Kapitalverlust etc.) | +| 1.5 | Liquiditätsplanung | 🔧 | Agent + Trustee-Daten + Budget-Logik | **Fehlend:** Prompt-Template; komplexer als Budget (braucht Prognose-Logik) | +| 1.6 | Gastro-Echtzeit-Rentabilität | ❌ | — | Kassensystem-/Virux-Integration fehlt komplett; erst sinnvoll wenn Kevin Use Case liefert | +| 1.7 | Abschlussunterstützung | 🔧 | Agent + Trustee-Daten | **Fehlend:** Prompt-Templates für Abgrenzungen, Saldovalidierung, Vorjahresvergleich | +| 1.8 | Mandantenmanagement | ✅ | Multi-Tenant-Plattform mit Feature-Store; ein Login, mehrere Mandate, strikte Datentrennung (RBAC) | Nur UX-Polishing für die Demo nötig | + +**Bling Demo-Strategie:** Use Cases 1.1, 1.2, 1.4 und 1.8 sind die stärksten Demo-Kandidaten. 1.1 wird durch den PWG-Plan mitabgedeckt (gleiche Trustee-Pipeline, anderer Connector). 1.2 und 1.4 brauchen primär **Prompt-Engineering + Testdaten**. 1.8 ist bereits Plattform-Kernfunktion. + +--- + +### PWG (Stiftung) + +| # | Use Case | Status | Was existiert | Was fehlt | +|---|----------|--------|---------------|-----------| +| 2.1 | Belegverarbeitung Abacus | ⏳ | Abacus-Connector, Trustee-Pipeline, Graph-Editor Workflow | Wird in trustee-tooling-plan umgesetzt (Phase 1–4) | +| 2.2 | Coaching-Tool (Mietergespräche) | 🔧 | CommCoach-Feature mit Personas, Sessions, Scoring, Scheduler | **Fehlend:** Immobilien-spezifische Personas (Mietrückstand, Nebenkosten, PWG-Stil) | +| 2.3 | KI-Arbeitsplatz + Neutralisierung | ✅ | Workspace (auto-instance), Neutralization Feature (PII-Masking, Playground), Private LLM | Demo-Config nötig: Neutralisierung aktivieren, fiktives Mieterdossier testen | +| 2.4 | Abacus-Datenauswertung | ⏳ | Agent + `queryFeatureInstance` + `aggregateTable` | Abgedeckt durch trustee-tooling-plan (Phase 1) | +| 2.5 | Grundstücksanalyse | 🔧 | RealEstate-Feature (Skeleton), Geo-Connectors (SwissTopo, ÖREB WFS, ZH Parcels) | Feature ist noch Shell; für Demo reicht Agent + `webSearch` + `readUrl` auf öffentliche Quellen | + +**PWG Demo-Strategie:** 2.1 und 2.4 werden durch den trustee-tooling-plan abgedeckt. 2.3 ist demo-ready (Config + Testdaten). **Grösster Hebel hier:** 2.2 CommCoach mit Immobilien-Personas — zeigt sofortigen, greifbaren Mehrwert mit wenig Aufwand. 2.5 kann als Agent-Demo mit Web-Recherche gezeigt werden. + +--- + +### Quid/ServiceHunter + +| # | Use Case | Status | Was existiert | Was fehlt | +|---|----------|--------|---------------|-----------| +| 3.1 | KPI-Dashboard | 🔧 | Agent + `createChart` + Dateiverarbeitung (Excel/CSV) | **Fehlend:** Kein Treuhandball-/ERP-Connector; Daten müssen als CSV/Excel importiert werden; Prompt-Templates für KPI-Berechnung | +| 3.2 | Zeiterfassung & Support-Analyse | 🆕 | Agent kann Dateien lesen und analysieren | **Fehlend:** Kein Zendesk-Connector; Workaround: CSV/Excel-Export aus Zendesk manuell hochladen | +| 3.3 | Prognosen & Proaktive Steuerung | 🔧 | Agent kann rechnen, Trends erkennen, Charts erstellen | **Fehlend:** Prompt-Templates; historische Testdaten | +| 3.4 | Konsolidierung (international) | ❌ | Multi-Mandate Grundstruktur | Regelbasierte Konsolidierung ist hochkomplex; erst nach Follow-up mit Lars sinnvoll | +| 3.5 | Spesen-Automatisierung | ⏳ | Gleiche Trustee-Pipeline wie Bling/PWG | SharePoint/Google Drive → Trustee; minimal anpassbar | + +**Quid Demo-Strategie:** 3.1 ist der stärkste Kandidat — mit manuell hochgeladenen CSV/Excel-Daten kann der Agent KPIs berechnen und visualisieren. 3.2 funktioniert als „Upload deine Zendesk-Exports und lass den Agent analysieren". 3.3 als Erweiterung von 3.1. 3.4 ist explizit zu komplex für eine erste Demo. + +--- + +## Synthese: Was bringt den grössten Demo-ROI? + +### Muster über alle Kunden hinweg + +| Capability | Bling | PWG | Quid | Aufwand | Priorität | +|-----------|-------|-----|------|---------|-----------| +| **Trustee-Pipeline (Belege → BuHa)** | 1.1 | 2.1 | 3.5 | ⏳ In Arbeit | P0 (bereits geplant) | +| **Agent Prompt-Templates (Analyse + Charts)** | 1.2, 1.3, 1.4 | 2.4 | 3.1, 3.3 | Klein (Prompts + Testdaten) | **P1** | +| **CommCoach Immobilien-Personas** | — | 2.2 | — | Klein (Persona-Config) | **P1** | +| **Neutralisierungs-Demo-Setup** | — | 2.3 | — | Klein (Config + Testdaten) | **P1** | +| **CSV/Excel-Import als Datenquelle** | — | — | 3.1, 3.2 | Mittel (Workspace-Dateien reichen) | **P2** | +| **Multi-Mandate Demo-Setup** | 1.8 | — | — | Klein (Demo-Mandanten anlegen) | **P2** | +| **Grundstücks-Recherche via Agent** | — | 2.5 | — | Klein (Prompt + Web-Tools) | **P3** | +| **Zendesk-Connector** | — | — | 3.2 | Gross (neuer Connector) | **P4** (nicht für erste Demo) | +| **Gastro-Integration** | 1.6 | — | — | Gross (Kassen-/Lohn-API) | **P4** (wartet auf Kevin) | +| **Konsolidierung** | — | — | 3.4 | Sehr gross | **P4** (wartet auf Lars-Meeting) | + +--- + +## Fokus und kritische Details + +### Prompt-Templates als Schlüssel-Asset + +Der Agent kann bereits Trustee-Daten lesen, aggregieren und Charts erstellen. Was fehlt, sind **vorkonfigurierte Prompt-Templates** (als Workspace-Dateien oder System-Prompts), die den Agent zuverlässig zur gewünschten Analyse führen: + +- **Budget-Vergleich:** „Lade Budget-Excel, vergleiche mit Ist-Daten aus Trustee pro Kontonummer, erstelle Abweichungs-Chart" +- **Cashflow:** „Berechne operativen Cashflow aus Bilanz + ER, berücksichtige Abschreibungen, zeige Warnung bei negativem Trend" +- **KPI-Dashboard:** „Berechne Bruttogewinn, ROI, Gewinnmarge, Kapitalverlust-Check aus den Trustee-Daten" +- **Prognose:** „Analysiere letzte 6 Monate, prognostiziere nächste 3 Monate mit linearer Extrapolation" + +Diese Templates können als **Workspace-Dateien** (Markdown mit Instruktionen) oder als **Graph-Editor System-Templates** (Workflow mit `ai.prompt`-Node) umgesetzt werden. + +### CommCoach: Geringer Aufwand, hoher Wow-Effekt + +CommCoach hat bereits: Persona-System, Session-Management, Scoring, Feedback. Für PWG braucht es nur **3–5 neue Personas** im Immobilienkontext: +- Mieter mit Zahlungsrückstand +- Mieter mit Nebenkostenfragen +- Neuer Mieter (Einzug/Vertragsklärung) +- Schwieriger Nachbar (Lärmbeschwerde) + +### Neutralisierung: Bereits gebaut, nur konfigurieren + +Das Feature ist vollständig: Playground, Text/Datei-Neutralisierung, Private-LLM-Integration. Für die Demo braucht es: +- Ein fiktives Mieterdossier (PDF mit Namen, Adressen, Mietzinsen) +- Neutralisierung aktiviert auf der Demo-Instanz +- Vorführung: Original → neutralisiert → AI-Analyse → Re-Personalisierung + +--- + +## Ziel und Nicht-Ziele + +**Ziel:** +- Für jeden der drei Kunden mindestens **2 Use Cases end-to-end demo-fähig** +- Prompt-Templates als wiederverwendbares Asset (nicht nur einmalige Demo-Hacks) +- Demo-Mandanten mit realistischen Testdaten pro Kunde +- CommCoach mit Immobilien-Personas für PWG +- Neutralisierungs-Demo-Flow getestet + +**Explizit NICHT:** +- Keine neuen Connector-Implementierungen (Zendesk, Kassensystem, Virux) +- Keine regelbasierte Konsolidierung +- Keine Gastro-Echtzeit-Integration +- Keine neuen Frontend-Features (UI-Enhancements laufen separat) +- Kein Abacus-Produktivzugang (Demo mit Sandbox/Mockdaten) + +## Betroffene Module + +- **Gateway:** `features/commcoach/` (Persona-Seeding), `features/trustee/` (Demo-Daten), `features/neutralization/` (Demo-Config) +- **Frontend:** keine Änderungen (UI-Enhancements separat) +- **DB-Migration:** nein +- **Andere Komponenten:** Testdaten (Excel, PDF, CSV), Prompt-Templates (Workspace-Dateien) + +## Entscheidungen + +| Datum | Entscheidung | Begründung | +|-------|-------------|------------| +| 2026-04-09 | Prompt-Templates statt Custom-Code für Analyse-Use-Cases | Agent + bestehende Tools (aggregateTable, createChart) reichen; Templates sind schnell erstellbar und wartbar | +| 2026-04-09 | Quid-Demo ohne Zendesk-Connector — CSV/Excel-Upload Workaround | Zendesk-Connector hat hohen Aufwand, CSV-Import zeigt den gleichen Analyse-Mehrwert | +| 2026-04-09 | Gastro-UC und Konsolidierung auf P4 (nicht für erste Demo) | Warten auf Kunden-Input (Kevin) bzw. Prozessverständnis (Lars-Meeting) | +| 2026-04-09 | CommCoach-Personas als schnellster Wow-Effekt für PWG priorisiert | Feature ist gebaut; 3–5 Persona-Definitionen im Immobilienkontext genügen | + +--- + +## Umsetzungs-Checkliste + +### Phase 1: Demo-Infrastruktur (Prio: hoch — Grundlage für alle Demos) + +- [ ] **Demo-Mandant "Bling Demo"** anlegen mit Bexio-Testverbindung + - Trustee-Instanz mit `connectorType: bexio` + - Workspace-Instanz + - Graph-Editor-Instanz + - 2–3 Demo-User (Admin, Buchhalter, Mandant) + +- [ ] **Demo-Mandant "PWG Demo"** anlegen (ergänzend zu trustee-tooling-plan Phase 5) + - Trustee-Instanz mit `connectorType: abacus` + - Workspace-Instanz + - CommCoach-Instanz + - Neutralisierung-Instanz + +- [ ] **Demo-Mandant "Quid Demo"** anlegen + - Workspace-Instanz + - Graph-Editor-Instanz + +### Phase 2: Prompt-Templates & Analyse-Flows (Prio: hoch — betrifft alle 3 Kunden) + +- [ ] **Prompt-Template: Budget-Vergleich (Soll/Ist)** + - Workspace-Datei mit Instruktionen für den Agent + - Schritte: Budget-Excel lesen → Trustee-Daten aggregieren (SUM pro Konto) → Abweichungen berechnen → Chart erstellen → Zusammenfassung + - Testdaten: Budget-Excel mit 10–15 Konten, passend zu Demo-Buchhaltungsdaten + +- [ ] **Prompt-Template: KPI-Dashboard / Kennzahlen** + - Bruttogewinn, ROI, Gewinnmarge, hälftiger Kapitalverlust, Überschuldungs-Check + - Agent soll mehrere Charts erstellen und kritische Werte highlighten + - Wiederverwendbar für Bling (1.4) und Quid (3.1) + +- [ ] **Prompt-Template: Cashflow-Rechnung** + - Bilanz + ER aus Trustee → operativer/investiver/finanzieller Cashflow + - Nicht-Cash-Positionen (Abschreibungen) erkennen und bereinigen + - Warnungen bei kritischen Werten + +- [ ] **Prompt-Template: Prognose (Trend-Analyse)** + - Historische Daten analysieren (6 Monate) → nächste 3 Monate prognostizieren + - Einfache lineare Extrapolation + Saisonalitätshinweis + - Chart mit Ist vs. Prognose + - Für Bling (1.5) und Quid (3.3) + +- [ ] **Prompt-Template: Jahresabschluss-Checks** + - Saldovalidierung, Vorjahresvergleich, Abgrenzungsbuchungen identifizieren + - Für Bling (1.7) + +### Phase 3: CommCoach Immobilien-Personas (Prio: hoch — PWG-Demo 16.04) + +- [ ] **Persona: Mieter mit Zahlungsrückstand** + - Kontext: 3 Monate Mietrückstand, hat Mahnungen erhalten, ist genervt + - Schwierigkeitsgrad: mittel + - Lernziel: Empathisches Einfordern, Zahlungsvereinbarung vorschlagen + +- [ ] **Persona: Mieter mit Nebenkostenfragen** + - Kontext: Nebenkostenabrechnung erhalten, versteht Positionen nicht, emotional aufgebracht + - Schwierigkeitsgrad: leicht + - Lernziel: Geduldig erklären, auf Rechtsgrundlage verweisen + +- [ ] **Persona: Neuer Mieter (Einzugsfragen)** + - Kontext: Fragen zu Wohnungsübergabe, Schlüssel, Hausordnung, Kaution + - Schwierigkeitsgrad: leicht + - Lernziel: Willkommenskultur, klare Informationsvermittlung + +- [ ] **Persona: Schwieriger Nachbar (Lärmbeschwerde)** + - Kontext: Beschwert sich über Lärm, droht mit Mietminderung + - Schwierigkeitsgrad: schwer + - Lernziel: Deeskalation, Mediation anbieten, Rechte und Pflichten + +- [ ] **Persona-Seeding** in CommCoach `onRegister` oder als manuelles Setup-Skript + +### Phase 4: Neutralisierungs-Demo (Prio: hoch — PWG-Demo 16.04) + +- [ ] **Fiktives Mieterdossier erstellen** (PDF) + - Enthält: Name, Adresse, Mietzins, Zahlungshistorie, Korrespondenz + - Realistisch aber komplett fiktiv (DSGVO-konform) + +- [ ] **Demo-Flow dokumentieren** + - Original-PDF hochladen → Neutralisierung zeigen (Namen → Platzhalter) + - Neutralisierten Text an AI senden → Analyse erhalten + - Re-Personalisierung demonstrieren + - Optional: Private LLM für sensitive Daten zeigen + +- [ ] **Neutralisierungs-Config** auf Demo-Instanz konfigurieren und testen + +### Phase 5: Testdaten & Demo-Skripte (Prio: mittel) + +- [ ] **Bling-Testdaten:** Bexio-kompatible Buchhaltungsdaten (Journal, Kontoplan, Bilanz/ER) +- [ ] **Bling-Testdaten:** Budget-Excel (Soll-Werte 2026 pro Konto) +- [ ] **Bling-Testdaten:** 3–5 Musterbelege (Rechnung, Spesenbeleg, Bankbeleg) +- [ ] **PWG-Testdaten:** Abacus-kompatible Daten (bereits in trustee-tooling-plan) +- [ ] **Quid-Testdaten:** CSV/Excel mit Umsatzdaten (6 Monate), Kundenliste mit Margen, Support-Zeiterfassung +- [ ] **Demo-Skript Bling:** Schritt-für-Schritt mit Screenshots/Notizen +- [ ] **Demo-Skript PWG:** Schritt-für-Schritt (ergänzend zu trustee-tooling-plan) +- [ ] **Demo-Skript Quid:** Schritt-für-Schritt + +### Phase 6: Quid-spezifisch — Datenanalyse ohne Connector (Prio: mittel) + +- [ ] **Demo-Flow: CSV/Excel hochladen → Agent analysiert** + - Quid lädt Buchhaltungs-Export (CSV) und Zendesk-Export (CSV) in den Workspace + - Agent liest beide Dateien, verknüpft über Quid-ID / E-Mail + - Berechnet KPIs: Kundenmarge, ACV, Lifetime Value, Support-Kosten pro Kunde + - Erstellt Dashboard-Charts + +- [ ] **Prompt-Template: Multi-Source KPI-Analyse** + - Instruktionen für den Agent: „Lies die hochgeladenen Dateien, identifiziere gemeinsame Identifier, berechne folgende KPIs..." + +### Querschnitt-Checks + +- [ ] API-Endpunkte: keine neuen nötig +- [ ] DB-Schema / Migration: nein +- [ ] Frontend-Komponenten: nein (separater Plan) +- [ ] RBAC / Permissions: Demo-User mit passenden Rollen +- [ ] Neutralisierung betroffen? ja (Phase 4) +- [ ] Navigation / Routing: nein +- [ ] Billing-Impact? Demo-Mandanten brauchen ausreichend Guthaben / Trial-Modus + +--- + +## Akzeptanzkriterien + +| # | Kriterium (Given-When-Then) | Prio | Kunde | +|---|---------------------------|------|-------| +| 1 | Given Bling-Demo-Mandant mit Bexio-Daten und Budget-Excel, When der Agent den Budget-Vergleich-Prompt ausführt, Then zeigt er Soll/Ist-Abweichungen pro Konto mit Chart | must | Bling | +| 2 | Given Bling-Demo-Mandant, When der Agent den KPI-Dashboard-Prompt ausführt, Then erstellt er mindestens 3 Kennzahlen-Charts (Bruttogewinn, ROI, Gewinnmarge) | must | Bling | +| 3 | Given PWG-Demo-Mandant mit CommCoach-Instanz, When ein User eine Coaching-Session mit Persona "Mieter mit Zahlungsrückstand" startet, Then spielt die KI den Mieter realistisch im Immobilienkontext | must | PWG | +| 4 | Given PWG-Demo-Mandant mit aktivierter Neutralisierung, When ein fiktives Mieterdossier hochgeladen und analysiert wird, Then werden PII-Daten vor dem LLM-Call neutralisiert und nach der Analyse re-personalisiert | must | PWG | +| 5 | Given Quid-Demo-Mandant mit hochgeladenen CSV-Dateien (Buchhaltung + Zendesk-Export), When der Agent die KPI-Analyse ausführt, Then verknüpft er Daten über gemeinsame IDs und erstellt Margen- und Support-Kosten-Charts | should | Quid | +| 6 | Given Demo-Mandant mit 2+ Mandaten, When ein Bling-Admin zwischen Mandanten wechselt, Then sieht er jeweils nur die Daten des aktiven Mandanten (Datentrennung funktioniert) | must | Bling | +| 7 | Given Cashflow-Prompt und Trustee-Daten, When der Agent die Analyse durchführt, Then berechnet er korrekten operativen Cashflow unter Berücksichtigung von Abschreibungen | should | Bling | + +## Testplan + +| ID | AC | Art | Automatisiert | Methode | Status | +|----|----|-----|--------------|---------|--------| +| T1 | 1 | e2e | nein | Manuell: Budget-Excel + Trustee-Daten + Agent-Prompt im Workspace | pending | +| T2 | 2 | e2e | nein | Manuell: KPI-Prompt im Workspace mit Trustee-Daten | pending | +| T3 | 3 | e2e | nein | Manuell: CommCoach-Session mit Immobilien-Persona starten | pending | +| T4 | 4 | e2e | nein | Manuell: PDF hochladen → Neutralisierung → Analyse → Re-Personalisierung | pending | +| T5 | 5 | e2e | nein | Manuell: CSV-Upload → Agent-Prompt → Charts prüfen | pending | +| T6 | 6 | e2e | nein | Manuell: Mandantenwechsel, Daten prüfen | pending | +| T7 | 7 | e2e | nein | Manuell: Cashflow-Prompt → Ergebnis gegen manuelle Berechnung prüfen | pending | + +## Links + +- Kundenwünsche: `local/notes/use-cases-inputs-customers.md` +- PWG Trustee-Tooling (parallel): `c-work/1-plan/2026-04-trustee-tooling-and-demo-prep.md` +- UI-Enhancements (parallel): `c-work/1-plan/2026-04-porta-ui-enhancements-team-meeting.md` +- INT-Stabilität (parallel): `c-work/1-plan/2026-04-gateway-int-stability-and-bugfixes.md` +- CommCoach-Feature: `gateway/modules/features/commcoach/` +- Neutralisierung-Feature: `gateway/modules/features/neutralization/` +- Trustee-Feature: `gateway/modules/features/trustee/` +- Workspace-Feature: `gateway/modules/features/workspace/` + +## Abschluss + +- [ ] b-reference/ aktualisiert (ggf. neue Feature-Docs unter `b-reference/gateway/features/`) +- [ ] TOPICS.md aktualisiert (falls neues Thema) +- [ ] Dieses Dokument → z-archive/ verschoben diff --git a/c-work/1-plan/2026-04-i18n-static-text-elimination.md b/c-work/1-plan/2026-04-i18n-static-text-elimination.md new file mode 100644 index 0000000..9b69965 --- /dev/null +++ b/c-work/1-plan/2026-04-i18n-static-text-elimination.md @@ -0,0 +1,4 @@ + + + +Dieser Plan wurde nach **`c-work/2-build/2026-04-i18n-static-text-elimination.md`** verschoben. Bitte dort weiterarbeiten. diff --git a/c-work/1-plan/2026-04-quick-actions-feature-dashboard.md b/c-work/1-plan/2026-04-quick-actions-feature-dashboard.md new file mode 100644 index 0000000..20ee519 --- /dev/null +++ b/c-work/1-plan/2026-04-quick-actions-feature-dashboard.md @@ -0,0 +1,445 @@ + + + + +# Quick Actions — Feature-Dashboard mit One-Click-Aktionen + +## Beschreibung und Kontext + +Treuhandbüros (Bling, PWG) und andere Kunden wünschen sich ein **Cockpit**, von dem aus sie ihre häufigsten Aufgaben per Knopfdruck starten können — Budget-Vergleich, Belegverarbeitung, KPI-Dashboard, Cashflow etc. Heute müssen sie dafür den Workspace öffnen und den richtigen Prompt manuell eintippen. + +**Business-Treiber:** Das Feature-Dashboard (z.B. Trustee Dashboard) ist aktuell eine passive Statistik-Seite (Anzahl Positionen, Dokumente, Sync-Status). Mit Quick Actions wird es zum **aktiven Cockpit** — der Einstiegspunkt für produktive Arbeit. Das macht den Unterschied zwischen "generischem AI-Chat" und "Branchenlösung für Treuhänder". + +**Abhängigkeiten:** +- Trustee Agent-Tools müssen funktionieren (`c-work/1-plan/2026-04-trustee-tooling-and-demo-prep.md`) +- Workspace SSE-Streaming muss stabil laufen (`c-work/1-plan/2026-04-gateway-int-stability-and-bugfixes.md`) +- Prompt-Templates aus `c-work/1-plan/2026-04-customer-demo-enablement.md` + +**Risiko bei Nicht-Umsetzung:** Kunden sehen PORTA als "noch ein Chat-Tool" statt als branchenspezifische Plattform. Die Hürde vom Login zum Mehrwert bleibt hoch. + +## Fokus und kritische Details + +### Ist-Zustand: Trustee Dashboard + +`frontend_nyla/src/pages/views/trustee/TrusteeDashboardView.tsx` zeigt aktuell: +- **Stats-Grid:** 4 Kacheln (Positionen, Dokumente, Buchhaltungs-Sync, Rollen) +- **Info-Sektion:** Instanz-Label, Mandant, Buchhaltungssystem + +Kein Weg zu einer Aktion — keine Buttons, keine Links zum Workspace, keine Workflows. + +### Architektur-Entscheid: Zwei Dispatch-Typen + +Quick Actions dispatchen zu **bestehender Infrastruktur** — es wird keine zweite AI-Oberfläche gebaut: + +| Typ | Dispatch-Ziel | Wann nutzen | +|-----|--------------|-------------| +| **`agentPrompt`** | Workspace mit vorgefülltem Prompt → Agent startet automatisch | Analyse-Aufgaben (Budget, KPIs, Cashflow, Prognosen, Jahresabschluss) | +| **`workflow`** | Graph-Editor System-Template wird direkt getriggert | Automatisierungs-Aufgaben (Belegimport, Daten-Sync, Spesen-Import) | +| **`link`** | Navigation zu einer bestehenden Seite | Schnellzugriff (Scan/Upload, Dokumente, Einstellungen) | + +### Kritische Stellen + +- **Workspace Pre-Fill:** Der Workspace (`WorkspacePage.tsx`) hat aktuell **keinen** Mechanismus für URL-Parameter `?prompt=...`. Das muss ergänzt werden. +- **Cross-Feature-Navigation:** Eine Trustee Quick Action muss den User zur Workspace-Instanz des gleichen Mandanten navigieren. Das erfordert Auflösung: Trustee-InstanceId → MandateId → Workspace-InstanceId. +- **RBAC-Filterung:** Quick Actions müssen nach Rolle gefiltert werden. Ein `trustee-client` soll "Belege hochladen" sehen, aber nicht "Jahresabschluss prüfen". +- **i18n:** Alle Labels müssen mehrsprachig sein (bestehendes `TextMultilingual`-Pattern nutzen). + +### Warum kein eigenes AI-Rendering auf dem Dashboard? + +Der Workspace hat bereits: Chat-Rendering, Chart-Anzeige, Datei-Handling, SSE-Streaming, Progressive Summarization, Tool-Ergebnisse. Das zu duplizieren wäre enormer Aufwand. Stattdessen nutzen wir den Workspace als "Execution Engine" und das Dashboard als "Launchpad". + +## Ziel und Nicht-Ziele + +**Ziel:** +- Feature-Dashboards (Trustee als Pilot, danach CommCoach, Workspace) zeigen kontextspezifische Quick Action Cards +- Klick auf eine `agentPrompt`-Card öffnet Workspace mit vorgefülltem Prompt und startet den Agent +- Klick auf eine `workflow`-Card triggert einen Graph-Editor Workflow +- Actions sind RBAC-gefiltert, i18n-ready und per Feature-Instanz konfigurierbar +- Wiederverwendbare `QuickActionBoard`-Komponente für alle Features + +**Explizit NICHT:** +- Kein AI-Rendering auf dem Dashboard selbst (kein Chat, keine Charts auf der Trustee-Seite) +- Keine neuen DB-Tabellen — Quick Actions leben im Code (wie `UI_OBJECTS`) + optional in `FeatureInstance.config` +- Keine neuen API-Verträge für Workflow-Execution (nutzt bestehenden `POST /{instanceId}/execute`) +- Kein Prompt-Editor für Endnutzer (kommt ggf. später) + +## Betroffene Module + +- **Gateway:** `features/trustee/mainTrustee.py` (Quick Action Definitionen), `features/trustee/routeFeatureTrustee.py` (API-Endpoint), ggf. `features/workspace/routeFeatureWorkspace.py` (Pre-Fill-Support) +- **Frontend:** `pages/views/trustee/TrusteeDashboardView.tsx` (Quick Action Board einbinden), neue Komponente `components/QuickActionBoard/`, `pages/views/workspace/WorkspacePage.tsx` (URL-Param-Support) +- **DB-Migration:** nein +- **Andere Komponenten:** Prompt-Templates (Markdown-Dateien, getrennt gepflegt) + +## Entscheidungen + +| Datum | Entscheidung | Begründung | +|-------|-------------|------------| +| 2026-04-09 | Quick Actions im Code definieren (wie `UI_OBJECTS`), nicht in einer DB-Tabelle | Einfach, versioniert, kein Migrations-Aufwand. Custom-Actions später über `FeatureInstance.config` | +| 2026-04-09 | Dispatch zu Workspace statt Inline-Rendering auf dem Dashboard | Workspace hat die komplette AI-Infrastruktur (Chat, Charts, Streaming). Kein Sinn in Duplizierung | +| 2026-04-09 | `QuickActionBoard` als generische Plattform-Komponente, nicht Trustee-spezifisch | CommCoach, Workspace, RealEstate können dieselbe Komponente nutzen | +| 2026-04-09 | Workspace bekommt URL-Parameter `?prompt=...&autoStart=true` | Einfachster Weg für Cross-Feature-Dispatch. Kein Backend-Spezialweg nötig | +| 2026-04-09 | Prompt-Templates als Konfigurationswert in der Quick Action, nicht als separate Dateien | Prompt gehört zur Aktion — eine Quelle der Wahrheit. Kein File-Lookup zur Laufzeit | + +--- + +## Umsetzungs-Checkliste + +### Phase 1: Backend — Quick Action Definitionen & API (Gateway) + +- [ ] **`QUICK_ACTIONS` in `mainTrustee.py` definieren** + +Gleiches Pattern wie `UI_OBJECTS`, `TEMPLATE_ROLES`: + +```python +QUICK_ACTIONS = [ + { + "id": "trustee-process-receipts", + "label": {"de": "Belege verarbeiten", "en": "Process Receipts", "fr": "Traiter les justificatifs"}, + "description": {"de": "Belege aus SharePoint importieren, klassifizieren und verbuchen", "en": "Import receipts from SharePoint, classify and book", "fr": "Importer les justificatifs depuis SharePoint, classer et comptabiliser"}, + "icon": "mdi-file-document-check-outline", + "color": "#4CAF50", + "category": "import", + "actionType": "workflow", + "config": { + "workflowTemplateCode": "trustee-receipt-import" + }, + "requiredRoles": ["trustee-user", "trustee-accountant", "trustee-admin"], + "sortOrder": 1 + }, + { + "id": "trustee-sync-accounting", + "label": {"de": "Daten synchronisieren", "en": "Sync Accounting Data", "fr": "Synchroniser les données"}, + "description": {"de": "Buchhaltungsdaten aus dem externen System aktualisieren", "en": "Refresh accounting data from external system", "fr": "Actualiser les données du système externe"}, + "icon": "mdi-sync", + "color": "#FF9800", + "category": "import", + "actionType": "agentPrompt", + "config": { + "prompt": "Aktualisiere die Buchhaltungsdaten aus dem verbundenen Buchhaltungssystem. Nutze refreshTrusteeData mit forceRefresh=true. Zeige mir danach eine Zusammenfassung: Anzahl Konten, Buchungen, Kontakte und den Zeitraum der Daten." + }, + "requiredRoles": ["trustee-accountant", "trustee-admin"], + "sortOrder": 2 + }, + { + "id": "trustee-budget-comparison", + "label": {"de": "Budget-Vergleich", "en": "Budget Comparison", "fr": "Comparaison budgétaire"}, + "description": {"de": "Soll/Ist-Vergleich der Buchhaltung mit Budget-Excel", "en": "Compare actuals vs. budget from Excel", "fr": "Comparer les données réelles avec le budget Excel"}, + "icon": "mdi-chart-bar", + "color": "#2196F3", + "category": "analyse", + "actionType": "agentPrompt", + "config": { + "prompt": "Ich möchte einen Budget-Soll/Ist-Vergleich durchführen. Bitte:\n1. Frage mich nach der Budget-Datei (Excel) oder suche im Workspace nach einer Datei mit 'Budget' im Namen\n2. Lade die aktuellen Buchhaltungsdaten (refreshTrusteeData falls nötig)\n3. Vergleiche die Soll-Werte aus dem Budget mit den Ist-Werten aus der Buchhaltung pro Konto\n4. Berechne die Abweichung (absolut und prozentual)\n5. Erstelle ein Abweichungs-Chart (Balkendiagramm: Soll vs. Ist pro Konto)\n6. Markiere kritische Abweichungen (>10%) und gib eine kurze Einschätzung", + "suggestFileUpload": true, + "uploadHint": {"de": "Budget-Excel hochladen", "en": "Upload budget Excel"} + }, + "requiredRoles": ["trustee-accountant", "trustee-admin"], + "sortOrder": 3 + }, + { + "id": "trustee-kpi-dashboard", + "label": {"de": "KPI-Dashboard", "en": "KPI Dashboard", "fr": "Tableau de bord KPI"}, + "description": {"de": "Kennzahlen berechnen und visualisieren", "en": "Calculate and visualize key metrics", "fr": "Calculer et visualiser les indicateurs clés"}, + "icon": "mdi-view-dashboard-outline", + "color": "#9C27B0", + "category": "analyse", + "actionType": "agentPrompt", + "config": { + "prompt": "Erstelle ein KPI-Dashboard basierend auf den aktuellen Buchhaltungsdaten. Berechne und visualisiere:\n1. **Bruttogewinn** und Bruttogewinnmarge\n2. **EBIT** (Betriebsergebnis)\n3. **Gewinnmarge** (Reingewinn / Umsatz)\n4. **Eigenkapitalquote** und Check auf hälftigen Kapitalverlust (OR Art. 725)\n5. **Liquiditätsgrad 1-3** (Cash Ratio, Quick Ratio, Current Ratio)\n6. **Überschuldungs-Check**\n\nErstelle für jede Kennzahl einen kurzen Kommentar (gut/kritisch/Handlungsbedarf). Erstelle mindestens 2 Charts: ein Übersichts-Chart der Margen und ein Liquiditäts-Chart." + }, + "requiredRoles": ["trustee-accountant", "trustee-admin"], + "sortOrder": 4 + }, + { + "id": "trustee-cashflow", + "label": {"de": "Cashflow-Rechnung", "en": "Cash Flow Statement", "fr": "Tableau des flux de trésorerie"}, + "description": {"de": "Cashflow berechnen und analysieren", "en": "Calculate and analyze cash flow", "fr": "Calculer et analyser le flux de trésorerie"}, + "icon": "mdi-cash-multiple", + "color": "#009688", + "category": "analyse", + "actionType": "agentPrompt", + "config": { + "prompt": "Erstelle eine Cashflow-Rechnung basierend auf den aktuellen Buchhaltungsdaten:\n1. **Operativer Cashflow:** Starte vom Reingewinn, bereinige um nicht-cash-wirksame Positionen (Abschreibungen, Rückstellungen, Wertberichtigungen)\n2. **Investitions-Cashflow:** Investitionen in Sachanlagen, Finanzanlagen\n3. **Finanzierungs-Cashflow:** Darlehensaufnahmen/-rückzahlungen, Dividenden, Kapitalerhöhungen\n4. **Netto-Cashflow** und Veränderung der liquiden Mittel\n\nWarne bei kritischen Werten. Erstelle ein Wasserfall-Chart oder gestapeltes Balkendiagramm der drei Cashflow-Bereiche." + }, + "requiredRoles": ["trustee-accountant", "trustee-admin"], + "sortOrder": 5 + }, + { + "id": "trustee-year-end-check", + "label": {"de": "Jahresabschluss prüfen", "en": "Year-End Review", "fr": "Contrôle de clôture annuelle"}, + "description": {"de": "Automatische Prüfungen für den Jahresabschluss", "en": "Automated year-end review checks", "fr": "Contrôles automatisés de clôture"}, + "icon": "mdi-clipboard-check-outline", + "color": "#795548", + "category": "abschluss", + "actionType": "agentPrompt", + "config": { + "prompt": "Führe eine automatische Jahresabschluss-Prüfung durch:\n1. **Saldovalidierung:** Prüfe alle Bilanzkonten auf Plausibilität (negative Saldi wo nicht erwartet, ungewöhnlich hohe Saldi)\n2. **Vorjahresvergleich:** Vergleiche Bilanz- und ER-Positionen mit dem Vorjahr, markiere Abweichungen >20%\n3. **Abgrenzungen:** Identifiziere potenzielle transitorische Aktiven/Passiven (regelmässige Aufwände ohne Dezember-Buchung, Erträge im Voraus)\n4. **Gesetzliche Prüfungen:** Hälftiger Kapitalverlust (OR 725), Überschuldung, Mindestkapital\n5. **MWST-Plausibilisierung:** Vorsteuer vs. geschätzter Aufwand, Umsatzsteuer vs. Umsatz\n\nErstelle eine Checkliste mit Status (OK / Warnung / Kritisch) pro Prüfpunkt." + }, + "requiredRoles": ["trustee-accountant", "trustee-admin"], + "sortOrder": 6 + }, + { + "id": "trustee-forecast", + "label": {"de": "Prognose erstellen", "en": "Create Forecast", "fr": "Créer une prévision"}, + "description": {"de": "Trend-Analyse und Prognose der nächsten Monate", "en": "Trend analysis and forecast for coming months", "fr": "Analyse de tendance et prévision"}, + "icon": "mdi-chart-timeline-variant", + "color": "#E91E63", + "category": "analyse", + "actionType": "agentPrompt", + "config": { + "prompt": "Erstelle eine Finanzprognose basierend auf den historischen Buchhaltungsdaten:\n1. Analysiere die Umsatz- und Aufwandsentwicklung der letzten 6 Monate (monatliche Aggregation)\n2. Identifiziere Trends und Saisonalitäten\n3. Prognostiziere Umsatz, Aufwand und Gewinn für die nächsten 3 Monate\n4. Erstelle ein Chart mit Ist-Werten und Prognose-Korridor (Best/Expected/Worst Case)\n5. Markiere Risiken: \"Wenn der Trend anhält, passiert X\"\n\nNutze eine einfache lineare Extrapolation mit Saisonalitätskorrektur wo sinnvoll." + }, + "requiredRoles": ["trustee-accountant", "trustee-admin"], + "sortOrder": 7 + }, + { + "id": "trustee-upload-receipt", + "label": {"de": "Beleg hochladen", "en": "Upload Receipt", "fr": "Télécharger un justificatif"}, + "description": {"de": "Beleg scannen oder als Datei hochladen", "en": "Scan or upload a receipt", "fr": "Scanner ou télécharger un justificatif"}, + "icon": "mdi-camera-document-outline", + "color": "#607D8B", + "category": "schnellzugriff", + "actionType": "link", + "config": { + "targetView": "scan-upload" + }, + "requiredRoles": ["trustee-user", "trustee-client", "trustee-accountant", "trustee-admin"], + "sortOrder": 8 + }, +] +``` + +- [ ] **`getQuickActions()` Funktion in `mainTrustee.py`** analog zu `getUiObjects()`, `getTemplateRoles()` + +- [ ] **API-Endpoint `GET /api/trustee/{instanceId}/quick-actions`** in `routeFeatureTrustee.py` + - Liest `QUICK_ACTIONS` + optional `FeatureInstance.config.get("quickActions", [])` + - Filtert nach User-Rollen (RBAC): nur Actions deren `requiredRoles` mit den Rollen des Users auf dieser Instanz übereinstimmen + - Sortiert nach `sortOrder` + - Gruppiert nach `category` (optional, Frontend kann auch selbst gruppieren) + - Response: `{ "actions": [...], "categories": [{ "id": "import", "label": {...} }, ...] }` + +### Phase 2: Frontend — QuickActionBoard Komponente + +- [ ] **Neue Komponente `components/QuickActionBoard/QuickActionBoard.tsx`** + +Generische, wiederverwendbare Komponente: + +```typescript +interface QuickAction { + id: string; + label: string; // bereits in User-Sprache aufgelöst + description: string; + icon: string; + color: string; + category: string; + actionType: 'agentPrompt' | 'workflow' | 'link'; + config: Record; +} + +interface QuickActionBoardProps { + actions: QuickAction[]; + onDispatch: (action: QuickAction) => void; + loading?: boolean; +} +``` + +UI: +- Responsive Card-Grid (`grid-template-columns: repeat(auto-fill, minmax(220px, 1fr))`) +- Jede Card: Icon (farbig) + Titel + Beschreibung (1-Zeiler) + Hover-Effekt +- Kategorien als optionale Section-Header +- Loading-Skeleton während API-Call +- Dark-Theme Support (bestehende CSS-Variablen nutzen) +- Kein eigener State — rein präsentational mit `onDispatch`-Callback + +- [ ] **CSS in `components/QuickActionBoard/QuickActionBoard.module.css`** + - Konsistentes Design mit bestehenden `TrusteeViews.module.css` Kacheln (`.statCard` Pattern) + - Hover: leichter Scale + Shadow-Verstärkung + - Active/Clicked: kurzer visueller Feedback (Pulse oder Farb-Flash) + - Icon-Rendering: `mdi-*` Icons aus bestehender Icon-Library oder als Unicode/SVG Fallback + +### Phase 3: Frontend — Dashboard-Integration + +- [ ] **`TrusteeDashboardView.tsx` erweitern** + +Unter dem bestehenden `statsGrid` und `infoSection`: + +```tsx +// Nach der infoSection: + +``` + +Dispatch-Handler: +```tsx +const _handleQuickAction = (action: QuickAction) => { + switch (action.actionType) { + case 'agentPrompt': + _navigateToWorkspaceWithPrompt(action.config); + break; + case 'workflow': + _triggerWorkflow(action.config); + break; + case 'link': + _navigateToView(action.config.targetView); + break; + } +}; +``` + +- [ ] **API-Hook `useTrusteeQuickActions(instanceId)`** in `hooks/useTrustee.ts` + - Fetcht `GET /api/trustee/{instanceId}/quick-actions` + - Cached Response (SWR-Pattern oder einfacher State) + - Resolved `label`/`description` in die aktive Sprache (wie bei Navigation-Labels) + +- [ ] **Trustee API Funktion `fetchQuickActions()`** in `api/trusteeApi.ts` + +### Phase 4: Frontend — Workspace Pre-Fill (Cross-Feature-Dispatch) + +- [ ] **URL-Parameter-Support in `WorkspacePage.tsx`** + +Workspace erkennt URL-Suchparameter: +- `?prompt=` → Füllt Prompt-Feld vor +- `&autoStart=true` → Startet den Agent automatisch nach dem Laden +- `&sourceFeature=trustee` → Optional: Kontext-Hinweis woher der User kommt +- `&sourceInstanceId=` → Optional: Trustee-Instanz für Feature-Data-Zugriff + +Implementierung: +```tsx +useEffect(() => { + const params = new URLSearchParams(window.location.search); + const prompt = params.get('prompt'); + const autoStart = params.get('autoStart') === 'true'; + + if (prompt) { + setInputText(decodeURIComponent(prompt)); + // URL bereinigen (Params entfernen, damit Reload nicht erneut startet) + window.history.replaceState({}, '', window.location.pathname); + + if (autoStart) { + // Kurze Verzögerung damit UI gerendert ist + setTimeout(() => _handleSend(), 300); + } + } +}, []); +``` + +- [ ] **Workspace-Instanz-Auflösung** für Cross-Feature-Navigation + +Helper-Funktion in Trustee Dashboard: +```typescript +const _navigateToWorkspaceWithPrompt = async (config: QuickActionConfig) => { + // 1. Workspace-Instanz des gleichen Mandanten finden + const workspaceInstance = instances.find( + i => i.featureCode === 'workspace' && i.mandateId === currentMandateId + ); + if (!workspaceInstance) { /* Fehlerbehandlung */ } + + // 2. Navigation mit Prompt-Parametern + const params = new URLSearchParams({ + prompt: config.prompt, + autoStart: 'true', + sourceFeature: 'trustee', + sourceInstanceId: instanceId, + }); + navigate(`/features/workspace/${workspaceInstance.id}/dashboard?${params}`); +}; +``` + +### Phase 5: Workflow-Dispatch (für `actionType: "workflow"`) + +- [ ] **Graph-Editor Workflow triggern** aus dem Trustee Dashboard + +Für `actionType: "workflow"`: Nutzt bestehenden `POST /api/graphicalEditor/{geInstanceId}/execute`: + +```typescript +const _triggerWorkflow = async (config: WorkflowActionConfig) => { + // 1. GraphicalEditor-Instanz des gleichen Mandanten finden + const geInstance = instances.find( + i => i.featureCode === 'graphicalEditor' && i.mandateId === currentMandateId + ); + + // 2. System-Template-Workflow finden (nach templateCode) + const workflows = await fetchWorkflowsByTemplate(geInstance.id, config.workflowTemplateCode); + + // 3. Ausführung triggern + const run = await executeWorkflow(geInstance.id, workflows[0].id); + + // 4. Feedback: Toast "Workflow gestartet" + optional Link zur Run-Ansicht + showToast({ message: t('quickActions.workflowGestartet'), action: { label: t('quickActions.details'), onClick: () => navigateToRun(run.id) } }); +}; +``` + +- [ ] **API-Funktionen** in `api/graphicalEditorApi.ts` (falls nicht vorhanden): `fetchWorkflowsByTemplate()`, `executeWorkflow()` + +### Querschnitt-Checks + +- [ ] API-Endpunkte: `GET /api/trustee/{instanceId}/quick-actions` (neu) +- [ ] DB-Schema / Migration: nein +- [ ] Frontend-Komponenten: `QuickActionBoard` (neu, generisch), `TrusteeDashboardView` (erweitert) +- [ ] RBAC / Permissions: Filterung über `requiredRoles` im API-Endpoint +- [ ] Neutralisierung betroffen? nein (Prompts gehen durch normale Workspace-Pipeline) +- [ ] Navigation / Routing: Workspace URL-Parameter-Support +- [ ] Billing-Impact? nein (Agent-Calls laufen über bestehende Billing-Pipeline) +- [ ] i18n: Alle Labels in `QUICK_ACTIONS` nutzen `TextMultilingual`-Format + +--- + +## Akzeptanzkriterien + +| # | Kriterium (Given-When-Then) | Prio | +|---|---------------------------|------| +| 1 | Given Trustee Dashboard, When ein User mit Rolle `trustee-accountant` die Seite öffnet, Then sieht er mindestens 6 Quick Action Cards (Belege, Sync, Budget, KPIs, Cashflow, Jahresabschluss) in einem Card-Grid unterhalb der Statistiken | must | +| 2 | Given Quick Action "Budget-Vergleich" (Typ `agentPrompt`), When der User auf die Card klickt, Then wird er zum Workspace navigiert mit dem vorgefüllten Prompt und der Agent startet automatisch | must | +| 3 | Given Quick Action "Belege verarbeiten" (Typ `workflow`), When der User auf die Card klickt, Then wird der zugehörige Graph-Editor Workflow getriggert und der User erhält eine Bestätigung | must | +| 4 | Given Quick Action "Beleg hochladen" (Typ `link`), When der User auf die Card klickt, Then wird er zur Scan/Upload-Seite der aktuellen Trustee-Instanz navigiert | must | +| 5 | Given ein User mit Rolle `trustee-client`, When er das Trustee Dashboard öffnet, Then sieht er nur die Quick Actions für seine Rolle (z.B. "Beleg hochladen"), nicht die Accountant-Aktionen (Budget, KPIs etc.) | must | +| 6 | Given Dark Theme aktiv, When das Dashboard mit Quick Actions gerendert wird, Then sind alle Cards visuell korrekt (Farben, Kontraste, Hover-Effekte) im Dark Mode | should | +| 7 | Given Workspace geöffnet via Quick Action mit `autoStart=true`, When der Agent gestartet wird, Then enthält der System-Prompt Kontext über die Trustee-Instanz und der Agent kann sofort auf Trustee-Daten zugreifen | should | +| 8 | Given schmales Viewport (< 768px), When das Dashboard angezeigt wird, Then sind die Quick Action Cards in einem 1-2 Spalten Grid und weiterhin klickbar | should | + +## Testplan + +| ID | AC | Art | Automatisiert | Repo-Pfad / Methode | Status | +|----|----|-----|--------------|---------------------|--------| +| T1 | 1, 5 | api | ja | `gateway/tests/features/trustee/test_quick_actions_api.py` — Endpoint liefert gefilterte Actions pro Rolle | pending | +| T2 | 2 | e2e | nein | Manuell: Card klicken → Workspace öffnet mit Prompt → Agent startet | pending | +| T3 | 3 | e2e | nein | Manuell: Workflow-Card klicken → Workflow läuft → Bestätigung sichtbar | pending | +| T4 | 4 | e2e | nein | Manuell: Link-Card klicken → korrekte Navigation | pending | +| T5 | 6 | visual | nein | Manuell: Dark/Light Mode vergleichen | pending | +| T6 | 7 | e2e | nein | Manuell: Budget-Vergleich aus Quick Action → Agent nutzt Trustee-Daten korrekt | pending | +| T7 | 8 | visual | nein | Manuell: Browser-Fenster schmaler als 768px | pending | + +## Spätere Erweiterungen (nicht in Scope) + +| Idee | Beschreibung | +|------|-------------| +| **Custom Quick Actions pro Mandant** | Admin kann eigene Actions definieren (in `FeatureInstance.config.quickActions`), die mit den System-Actions gemergt werden | +| **Workspace Empty State** | Quick Actions des aktiven Features im Workspace Empty State anzeigen (wenn kein Chat offen) | +| **Inline-Ergebnis-Preview** | Nach Agent-Ausführung: Zusammenfassung und Charts auf dem Dashboard selbst anzeigen (statt nur im Workspace) | +| **Favoriten / Pinned Actions** | User kann Actions pinnen; gepinnte Actions erscheinen zuoberst oder auf einer persönlichen "Home"-Seite | +| **CommCoach Quick Actions** | "Mietergespräch üben", "Nebenkostenfragen trainieren" etc. auf dem CommCoach Dashboard | +| **Prompt-Editor** | Power-User können Prompts der Quick Actions anpassen (Mandanten-spezifisch) | + +## Links + +- Kundenwünsche: `local/notes/use-cases-inputs-customers.md` +- Customer Demo Enablement: `c-work/1-plan/2026-04-customer-demo-enablement.md` +- Trustee Tooling: `c-work/1-plan/2026-04-trustee-tooling-and-demo-prep.md` +- Trustee Dashboard (Frontend): `frontend_nyla/src/pages/views/trustee/TrusteeDashboardView.tsx` +- Trustee Feature (Gateway): `gateway/modules/features/trustee/mainTrustee.py` +- Trustee Routes (Gateway): `gateway/modules/features/trustee/routeFeatureTrustee.py` +- Workspace Routes (Gateway): `gateway/modules/features/workspace/routeFeatureWorkspace.py` +- Workspace Page (Frontend): `frontend_nyla/src/pages/views/workspace/WorkspacePage.tsx` +- FeatureView Registry (Frontend): `frontend_nyla/src/pages/FeatureView.tsx` +- Quick Action Board (Frontend, neu): `frontend_nyla/src/components/QuickActionBoard/` +- Navigation API: `wiki/b-reference/platform/navigation.md` + +## Abschluss + +- [ ] b-reference/ aktualisiert (`b-reference/gateway/features/trustee.md` — neu anlegen mit Quick Actions) +- [ ] b-reference/frontend-nyla/architecture.md aktualisiert (QuickActionBoard-Komponente) +- [ ] TOPICS.md aktualisiert (neues Thema "Quick Actions") +- [ ] Dieses Dokument → z-archive/ verschoben diff --git a/c-work/2-build/2026-04-i18n-static-text-elimination.md b/c-work/2-build/2026-04-i18n-static-text-elimination.md new file mode 100644 index 0000000..a53e578 --- /dev/null +++ b/c-work/2-build/2026-04-i18n-static-text-elimination.md @@ -0,0 +1,369 @@ + + + +# Statische Texte eliminieren — vollständige i18n-Migration + +## Fortschritt + +| Phase | Inhalt | Status | +|-------|--------|--------| +| 1 | Feature-Module (`mainXxx.py`), `registry.py`, `interfaceBootstrap.py` | **done** | +| 2 | `nodeDefinitions/*`, `portTypes.py`, `nodeRegistry.py`, `entryPoints.py` | **done** | +| 3–5 | Datamodels, `frontendTypes`, Frontend `t()` | offen | + +**Umsetzung 1–2:** Skript `local/scripts/_flatten_i18n_dicts.py` (mehrsprachige Dicts → deutscher String / `json.dumps`). Anschliessend manuell: `mainSystem.py` AICore-`providerLabels`-Fallback; `portTypes.PortField.description` auf `str`; `_deriveFormPayloadSchema` / `_deriveTransformSchema`; `entryPoints._normalize_title` liefert `str`. **`Role.description`** bleibt `TextMultilingual`: `coerce_text_multilingual()` in `datamodelUtils.py` wandelt Template-Strings/Dicts; Bootstrap- und Feature-`Role(...)`-Aufrufe nutzen `coerce_text_multilingual(...)`. + +## Problemstellung + +Trotz Phase 1–7 der i18n-Unification existieren noch **~640+ statische mehrsprachige Dicts** (`{"en":…, "de":…, "fr":…}`) im Gateway und **~60+ Stellen** im Frontend. Diese Dicts: + +- Müssen bei jeder neuen Sprache manuell erweitert werden +- Umgehen das zentrale i18n-System (`t()`, Admin-UI, AI-Übersetzung) +- Sind inkonsistent (manche nur en/de, manche nur en/fr, manche en/de/fr) + +**Ziel:** Jeder UI-sichtbare Text wird als **deutscher Klartext-Key** gespeichert und zur Laufzeit über `t()` übersetzt. Mehrsprachige Dicts verschwinden komplett. + +--- + +## Architektur-Entscheidung + +### Prinzip: Deutscher Klartext = i18n-Key + +``` +# VORHER (statisch, 3 Sprachen hardcoded): +"label": {"en": "Documents", "de": "Dokumente", "fr": "Documents"} + +# NACHHER (dynamisch, beliebig viele Sprachen): +"label": "Dokumente" +``` + +Beim Boot registriert `_registerXxxLabels()` den deutschen Text als Key im `xx`-Basisset. `t("Dokumente")` liefert zur Laufzeit die Übersetzung in der aktuellen Sprache. + +### Sonderfälle + +| Fall | Lösung | +|------|--------| +| `outputLabels` (Listen von Strings pro Sprache) | Jedes Element einzeln als Key: `"Ja"`, `"Nein"` | +| `_ISO_LABELS` (Sprachnamen) | Bleiben statisch — sind ISO-Referenzdaten, keine UI-Texte | +| Locale-Code-Maps (`"de": "de-DE"`) | Bleiben statisch — technische Mappings | +| `BUILTIN_PLANS` (Subscription) | Werden zu Keys, AI übersetzt | +| Datamodel `frontend_options` | Labels werden zu Keys, Boot-Registrierung | + +--- + +## Datei-Index (vollständig) + +### Gateway — Feature-Module (Kategorie A: RBAC/Katalog-Labels) + +| # | Datei | Stellen | Muster | Phase | +|---|-------|---------|--------|-------| +| A1 | `features/trustee/mainTrustee.py` | ~62 | `DATA_OBJECTS`, `RESOURCE_OBJECTS`, `UI_OBJECTS`, `TEMPLATE_ROLES`, Workflow-Gruppen, Rollen-Beschreibungen | 1 | +| A2 | `system/mainSystem.py` | ~27 | `DATA_OBJECTS`, LLM-Provider-Labels | 1 | +| A3 | `features/commcoach/mainCommcoach.py` | ~17 | `DATA_OBJECTS`, `RESOURCE_OBJECTS`, `TEMPLATE_ROLES` | 1 | +| A4 | `features/teamsbot/mainTeamsbot.py` | ~11 | `DATA_OBJECTS`, `RESOURCE_OBJECTS`, `TEMPLATE_ROLES` | 1 | +| A5 | `features/workspace/mainWorkspace.py` | ~10 | `DATA_OBJECTS`, `RESOURCE_OBJECTS`, `TEMPLATE_ROLES` | 1 | +| A6 | `features/chatbot/mainChatbot.py` | ~7 | `DATA_OBJECTS`, `TEMPLATE_ROLES` | 1 | +| A7 | `features/neutralization/mainNeutralization.py` | ~7 | `DATA_OBJECTS`, `RESOURCE_OBJECTS` | 1 | +| A8 | `features/realEstate/mainRealEstate.py` | ~6 | `DATA_OBJECTS`, `RESOURCE_OBJECTS` | 1 | +| A9 | `features/graphicalEditor/mainGraphicalEditor.py` | ~6 | Permissions, Rollen-Beschreibungen | 1 | +| A10 | `serviceCenter/registry.py` | ~14 | Service-Kategorie-Labels | 1 | +| A11 | `interfaces/interfaceBootstrap.py` | ~4 | Template-Rollen-Beschreibungen (admin/user/viewer/sysadmin) | 1 | + +**Summe Kategorie A: ~171 Stellen, 11 Dateien** + +### Gateway — Graph-Editor Node-Definitionen (Kategorie B) + +| # | Datei | Stellen | Muster | Phase | +|---|-------|---------|--------|-------| +| B1 | `graphicalEditor/nodeDefinitions/clickup.py` | ~50 | Node-Label, Parameter-Descriptions | 2 | +| B2 | `graphicalEditor/nodeDefinitions/input.py` | ~31 | Node-Label, Parameter-Descriptions | 2 | +| B3 | `graphicalEditor/portTypes.py` | ~33 | Port-Feld-Descriptions | 2 | +| B4 | `graphicalEditor/nodeDefinitions/sharepoint.py` | ~27 | Node-Label, Parameter-Descriptions | 2 | +| B5 | `graphicalEditor/nodeDefinitions/email.py` | ~27 | Node-Label, Parameter-Descriptions | 2 | +| B6 | `graphicalEditor/nodeDefinitions/ai.py` | ~23 | Node-Label, Parameter-Descriptions | 2 | +| B7 | `graphicalEditor/nodeDefinitions/trustee.py` | ~20 | Node-Label, Parameter-Descriptions | 2 | +| B8 | `graphicalEditor/nodeDefinitions/flow.py` | ~14 | Node-Label, `outputLabels` (Sonderfall: Liste) | 2 | +| B9 | `graphicalEditor/nodeDefinitions/data.py` | ~9 | Node-Label, Parameter-Descriptions | 2 | +| B10 | `graphicalEditor/nodeDefinitions/triggers.py` | ~8 | Node-Label, Parameter-Descriptions | 2 | +| B11 | `graphicalEditor/nodeDefinitions/file.py` | ~7 | Node-Label, Parameter-Descriptions | 2 | +| B12 | `graphicalEditor/nodeRegistry.py` | ~10 | Kategorie-Labels | 2 | +| B13 | `graphicalEditor/entryPoints.py` | ~3 | Entry-Point-Titel | 2 | + +**Summe Kategorie B: ~262 Stellen, 13 Dateien** + +### Gateway — Datamodel-Options (Kategorie C) + +| # | Datei | Stellen | Muster | Phase | +|---|-------|---------|--------|-------| +| C1 | `datamodels/datamodelRbac.py` | ~19 | Scope/Access-Level Option-Labels (en/de/fr) | 3 | +| C2 | `datamodels/datamodelChat.py` | ~7 | Status/Mode Option-Labels (en/fr, kein de!) | 3 | +| C3 | `datamodels/datamodelMessaging.py` | ~11 | Channel/Status Option-Labels (en/fr) | 3 | +| C4 | `datamodels/datamodelNotification.py` | ~8 | Type/Status Option-Labels (en/de) | 3 | +| C5 | `datamodels/datamodelUam.py` | ~7 | Subscription-Status + Sprach-Options (en/de/fr) | 3 | +| C6 | `datamodels/datamodelSubscription.py` | ~8 | Plan-Titel + Descriptions (en/de/fr, teils ohne fr) | 3 | +| C7 | `datamodels/datamodelFiles.py` | ~4 | Scope Option-Labels (en/de) | 3 | +| C8 | `datamodels/datamodelDataSource.py` | ~4 | Scope Option-Labels (en/de) | 3 | +| C9 | `datamodels/datamodelFeatureDataSource.py` | ~4 | Scope Option-Labels (en/de) | 3 | +| C10 | `datamodels/datamodelUiLanguage.py` | ~3 | Sync-Status Option-Labels (de/en) | 3 | +| C11 | `features/trustee/datamodelFeatureTrustee.py` | ~13 | Währung + Dokumenttyp Option-Labels | 3 | +| C12 | `features/neutralization/datamodelFeatureNeutralizer.py` | ~4 | Scope Option-Labels | 3 | + +**Summe Kategorie C: ~92 Stellen, 12 Dateien** + +### Gateway — Sonstige (Kategorie D) + +| # | Datei | Stellen | Muster | Phase | +|---|-------|---------|--------|-------| +| D1 | `shared/frontendTypes.py` | ~14 | `CUSTOM_TYPE_DESCRIPTIONS` (aktuell ungenutzt) | 4 | +| D2 | `features/trustee/accounting/connectors/accountingConnectorBexio.py` | ~4 | Connector-Label + Feld-Labels | 4 | +| D3 | `features/trustee/accounting/connectors/accountingConnectorRma.py` | ~4 | Connector-Label + Feld-Labels | 4 | +| D4 | `features/trustee/accounting/connectors/accountingConnectorAbacus.py` | ~5 | Connector-Label + Feld-Labels | 4 | + +**Summe Kategorie D: ~27 Stellen, 4 Dateien** + +### Frontend (Kategorie E) + +| # | Datei | Stellen | Muster | Phase | +|---|-------|---------|--------|-------| +| E1 | `pages/Store.tsx` | ~5 | `FEATURE_DESCRIPTIONS` Dict (de/en/fr) | 5 | +| E2 | `types/mandate.ts` | ~45 | Statische Navigation-Labels (de/en) | 5 | +| E3 | `pages/views/trustee/TrusteeAbschlussView.tsx` | ~6 | Tile-Titel/Descriptions (de/en/fr) | 5 | +| E4 | `pages/views/trustee/TrusteeAnalyseView.tsx` | ~4 | Tile-Descriptions (de/en) | 5 | +| E5 | `components/UnifiedDataBar/UnifiedDataBar.tsx` | ~3 | `_TAB_LABELS` (de/en/fr) | 5 | +| E6 | `api/featuresApi.ts` | ~4 | Mock-Labels (de/en) | 5 | +| E7 | Diverse (12 Dateien) | ~12 | Hardcoded deutsche Strings ohne `t()` | 5 | + +**Summe Kategorie E: ~79 Stellen, ~18 Dateien** + +### Ausnahmen (bleiben statisch) + +| Datei | Grund | +|-------|-------| +| `routes/routeI18n.py` (`_ISO_LABELS`) | ISO-Referenzdaten (Sprachnamen), kein UI-Text | +| `serviceAgent/coreTools/_mediaTools.py` | Locale-Code-Map (`"de"→"de-DE"`), technisch | +| `serviceAgent/conversationManager.py` | Sprach-Name-Map für Agent-Kontext, technisch | + +--- + +## Gesamtübersicht + +| Kategorie | Dateien | Stellen | Komplexität | +|-----------|---------|---------|-------------| +| A: Feature-Module | 11 | ~171 | Mittel — uniformes Muster, braucht Boot-Registrierung | +| B: Node-Definitionen | 13 | ~262 | Mittel — uniformes Muster, braucht eigene Registrierung | +| C: Datamodel-Options | 12 | ~92 | Hoch — verschiedene Patterns, braucht generische Lösung | +| D: Sonstige Gateway | 4 | ~27 | Niedrig — einfache Ersetzung | +| E: Frontend | ~18 | ~79 | Niedrig — `t()` wrappen | +| **Total** | **~58** | **~631** | | + +--- + +## Umsetzungsplan (5 Phasen) + +### Phase 1: Feature-Module (Kategorie A) — Composer-geeignet + +**Aufwand:** Mittel | **Modell:** Composer (schnelles Modell) | **Risiko:** Niedrig + +**Vorbereitung (einmalig, Opus):** +- `_registerRbacLabels()` in `i18nRegistry.py` erweitern: neben `DATA_OBJECTS`, `RESOURCE_OBJECTS`, `TEMPLATE_ROLES` auch scannen: + - `UI_OBJECTS[].label` + - Workflow-Gruppen-Labels (`TRUSTEE_WORKFLOW_GROUPS`, `TRUSTEE_SERVICE_CATEGORIES`) + - Rollen-`description` Blöcke + - Service-Kategorie-Labels (`serviceCenter/registry.py`) + - Bootstrap-Rollen (`interfaceBootstrap.py`) + +**Transformation (pro Datei, Composer):** +Jedes `"label": {"en": "X", "de": "Y", "fr": "Z"}` wird zu `"label": "Y"` (deutscher Text). +Jedes `"description": {"en": "X", "de": "Y", "fr": "Z"}` wird zu `"description": "Y"`. + +**Regel für Composer:** +``` +In der Datei [DATEI]: +- Ersetze jedes Dict {"en": "...", "de": "DEUTSCH", "fr": "..."} durch den deutschen Wert "DEUTSCH" +- Ersetze jedes Dict {"de": "DEUTSCH", "en": "...", "fr": "..."} durch "DEUTSCH" +- Wenn kein "de" vorhanden: nimm "en" Wert +- Lasse alle anderen Felder unverändert +``` + +**Dateien:** A1–A11 (11 Dateien) + +**Akzeptanzkriterien:** +- [ ] Kein `"fr":` mehr in den 11 Dateien (ausser Ausnahmen) +- [ ] `_registerRbacLabels()` registriert alle neuen Key-Kategorien +- [ ] Gateway startet fehlerfrei +- [ ] Admin-UI Sprachen-Seite zeigt neue Keys im xx-Set + +--- + +### Phase 2: Node-Definitionen (Kategorie B) — Composer-geeignet + +**Aufwand:** Mittel | **Modell:** Composer (schnelles Modell) | **Risiko:** Niedrig + +**Vorbereitung (einmalig, Opus):** +- Neue Funktion `_registerNodeLabels()` in `i18nRegistry.py`: + - Scannt `STATIC_NODE_TYPES` aus `nodeDefinitions/__init__.py` + - Registriert `label`, `description`, `parameters[].description`, `outputLabels[]` als Keys + - Context: `node.label`, `node.desc`, `node.param`, `node.output` +- Scannt `portTypes.PORT_TYPE_CATALOG` für Port-Feld-Descriptions + - Context: `port.desc` +- Scannt `nodeRegistry` Kategorie-Labels + - Context: `node.category` +- Scannt `entryPoints` Titel + - Context: `node.entry` + +**Transformation (pro Datei, Composer):** +Identisches Muster wie Phase 1: Dict → deutscher String. + +**Sonderfall `flow.py` `outputLabels`:** +```python +# VORHER: +"outputLabels": {"en": ["Yes", "No"], "de": ["Ja", "Nein"], "fr": ["Oui", "Non"]} + +# NACHHER: +"outputLabels": ["Ja", "Nein"] +``` + +**Dateien:** B1–B13 (13 Dateien) + +**Akzeptanzkriterien:** +- [ ] Kein `"fr":` mehr in den 13 Dateien +- [ ] `_registerNodeLabels()` registriert alle Node-Keys +- [ ] Graph-Editor zeigt Nodes korrekt an (Labels übersetzt) +- [ ] Node-Parameter-Descriptions im Config-Panel korrekt + +--- + +### Phase 3: Datamodel-Options (Kategorie C) — Opus nötig + +**Aufwand:** Hoch | **Modell:** Opus | **Risiko:** Mittel + +**Warum Opus:** Die Patterns sind uneinheitlich (en/fr, en/de, en/de/fr), die `frontend_options` Struktur variiert, und die Boot-Registrierung muss generisch über alle Datamodels funktionieren. + +**Vorbereitung:** +- Neue generische Funktion `_registerDatamodelOptionLabels()` in `i18nRegistry.py`: + - Scannt alle Pydantic-Modelle mit `json_schema_extra` → `frontend_options` + - Extrahiert `label` Dicts und registriert den deutschen (oder englischen) Text als Key + - Context: `option.{ModelName}.{fieldName}` +- `BUILTIN_PLANS` in `datamodelSubscription.py`: `title`/`description` zu Keys + +**Transformation (pro Datei):** +```python +# VORHER: +{"value": "active", "label": {"en": "Active", "de": "Aktiv", "fr": "Actif"}} + +# NACHHER: +{"value": "active", "label": "Aktiv"} +``` + +**Problem: Fehlende Sprachen.** Einige Dicts haben kein `"de"` (z.B. `datamodelChat.py` nur en/fr). Hier wird `"en"` als Fallback genommen und der englische Text als Key registriert — die AI-Übersetzung erzeugt dann `de` und `fr`. + +**Dateien:** C1–C12 (12 Dateien) + +**Akzeptanzkriterien:** +- [ ] Kein `"fr":` / `"en":` Dict-Pattern mehr in den 12 Dateien +- [ ] `_registerDatamodelOptionLabels()` registriert alle Option-Keys +- [ ] Frontend Select-Felder zeigen korrekte Labels +- [ ] Subscription-Plan-Texte korrekt übersetzt + +--- + +### Phase 4: Sonstige Gateway (Kategorie D) — Composer-geeignet + +**Aufwand:** Niedrig | **Modell:** Composer (schnelles Modell) | **Risiko:** Niedrig + +**Transformation:** +- `frontendTypes.py`: `CUSTOM_TYPE_DESCRIPTIONS` komplett entfernen (ungenutzt) + `getCustomTypeDescription()` und `registerCustomType()` vereinfachen oder entfernen +- Accounting-Connectors: `displayName()` und Feld-Labels zu deutschen Strings + +**Dateien:** D1–D4 (4 Dateien) + +**Akzeptanzkriterien:** +- [ ] `CUSTOM_TYPE_DESCRIPTIONS` entfernt +- [ ] Accounting-Connector-Labels als deutsche Strings +- [ ] Kein `"fr":` mehr in den 4 Dateien + +--- + +### Phase 5: Frontend (Kategorie E) — Composer-geeignet + +**Aufwand:** Niedrig | **Modell:** Composer (schnelles Modell) | **Risiko:** Niedrig + +**Transformation:** +- Alle `{"en": "X", "de": "Y", "fr": "Z"}` Dicts durch `t("Y")` ersetzen +- Alle hardcodierten deutschen Strings in JSX-Attributen mit `t()` wrappen +- `mandate.ts` Navigation-Labels: zu `t()`-Keys (Backend liefert bereits i18n-Keys) +- `_TAB_LABELS` in `UnifiedDataBar.tsx`: zu `t()`-Aufrufen +- `FEATURE_DESCRIPTIONS` in `Store.tsx`: zu `t()`-Keys + +**Dateien:** E1–E7 (~18 Dateien) + +**Akzeptanzkriterien:** +- [ ] Kein statisches `de:`/`en:`/`fr:` Dict-Pattern im Frontend +- [ ] Alle UI-Texte via `t()` getaggt +- [ ] Sprache wechseln → alle Texte ändern sich + +--- + +## Composer-Anweisungen (Copy-Paste-fertig) + +### Für Phase 1 + 2 + 4 (uniforme Dict→String Ersetzung): + +``` +Aufgabe: Ersetze in [DATEI] alle statischen mehrsprachigen Dicts durch den deutschen Klartext-String. + +Regeln: +1. {"en": "...", "de": "DEUTSCH", "fr": "..."} → "DEUTSCH" +2. {"de": "DEUTSCH", "en": "...", "fr": "..."} → "DEUTSCH" +3. {"en": "ENGLISH", "fr": "..."} (kein "de") → "ENGLISH" +4. {"en": "ENGLISH", "de": "DEUTSCH"} (kein "fr") → "DEUTSCH" +5. Listen-Sonderfall: {"en": [...], "de": [LISTE], "fr": [...]} → [LISTE] +6. Nur "label", "description", "title", "displayName" Felder ändern +7. Keine Imports, Funktionssignaturen oder Logik ändern +8. Keine Kommentare hinzufügen +``` + +### Für Phase 5 (Frontend t()-Wrapping): + +``` +Aufgabe: Ersetze in [DATEI] alle statischen Texte durch t()-Aufrufe. + +Regeln: +1. {"en": "...", "de": "DEUTSCH", "fr": "..."} → t("DEUTSCH") +2. Hardcoded string "DEUTSCH" in label/title/placeholder/aria-label → t("DEUTSCH") +3. Import { useLanguage } from '...LanguageContext' hinzufügen falls fehlend +4. const { t } = useLanguage(); in der Komponente falls fehlend +5. Keine Logik ändern, nur Texte wrappen +``` + +--- + +## Reihenfolge und Abhängigkeiten + +``` +Phase 1 ──→ Phase 2 ──→ Phase 3 ──→ Phase 4 + (A) (B) (C) (D) + │ + ▼ + Phase 5 + (E) +``` + +- Phase 1 muss zuerst: erweitert `_registerRbacLabels()` als Grundlage +- Phase 2 nach 1: braucht das Pattern von Phase 1 +- Phase 3 nach 2: komplexeste Phase, braucht neue generische Registrierung +- Phase 4 + 5: unabhängig voneinander, nach Phase 1 + +--- + +## Aufwandsschätzung + +| Phase | Modell | Dateien | Geschätzte Zeit | +|-------|--------|---------|-----------------| +| 1 (Vorbereitung) | Opus | 1 | 15 min | +| 1 (Transformation) | Composer | 11 | 30 min | +| 2 (Vorbereitung) | Opus | 1 | 15 min | +| 2 (Transformation) | Composer | 13 | 30 min | +| 3 | Opus | 13 | 45 min | +| 4 | Composer | 4 | 10 min | +| 5 | Composer | 18 | 30 min | +| **Total** | | **~58** | **~3 Stunden** | diff --git a/c-work/2-build/gateway-i18n-unified.md b/c-work/3-validate/2026-04 gateway-i18n-unified.md similarity index 67% rename from c-work/2-build/gateway-i18n-unified.md rename to c-work/3-validate/2026-04 gateway-i18n-unified.md index 4a47e2d..add102c 100644 --- a/c-work/2-build/gateway-i18n-unified.md +++ b/c-work/3-validate/2026-04 gateway-i18n-unified.md @@ -1,4 +1,4 @@ - + @@ -283,52 +283,56 @@ async def _i18nMiddleware(request, call_next): ### Phase 1: Infrastruktur + Decorator -- Cursor: **Opus 4.6** Architektur-Arbeit: neues Modul, Boot-Integration, Decorator-Logik, `attributeUtils` Umbau. Braucht tiefes Verstaendnis der bestehenden Codebasis (DB-Schema, Boot-Reihenfolge, ContextVar, async). -- [ ] `i18nRegistry.py` erstellen: `t()`, `@i18nModel`, `_REGISTRY`, `_CACHE`, `_setLanguage`, `_syncRegistryToDb`, `_loadCache` -- [ ] `app.py`: Boot-Hook nach DB-Init: `_syncRegistryToDb()` + `_loadCache()` -- [ ] `app.py`: Request-Middleware fuer `_setLanguage()` (aus Accept-Language oder User-Session) -- [ ] `routeI18n.py`: `_loadCache()` nach sync/update aufrufen (Cache invalidieren) -- [ ] `attributeUtils.py`: `getModelLabels()`/`getModelLabel()` auf neues MODEL_LABELS-Format (str statt Dict) + t()-Cache umstellen -- [ ] 2-3 Beispiel-Models migrieren (`datamodelBase.py`, `datamodelFeatures.py`) als Referenz fuer Phase 2 -- [ ] Gateway starten, pruefen ob Decorator + Boot-Sync funktioniert +- [x] `i18nRegistry.py` erstellen: `t()`, `@i18nModel`, `_REGISTRY`, `_CACHE`, `_setLanguage`, `_syncRegistryToDb`, `_loadCache` +- [x] `app.py`: Boot-Hook nach DB-Init: `_syncRegistryToDb()` + `_loadCache()` +- [x] `app.py`: Request-Middleware fuer `_setLanguage()` (aus Accept-Language oder User-Session) +- [x] `routeI18n.py`: `_loadCache()` nach sync/update aufrufen (Cache invalidieren) +- [x] `attributeUtils.py`: `getModelLabels()`/`getModelLabel()` auf neues MODEL_LABELS-Format (str statt Dict) + t()-Cache umstellen +- [x] 2-3 Beispiel-Models migrieren (`datamodelBase.py`, `datamodelFeatures.py`) als Referenz fuer Phase 2 +- [x] Gateway starten, pruefen ob Decorator + Boot-Sync funktioniert ### Phase 2: Pydantic-Models migrieren (~27 verbleibende Dateien) -- Cursor: **Auto / Fast** Repetitive Arbeit nach klarem Pattern aus Phase 1: Decorator drauf, `json_schema_extra["label"]` ergaenzen, `registerModelLabels()` loeschen. In Batches von 5-8 Dateien. -- [ ] Alle verbleibenden Pydantic-Models: `@i18nModel("Label")` Decorator + `json_schema_extra={"label": "..."}` zu Fields -- [ ] Alle `registerModelLabels()`-Aufrufe loeschen -- [ ] `from modules.shared.attributeUtils import registerModelLabels` Imports entfernen -- [ ] Nach jedem Batch: Gateway starten und pruefen +- [x] Alle verbleibenden Pydantic-Models: `@i18nModel("Label")` Decorator + `json_schema_extra={"label": "..."}` zu Fields +- [x] Alle `registerModelLabels()`-Aufrufe loeschen +- [x] `from modules.shared.attributeUtils import registerModelLabels` Imports entfernen +- [x] Nach jedem Batch: Gateway starten und pruefen ### Phase 3: HTTPException-Texte umstellen (~21 Dateien, ~150 Stellen) -- Cursor: **Auto / Fast** -Mechanische Arbeit: `detail="Text"` wird zu `detail=t("Text", "api.routeName", "Beschreibung")`. Klares Pattern, in Batches von 5-7 Dateien. -- [ ] Alle UI-sichtbaren `HTTPException(detail="...")` in `routes/*.py` auf `t()` umstellen -- [ ] Interne/technische Fehlermeldungen (die nie im UI erscheinen) NICHT umstellen +Mechanische Arbeit: `detail="Text"` wird zu `detail=routeApiMsg("Text")` mit `routeApiMsg = apiRouteContext("route")` (Shorthand fuer `t(key, "api.route", "")`). Skript: `gateway/scripts/wrapRouteHttpDetails.py` (nur einzeilige `detail="..."`; mehrzeilige Imports und f-Strings manuell pruefen). +- [x] Alle UI-sichtbaren `HTTPException(detail="...")` in `modules/**/route*.py` auf `routeApiMsg(...)` umgestellt +- [x] Interne/technische Fehlermeldungen (`detail=str(e)`, `detail=f"...{e}..."`) unveraendert gelassen ### Phase 4: TextMultilingual UI (Frontend, 2-3 Dateien) -- Cursor: **Opus 4.6** React-Hooks, dynamische Rendering-Logik, `ge`->`de` Mapping. Braucht Verstaendnis des Frontend-i18n-Systems und FormGenerator-Architektur. -- [ ] `FormGeneratorForm.tsx`: `renderMultilingualField` dynamisch aus `availableLanguages` -- [ ] `FormGeneratorTable.tsx`: `formatTextMultilingual` dynamisch -- [ ] `TextMultilingual` Backend-Typ pruefen: `ge` -> `de` Mapping ggf. anpassen +- [x] `FormGeneratorForm.tsx`: `renderMultilingualField` dynamisch aus `availableLanguages` (Fallback auf `[en, ge]` wenn keine Sprachen geladen) +- [x] `FormGeneratorTable.tsx`: `formatTextMultilingual` + `convertToDisplayString` dynamisch (hardcoded `langMap` durch zentrales `_toBackendLang` ersetzt) +- [x] `TextMultilingual` Backend-Typ: `get_text()` und `from_dict()` akzeptieren jetzt `de` als Alias fuer `ge`. DB-Schema bleibt `ge` (bestehende Daten). ### Phase 5: Integration + Test -- Cursor: **Opus 4.6** End-to-End Pruefung, Debugging, Log-Analyse, ggf. Fixes. Braucht das staerkste Modell fuer Fehleranalyse. -- [ ] Gateway starten, pruefen ob Keys in `UiLanguageSet(xx)` erscheinen (context=api, table.*) -- [ ] Admin-UI: Sprache synchronisieren, pruefen ob Gateway-Keys uebersetzt werden -- [ ] UI mit anderer Sprache testen: Fehlermeldungen, Tabellen-Labels, TextMultilingual-Felder +- [x] Gateway-Import aller Route-Module: 36/41 ok (5 Fehler = fehlende optionale Deps: aiohttp, langchain_core, tavily) +- [x] `@i18nModel` registriert 90 Models mit 490 table-Keys in `_REGISTRY` + `MODEL_LABELS` +- [x] `getModelLabel` / `getModelLabels` / `getModelAttributeDefinitions` lesen korrekt aus `i18nRegistry.MODEL_LABELS` +- [x] `routeApiMsg` (api-Keys) registrieren sich lazy beim ersten `t()`-Aufruf zur Laufzeit +- [x] `app.py`: Middleware (`_i18nMiddleware`) + Boot-Hooks (`_syncRegistryToDb`, `_loadCache`) vorhanden +- [x] Admin-UI: Sprache synchronisieren, Gateway-Keys werden uebersetzt (manuell getestet) +- [x] UI mit anderer Sprache testen: Fehlermeldungen, Tabellen-Labels, TextMultilingual-Felder (manuell getestet) ### Phase 6: Wiki / Coding-Conventions aktualisieren -- Cursor: **Auto / Fast** Reine Doku-Arbeit. Inhalte stehen bereits im Plan (siehe "Wiki-Anpassungen fuer Cursor AI Coding" unten). Nur Einpflegen und Formatieren. -- [ ] `d-guides/coding-conventions.md`: Backend-i18n-Regeln hinzufuegen (t(), @i18nModel, json_schema_extra["label"]) -- [ ] `d-guides/coding-conventions.md`: Regel fuer HTTPException-Texte mit t() -- [ ] `d-guides/coding-conventions.md`: Regel fuer neue Pydantic-Models (@i18nModel Pflicht) -- [ ] `b-reference/gateway/architecture.md`: i18n-Architektur dokumentieren (i18nRegistry, Boot-Sync, Cache) -- [ ] `b-reference/frontend-nyla/architecture.md`: TextMultilingual dynamisch dokumentieren -- [ ] `TOPICS.md`: Thema "i18n / Mehrsprachigkeit" hinzufuegen mit Verweis auf relevante Seiten +- [x] `d-guides/coding-conventions.md`: Backend-i18n-Regeln hinzugefuegt (t(), @i18nModel, json_schema_extra["label"], apiRouteContext) +- [x] `d-guides/coding-conventions.md`: Regel fuer HTTPException-Texte mit routeApiMsg() +- [x] `d-guides/coding-conventions.md`: Regel fuer neue Pydantic-Models (@i18nModel Pflicht) +- [x] `b-reference/gateway/architecture.md`: i18n-Architektur dokumentiert (i18nRegistry, Boot-Sync, Cache, Context-Namensraeume, Entry-Identitaet) +- [x] `b-reference/frontend-nyla/architecture.md`: TextMultilingual dynamisch + AdminLanguagesKeepAlive dokumentiert +- [x] `TOPICS.md`: Thema "i18n / Mehrsprachigkeit" hinzugefuegt (Cross-Cutting + Aktive Arbeiten) ### Abschluss -- [ ] RBAC / Permissions: nicht betroffen -- [ ] Neutralisierung: nicht betroffen -- [ ] Navigation / Routing: nicht betroffen -- [ ] Billing-Impact: nicht betroffen +- [x] RBAC / Permissions: nicht betroffen +- [x] Neutralisierung: nicht betroffen +- [x] Navigation / Routing: nicht betroffen +- [x] Billing-Impact: nicht betroffen ## Wiki-Anpassungen fuer Cursor AI Coding @@ -389,6 +393,12 @@ class User(PowerOnModel): TextMultilingual-Felder rendern automatisch Eingabefelder fuer alle verfuegbaren Sprachen (aus `availableLanguages`). Keine hardcodierten Sprach-Codes (en/ge/fr/it) mehr verwenden. + +**Geplanter UX-Mehrwert:** Pro mehrsprachigem Feld ein Button (z. B. „In alle Sprachen +uebersetzen“), der den Inhalt der **Quellsprache** (Default: z. B. `en` als Pflichtfeld im +Modell, oder die vom Nutzer befuellte Zeile / aktuelle UI-Sprache — festzulegen) per **KI** +in alle **anderen** Sprachfelder uebernimmt — dieselbe Logik wie die Admin-Sprachen-AI +(siehe *Phase 7b* im Hauptdokument). ``` ## Akzeptanzkriterien @@ -431,8 +441,68 @@ TextMultilingual-Felder rendern automatisch Eingabefelder fuer alle verfuegbaren - UiLanguageSet Model: `gateway/modules/datamodels/datamodelUiLanguage.py` - TextMultilingual: `gateway/modules/datamodels/datamodelUtils.py` +## Phase 7 (Vorschlag): RBAC-Labels & Quick Actions — Abgleich mit dem Code + +### Verifiziert (Stand Pruefung) + +| Mechanismus | Code / Pfad | Befund | +|-------------|-------------|--------| +| **TextMultilingual** | `gateway/modules/datamodels/datamodelUtils.py` | Pydantic-Modell: **`en` Pflicht**, `de`/`fr`/`it` optional; `get_text(lang)` mit Fallback auf `en`. | +| **Rollenbeschreibung in der DB** | `gateway/modules/datamodels/datamodelRbac.py` — `Role.description: TextMultilingual` | Feld ist **explizit mehrsprachig**; im Schema `frontend_type: "multilingual"`. | +| **Admin-Formular** | `FormGeneratorForm.tsx` | Felder mit Typ `multilingual` rendern **pro Sprache Eingaben** aus `availableLanguages` — passt zu **TextMultilingual-Objekten** (nicht zu einem einzelnen i18n-Key). | +| **Template-Rollen (Code)** | `mainTrustee.py` etc. — `TEMPLATE_ROLES[].description` | Im Python **Dict** `{en,de,fr}`; beim Sync in die DB als **TextMultilingual**/`Role`-Record. | +| **RBAC-Katalog (RAM)** | `rbacCatalog.py` — `registerDataObject` / `registerResourceObject` | Labels sind **lose Dicts** `{en,de,...}` im Speicher — **kein** Pydantic-TextMultilingual-Typ auf dem Katalog-Eintrag. | +| **Feature-UI (Navigation)** | `UI_OBJECTS[].label` | Bereits auf **deutschen String** (Basis-Key) umgestellt; Navigation nutzt **`t()`** im Frontend. | +| **Quick Actions** | `routeFeatureTrustee.py` — `GET .../quick-actions?language=` | Backend **loest** `label`/`description`-Dicts **serverseitig** mit `language` auf; Response = **fertige Strings**. | +| **QuickActionBoard** | `QuickActionBoard.tsx` | Erwartet **`label: string`**, **`description: string`** — **keine** TextMultilingual-Objekte auf dem Draht. | +| **TrusteeDashboardView** | `TrusteeDashboardView.tsx` | Laed Quick Actions neu bei **`currentLanguage`**-Wechsel (useEffect-Dependency). | + +**Kernpunkt:** Es gibt **zwei legitime Muster** im gleichen Produkt: + +1. **Persistierte Entitaeten** (z. B. `Role`) mit **TextMultilingual** — Bearbeitung im UI als **Objekt mit Sprachfeldern** (bereits vorhanden). +2. **Statische Code-Listen** (Katalog-Dicts, Quick-Action-Definitionen) — heute **Dicts im Python** oder **serverseitige Aufloesung**; Navigation/UI-Labels der zweiten Schicht sind auf **String-Key + `t()`** migriert. + +### Phase 7 — angepasste Empfehlung + +**Nicht** alles auf „ein deutscher String = einziger Key“ vereinheitlichen, wenn **TextMultilingual** und **FormGenerator** bereits passen: + +- **`Role.description` (und gleichartige DB-Felder):** Bei **TextMultilingual** bleiben: Übersetzungen koennen weiterhin **pro Sprache in der DB** gepflegt werden **oder** spaeter mit UiLanguageSet synchronisiert werden (separates Konzept: „Spiegelung“ vs. Duplikat vermeiden). +- **`DATA_OBJECTS` / `RESOURCE_OBJECTS`:** Entweder (a) **Dicts** beibehalten und zusaetzlich **deutsche Basis-Texte** als i18n-Keys in `_REGISTRY` registrieren (`context=rbac.*`) fuer Admin/AI, **oder** (b) auf **TextMultilingual-Shape** im Katalog vereinheitlichen (Aufwand: API + Admin-Anzeige). +- **Quick Actions:** Entweder (a) **serverseitige** Aufloesung beibehalten und **Gateway `t()`** auf die **deutschen Basis-Strings** aus den Dicts anwenden (Cache pro Request-Sprache), **oder** (b) nur noch **deutsche Keys** ausliefern und **`t()` im Frontend** (wie MandateNavigation) — dann `QuickActionBoard` um `t(action.label)` erweitern. + +**Konkreter naechster technischer Schritt (klein):** `_registerRbacLabels()` in `i18nRegistry.py` — aus allen `DATA_OBJECTS`/`RESOURCE_OBJECTS` die **de**-Texte (und optional Template-**description**-de) als Keys mit `context` `rbac.data` / `rbac.resource` / `rbac.role` ins **xx**-Set syncen, **ohne** das Datenmodell `TextMultilingual` zu ersetzen. + +**Nicht empfohlen:** `Role.description` auf einen reinen String-Key ohne Migration umstellen — bricht **FormGenerator**-Erwartung und bestehende DB-Daten, solange `TextMultilingual` Pflicht bleibt. + +### Phase 7b (UX): TextMultilingual — Button „In alle Sprachen uebersetzen“ + +**Ziel:** Echten Mehrwert im Formular: Nutzer traegt den Text **einmal** in der gewuenschten +**Ausgangs-Sprache** ein und kann per Klick die **uebrigen** Sprachfelder automatisch fuellen +(statt fuenfmal manuell zu tippen). + +**Machbarkeit:** **Ja.** Technisch gut andockbar: + +| Baustein | Bemerkung | +|----------|-----------| +| **Gateway** | `routeI18n.py` enthaelt bereits `_translateBatch` (KI, Batches, Kapitalisierung `_matchCapitalization`). Ergaenzung: schlanker Endpoint z. B. `POST /api/i18n/translate-field` mit Body `{ "sourceText": "...", "sourceLang": "de", "targetLangs": ["en","fr"] }` und Response `{ "en": "...", "fr": "..." }` — **Auth + Billing** analog zu bestehenden Uebersetzungs-Jobs. | +| **Frontend** | `FormGeneratorForm.tsx` — `renderMultilingualField`: neben dem Feld-Label oder unter den Inputs ein Button; onClick: API aufrufen, dann `handleMultilingualChange` fuer jede Zielsprache setzen (Quellsprache unveraendert lassen). Loading/Disabled waehrend der Anfrage; Fehler via Toast. | +| **Quellsprache** | Produktregel festlegen: (A) immer **englisch** (`en`), weil im Modell Pflicht, oder (B) **aktuelle UI-Sprache** (`currentLanguage`), oder (C) die **erste nicht-leere** Zeile unter den Sprach-Inputs. Empfehlung: **(C)** mit Fallback auf `en`, damit es intuitiv bleibt. | +| **Kosten / Limits** | Gleiche Policy wie Admin-AI-Uebersetzung (Billing-Callback, Rate-Limits). | + +**Abgrenzung:** Kein Ersatz fuer professionelles Review; KI kann Fachbegriffe falsch setzen — +Button-Tooltip mit Hinweis optional. + +**Status:** ✅ Umgesetzt (Phase 7 + 7b). + +- `_registerRbacLabels()` registriert 118 Keys (rbac.data, rbac.resource, rbac.role, rbac.quickaction) im xx-Basisset. +- `POST /api/i18n/translate-field` Endpoint fuer On-Demand-Uebersetzung von TextMultilingual-Feldern. +- FormGenerator: Button „In alle Sprachen uebersetzen" in multilingualen Feldern. + +**Konkreter Umsetzungsplan (Arbeitspakete, Sprints, Abnahme):** siehe +`c-work/1-plan/2026-04-gateway-i18n-phase-7-implementation.md`. + ## Abschluss -- [ ] b-reference/ aktualisiert (gateway/architecture.md, frontend-nyla/architecture.md) -- [ ] TOPICS.md aktualisiert (neues Thema: i18n/Mehrsprachigkeit) -- [ ] Dieses Dokument -> z-archive/ verschoben +- [x] b-reference/ aktualisiert (gateway/architecture.md, frontend-nyla/architecture.md) +- [x] TOPICS.md aktualisiert (neues Thema: i18n/Mehrsprachigkeit) +- [ ] Dieses Dokument -> z-archive/ verschoben (nach finaler Validierung) diff --git a/c-work/3-validate/2026-04-gateway-duplicate-class-names.md b/c-work/3-validate/2026-04-gateway-duplicate-class-names.md new file mode 100644 index 0000000..54e409c --- /dev/null +++ b/c-work/3-validate/2026-04-gateway-duplicate-class-names.md @@ -0,0 +1,133 @@ + + + + +# Gateway: Doppelte Klassennamen bereinigen + +## Beschreibung und Kontext + +Beim Aufräumen der `@i18nModel`-Migration (Phase 2) wurde festgestellt, dass mehrere Python-Klassen im Gateway **denselben Namen** tragen, obwohl sie in verschiedenen Modulen leben. Das ist problematisch, weil: + +1. **i18n-Kollision:** `@i18nModel` registriert nach `cls.__name__` in einem globalen Dict — bei gleichem Namen überschreibt der letzte Import den ersten. +2. **Lesbarkeit:** Import-Aliase (`from ... import TaskResult as WorkflowTaskResult`) sind fragil und leicht vergessen. +3. **Tooling:** IDE-Suche, Debugging-Stacktraces und `getModelClasses()` liefern mehrdeutige Treffer. + +**Business-Treiber:** Saubere Klassennamen verhindern stille Label-Fehler in der UI und reduzieren Wartungsaufwand bei zukünftigen Erweiterungen. + +--- + +## Vollständige Liste der Duplikate + +Ermittelt per AST-Scan über `gateway/modules/` (nur Klassen, die in **mehr als einer Datei** vorkommen): + +### Kritisch: Pydantic-Modelle mit `@i18nModel` (i18n-Dict-Kollision) + +| Klassenname | Datei 1 | Datei 2 | Beschreibung | +|-------------|---------|---------|--------------| +| **`TaskResult`** | `datamodels/datamodelChat.py` | `datamodels/datamodelWorkflow.py` | Chat: Aufgabenergebnis mit Status/Feedback. Workflow: Minimales Ergebnis mit `actionResult`. Beide haben `@i18nModel("Aufgaben-Ergebnis")`. | +| **`RequestContext`** | `datamodels/datamodelWorkflow.py` (Pydantic `BaseModel`) | `auth/authentication.py` (plain `class`) | Workflow: Normalisierter Benutzer-Input. Auth: Request-Kontext mit User/Mandate/Rollen. Kein i18n-Konflikt (Auth-Klasse ist kein Pydantic-Modell), aber Name ist irreführend. | + +### Mittel: Lokale Hilfsklassen (kein i18n, aber verwirrend) + +| Klassenname | Datei 1 | Datei 2 | Beschreibung | +|-------------|---------|---------|--------------| +| **`AiResponse`** | `datamodels/datamodelWorkflow.py` (Pydantic) | `serviceAi/subStructureFilling.py` (inline `class` in try/except, 4×) | Workflow: Vollständiges AI-Antwort-Modell. StructureFiller: Minimaler Wrapper `AiResponse(content)` als Fallback bei Parse-Fehlern. | +| **`TableData`** | `datamodels/datamodelDocument.py` (Pydantic) | `neutralization/.../subProcessList.py` (`@dataclass`) | Document: Strukturierte Tabelle mit Headers/Rows/Caption. Neutralization: Einfache Tabelle mit `source_type`. | +| **`Token`** | `datamodels/datamodelSecurity.py` (Pydantic `PowerOnModel`) | `shared/jsonContinuation.py` (`@dataclass`) | Security: DB-Token (JWT, Refresh etc.). JsonContinuation: JSON-Parser-Token (internes Parsing). | + +### Niedrig: Architektur-Helfer (domänengetrennt, kaum Verwechslungsgefahr) + +| Klassenname | Dateien | Beschreibung | +|-------------|---------|--------------| +| `ChatObjects` | `features/chatbot/interfaceFeatureChatbot.py`, `interfaces/interfaceDbChat.py` | Identische Rolle (Chat-Objekt-Container), ggf. zusammenführbar. | +| `ConnectionHelper` | `workflows/methods/methodOutlook/helpers/connection.py`, `workflows/methods/methodSharepoint/helpers/connection.py` | Jeweils Outlook- bzw. SharePoint-spezifisch; Name ist generisch, aber Module sind klar getrennt. | +| `DocumentParsingHelper` | `workflows/methods/methodJira/helpers/documentParsing.py`, `workflows/methods/methodSharepoint/helpers/documentParsing.py` | Jira- bzw. SharePoint-spezifisch; gleiche Situation wie `ConnectionHelper`. | +| `StructureGenerator` | `serviceAi/subStructureGeneration.py`, `serviceGeneration/subStructureGenerator.py` | Zwei Services mit ähnlicher Aufgabe; ggf. Konsolidierung prüfen. | +| `_ResolverDbAdapter` | `features/graphicalEditor/routeFeatureGraphicalEditor.py`, `features/workspace/routeFeatureWorkspace.py` | Interner Adapter (`_`-Prefix); lebt nur im jeweiligen Route-Modul. | +| `_ServicesAdapter` | 4× in `serviceCenter/services/*/main*.py` | Interner Adapter pro Service; bewusst gleichnamig, nie cross-importiert. | + +--- + +## Lösungsvorschlag + +### 1. `TaskResult` → Umbenennung (Priorität: hoch) + +**Problem:** Beide Klassen haben `@i18nModel("Aufgaben-Ergebnis")` — der letzte Import gewinnt im Label-Dict. + +**Lösung:** + +| Aktuell | Neu | Modul | +|---------|-----|-------| +| `TaskResult` in `datamodelChat.py` | **`ChatTaskResult`** | Chat-Domäne: Status, Feedback, Error | +| `TaskResult` in `datamodelWorkflow.py` | **`WorkflowTaskResult`** | Workflow-Domäne: taskId + actionResult | + +**Betroffene Imports (5 Dateien):** + +- `workflows/processing/modes/modeBase.py` — importiert aus `datamodelChat` +- `workflows/processing/modes/modeDynamic.py` — importiert aus `datamodelChat` +- `workflows/processing/modes/modeAutomation.py` — importiert aus `datamodelChat` + `datamodelWorkflow` (bereits `as WorkflowTaskResult`) +- `workflows/workflowManager.py` — importiert aus `datamodelWorkflow` (bereits `as WorkflowTaskResult`) +- `workflows/processing/workflowProcessor.py` — importiert aus `datamodelWorkflow` +- `tests/unit/datamodels/test_workflow_models.py` — importiert aus `datamodelWorkflow` + +**i18n-Labels anpassen:** + +- `ChatTaskResult`: `@i18nModel("Chat-Aufgabenergebnis")` +- `WorkflowTaskResult`: `@i18nModel("Workflow-Aufgabenergebnis")` + +**Aufwand:** Klein (6 Dateien, reine Umbenennung + Import-Anpassung). + +### 2. `AiResponse` in `subStructureFilling.py` → Inline-Klasse eliminieren (Priorität: mittel) + +**Problem:** 4× identische `class AiResponse` inline in try/except-Blöcken als Fallback-Wrapper. + +**Lösung:** Eine private Klasse `_AiResponseFallback` am Modulanfang definieren, die 4 Inline-Definitionen ersetzen. + +```python +@dataclass +class _AiResponseFallback: + content: Any +``` + +**Aufwand:** Klein (1 Datei, 4 Stellen). + +### 3. `TableData` in `subProcessList.py` → Umbenennen (Priorität: mittel) + +**Lösung:** `TableData` in `subProcessList.py` → **`NeutralizationTableData`** (oder `_ParsedTableData`). Wird nur modulintern verwendet. + +**Aufwand:** Minimal (1 Datei). + +### 4. `Token` in `jsonContinuation.py` → Umbenennen (Priorität: niedrig) + +**Lösung:** `Token` → **`JsonToken`** (passend zu `TokenType` → `JsonTokenType`). Wird nur modulintern verwendet. + +**Aufwand:** Minimal (1 Datei, rein intern). + +### 5. `RequestContext` — Kein Handlungsbedarf + +Die Auth-`RequestContext` ist kein Pydantic-Modell und hat kein `@i18nModel`. Die Workflow-`RequestContext` ist ein Pydantic-Modell mit `@i18nModel`. Es gibt **keine Import-Überschneidung** (Auth wird nie aus `datamodelWorkflow` importiert und umgekehrt). Kein Refactoring nötig. + +### 6. Niedrige Kategorie — Kein Handlungsbedarf + +`ChatObjects`, `ConnectionHelper`, `DocumentParsingHelper`, `StructureGenerator`, `_ResolverDbAdapter`, `_ServicesAdapter` leben in klar getrennten Domänen und werden nie cross-importiert. Umbenennung wäre kosmetisch. + +--- + +## Umsetzungsreihenfolge + +| Schritt | Was | Dateien | Aufwand | +|---------|-----|---------|---------| +| 1 | `TaskResult` → `ChatTaskResult` / `WorkflowTaskResult` | 8 | 30 min | +| 2 | Inline `AiResponse` → `_AiResponseFallback` | 1 | 10 min | +| 3 | `TableData` → `NeutralizationTableData` | 1 | 5 min | +| 4 | `Token` → `JsonToken` | 1 | 5 min | + +**Gesamtaufwand:** ~50 min, kein Risiko für Laufzeitverhalten (reine Umbenennungen). + +--- + +## Validierung + +- `python -c "import app"` muss fehlerfrei durchlaufen +- Bestehende Tests (`tests/unit/datamodels/test_workflow_models.py`) anpassen und grün halten +- `getModelAttributeDefinitions` für betroffene Modelle prüfen (Labels eindeutig) diff --git a/c-work/3-validate/2026-04-gateway-i18n-phase-7-implementation.md b/c-work/3-validate/2026-04-gateway-i18n-phase-7-implementation.md new file mode 100644 index 0000000..88707ca --- /dev/null +++ b/c-work/3-validate/2026-04-gateway-i18n-phase-7-implementation.md @@ -0,0 +1,210 @@ + + + +# Gateway i18n — Phase 7: Konkreter Umsetzungsplan + +Dieses Dokument ist der **ausfuehrbare Umsetzungsplan** fuer die in +`c-work/2-build/2026-04 gateway-i18n-unified.md` beschriebene **Phase 7** (RBAC-/Katalog-Labels, +Quick Actions, optional Phase 7b TextMultilingual-KI-Button). Es ergaenzt das Konzeptdokument um +Reihenfolge, Abhaengigkeiten, Dateien und Abnahmekriterien. + +--- + +## 1. Ziele + +| ID | Ziel | Messbar | +|----|------|---------| +| G1 | Alle **RBAC-relevanten** statischen Texte (DATA/RESOURCE-Katalog, optional Template-Rollenbeschreibung **de**) erscheinen im **xx-Basisset** und sind fuer **AI-Sync** / Admin-Sprachen abbildbar | Keys in `UiLanguageSet(xx).entries` mit `context` `rbac.*` | +| G2 | **Kein Bruch** von `TextMultilingual` in der DB (`Role.description` etc.); FormGenerator bleibt **multilingual**-kompatibel | Bestehende Formulare unveraendert nutzbar | +| G3 | **Quick Actions:** Uebersetzungen konsistent mit dem gewaehlten Ansatz (siehe Arbeitspaket C) | Sichtbar korrekte Sprache nach Wechsel | +| G4 | **Phase 7b:** Ein-Klick-Uebersetzung fuer **TextMultilingual**-Felder im Formular (optional eigenes Release) | Button fuellt Zielsprachen; Fehler/Loading klar | + +--- + +## 2. Nicht-Ziele (Scope-Ausschluss) + +- **Kein** Ersatz von `TextMultilingual` durch reine String-Keys in `datamodelRbac.Role` ohne Migrationskonzept. +- **Kein** vollstaendiges Umbauen aller Admin-UI-Tabellen auf `t()` fuer Katalog-Labels in einem Schritt (kann folgen, wenn G1 live ist). +- **Keine** Aenderung der **Bedeutung** von AccessRules oder RBAC-Resolution — nur Label-/i18n-Schicht. + +--- + +## 3. Abhaengigkeiten zwischen Arbeitspaketen + +```mermaid +flowchart LR + A[WP-A: _registerRbacLabels] --> B[WP-B: Admin-Zaehler / Doku] + A --> C[WP-C: Quick Actions] + D[WP-D: Phase 7b API] --> E[WP-E: FormGenerator Button] + A -.-> D +``` + +- **WP-A** ist **Grundlage** fuer xx-Set und AI-Workflows zu Katalog-Texten. +- **WP-C** (Quick Actions) kann **parallel** zu B starten, baut aber auf **gleicher** i18n-Policy auf; empfohlen: A zuerst merge-faehig. +- **WP-D/E** (Phase 7b) sind **unabhaengig** von A fuer die reine API, aber **sinnvoll** nach A, damit `_translateBatch`-Nutzung und Billing einheitlich dokumentiert sind. + +--- + +## 4. Arbeitspaket A — `_registerRbacLabels()` und Boot-Sync + +### A.1 Inhalt + +1. In `gateway/modules/shared/i18nRegistry.py` Funktion **`_registerRbacLabels()`** implementieren (falls noch nicht vorhanden): + - Alle Feature-Module mit `DATA_OBJECTS` / `RESOURCE_OBJECTS` durchlaufen (gleiche Modulliste wie bei `_registerFeatureUiLabels` oder erweitern). + - Pro Eintrag: `label` ist **Dict** → `key = label.get("de") or label.get("en")` (nicht-leer); `context`: + - `rbac.data` fuer DATA_OBJECTS + - `rbac.resource` fuer RESOURCE_OBJECTS + - Optional **System-`mainSystem`**: `DATA_OBJECTS` / `RESOURCE_OBJECTS` aus `modules/system/mainSystem.py` falls vorhanden. +2. **`TEMPLATE_ROLES[].description`:** nur **`de`**-Text als Key registrieren, `context` `rbac.role` (ein Key pro Rolle reicht fuer Admin-Uebersicht; Duplikat-Texte teilen sich dieselbe Key-Zeile — akzeptabel). +3. `_syncRegistryToDb()` um Aufruf **`_registerRbacLabels()`** nach `_registerFeatureUiLabels()` erweitern (Reihenfolge dokumentieren). +4. **Merge-Logik** (`routeI18n.py` / `xx`-Sync): sicherstellen, dass `context` `rbac.*` wie andere **Gateway**-Kontexte behandelt werden (nicht `ui` ueberschreiben). + +### A.2 Dateien (voraussichtlich) + +| Datei | Aenderung | +|-------|-----------| +| `gateway/modules/shared/i18nRegistry.py` | `_registerRbacLabels`, Aufruf in `_syncRegistryToDb` | +| `gateway/modules/system/mainSystem.py` | Nur falls DATA/RESOURCE dort noch nicht importiert werden — Scan | +| `gateway/modules/routes/routeI18n.py` | Nur falls Sync-Logik `rbac.*` explizit filtern muss — pruefen | + +### A.3 Abnahme + +- [x] Nach Gateway-Start: xx-Set enthaelt neue Eintraege mit `context` `rbac.data` / `rbac.resource` / `rbac.role` / `rbac.quickaction` (118 Keys). +- [x] Keine Regression: bestehende `ui`- und `api.*`-Keys unveraendert zaehlbar. +- [x] Log-Zeile: `i18n rbac labels: 118 new keys (rbac.* context)`. + +### A.4 Aufwand + +- **Klein** (ca. 0.5–1 Tag), wenn Modulliste und Dict-Extraktion zentral und getestet sind. + +--- + +## 5. Arbeitspaket B — Admin-Sprachen-UI und Doku + +### B.1 Inhalt + +1. **AdminLanguagesPage** (optional): Spalte oder Filter **„Kontext“** — `rbac.*` sichtbar (falls noch nicht generisch). +2. **Wiki:** `gateway-i18n-unified.md` — Verweis auf dieses Umsetzungsplan-Dokument; Status Phase 7 **in Arbeit** → **done** nach Merge. +3. **coding-conventions.md** (kurz): Regel „neue DATA/RESOURCE-Labels: `de`-Text als Basis-Key; `en`/`fr` im Dict fuer Legacy-Anzeige bis Migration“. + +### B.2 Abnahme + +- [x] Dokumentation ist verlinkt. +- [x] Kein Muss fuer UI-Spalte, wenn Tabelle bereits nach `context` filterbar ist. + +--- + +## 6. Arbeitspaket C — Quick Actions (Entscheidung + Umsetzung) + +### C.0 Entscheidung (vor Codieren) + +| Option | Beschreibung | Aufwand | +|--------|--------------|---------| +| **C1** | **Backend:** `de`-String aus Dict als Basis; Aufloesung in `getQuickActions` via **`t()`** / Cache (Request-Sprache) statt nur `language`-Dict-Lookup | Mittel | +| **C2** | **Backend** liefert nur **deutsche Keys**; **Frontend** `QuickActionBoard` nutzt `t(action.label)` / `t(action.description)` (wie Navigation) | Mittel | +| **C3** | **Status quo** belassen; nur **WP-A** registriert Keys — Admin kann Sprachen pflegen, **API** bleibt dict-basiert bis spaeter | Gering | + +**Empfehlung:** Zuerst **C3** mit A; **C1 oder C2** in einem **separaten** PR nach Product-Entscheidung. + +### C.1 Schritte fuer C1 (falls gewaehlt) + +1. `mainTrustee.py` (und ggf. andere Features): `QUICK_ACTIONS` / Kategorien auf **deutsche Basis-Strings** umstellen (analog UI_OBJECTS) **oder** Dict beibehalten und **zusaetzlich** `key`/`labelKey` einfuehren. +2. `routeFeatureTrustee.getQuickActions`: `_resolveText` ersetzen/ergaenzen durch **`t()`** aus `i18nRegistry` mit Request-Sprache. +3. Keys in `xx`/`_REGISTRY` via WP-A oder dedizierte Registrierung. + +### C.2 Abnahme + +- [x] Quick-Action-Labels und -Descriptions als `rbac.quickaction` Keys registriert (C3-Ansatz). +- [x] Keine doppelten Keys ohne `context`-Trennung (Composite-Key-Modell beachten). + +--- + +## 7. Arbeitspaket D — Phase 7b: API `translate-field` + +### D.1 Inhalt + +1. Neuer Endpoint in `gateway/modules/routes/routeI18n.py`, z. B.: + - `POST /api/i18n/translate-field` + - Body: `{ "sourceText": string, "sourceLang": string, "targetLangs": string[] }` + - Response: `{ "translations": { "de": "...", "fr": "..." } }` (ohne Source-Lang) +2. Intern: Wiederverwendung von **`_translateBatch`** mit einem kuenstlichen Key-Set (oder schlanker Helper), inkl. **`_matchCapitalization`**. +3. **Auth:** `Depends(getRequestContext)`; **Billing:** gleicher Callback wie bei `translate` Jobs. +4. **Rate-Limit** und **Payload-Groesse** (max. Zeichen) begrenzen. + +### D.2 Abnahme + +- [x] Nur authentifizierte Nutzer (`Depends(getCurrentUser)`). +- [x] Leerer `sourceText` → 422 (Pydantic `min_length=1`). +- [ ] Integrationstest oder manueller Test mit zwei Zielsprachen. + +### D.3 Aufwand + +- **Klein bis mittel** (ca. 1 Tag inkl. Tests). + +--- + +## 8. Arbeitspaket E — Phase 7b: FormGenerator Button + +### E.1 Inhalt + +1. `FormGeneratorForm.tsx` — `renderMultilingualField`: + - Button **„In alle Sprachen uebersetzen“** (Text via `t()`). + - **Quellsprache:** implementierte Regel festhalten (z. B. erste nicht-leere Sprache in `multilingualLangs`-Reihenfolge, sonst `en`). + - **Ziel:** alle anderen Codes aus `multilingualLangs` ohne Quelle. +2. `onClick`: `POST /api/i18n/translate-field`, dann `handleMultilingualChange` pro Ziel. +3. **UX:** Loading-Spinner, `disabled` waehrend Request, **Toast** bei Fehler. +4. Optional: Tooltip **Hinweis KI-Qualitaet**. + +### E.2 Abnahme + +- [x] Role-Formular (multilingual description): Button implementiert. +- [x] Readonly-Modus: kein Button (nur in Edit-/Create-Modus sichtbar). + +### E.3 Aufwand + +- **Mittel** (ca. 1–1.5 Tage inkl. Styling und Edge Cases). + +--- + +## 9. Testplan (Phase 7 gesamt) + +| Nr | Szenario | Erwartung | +|----|----------|-----------| +| T1 | Boot mit WP-A | xx-Set enthaelt `rbac.*` Eintraege | +| T2 | Admin: AI-Uebersetzung fuer ein `rbac.data`-Key | Wert in Zielsprache gesetzt | +| T3 | Quick Actions (nach C1/C2) | Texte passen zur UI-Sprache | +| T4 | Phase 7b: Button + leerer Source | Validation / keine KI-Call | +| T5 | Phase 7b: langer Text | Limit oder Chunking klar | + +--- + +## 10. Risiken und Rollback + +| Risiko | Massnahme | +|--------|-----------| +| Zu viele Keys in xx (Duplikate) | Composite-Key `(key, context)` bleibt Massstab; Dokumentation | +| KI-Kosten Phase 7b | Limits, Feature-Flag optional | +| Regression Boot-Sync | Feature-Flag `_registerRbacLabels` optional abschaltbar | + +Rollback: WP-A durch Entfernen des Aufrufs `_registerRbacLabels()` deaktivieren; keine DB-Schema-Aenderung fuer A. + +--- + +## 11. Reihenfolge-Empfehlung (Sprints) + +| Sprint | Inhalt | Deliverable | +|--------|--------|---------------| +| **S1** | WP-A + B (minimal) | Rbac-Keys im xx-Set, Doku-Link | +| **S2** | WP-C (nach Entscheidung C1/C2/C3) | Quick Actions Policy | +| **S3** | WP-D + E | Phase 7b fertig | + +--- + +## 12. Links + +- Konzept & Phase-7-Text: `c-work/2-build/2026-04 gateway-i18n-unified.md` +- i18n Registry: `gateway/modules/shared/i18nRegistry.py` +- i18n API: `gateway/modules/routes/routeI18n.py` +- Formular: `frontend_nyla/src/components/FormGenerator/FormGeneratorForm/FormGeneratorForm.tsx` + + diff --git a/c-work/3-validate/2026-04-generic-graph-editor.md b/c-work/3-validate/2026-04-generic-graph-editor.md index e9f9369..2a3ba90 100644 --- a/c-work/3-validate/2026-04-generic-graph-editor.md +++ b/c-work/3-validate/2026-04-generic-graph-editor.md @@ -1,5 +1,5 @@ - - + + # Typed Node Handover System — Spezifikation & Execution Plan diff --git a/d-guides/coding-conventions.md b/d-guides/coding-conventions.md index 6c1f3d5..8d9f026 100644 --- a/d-guides/coding-conventions.md +++ b/d-guides/coding-conventions.md @@ -1,4 +1,4 @@ - doku nachgeführt werden an + # Coding-Konventionen @@ -48,6 +48,73 @@ t('Offen (Status)') // vs. t('Offen (Zustand)') - Fehler propagieren -- Exceptions explizit werfen, nicht schlucken - Config ueber `APP_CONFIG` (aus `modules/shared/configuration.py`) +### i18n-Pflicht: `t()` fuer alle UI-sichtbaren Gateway-Texte + +Jeder Text der im Frontend angezeigt wird (HTTPException-Details, API-Response-Messages, Erfolgs-/Fehlermeldungen) **muss** mit `t()` getaggt werden. + +```python +from modules.shared.i18nRegistry import t + +# Fehlermeldung (context automatisch = "api") +raise HTTPException(status_code=403, detail=t("Zugriff verweigert", "api.routeSecurity", + "Fehlermeldung bei fehlendem Zugriff")) + +# Erfolgsmeldung +return {"message": t("Datei erfolgreich hochgeladen", "api.routeFiles", + "Bestaetigung nach Datei-Upload")} +``` + +**Nicht** mit `t()` taggen: Log-Eintraege, AI-Prompts, interne technische Fehlermeldungen. + +Fuer Route-Module gibt es den Shorthand `apiRouteContext`: + +```python +from modules.shared.i18nRegistry import apiRouteContext +routeApiMsg = apiRouteContext("routeBilling") + +raise HTTPException(status_code=403, detail=routeApiMsg("Zugriff verweigert")) +``` + +### Pydantic-Models: `@i18nModel` Decorator Pflicht + +Jedes Pydantic-Model das im UI angezeigt wird (Tabellen, Formulare) **muss** den `@i18nModel` Decorator haben. Feld-Labels werden in `json_schema_extra["label"]` definiert. + +```python +from modules.shared.i18nRegistry import i18nModel + +@i18nModel("Benutzer") +class User(PowerOnModel): + name: str = Field( + description="Full name of the user", + json_schema_extra={"label": "Name", "frontend_type": "text"} + ) + email: str = Field( + description="Email address for login and notifications", + json_schema_extra={"label": "E-Mail-Adresse", "frontend_type": "text"} + ) +``` + +- `@i18nModel("Deutscher Modelname")` -- AI-Kontext kommt automatisch aus dem Class-Docstring +- `json_schema_extra={"label": "Deutscher Feldname"}` -- Pflicht fuer jedes UI-sichtbare Feld +- `Field(description=...)` -- wird als AI-Kontext fuer die Uebersetzung verwendet +- **Kein** `registerModelLabels()` mehr verwenden (entfernt) + +### Feature-Module: Labels als deutsche Basis-Strings + +Neue `DATA_OBJECTS`, `RESOURCE_OBJECTS` und `UI_OBJECTS` Labels verwenden **deutsche Klartext-Strings** als Basis-Key. Bestehende `{en, de, fr}`-Dicts werden beim Boot automatisch ueber `_registerRbacLabels()` registriert (Kontext `rbac.data`, `rbac.resource`, `rbac.role`, `rbac.quickaction`). Fuer **neue** Eintraege: `de`-Text als Basis-Key verwenden, `en`/`fr` im Dict fuer Legacy-Anzeige bis vollstaendige Migration. + +```python +DATA_OBJECTS = [ + { + "objectKey": "data.uam.UserInDB", + "label": {"en": "User", "de": "Benutzer", "fr": "Utilisateur"}, + "meta": {"table": "UserInDB", "namespace": "uam"} + }, +] +``` + +Die `de`-Texte erscheinen automatisch im xx-Basisset und koennen per AI uebersetzt werden. + ## Projektstruktur Gateway ```