Darstellung
02 – Multi-Tenancy, Company & Settings
Reifegrad: 🟢 produktiv · Schicht: companies-Tabelle, src/app/settings/*, src/app/api/settings/*, @work7/storage
Zweck
Mandantentrennung (jeder Betrieb = eine company), Firmenstammdaten, Branding, Rechnungs-/ Steuer-Defaults und mandantenspezifische Integrations-/Storage-Einstellungen.
Tenancy-Modell
- Wurzel ist
companiesmit dem fachlichen Schlüsselcompany_id(VARCHAR, UNIQUE) – nicht der numerischenid. Nahezu jede Tabelle referenziertcompany_id. - Nutzer ↔ Firma über
users.company_idundmemberships(role,status,department_id,manager_id;UNIQUE (user_id, company_id)). - Tenancy wird serverseitig erzwungen:
requireSessionliefertcompanyId, Domain-Guards (requireTenantScope) verhindern Cross-Tenant-Zugriffe.
Firmenstammdaten (companies)
Sehr breite Tabelle – die wichtigsten Feldgruppen:
| Gruppe | Felder (Auswahl) |
|---|---|
| Identität | name, company_id, country_code (DE/AT…), legal_form, industry, founded_date |
| Adresse/Kontakt | street, postal_code, city, state, phone, fax_number, email, website |
| Recht/Steuer | vat_number, tax_number, commercial_register, commercial_register_court, company_seat, jurisdiction |
| Bank | iban, bic, bank_name |
| Branding | primary_color, secondary_color, footer_text, logo (BYTEA), logo_mime |
| Rechnungs-Defaults | invoice_number_format, quote_number_format, credit_number_format, payment_terms_default, default_vat_rate, default_tax_profile, cash_discount_percent/_days |
| E-Rechnung | einvoice_enabled, einvoice_format (XRechnung/…), reverse_charge_default |
| Bau-spezifisch | progress_billing_mode, retention_enabled/_rate/_cap/_release, cost_code_schema, cost_center_required |
| Mahnwesen | dunning_enabled, dunning_levels (JSONB) |
| Aufbewahrung | data_retention_years, audit_log_retention_days |
Settings-Oberfläche & APIs
UI: /settings (Stammdaten/Branding), /settings/integrations, /settings/leave.
| Endpoint | Funktion |
|---|---|
GET/PUT /api/settings/company | Firmenstammdaten lesen/ändern |
POST /api/settings/company/logo · GET /api/company/logo/[companyId] | Logo-Upload / Auslieferung |
/api/settings/storage/* | Mandanten-Storage (siehe unten + 13-integrationen-google-microsoft-storage) |
/api/leave/types, /api/invoices/labor-rates | weitere mandantenweite Konfiguration |
Mandanten-Storage (@work7/storage)
Pro Tenant konfigurierbarer Dokumentenspeicher; Default Azure Blob, optional OAuth-Provider.
- Tabellen (Migration 034
tenant_storage):tenant_storage_settings(primary_provider∈ {sharepoint, google_drive, dropbox, nextcloud, azure_blob},status),tenant_storage_oauth_credentials(Tokens verschlüsselt,@work7/storage/crypto),document_storage_mappings(Dokument ↔ externe Datei). - Flow:
POST /api/settings/storage/setup→connect/[provider]/start(PKCE-OAuth) →callback→test→connections. Migration vorhandener Dateien:POST /api/settings/storage/migration/start. - Implementierung:
service.ts,router.ts,providers/{azure,external,folder-bootstrap}.ts,graph-sharepoint.ts,oauth.ts,pkce.ts,crypto.ts,audit.ts,workspace.ts(Pfad-Helpers). - Bootstrap-Skript:
scripts/bootstrap-tenant-storage.ts,scripts/check-storage-providers.ts. - Einheitliche Ordnerstruktur unter
{company_id}/work7-app/(Anfragen, Projekte, System) — Details und Zuordnungstabelle in 13-integrationen-google-microsoft-storage.
Geschäftsregeln
- Auto-Nummerierung pro Mandant über Counter-Tabellen:
customer_counters,invoice_counters(per Jahr), Triggerset_customer_number. - Branding (Logo/Farben/Footer) fließt in PDF-Templates ein (siehe 18-pdf-print-templates).
- E-Rechnungs-/Steuer-Defaults steuern Rechnungs- und Export-Logik (siehe 10-rechnungen-e-rechnung).
Bekannte Befunde / offene Punkte
- ⚠️ Doppelte Migrationsnummer 034:
034_customer_position.sqlund034_tenant_storage.sqlexistieren parallel. Funktioniert (idempotent), ist aber sauber zu deduplizieren/umzunummerieren. logoals BYTEA in der DB (kein Blob-Storage) – pragmatisch, aber DB-lastig.- Storage-Provider außer Azure Blob sind als Beta einzustufen (OAuth-Pfad vorhanden, Reife je Provider unterschiedlich).