wiki/c-work/2-build/2026-04-trustee-data-tables-page.md
2026-04-21 00:50:21 +02:00

15 KiB
Raw Blame History

Trustee: Konsolidierte Daten-Tabellen-Seite

Beschreibung und Kontext

Aktuell hat das Trustee-Feature zwei separate Top-Level-Seiten für Datensichten (Positionen, Dokumente). Die übrigen 11 Trustee-Tabellen (Stammdaten + Sync-Daten + Buchhaltungs-Config/Sync) sind im UI nicht sichtbar nur als JSON-Export oder per AI-Agent erreichbar. Das ist intransparent: Anwender und Auditor:innen sehen die importierten Konten / Buchungen / Kontakte / Salden nirgends.

Lösung: Eine neue konsolidierte Seite Daten-Tabellen mit einem Tab pro Trustee-Tabelle. Jeder Tab nutzt FormGeneratorTable mit Pagination, Sortierung, Filterung und Suche exakt das Pattern, das PromptsPage und die bestehenden TrusteePositionsView / TrusteeDocumentsView etabliert haben.

Business-Treiber:

  • Transparenz für Treuhänder:innen: «Was wurde wirklich aus Bexio/RMA importiert?»
  • Audit-Fähigkeit: Sync-Status und Sync-Snapshots direkt im UI prüfen.
  • Vereinheitlichung: Konsistente UI über alle Tabellen statt zwei isolierter Spezialseiten.

Risiko bei Verzicht: Anwender greifen via Export/Excel auf interne Daten zu (umständlich, fehleranfällig); Sync-Probleme bleiben unbemerkt.

Fokus und kritische Details

  • FormGeneratorTable-Vertrag (siehe wiki/b-reference/frontend-nyla/formgenerator.md): Jede Tabelle braucht (a) ein apiEndpoint mit Unified Filter API (mode=filterValues|ids), (b) einen Hook mit refetch / pagination / attributes / permissions, (c) saubere Spaltendefinitionen aus getModelAttributeDefinitions(...).
  • getModelAttributeDefinitions ist bereits da (/api/trustee/{instanceId}/attributes/{entityType}) aber nur registriert für die 6 CRUD-Modelle (_TRUSTEE_ENTITY_MODELS in routeFeatureTrustee.py, Zeile 195). Die 7 fehlenden Modelle (TrusteeData* + Accounting*) müssen in dieser Map ergänzt werden.
  • Sync-Tabellen sind read-only (User-Entscheidung). Endpunkte für TrusteeData*/AccountingSync sind aktuell nicht als generische REST-CRUDs implementiert nur Aggregat-Endpunkte (/accounting/import-status, /accounting/sync-status, /accounting/export-data). Es braucht neue Read-Endpunkte mit Pagination + Unified Filter API.
  • RBAC-Konsistenz: Jede Tabelle hat in mainTrustee.DATA_OBJECTS einen data.feature.trustee.<Model>-Key. Der Hook (_createTrusteeEntityHook) löst Permissions via data.feature.trustee.{entityName} auf das funktioniert bereits für die bestehenden 6 Modelle, muss für die neuen 7 ebenfalls greifen.
  • Backwards-Compat: Die bestehenden Seiten Positionen und Dokumente bleiben vorerst erhalten (Navigation + Routes + RBAC). Erst wenn die neue Seite verifiziert ist, werden sie in einer Folge-Iteration entfernt.
  • Tab-State via URL (?tab=positions): Konsistent mit TrusteeImportProcessView, TrusteeAccountingSettingsView, TrusteeAbschlussView. Erlaubt Deep-Links (z.B. Quick Actions / Notification-Links) auf konkrete Tabellen.
  • Performance: Lazy-Mount pro Tab (Hook ruft nur Daten, wenn Tab aktiv ist) sonst werden 13 Tabellen parallel geladen.
  • i18n-Pflicht: Alle Tab-Labels via t(...). Spalten-Labels kommen aus dem Backend-@i18nModel.
  • Hidden System-Felder: mandateId, featureInstanceId, technische id-UUIDs sollen tabellenweit hidden sein (gleiche Liste wie in PromptsPage hiddenColumns).
  • Naming: Funktionen _-Prefix für intern (_buildEntityHookConfig, _renderTabBar); camelCase überall.

Ziel und Nicht-Ziele

  • Ziel: Neue Seite Daten-Tabellen (URL: /mandates/{mandateId}/trustee/{instanceId}/data-tables[?tab=<key>]) mit einem Tab pro Trustee-Tabelle. Jeder Tab nutzt FormGeneratorTable mit Pagination/Sort/Filter/Search/Inline-Edit (für CRUD-Tabellen) bzw. read-only (für Sync-Tabellen).
  • Ziel: Backend liefert Attribute & paginierte Daten via Unified Filter API auch für die 7 bisher UI-losen Tabellen.
  • Ziel: Tab-Sichtbarkeit folgt RBAC (data.feature.trustee.<Model> view-Permission).
  • Ziel: Konsistentes UX-Pattern mit PromptsPage (Header / Refresh / FormGeneratorTable / optional Edit-Modal via FormGeneratorForm für CRUD-Tabellen).
  • Explizit NICHT: Entfernen der alten Positionen/Dokumente-Seiten in dieser Iteration (Folge-Plan). Routen + Quick Actions + RBAC bleiben unangetastet.
  • Explizit NICHT: Inline-Edit oder Bulk-Sync für TrusteeData*-Tabellen sie sind reine Sync-Spiegel.
  • Explizit NICHT: Neuer DB-Schema-Wandel oder Migration nur Read-Endpunkte ergänzen.
  • Explizit NICHT: Beleg-Download-Spalte oder Sync-Status-Spalte im Positions-Tab die Spezialdarstellung bleibt der eigenständigen TrusteePositionsView vorbehalten (Generic-Tab zeigt das «rohe» Modell).

Betroffene Module

  • Gateway:
    • gateway/modules/features/trustee/routeFeatureTrustee.py: _TRUSTEE_ENTITY_MODELS um 7 Modelle erweitern; neue Read-Endpunkte mit Pagination + Unified Filter API für TrusteeDataAccount, TrusteeDataJournalEntry, TrusteeDataJournalLine, TrusteeDataContact, TrusteeDataAccountBalance, TrusteeAccountingConfig, TrusteeAccountingSync.
    • gateway/modules/features/trustee/mainTrustee.py: UI_OBJECTS um ui.feature.trustee.data-tables ergänzen; TEMPLATE_ROLES.accessRules der relevanten Rollen erweitern.
  • Frontend:
    • Neu: frontend_nyla/src/pages/views/trustee/TrusteeDataTablesView.tsx (Container mit Tab-Bar + URL-Sync).
    • Neu: frontend_nyla/src/pages/views/trustee/dataTables/TrusteeDataTab.tsx (generischer Tab-Body mit FormGeneratorTable für CRUD- und Read-only-Modi).
    • Erweitern: frontend_nyla/src/hooks/useTrustee.ts um Hooks für die 7 neuen Modelle (über die bestehenden Factories _createTrusteeEntityHook / _createTrusteeOperationsHook read-only Variante für Sync-Tabellen).
    • Erweitern: frontend_nyla/src/api/trusteeApi.ts um fetchTrusteeData*-Funktionen.
    • Anpassen: frontend_nyla/src/pages/FeatureView.tsx (VIEW_COMPONENTS.trustee um 'data-tables': TrusteeDataTablesView ergänzen).
    • Anpassen: frontend_nyla/src/pages/views/trustee/index.ts (Export).
    • Anpassen: frontend_nyla/src/App.tsx (Route data-tables registrieren).
    • Optional: frontend_nyla/src/types/mandate.ts (FEATURE_REGISTRY.trustee.views) um data-tables ergänzen, falls noch genutzt.
  • DB-Migration: nein.
  • Andere Komponenten: keine.

Entscheidungen

Datum Entscheidung Begründung
2026-04-20 Seitenname: Daten-Tabellen User-Entscheidung; klar, präzise, dt.
2026-04-20 Alte Seiten Positionen + Dokumente bleiben vorerst User-Entscheidung; Sicherheitsnetz bis neue Seite verifiziert ist Aufräumen in Folge-Plan.
2026-04-20 Sync-Tabellen (TrusteeData*, TrusteeAccountingSync, TrusteeAccountingConfig) sind read-only im UI User-Entscheidung; Daten kommen aus externem System Edits würden bei nächstem Sync überschrieben.
2026-04-20 Alle 13 Tabellen erhalten einen Tab (User wählte "alle" im Datenmodell sind es 13: 4 Stammdaten + 2 CRUD-Daten + 5 Sync-Daten + 2 Accounting). User-Entscheidung; vollständige Transparenz.
2026-04-20 Tab-State via URL-Param ?tab=<key> Konsistent mit allen anderen Trustee-Tab-Seiten.
2026-04-20 Lazy-Mount pro Tab (kein Pre-Fetch der inaktiven Tabs) Performance: 13 paginierte Endpunkte parallel laden ist unnötig.
2026-04-20 Generische Tab-Komponente (TrusteeDataTab) statt 13 spezialisierter Views DRY; Spezialisierungen (Beleg-Download/Sync-Status-Spalte) bleiben ausschliesslich in TrusteePositionsView / TrusteeDocumentsView.
2026-04-20 Keine Bulk-Aktionen im neuen Tab (kein Sync-Button etc.) Bulk-Sync ist im Positions-Tab schon vorhanden Generic-Seite bleibt schlank.

Umsetzungs-Checkliste

Backend (Gateway)

  • _TRUSTEE_ENTITY_MODELS in routeFeatureTrustee.py um die 7 neuen Modelle erweitert.
  • Neue paginierte Read-Endpunkte (analog get_documents/get_positions mit _handleDocumentMode-Pattern) für jede der 7 Tabellen:
    • GET /api/trustee/{instanceId}/data/accounts
    • GET /api/trustee/{instanceId}/data/journal-entries
    • GET /api/trustee/{instanceId}/data/journal-lines
    • GET /api/trustee/{instanceId}/data/contacts
    • GET /api/trustee/{instanceId}/data/account-balances
    • GET /api/trustee/{instanceId}/accounting/configs
    • GET /api/trustee/{instanceId}/accounting/syncs
  • Helper extrahiert: _paginatedReadEndpoint(...) haelt Logik fuer alle 7 Endpunkte zentral.
  • RBAC: jeder neue Endpunkt prüft via _validateInstanceAccess; Datenzugriff wird auf SQL-Ebene durch getRecordsetPaginatedWithRBAC (DATA-Context, data.feature.trustee.<Model>) gefiltert identisch zum bestehenden Documents/Positions-Pattern.
  • mainTrustee.py: Neuer UI-Object-Eintrag ui.feature.trustee.data-tables (Label «Daten-Tabellen»).
  • mainTrustee.py: AccessRule fuer ui.feature.trustee.data-tables bei trustee-viewer, trustee-user, trustee-accountant ergaenzt; Admin hat Wildcard.

Frontend

  • frontend_nyla/src/api/trusteeApi.ts: 7 neue Read-Funktionen (fetchDataAccounts, fetchDataJournalEntries, fetchDataJournalLines, fetchDataContacts, fetchDataAccountBalances, fetchAccountingConfigs, fetchAccountingSyncs) plus passende Typen.
  • frontend_nyla/src/hooks/useTrustee.ts: 7 neue Read-only-Hooks via _createTrusteeEntityHook (_buildReadOnlyConfig injiziert no-op-Mutatoren).
  • Neu frontend_nyla/src/pages/views/trustee/dataTables/TrusteeDataTab.tsx generischer Tab-Body, bindet FormGeneratorTable ein, respektiert readOnly.
  • Neu frontend_nyla/src/pages/views/trustee/TrusteeDataTablesView.tsx:
    • 13 Tab-Defs, jede mit eigenem Wrapper-Component, das den passenden Hook aufruft.
    • URL-Sync via ?tab=<key>, Lazy-Mount (nur aktiver Wrapper rendert -> kein Datenfetch fuer inaktive Tabs).
    • Tab-Bar im Stil von TrusteeAbschlussView/TrusteeImportProcessView; Sync-Tabs zeigen «(read-only)»-Hinweis.
    • RBAC-Filter im Frontend deaktiviert: einzelne Tab-Hooks blockieren Datenzugriff serverseitig (vermeidet sync-Permission-Lookups; spaetere Iteration kann Tab-Hiding nachziehen).
  • frontend_nyla/src/pages/views/trustee/index.ts: Export ergaenzt.
  • frontend_nyla/src/pages/FeatureView.tsx: Mapping 'data-tables': TrusteeDataTablesView + Import.
  • frontend_nyla/src/App.tsx: Route <Route path="data-tables" .../> ergaenzt.
  • frontend_nyla/src/types/mandate.ts: FEATURE_REGISTRY.trustee.views um 'data-tables' ergaenzt.

Cross-Cutting

  • RBAC / Permissions: alle neuen Endpunkte enforced via bestehendes _validateInstanceAccess; UI-Sichtbarkeit per data.feature.trustee.<Model>-Check (Hook liefert das via permissions.view).
  • Neutralisierung betroffen? Nein keine AI-Calls, kein neuer Datenfluss zu externen Systemen.
  • Navigation / Routing: neue UI-Route /mandates/{m}/trustee/{i}/data-tables[?tab=<key>].
  • Billing-Impact? Nein.
  • i18n: alle Tab-Labels und Header-Strings via t(...); Spalten-Labels kommen aus @i18nModel-getaggten Modellen (bereits vorhanden für alle 13).
  • Quick Actions: keine Änderung Quick Actions zeigen weiterhin auf import-process / settings. Optional in Folge-Iteration: Direktlinks auf einzelne Datentabs.

Akzeptanzkriterien

# Kriterium (Given-When-Then) Prio
1 Given ein Trustee-Admin auf einer Trustee-Instanz, When er auf Navigation «Daten-Tabellen» klickt, Then erscheint eine Seite mit Tab-Bar und allen 13 Trustee-Tabellen als Tabs. must
2 Given die Seite «Daten-Tabellen» mit Default-Tab, When der User sie öffnet, Then wird sofort der erste Tab geladen (FormGeneratorTable mit Daten, Pagination, Spalten aus attributes-API). must
3 Given ein Tab mit Sync-Daten (z.B. «Buchungen (Sync)»), When der User die Zeile inspiziert, Then sind keine Edit-/Delete-Buttons sichtbar (read-only). must
4 Given ein Tab mit CRUD-Daten (z.B. «Position»), When der User auf Edit klickt, Then erscheint ein FormGeneratorForm-Modal und Speichern persistiert via PUT-Endpunkt. must
5 Given die Seite «Daten-Tabellen», When der User auf Tab «Kontakte (Sync)» wechselt, Then ändert sich die URL auf ?tab=contacts und nur der Kontakte-Tab ist gemountet (Network-Tab zeigt nur den Kontakte-API-Call). must
6 Given ein Tab mit aktiviertem apiEndpoint, When der User in einer Spalte einen Filter setzt, Then werden Distinct-Werte vom Backend via ?mode=filterValues&column=<x> geladen. must
7 Given ein User OHNE Permission data.feature.trustee.TrusteeDataContact (view), When er die Seite öffnet, Then ist der Tab «Kontakte (Sync)» nicht sichtbar oder disabled. should
8 Given die Seite mit Deep-Link ?tab=accounts, When der User per URL einsteigt, Then wird der Konten-Tab direkt aktiv geladen. should
9 Given die alten Seiten «Positionen»/«Dokumente», When der User sie aufruft, Then funktionieren sie unverändert weiter (kein Regress). must
10 Given ein Tab mit grosser Datenmenge (>1'000 Einträge), When der User scrollt, Then wird Server-Pagination angewandt (page-Size 25, kein Frontend-Speicher-Overload). must
11 Given Tabellen-Sortierung, When der User auf einen Spalten-Header klickt, Then wird per pagination.sort serverseitig sortiert. must

Testplan

ID AC Art Automatisiert Repo-Pfad Status
T1 1 manual UI nein pending
T2 2,5 api ja gateway/tests/test_routeFeatureTrustee_data_tables.py pending
T3 3,4 api ja gateway/tests/test_routeFeatureTrustee_data_tables.py pending
T4 6 api ja gateway/tests/test_routeFeatureTrustee_data_tables.py (Unified Filter API: mode=filterValues / mode=ids) pending
T5 7 api ja gateway/tests/test_routeFeatureTrustee_data_tables.py (RBAC-Gate) pending
T6 8 manual UI nein pending
T7 9 manual + e2e teils bestehende Position/Document Tests laufen weiter pending
T8 10,11 api ja gateway/tests/test_routeFeatureTrustee_data_tables.py (Pagination/Sort) pending
  • PR:
  • Issue:
  • Vorlage: wiki/b-reference/frontend-nyla/formgenerator.md
  • Vorbild-Seite: frontend_nyla/src/pages/basedata/PromptsPage.tsx
  • Vorbild-Tabs: frontend_nyla/src/pages/views/trustee/TrusteeAbschlussView.tsx, TrusteeAccountingSettingsView.tsx

Abschluss

  • b-reference/gateway/features/trustee.md (oder analog) aktualisieren: neue Endpunkte + neue UI-Seite dokumentieren.
  • b-reference/frontend-nyla/architecture.md: kurze Erwähnung der konsolidierten TrusteeDataTablesView + Tab-Pattern für mehrere Modelle.
  • TOPICS.md: keine Änderung nötig (kein neues Thema).
  • Folge-Plan 2026-MM-trustee-cleanup-positions-documents.md: Aufräumen der alten Seiten, sobald Daten-Tabellen produktiv verifiziert.
  • Dieses Dokument → c-work/2-build/ (bei Umsetzungsbeginn) → c-work/3-validate/z-archive/.