Skip to main content

Datenbank-Schema - Backoffice & CRM (Phase 2)

PostgreSQL-Datenbankstruktur für WorkmateOS Phase 2


Übersicht

Die Backoffice-Datenbank umfasst zwei Hauptbereiche:

  1. Core-Tabellen: Grundlegende Entitäten (Mitarbeiter, Abteilungen, Rollen, etc.)
  2. CRM & Backoffice-Tabellen: Kundenverwaltung, Projekte, Zeiterfassung, Finanzen

📊 Entity Relationship Diagram

Visuelle Darstellung

Backoffice Database Schema

Vollständiges ERD mit allen Tabellen und Beziehungen

Backoffice Module Architecture

Modul-Architektur und Datenfluss


🗄️ Core-Tabellen

employees (Mitarbeiter)

Beschreibung: Mitarbeiterstammdaten mit Rollen- und Abteilungszuordnung

SpalteTypBeschreibung
iduuidPrimary Key
firstnamevarcharVorname
lastnamevarcharNachname
emailvarcharE-Mail-Adresse
role_iduuidForeign Key → roles.id
department_iduuidForeign Key → departments.id
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Relationen:

  • role_idroles.id (Many-to-One)
  • department_iddepartments.id (Many-to-One)
  • Rückverweise: time_entries, chat_messages, dashboards, reminders, documents

departments (Abteilungen)

Beschreibung: Organisationsstruktur mit Abteilungen und Managern

SpalteTypBeschreibung
iduuidPrimary Key
namevarcharAbteilungsname
manager_iduuidForeign Key → employees.id
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Relationen:

  • manager_idemployees.id (Many-to-One)
  • Rückverweise: employees, projects

roles (Rollen & Berechtigungen)

Beschreibung: Rollen mit JSON-basiertem Berechtigungssystem

SpalteTypBeschreibung
iduuidPrimary Key
namevarcharRollenname (z.B. "Admin", "Manager")
permissionsjsonbBerechtigungen als JSON
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Beispiel permissions JSON:

{
"crm": ["read", "write", "delete"],
"projects": ["read", "write"],
"invoices": ["read"],
"admin_panel": ["access"]
}

Relationen:

  • Rückverweise: employees

documents (Dokumentenverwaltung)

Beschreibung: Zentrale Dokumentenverwaltung mit polymorpher Verknüpfung

SpalteTypBeschreibung
iduuidPrimary Key
titlevarcharDokumenttitel
file_pathtextDateipfad auf Server
typevarcharDateityp (pdf, docx, xlsx, etc.)
categoryvarcharKategorie (contract, invoice, report)
owner_iduuidForeign Key → employees.id
linked_modulevarcharModulname (customer, project, invoice)
linked_iduuidID des verknüpften Objekts
checksumvarcharSHA256-Prüfsumme
is_confidentialbooleanVertraulich?
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Polymorphe Verknüpfung:

  • linked_module + linked_id ermöglichen flexible Zuordnung zu beliebigen Entities
  • Beispiel: linked_module = "customer", linked_id = "123-456-789" → Dokument gehört zu Kunde mit ID 123-456-789

Relationen:

  • owner_idemployees.id (Many-to-One)

reminders (Erinnerungen & Aufgaben)

Beschreibung: Aufgabenverwaltung mit Fälligkeitsdatum und Priorität

SpalteTypBeschreibung
iduuidPrimary Key
titlevarcharAufgabentitel
due_datedateFälligkeitsdatum
priorityvarcharPriorität (low, medium, high)
linked_tovarcharVerknüpfung (customer, project, invoice)
owner_iduuidForeign Key → employees.id
is_donebooleanErledigt?
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Relationen:

  • owner_idemployees.id (Many-to-One)

dashboards (Benutzer-Dashboards)

Beschreibung: Personalisierte Dashboard-Layouts pro Benutzer

SpalteTypBeschreibung
iduuidPrimary Key
user_iduuidForeign Key → employees.id
layout_jsonjsonbWidget-Layout als JSON
themevarcharTheme (dark, light)
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Beispiel layout_json:

{
"widgets": [
{"id": "crm-stats", "x": 0, "y": 0, "w": 4, "h": 2},
{"id": "recent-customers", "x": 4, "y": 0, "w": 4, "h": 2},
{"id": "project-timeline", "x": 0, "y": 2, "w": 8, "h": 3}
]
}

Relationen:

  • user_idemployees.id (Many-to-One)

🏢 CRM & Backoffice-Tabellen

customers (Kunden)

Beschreibung: Kundenstammdaten für CRM

SpalteTypBeschreibung
iduuidPrimary Key
namevarcharFirmenname / Name
typevarcharKundentyp (B2B, B2C)
emailvarcharE-Mail-Adresse
phonevarcharTelefonnummer
tax_idvarcharSteuernummer / USt-IdNr.
addresstextVollständige Adresse
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Relationen:

  • Rückverweise: contacts, projects, invoices

contacts (Kontaktpersonen)

Beschreibung: Ansprechpartner bei Kunden

SpalteTypBeschreibung
iduuidPrimary Key
customer_iduuidForeign Key → customers.id
firstnamevarcharVorname
lastnamevarcharNachname
emailvarcharE-Mail-Adresse
phonevarcharTelefonnummer
positionvarcharPosition (z.B. "Geschäftsführer")
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Relationen:

  • customer_idcustomers.id (Many-to-One)

projects (Projekte)

Beschreibung: Kundenprojekte mit Status und Zeitrahmen

SpalteTypBeschreibung
iduuidPrimary Key
customer_iduuidForeign Key → customers.id
department_iduuidForeign Key → departments.id
titlevarcharProjekttitel
statusvarcharStatus (planned, in_progress, completed, cancelled)
start_datedateStartdatum
end_datedateEnddatum
descriptiontextProjektbeschreibung
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Relationen:

  • customer_idcustomers.id (Many-to-One)
  • department_iddepartments.id (Many-to-One)
  • Rückverweise: time_entries, invoices, expenses, chat_messages

time_entries (Zeiterfassung)

Beschreibung: Arbeitszeiterfassung pro Mitarbeiter und Projekt

SpalteTypBeschreibung
iduuidPrimary Key
employee_iduuidForeign Key → employees.id
project_iduuidForeign Key → projects.id
start_timetimestampStartzeit
end_timetimestampEndzeit (NULL = läuft noch)
durationintervalDauer (PostgreSQL interval)
notetextNotiz zur Tätigkeit
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Besonderheiten:

  • duration wird automatisch aus end_time - start_time berechnet
  • end_time = NULL bedeutet "Timer läuft noch"

Relationen:

  • employee_idemployees.id (Many-to-One)
  • project_idprojects.id (Many-to-One)

invoices (Rechnungen)

Beschreibung: Kundenrechnungen mit PDF-Export

SpalteTypBeschreibung
iduuidPrimary Key
customer_iduuidForeign Key → customers.id
project_iduuidForeign Key → projects.id (optional)
totalnumericGesamtbetrag
statusvarcharStatus (draft, sent, paid, overdue)
due_datedateFälligkeitsdatum
issued_datedateRechnungsdatum
pdf_pathtextPfad zur PDF-Datei
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Relationen:

  • customer_idcustomers.id (Many-to-One)
  • project_idprojects.id (Many-to-One, optional)
  • Rückverweise: payments, expenses

payments (Zahlungen)

Beschreibung: Zahlungseingänge für Rechnungen

SpalteTypBeschreibung
iduuidPrimary Key
invoice_iduuidForeign Key → invoices.id
amountnumericZahlungsbetrag
payment_datedateZahlungsdatum
methodvarcharZahlungsmethode (bank_transfer, credit_card, cash, paypal)
notetextNotiz
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Besonderheiten:

  • Mehrere Payments pro Invoice möglich (Teilzahlungen)
  • Summe aller Payments = Invoice.total → Status wird automatisch auf "paid" gesetzt

Relationen:

  • invoice_idinvoices.id (Many-to-One)

expenses (Ausgaben)

Beschreibung: Projekt- und Rechnungsausgaben

SpalteTypBeschreibung
iduuidPrimary Key
project_iduuidForeign Key → projects.id (optional)
invoice_iduuidForeign Key → invoices.id (optional)
categoryvarcharKategorie (material, personnel, service, other)
amountnumericBetrag
notetextBeschreibung
created_attimestampErstellungsdatum
updated_attimestampLetzte Änderung

Relationen:

  • project_idprojects.id (Many-to-One, optional)
  • invoice_idinvoices.id (Many-to-One, optional)

chat_messages (Projekt-Chat)

Beschreibung: Projektkommunikation im Team

SpalteTypBeschreibung
iduuidPrimary Key
project_iduuidForeign Key → projects.id
author_iduuidForeign Key → employees.id
messagetextNachrichtentext
created_attimestampErstellungsdatum

Relationen:

  • project_idprojects.id (Many-to-One)
  • author_idemployees.id (Many-to-One)

🔗 Beziehungsübersicht

Haupt-Datenfluss

┌──────────────┐
│ employees │◄──────────┐
└──────┬───────┘ │
│ │
│ owns │ belongs to
↓ │
┌──────────────┐ ┌──────────────┐
│ departments │────│ time_entries │
└──────┬───────┘ └──────┬───────┘
│ │
│ manages │ tracked on
↓ ↓
┌──────────────┐ ┌──────────────┐
│ projects │◄───│ customers │
└──────┬───────┘ └──────┬───────┘
│ │
│ billed in │ has
↓ ↓
┌──────────────┐ ┌──────────────┐
│ invoices │ │ contacts │
└──────┬───────┘ └──────────────┘

│ paid with

┌──────────────┐
│ payments │
└──────────────┘

Kardinalitäten

BeziehungTypBeschreibung
employeesrolesMany-to-OneViele Mitarbeiter können dieselbe Rolle haben
employeesdepartmentsMany-to-OneViele Mitarbeiter können in derselben Abteilung sein
departmentsemployees (manager)Many-to-OneJede Abteilung hat einen Manager
customerscontactsOne-to-ManyEin Kunde kann mehrere Kontakte haben
customersprojectsOne-to-ManyEin Kunde kann mehrere Projekte haben
projectstime_entriesOne-to-ManyEin Projekt hat viele Zeiteinträge
projectschat_messagesOne-to-ManyEin Projekt hat viele Chat-Nachrichten
projectsinvoicesOne-to-ManyEin Projekt kann mehrere Rechnungen haben
invoicespaymentsOne-to-ManyEine Rechnung kann mehrere Zahlungen haben
invoicesexpensesOne-to-ManyEine Rechnung kann mehrere Ausgaben haben

📝 DBML-Datei

Die vollständige Datenbankdefinition als DBML (Database Markup Language) findest du in:

📄 workmateos_phase2.dbml

Diese Datei kann mit Tools wie dbdiagram.io visualisiert werden.


🔧 Datenbank-Setup

Migration erstellen (Alembic)

# Neue Migration generieren
alembic revision --autogenerate -m "Add backoffice tables"

# Migration ausführen
alembic upgrade head

Initiale Daten (Seeds)

-- Beispiel-Rolle anlegen
INSERT INTO roles (id, name, permissions) VALUES
(gen_random_uuid(), 'Admin', '{"crm": ["read", "write", "delete"], "admin_panel": ["access"]}'),
(gen_random_uuid(), 'Manager', '{"crm": ["read", "write"], "projects": ["read", "write"]}'),
(gen_random_uuid(), 'Employee', '{"crm": ["read"], "projects": ["read"], "time_entries": ["write"]}');

-- Beispiel-Abteilung
INSERT INTO departments (id, name) VALUES
(gen_random_uuid(), 'Sales'),
(gen_random_uuid(), 'Development'),
(gen_random_uuid(), 'Management');

🔐 Indizes & Performance

Empfohlene Indizes

-- Häufige Lookups
CREATE INDEX idx_employees_role_id ON employees(role_id);
CREATE INDEX idx_employees_department_id ON employees(department_id);
CREATE INDEX idx_contacts_customer_id ON contacts(customer_id);
CREATE INDEX idx_projects_customer_id ON projects(customer_id);
CREATE INDEX idx_time_entries_employee_id ON time_entries(employee_id);
CREATE INDEX idx_time_entries_project_id ON time_entries(project_id);
CREATE INDEX idx_invoices_customer_id ON invoices(customer_id);
CREATE INDEX idx_payments_invoice_id ON payments(invoice_id);

-- Polymorphe Verknüpfungen
CREATE INDEX idx_documents_linked ON documents(linked_module, linked_id);

-- Status-Filter
CREATE INDEX idx_invoices_status ON invoices(status);
CREATE INDEX idx_projects_status ON projects(status);

-- Zeitbasierte Queries
CREATE INDEX idx_time_entries_start_time ON time_entries(start_time);
CREATE INDEX idx_invoices_due_date ON invoices(due_date);

Datenbank: PostgreSQL 15+ ORM: SQLAlchemy 2.0 Migrations: Alembic Letzte Aktualisierung: 30. Dezember 2025