diff --git a/src/api/trusteeApi.ts b/src/api/trusteeApi.ts index a95c2ad..82aeb41 100644 --- a/src/api/trusteeApi.ts +++ b/src/api/trusteeApi.ts @@ -80,8 +80,7 @@ export interface TrusteeDocument { export interface TrusteePosition { id: string; - organisationId: string; - contractId: string; + documentId?: string; valuta?: string; transactionDateTime?: number; company: string; @@ -93,6 +92,11 @@ export interface TrusteePosition { originalAmount: number; vatPercentage: number; vatAmount: number; + debitAccountNumber?: string; + creditAccountNumber?: string; + taxCode?: string; + costCenter?: string; + bookingReference?: string; mandateId?: string; _createdAt?: number; _modifiedAt?: number; @@ -101,18 +105,39 @@ export interface TrusteePosition { [key: string]: any; } -export interface TrusteePositionDocument { +export interface AccountingConnectorInfo { + connectorType: string; + label: Record; + configFields: Array<{ + key: string; + label: Record; + fieldType: string; + secret: boolean; + required: boolean; + placeholder?: string; + }>; +} + +export interface AccountingConfig { + configured: boolean; + id?: string; + connectorType?: string; + displayLabel?: string; + isActive?: boolean; + lastSyncAt?: number; + lastSyncStatus?: string; + /** Masked config for form prefill: secret fields are "***", others have saved values. */ + configMasked?: Record; +} + +export interface AccountingSyncStatus { id: string; - organisationId: string; - contractId: string; - documentId: string; positionId: string; - mandateId?: string; - _createdAt?: number; - _modifiedAt?: number; - _createdBy?: string; - _modifiedBy?: string; - [key: string]: any; + connectorType: string; + externalId?: string; + syncStatus: string; + syncedAt?: number; + errorMessage?: string; } export interface PaginationParams { @@ -660,91 +685,89 @@ export async function deletePosition( } // ============================================================================ -// POSITION-DOCUMENT API +// ACCOUNTING API // ============================================================================ -export async function fetchPositionDocuments( +export async function fetchAccountingConnectors( request: ApiRequestFunction, - instanceId: string, - params?: PaginationParams -): Promise | TrusteePositionDocument[]> { + instanceId: string +): Promise { return await request({ - url: `${_getTrusteeBaseUrl(instanceId)}/position-documents`, - method: 'get', - params: _buildPaginationParams(params) - }); -} - -export async function fetchPositionDocumentById( - request: ApiRequestFunction, - instanceId: string, - linkId: string -): Promise { - try { - return await request({ - url: `${_getTrusteeBaseUrl(instanceId)}/position-documents/${linkId}`, - method: 'get' - }); - } catch (error: any) { - console.error('Error fetching position-document link by ID:', error); - return null; - } -} - -export async function fetchDocumentsForPosition( - request: ApiRequestFunction, - instanceId: string, - positionId: string -): Promise { - return await request({ - url: `${_getTrusteeBaseUrl(instanceId)}/position-documents/position/${positionId}`, + url: `${_getTrusteeBaseUrl(instanceId)}/accounting/connectors`, method: 'get' }); } -export async function fetchPositionsForDocument( +export async function fetchAccountingConfig( request: ApiRequestFunction, - instanceId: string, - documentId: string -): Promise { + instanceId: string +): Promise { return await request({ - url: `${_getTrusteeBaseUrl(instanceId)}/position-documents/document/${documentId}`, + url: `${_getTrusteeBaseUrl(instanceId)}/accounting/config`, method: 'get' }); } -export async function createPositionDocument( +export async function saveAccountingConfig( request: ApiRequestFunction, instanceId: string, - data: Partial -): Promise { + data: { connectorType: string; displayLabel: string; config: Record } +): Promise { return await request({ - url: `${_getTrusteeBaseUrl(instanceId)}/position-documents`, + url: `${_getTrusteeBaseUrl(instanceId)}/accounting/config`, method: 'post', data }); } -export async function updatePositionDocument( +export async function deleteAccountingConfig( request: ApiRequestFunction, - instanceId: string, - linkId: string, - data: Partial -): Promise { - return await request({ - url: `${_getTrusteeBaseUrl(instanceId)}/position-documents/${linkId}`, - method: 'put', - data - }); -} - -export async function deletePositionDocument( - request: ApiRequestFunction, - instanceId: string, - linkId: string + instanceId: string ): Promise { await request({ - url: `${_getTrusteeBaseUrl(instanceId)}/position-documents/${linkId}`, + url: `${_getTrusteeBaseUrl(instanceId)}/accounting/config`, method: 'delete' }); } + +export async function testAccountingConnection( + request: ApiRequestFunction, + instanceId: string +): Promise<{ success: boolean; errorMessage?: string }> { + return await request({ + url: `${_getTrusteeBaseUrl(instanceId)}/accounting/test-connection`, + method: 'post' + }); +} + +export async function fetchChartOfAccounts( + request: ApiRequestFunction, + instanceId: string +): Promise> { + return await request({ + url: `${_getTrusteeBaseUrl(instanceId)}/accounting/chart-of-accounts`, + method: 'get' + }); +} + +export async function syncPositionsToAccounting( + request: ApiRequestFunction, + instanceId: string, + positionIds: string[] +): Promise<{ total: number; success: number; errors: number; results: any[] }> { + return await request({ + url: `${_getTrusteeBaseUrl(instanceId)}/accounting/sync`, + method: 'post', + data: { positionIds } + }); +} + +export async function fetchSyncStatus( + request: ApiRequestFunction, + instanceId: string +): Promise<{ items: AccountingSyncStatus[] }> { + return await request({ + url: `${_getTrusteeBaseUrl(instanceId)}/accounting/sync-status`, + method: 'get' + }); +} diff --git a/src/config/pageRegistry.tsx b/src/config/pageRegistry.tsx index 487f248..35ccc0e 100644 --- a/src/config/pageRegistry.tsx +++ b/src/config/pageRegistry.tsx @@ -75,9 +75,9 @@ export const PAGE_ICONS: Record = { 'page.feature.trustee.dashboard': , 'page.feature.trustee.positions': , 'page.feature.trustee.documents': , - 'page.feature.trustee.position-documents': , 'page.feature.trustee.expense-import': , 'page.feature.trustee.instance-roles': , + 'page.feature.trustee.settings': , // Feature pages - Real Estate 'page.feature.realestate.projects': , diff --git a/src/hooks/useTrustee.ts b/src/hooks/useTrustee.ts index edf2422..3a993e2 100644 --- a/src/hooks/useTrustee.ts +++ b/src/hooks/useTrustee.ts @@ -18,7 +18,6 @@ import { type TrusteeContract, type TrusteeDocument, type TrusteePosition, - type TrusteePositionDocument, type PaginationParams, // Organisation API fetchOrganisations as fetchOrganisationsApi, @@ -56,14 +55,8 @@ import { createPosition as createPositionApi, updatePosition as updatePositionApi, deletePosition as deletePositionApi, - // Position-Document API - fetchPositionDocuments as fetchPositionDocumentsApi, - createPositionDocument as createPositionDocumentApi, - updatePositionDocument as updatePositionDocumentApi, - deletePositionDocument as deletePositionDocumentApi, } from '../api/trusteeApi'; -// Re-export types export type { TrusteeOrganisation, TrusteeRole, @@ -71,7 +64,6 @@ export type { TrusteeContract, TrusteeDocument, TrusteePosition, - TrusteePositionDocument, PaginationParams }; @@ -586,18 +578,3 @@ const positionConfig: TrusteeEntityConfig = { export const useTrusteePositions = _createTrusteeEntityHook(positionConfig); export const useTrusteePositionOperations = _createTrusteeOperationsHook(positionConfig); -// ============================================================================ -// POSITION-DOCUMENT HOOKS -// ============================================================================ - -const positionDocumentConfig: TrusteeEntityConfig = { - entityName: 'TrusteePositionDocument', - fetchAll: fetchPositionDocumentsApi, - fetchById: async () => null, - create: createPositionDocumentApi, - update: updatePositionDocumentApi, - deleteItem: deletePositionDocumentApi -}; - -export const useTrusteePositionDocuments = _createTrusteeEntityHook(positionDocumentConfig); -export const useTrusteePositionDocumentOperations = _createTrusteeOperationsHook(positionDocumentConfig); diff --git a/src/pages/FeatureView.tsx b/src/pages/FeatureView.tsx index f3686fc..7afe1b4 100644 --- a/src/pages/FeatureView.tsx +++ b/src/pages/FeatureView.tsx @@ -14,10 +14,10 @@ import { getLabel, FEATURE_REGISTRY } from '../types/mandate'; // Note: TrusteeOrganisationsView and TrusteeContractsView removed - Feature-Instanz = Organisation import { TrusteeDocumentsView } from './views/trustee/TrusteeDocumentsView'; import { TrusteePositionsView } from './views/trustee/TrusteePositionsView'; -import { TrusteePositionDocumentsView } from './views/trustee/TrusteePositionDocumentsView'; import { TrusteeDashboardView } from './views/trustee/TrusteeDashboardView'; import { TrusteeInstanceRolesView } from './views/trustee/TrusteeInstanceRolesView'; import { TrusteeExpenseImportView } from './views/trustee/TrusteeExpenseImportView'; +import { TrusteeAccountingSettingsView } from './views/trustee/TrusteeAccountingSettingsView'; // Chatbot Views import { ChatbotConversationsView } from './views/chatbot/ChatbotConversationsView'; @@ -95,9 +95,9 @@ const VIEW_COMPONENTS: Record> = { dashboard: TrusteeDashboardView, documents: TrusteeDocumentsView, positions: TrusteePositionsView, - 'position-documents': TrusteePositionDocumentsView, 'instance-roles': TrusteeInstanceRolesView, 'expense-import': TrusteeExpenseImportView, + settings: TrusteeAccountingSettingsView, }, chatworkflow: { dashboard: ChatworkflowDashboard, diff --git a/src/pages/views/trustee/TrusteeAccountingSettingsView.tsx b/src/pages/views/trustee/TrusteeAccountingSettingsView.tsx new file mode 100644 index 0000000..29797cb --- /dev/null +++ b/src/pages/views/trustee/TrusteeAccountingSettingsView.tsx @@ -0,0 +1,269 @@ +/** + * TrusteeAccountingSettingsView + * + * Settings page for configuring the accounting system integration. + * Allows selecting a connector (RMA, Bexio, Abacus), entering credentials, + * testing the connection, and removing the integration. + */ + +import React, { useState, useEffect, useCallback } from 'react'; +import { useCurrentInstance } from '../../../hooks/useCurrentInstance'; +import { useApiRequest } from '../../../hooks/useApi'; +import { useToast } from '../../../contexts/ToastContext'; +import { + fetchAccountingConnectors, + fetchAccountingConfig, + saveAccountingConfig, + deleteAccountingConfig, + testAccountingConnection, + type AccountingConnectorInfo, + type AccountingConfig, +} from '../../../api/trusteeApi'; +import styles from './TrusteeViews.module.css'; + +export const TrusteeAccountingSettingsView: React.FC = () => { + const { instanceId } = useCurrentInstance(); + const { request } = useApiRequest(); + const { showSuccess, showError } = useToast(); + + const [connectors, setConnectors] = useState([]); + const [existingConfig, setExistingConfig] = useState(null); + const [selectedType, setSelectedType] = useState(''); + const [displayLabel, setDisplayLabel] = useState(''); + const [configValues, setConfigValues] = useState>({}); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [testing, setTesting] = useState(false); + const [testResult, setTestResult] = useState<{ success: boolean; message?: string } | null>(null); + + const loadData = useCallback(async () => { + if (!instanceId) return; + setLoading(true); + try { + const [availableConnectors, config] = await Promise.all([ + fetchAccountingConnectors(request, instanceId), + fetchAccountingConfig(request, instanceId), + ]); + setConnectors(availableConnectors || []); + setExistingConfig(config); + if (config?.configured && config.connectorType) { + setSelectedType(config.connectorType); + setDisplayLabel(config.displayLabel || ''); + if (config.configMasked && typeof config.configMasked === 'object') { + setConfigValues(config.configMasked as Record); + } + } + } catch (err: any) { + console.error('Failed to load accounting settings:', err); + } finally { + setLoading(false); + } + }, [instanceId, request]); + + useEffect(() => { + loadData(); + }, [loadData]); + + const _getSelectedConnector = (): AccountingConnectorInfo | undefined => { + return connectors.find(c => c.connectorType === selectedType); + }; + + const handleTypeChange = (newType: string) => { + setSelectedType(newType); + setConfigValues({}); + setTestResult(null); + }; + + const handleConfigChange = (key: string, value: string) => { + setConfigValues(prev => ({ ...prev, [key]: value })); + }; + + const handleSave = async () => { + if (!instanceId || !selectedType) return; + setSaving(true); + try { + await saveAccountingConfig(request, instanceId, { + connectorType: selectedType, + displayLabel, + config: configValues, + }); + showSuccess('Saved', 'Accounting configuration saved successfully.'); + await loadData(); + } catch (err: any) { + showError('Error', err.response?.data?.detail || err.message || 'Failed to save configuration.'); + } finally { + setSaving(false); + } + }; + + const handleTestConnection = async () => { + if (!instanceId) return; + setTesting(true); + setTestResult(null); + try { + const result = await testAccountingConnection(request, instanceId); + setTestResult({ success: result.success, message: result.errorMessage }); + if (result.success) { + showSuccess('Connection OK', 'Successfully connected to the accounting system.'); + } else { + showError('Connection Failed', result.errorMessage || 'Could not connect.'); + } + } catch (err: any) { + const msg = err.response?.data?.detail || err.message || 'Connection test failed.'; + setTestResult({ success: false, message: msg }); + showError('Error', msg); + } finally { + setTesting(false); + } + }; + + const handleRemove = async () => { + if (!instanceId) return; + if (!window.confirm('Remove the accounting integration? This does not delete synced data.')) return; + setSaving(true); + try { + await deleteAccountingConfig(request, instanceId); + showSuccess('Removed', 'Accounting integration removed.'); + setSelectedType(''); + setDisplayLabel(''); + setConfigValues({}); + setTestResult(null); + await loadData(); + } catch (err: any) { + showError('Error', err.message || 'Failed to remove configuration.'); + } finally { + setSaving(false); + } + }; + + const selectedConnector = _getSelectedConnector(); + + if (loading) { + return
Loading accounting settings...
; + } + + return ( +
+
+

Accounting System Integration

+

+ Connect an accounting system to automatically sync bookings from this Trustee instance. +

+ + {existingConfig?.configured && ( +
+ Connected: {existingConfig.displayLabel || existingConfig.connectorType} + {existingConfig.lastSyncStatus && ( + <> — Last sync: {existingConfig.lastSyncStatus} + )} +
+ )} + + {/* Step 1: Select system */} +
+
1
+
+

Accounting System

+ +
+
+ + {/* Step 2: Credentials */} + {selectedConnector && ( +
+
2
+
+

Credentials

+
+
+ + setDisplayLabel(e.target.value)} + placeholder="e.g. Run My Accounts - Muster AG" + /> +
+ {selectedConnector.configFields.map(field => ( +
+ + handleConfigChange(field.key, e.target.value)} + placeholder={field.placeholder || ''} + autoComplete={field.secret ? 'new-password' : 'off'} + /> +
+ ))} +
+
+
+ )} + + {/* Step 3: Save & Test */} + {selectedConnector && ( +
+
3
+
+

Save & Test

+ {testResult && ( +
+ {testResult.success ? 'Connection successful!' : `Connection failed: ${testResult.message || 'Unknown error'}`} +
+ )} +
+ + {existingConfig?.configured && ( + + )} + {existingConfig?.configured && ( + + )} +
+
+
+ )} +
+
+ ); +}; + +export default TrusteeAccountingSettingsView; diff --git a/src/pages/views/trustee/TrusteeDashboardView.tsx b/src/pages/views/trustee/TrusteeDashboardView.tsx index af8a966..dd12b74 100644 --- a/src/pages/views/trustee/TrusteeDashboardView.tsx +++ b/src/pages/views/trustee/TrusteeDashboardView.tsx @@ -1,27 +1,54 @@ /** * TrusteeDashboardView * - * Übersicht/Dashboard für eine Trustee-Instanz. - * Zeigt Statistiken über Positionen, Dokumente und Verknüpfungen. + * Overview dashboard for a Trustee instance. + * Shows statistics about positions, documents, and accounting sync status. */ -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { useCurrentInstance } from '../../../hooks/useCurrentInstance'; -import { useTrusteePositions, useTrusteeDocuments, useTrusteePositionDocuments } from '../../../hooks/useTrustee'; +import { useTrusteePositions, useTrusteeDocuments } from '../../../hooks/useTrustee'; +import { useApiRequest } from '../../../hooks/useApi'; +import { fetchAccountingConfig, fetchSyncStatus, type AccountingConfig, type AccountingSyncStatus } from '../../../api/trusteeApi'; import styles from './TrusteeViews.module.css'; export const TrusteeDashboardView: React.FC = () => { - const { instance } = useCurrentInstance(); + const { instance, instanceId } = useCurrentInstance(); const { items: positions, loading: posLoading } = useTrusteePositions(); const { items: documents, loading: docsLoading } = useTrusteeDocuments(); - const { items: links, loading: linksLoading } = useTrusteePositionDocuments(); + const { request } = useApiRequest(); - const isLoading = posLoading || docsLoading || linksLoading; + const [accountingConfig, setAccountingConfig] = useState(null); + const [syncItems, setSyncItems] = useState([]); + const [accountingLoading, setAccountingLoading] = useState(true); + + useEffect(() => { + if (!instanceId) return; + const loadAccountingData = async () => { + setAccountingLoading(true); + try { + const [config, syncData] = await Promise.all([ + fetchAccountingConfig(request, instanceId), + fetchSyncStatus(request, instanceId), + ]); + setAccountingConfig(config); + setSyncItems(syncData?.items || []); + } catch { + // Accounting not configured is fine + } finally { + setAccountingLoading(false); + } + }; + loadAccountingData(); + }, [instanceId, request]); + + const isLoading = posLoading || docsLoading || accountingLoading; + const syncedCount = syncItems.filter(s => s.syncStatus === 'synced').length; + const syncErrorCount = syncItems.filter(s => s.syncStatus === 'error').length; return (
- {/* Positionen Card */}
📊
@@ -32,7 +59,6 @@ export const TrusteeDashboardView: React.FC = () => {
- {/* Dokumente Card */}
📄
@@ -43,24 +69,28 @@ export const TrusteeDashboardView: React.FC = () => {
- {/* Verknüpfungen Card */}
-
🔗
+
+ {accountingConfig?.configured ? '✓' : '○'} +
-
- {isLoading ? '...' : links.length} +
+ {isLoading ? '...' : ( + accountingConfig?.configured + ? <>{syncedCount} synced{syncErrorCount > 0 && / {syncErrorCount} errors} + : 'Not configured' + )}
-
Zuordnungen
+
Buchhaltung
- - {/* Rollen Card */} +
👤
{instance?.userRoles?.length ? ( - instance.userRoles.map((role, idx) => ( + instance.userRoles.map((role: string, idx: number) => (
{role}
)) ) : '-'} @@ -72,7 +102,6 @@ export const TrusteeDashboardView: React.FC = () => {
- {/* Info-Bereich */}

Instanz-Details

@@ -84,6 +113,15 @@ export const TrusteeDashboardView: React.FC = () => { Mandant: {instance?.mandateName}
+ {accountingConfig?.configured && ( +
+ Buchhaltungssystem: + + {accountingConfig.displayLabel || accountingConfig.connectorType} + {accountingConfig.lastSyncStatus && ` (${accountingConfig.lastSyncStatus})`} + +
+ )}
diff --git a/src/pages/views/trustee/TrusteeExpenseImportView.tsx b/src/pages/views/trustee/TrusteeExpenseImportView.tsx index 2ec1fdc..506d6ec 100644 --- a/src/pages/views/trustee/TrusteeExpenseImportView.tsx +++ b/src/pages/views/trustee/TrusteeExpenseImportView.tsx @@ -14,7 +14,7 @@ import api from '../../../api'; import styles from './TrusteeViews.module.css'; // Default extraction prompt (from automation template) -const DEFAULT_EXTRACTION_PROMPT = `Du bist ein Spezialist für die Extraktion von Spesendaten aus PDF-Dokumenten. +const DEFAULT_EXTRACTION_PROMPT = `Du bist ein Spezialist für die Extraktion von Spesendaten aus PDF-Dokumenten und deren buchhalterische Kontierung. AUFGABE: Extrahiere alle Speseneinträge aus dem bereitgestellten PDF-Dokument und gib sie im CSV-Format zurück. @@ -26,9 +26,10 @@ WICHTIGE REGELN: 4. Feld "company" enthält den Lieferanten/Verkäufer der Buchung 5. Tags müssen aus dieser Liste gewählt werden: customer, meeting, license, subscription, fuel, food, material - Mehrere zutreffende Tags mit Komma trennen +6. Buchhalterische Kontierung: Schlage Soll-/Haben-Kontonummern vor basierend auf Schweizer Kontenrahmen (KMU) CSV-SPALTEN (in dieser Reihenfolge): -valuta,transactionDateTime,company,desc,tags,bookingCurrency,bookingAmount,originalCurrency,originalAmount,vatPercentage,vatAmount +valuta,transactionDateTime,company,desc,tags,bookingCurrency,bookingAmount,originalCurrency,originalAmount,vatPercentage,vatAmount,debitAccountNumber,creditAccountNumber,taxCode,costCenter,bookingReference DATENFORMAT: - valuta: YYYY-MM-DD (Valutadatum) @@ -42,6 +43,21 @@ DATENFORMAT: - originalAmount: Original-Betrag als Dezimalzahl - vatPercentage: MwSt-Prozentsatz (z.B. 8.1 für 8.1%) - vatAmount: MwSt-Betrag als Dezimalzahl +- debitAccountNumber: Soll-Konto (Aufwandkonto, z.B. 4200=Materialaufwand, 4400=Büromaterial, 6000=Mietaufwand, 6500=Reisespesen) +- creditAccountNumber: Haben-Konto (z.B. 1020=Durchlaufkonto, 1000=Kasse, 1100=Debitoren) +- taxCode: Steuercode falls erkennbar (z.B. VM77=Vorsteuer 7.7%, VM81=Vorsteuer 8.1%) +- costCenter: Kostenstelle falls erkennbar (leer lassen wenn unbekannt) +- bookingReference: Belegnummer/Rechnungsnummer vom Dokument + +KONTIERUNGSREGELN (Schweizer Kontenrahmen KMU): +- Spesenbelege: Soll=Aufwandkonto (4xxx-6xxx), Haben=1020 (Durchlaufkonto) +- Materialkosten: Soll=4200, Haben=1020 +- Büromaterial: Soll=4400, Haben=1020 +- Reisespesen/Transport: Soll=6500, Haben=1020 +- Verpflegung: Soll=6510, Haben=1020 +- Lizenzen/Abos: Soll=6800, Haben=1020 +- Treibstoff: Soll=6200, Haben=1020 +- Wenn unsicher: debitAccountNumber und creditAccountNumber leer lassen HINWEISE: - Wenn nur ein MwSt-Satz vorhanden ist, einen Datensatz erstellen diff --git a/src/pages/views/trustee/TrusteePositionsView.tsx b/src/pages/views/trustee/TrusteePositionsView.tsx index 3c5adc4..c2594e9 100644 --- a/src/pages/views/trustee/TrusteePositionsView.tsx +++ b/src/pages/views/trustee/TrusteePositionsView.tsx @@ -49,8 +49,8 @@ export const TrusteePositionsView: React.FC = () => { } }, [instanceId]); - // Hidden columns (not shown in table view, but available in form) - const hiddenColumns = ['desc', 'featureInstanceId', 'mandateId']; + // Hidden columns (not shown in table view, but available in edit form) + const hiddenColumns = ['desc', 'featureInstanceId', 'mandateId', 'taxCode', 'costCenter']; // Generate columns from attributes + add system columns const columns = useMemo(() => { diff --git a/src/pages/views/trustee/index.ts b/src/pages/views/trustee/index.ts index 753e993..5d0583f 100644 --- a/src/pages/views/trustee/index.ts +++ b/src/pages/views/trustee/index.ts @@ -1,13 +1,10 @@ /** * Trustee Views Export - * - * Note: TrusteeOrganisationsView, TrusteeContractsView, TrusteeRolesView, TrusteeAccessView - * wurden entfernt - Feature-Instanz = Organisation */ export { TrusteeDashboardView } from './TrusteeDashboardView'; export { TrusteeDocumentsView } from './TrusteeDocumentsView'; export { TrusteePositionsView } from './TrusteePositionsView'; -export { TrusteePositionDocumentsView } from './TrusteePositionDocumentsView'; export { TrusteeInstanceRolesView } from './TrusteeInstanceRolesView'; export { TrusteeExpenseImportView } from './TrusteeExpenseImportView'; +export { TrusteeAccountingSettingsView } from './TrusteeAccountingSettingsView';