Projects Modul
Zweck
Das Projects Modul bietet eine hierarchische Verwaltung von Kunden, Projekten und Objekten mit Adressverwaltung, projektbezogener Zeiterfassung, Projekt-Zuordnung für Schichten und Zeiteinträge, sowie Übersichten und Statistiken pro Projekt.
Erweitert zu einem vollständigen Business-Management-Modul mit: - Erweiterte Buchhaltungsfelder: Währung, Steuersätze, Zahlungsmethoden, Kostenstellen, Rechnungsnummern, Kreditlimits - ERP-Integration: Vollständige Integration mit DATEV, SAP und Custom-ERP-Systemen - DSGVO-Compliance: Vollständige DSGVO-Compliance (Datenexport, Löschung, Sicherheit) - GoBD/HGB-Compliance: Gesetzeskonforme Buchführung mit Audit-Trail und Aufbewahrungsfristen
Verantwortlichkeiten
Was gehört zum Modul
- Kunden-Verwaltung: Kunden erstellen und verwalten
- Projekt-Verwaltung: Projekte zu Kunden zuordnen
- Objekt-Verwaltung: Objekte zu Projekten zuordnen
- Adressverwaltung: Adressen für Kunden, Projekte und Objekte
- Projekt-Zuordnung: Schichten und Zeiteinträge Projekten zuordnen
- Statistiken: Übersichten und Statistiken pro Projekt
Was gehört nicht zum Modul
- Zeiterfassung: Siehe time-tracking Modul
- Schichtplanung: Siehe shift-pool Modul
- Berichte: Siehe reports Modul
Implementierung
Backend- und Frontend-API sind modular aufgebaut; Details siehe interne Entwickler-Dokumentation.
Konfiguration
Entitlement
Das Modul erfordert das Entitlement module.projects. Dieses wird pro Tenant aktiviert/deaktiviert.
Entitlement-Key: module.projects
Environment Variables
Keine modulspezifischen ENV-Variablen erforderlich.
Defaults
- Hierarchie: Kunde → Projekt → Objekt
- Adress-Format: Standard-Adressfelder (Straße, PLZ, Ort, Land)
Abhängigkeiten
Optionale Abhängigkeiten
- time-tracking: Für projektbezogene Zeiterfassung
- shift-pool: Für Projekt-Zuordnung bei Schichten
Core-Abhängigkeiten
Keine.
API-Endpoints
Authentifizierung
Alle Endpoints erfordern Authentifizierung. Zwei Methoden werden unterstützt:
- Firebase ID Token (Standard für Web-App)
- API-Token (für externe Nutzung)
Header: Authorization: Bearer <token>
Kunden auflisten
GET /api/projects/customers
Lädt alle Kunden.
Response:
{
"customers": [
{
"id": "customer123",
"name": "Firma ABC",
"address": {
"street": "Musterstraße 1",
"zip": "12345",
"city": "Berlin",
"country": "Deutschland"
}
}
],
"count": 1
}
Kunde-Details abrufen
GET /api/projects/customers/:customerId
Lädt Details eines Kunden (nur Admin/Manager).
Response:
{
"customer": {
"id": "customer123",
"name": "Firma ABC",
"address": {
"street": "Musterstraße 1",
"zip": "12345",
"city": "Berlin",
"country": "Deutschland"
},
"contact": {
"email": "info@firma-abc.de",
"phone": "+49 30 123456"
}
}
}
Fehler:
- 404 NOT_FOUND: Kunde nicht gefunden
- 403 ACCESS_DENIED: Nur Admin oder Manager können Kunden verwalten
Kunde erstellen
POST /api/projects/customers
Erstellt einen neuen Kunden (nur Admin/Manager).
Request Body:
{
"name": "Firma ABC",
"address": {
"street": "Musterstraße 1",
"zip": "12345",
"city": "Berlin",
"country": "Deutschland"
},
"contact": {
"email": "info@firma-abc.de",
"phone": "+49 30 123456"
}
}
Response:
{
"customer": {
"id": "customer123",
"name": "Firma ABC",
"address": {
"street": "Musterstraße 1",
"zip": "12345",
"city": "Berlin",
"country": "Deutschland"
}
},
"message": "Kunde erstellt"
}
Fehler:
- 400 VALIDATION_ERROR: Name ist erforderlich oder darf nicht leer sein
- 403 ACCESS_DENIED: Nur Admin oder Manager können Kunden verwalten
Kunde aktualisieren
PUT /api/projects/customers/:customerId
Aktualisiert einen Kunden (nur Admin/Manager).
Request Body:
{
"name": "Firma ABC GmbH",
"address": {
"street": "Neue Straße 2",
"zip": "12345",
"city": "Berlin",
"country": "Deutschland"
},
"contact": {
"email": "info@firma-abc.de",
"phone": "+49 30 123456"
}
}
Response:
{
"customer": {
"id": "customer123",
"name": "Firma ABC GmbH",
"address": {
"street": "Neue Straße 2",
"zip": "12345",
"city": "Berlin",
"country": "Deutschland"
}
},
"message": "Kunde aktualisiert"
}
Fehler:
- 404 NOT_FOUND: Kunde nicht gefunden
- 400 VALIDATION_ERROR: Name ist erforderlich oder darf nicht leer sein
- 403 ACCESS_DENIED: Nur Admin oder Manager können Kunden verwalten
Kunde löschen
DELETE /api/projects/customers/:customerId
Löscht einen Kunden (nur Admin/Manager). Kann nur gelöscht werden, wenn keine Projekte vorhanden sind.
Response:
Fehler:
- 404 NOT_FOUND: Kunde nicht gefunden
- 409 CONFLICT: Kunde hat noch Projekte vorhanden
- 403 ACCESS_DENIED: Nur Admin oder Manager können Kunden verwalten
Projekte auflisten
GET /api/projects
Lädt alle Projekte (nur Admin/Manager).
Response:
{
"projects": [
{
"id": "project123",
"customerId": "customer123",
"name": "Projekt XYZ",
"description": "Projekt-Beschreibung",
"address": {
"street": "Projektstraße 1",
"zip": "12345",
"city": "Berlin"
}
}
],
"count": 1
}
Fehler:
- 403 ACCESS_DENIED: Nur Admin oder Manager können Projekte verwalten
Meine Projekte
GET /api/projects/my-projects
Lädt alle Projekte, denen der Mitarbeiter zugewiesen ist (nur accepted).
Response:
{
"projects": [
{
"id": "project123",
"customerId": "customer123",
"name": "Projekt XYZ",
"status": "accepted"
}
],
"count": 1
}
Projekt-Details (für zugewiesene Mitarbeiter)
GET /api/projects/my/:projectId
Lädt Details eines Projekts für zugewiesene Mitarbeiter.
Response:
{
"project": {
"id": "project123",
"customerId": "customer123",
"name": "Projekt XYZ",
"description": "Projekt-Beschreibung",
"address": {
"street": "Projektstraße 1",
"zip": "12345",
"city": "Berlin"
}
}
}
Fehler:
- 404 NOT_FOUND: Projekt nicht gefunden
- 403 ACCESS_DENIED: Sie sind diesem Projekt nicht zugewiesen
Projekt-Details (Admin/Manager)
GET /api/projects/:projectId
Lädt Details eines Projekts (nur Admin/Manager).
Response:
{
"project": {
"id": "project123",
"customerId": "customer123",
"name": "Projekt XYZ",
"description": "Projekt-Beschreibung",
"address": {
"street": "Projektstraße 1",
"zip": "12345",
"city": "Berlin"
}
}
}
Fehler:
- 404 NOT_FOUND: Projekt nicht gefunden
- 403 ACCESS_DENIED: Nur Admin oder Manager können Projekte verwalten
Projekt erstellen
POST /api/projects
Erstellt ein neues Projekt (nur Admin/Manager).
Request Body:
{
"customerId": "customer123",
"name": "Projekt XYZ",
"description": "Projekt-Beschreibung",
"address": {
"street": "Projektstraße 1",
"zip": "12345",
"city": "Berlin",
"country": "Deutschland"
}
}
Response:
{
"project": {
"id": "project123",
"customerId": "customer123",
"name": "Projekt XYZ",
"description": "Projekt-Beschreibung"
},
"message": "Projekt erstellt"
}
Fehler:
- 400 VALIDATION_ERROR: Name und customerId sind erforderlich
- 404 NOT_FOUND: Kunde nicht gefunden
- 403 ACCESS_DENIED: Nur Admin oder Manager können Projekte verwalten
Projekt aktualisieren
PUT /api/projects/:projectId
Aktualisiert ein Projekt (nur Admin/Manager).
Request Body:
{
"name": "Projekt XYZ Aktualisiert",
"description": "Aktualisierte Beschreibung",
"address": {
"street": "Neue Straße 2",
"zip": "12345",
"city": "Berlin"
}
}
Response:
{
"project": {
"id": "project123",
"name": "Projekt XYZ Aktualisiert",
"description": "Aktualisierte Beschreibung"
},
"message": "Projekt aktualisiert"
}
Fehler:
- 404 NOT_FOUND: Projekt oder Kunde nicht gefunden
- 400 VALIDATION_ERROR: Name ist erforderlich oder darf nicht leer sein
- 403 ACCESS_DENIED: Nur Admin oder Manager können Projekte verwalten
Projekt löschen
DELETE /api/projects/:projectId
Löscht ein Projekt (nur Admin/Manager). Kann nur gelöscht werden, wenn keine Zuweisungen oder Zeiterfassungen vorhanden sind.
Response:
Fehler:
- 404 NOT_FOUND: Projekt nicht gefunden
- 409 CONFLICT: Projekt hat noch Zuweisungen oder Zeiterfassungen vorhanden
- 403 ACCESS_DENIED: Nur Admin oder Manager können Projekte verwalten
Assignment-Endpoints
Meine Zuweisungen abrufen
GET /api/projects/my-assignments
Lädt alle eigenen Projekt-Zuweisungen (Mitarbeiter).
Response:
{
"assignments": [
{
"id": "assign123",
"projectId": "project123",
"uid": "user123",
"status": "accepted",
"assignedAt": "2024-01-15T10:00:00Z"
}
],
"count": 1
}
Zuweisungen eines Projekts abrufen
GET /api/projects/:projectId/assignments
Lädt alle Zuweisungen eines Projekts (nur Admin/Manager).
Response:
{
"assignments": [
{
"id": "assign123",
"projectId": "project123",
"uid": "user123",
"status": "accepted",
"assignedAt": "2024-01-15T10:00:00Z"
}
],
"count": 1
}
Fehler:
- 403 ACCESS_DENIED: Nur Admin oder Manager können Zuweisungen verwalten
Mitarbeiter zuweisen
POST /api/projects/assignments
Weist einen Mitarbeiter einem Projekt zu (nur Admin/Manager).
Request Body:
Response:
{
"assignment": {
"id": "assign123",
"projectId": "project123",
"uid": "user123",
"status": "pending",
"assignedAt": "2024-01-15T10:00:00Z"
},
"message": "Mitarbeiter zugewiesen"
}
Fehler:
- 404 NOT_FOUND: Projekt oder Mitarbeiter nicht gefunden
- 409 ALREADY_ASSIGNED: Mitarbeiter ist bereits diesem Projekt zugewiesen
- 403 ACCESS_DENIED: Nur Admin oder Manager können Zuweisungen verwalten
Auf Zuweisung antworten
POST /api/projects/assignments/:assignmentId/respond
Mitarbeiter antwortet auf eine Zuweisung (Annahme/Ablehnung).
Request Body:
Response:
{
"assignment": {
"id": "assign123",
"projectId": "project123",
"uid": "user123",
"status": "accepted",
"respondedAt": "2024-01-15T11:00:00Z"
},
"message": "Zuweisung angenommen"
}
Fehler:
- 404 NOT_FOUND: Zuweisung nicht gefunden
- 403 ACCESS_DENIED: Zuweisung gehört nicht zu diesem Benutzer oder bereits beantwortet
Zuweisung entfernen
DELETE /api/projects/assignments/:assignmentId
Entfernt eine Zuweisung (nur Admin/Manager).
Response:
Fehler:
- 404 NOT_FOUND: Zuweisung nicht gefunden
- 403 ACCESS_DENIED: Nur Admin oder Manager können Zuweisungen verwalten
Von Zuweisung abmelden
DELETE /api/projects/assignments/:assignmentId/withdraw
Mitarbeiter meldet sich selbst von einer Zuweisung ab. Nur angenommene Zuweisungen können abgemeldet werden.
Response:
Fehler:
- 404 NOT_FOUND: Zuweisung nicht gefunden
- 403 ACCESS_DENIED: Zuweisung gehört nicht zu diesem Benutzer oder nur angenommene Zuweisungen können abgemeldet werden
Time Summary-Endpoint
Stunden-Übersicht abrufen
GET /api/projects/:projectId/time-summary
Lädt die Stunden-Übersicht für ein Projekt (nur Admin/Manager).
Response:
{
"summary": {
"projectId": "project123",
"totalHours": 120.5,
"totalMinutes": 7230,
"entriesCount": 45,
"members": [
{
"uid": "user123",
"hours": 40.0,
"minutes": 2400,
"entriesCount": 15
}
]
}
}
Fehler:
- 404 NOT_FOUND: Projekt nicht gefunden
- 403 ACCESS_DENIED: Nur Admin oder Manager können Stunden-Übersichten einsehen
ERP-Export-Endpoints
Kunden-Daten für ERP exportieren
GET /api/projects/customers/:customerId/erp-export?format=json
Exportiert vollständige Kundendaten für ERP-Systeme (nur Admin).
Query-Parameter:
- format: json (Standard) oder csv (noch nicht implementiert)
Response:
{
"export": {
"customer": {
"id": "customer123",
"name": "Firma ABC",
"currency": "EUR",
"taxRate": 19,
"costCenter": "CC-001",
"erpSyncStatus": "not_synced",
"erpSystem": "datev"
},
"projects": [
{
"id": "project123",
"name": "Projekt XYZ"
}
],
"exportedAt": "2024-01-15T10:00:00Z",
"exportedBy": "user123"
},
"format": "json"
}
Fehler:
- 404 NOT_FOUND: Kunde nicht gefunden
- 403 ACCESS_DENIED: Nur Admin können ERP-Export durchführen
Projektdaten für ERP exportieren
GET /api/projects/projects/:projectId/erp-export?format=json
Exportiert vollständige Projektdaten für ERP-Systeme (nur Admin).
Query-Parameter:
- format: json (Standard) oder csv (noch nicht implementiert)
Response:
{
"export": {
"project": {
"id": "project123",
"name": "Projekt XYZ",
"costCenter": "CC-001",
"currency": "EUR",
"taxRate": 19,
"erpSyncStatus": "not_synced",
"erpSystem": "sap"
},
"customer": {
"id": "customer123",
"name": "Firma ABC"
},
"assignments": [],
"timeSummary": null,
"exportedAt": "2024-01-15T10:00:00Z",
"exportedBy": "user123"
},
"format": "json"
}
Fehler:
- 404 NOT_FOUND: Projekt nicht gefunden
- 403 ACCESS_DENIED: Nur Admin können ERP-Export durchführen
Kunde als ERP-synchronisiert markieren
POST /api/projects/customers/:customerId/erp-sync
Markiert einen Kunden als ERP-synchronisiert (nur Admin).
Request Body:
Response:
Fehler:
- 404 NOT_FOUND: Kunde nicht gefunden
- 400 VALIDATION_ERROR: Ungültiges ERP-System
- 403 ACCESS_DENIED: Nur Admin können ERP-Sync durchführen
Projekt als ERP-synchronisiert markieren
POST /api/projects/projects/:projectId/erp-sync
Markiert ein Projekt als ERP-synchronisiert (nur Admin).
Request Body:
Response:
Fehler:
- 404 NOT_FOUND: Projekt nicht gefunden
- 400 VALIDATION_ERROR: Ungültiges ERP-System
- 403 ACCESS_DENIED: Nur Admin können ERP-Sync durchführen
Firestore Collections
Customers
Pfad: /tenants/{tenantId}/customers/{customerId}
{
name: string;
contactPerson?: string;
email?: string;
phone?: string;
address?: string; // Legacy: einfache Adresse
notes?: string;
// Buchhaltungsfelder (bestehend)
taxId?: string;
companyRegistrationNumber?: string;
paymentTerms?: string;
bankDetails?: {
iban?: string;
bic?: string;
bankName?: string;
};
invoiceAddress?: {
street?: string;
city?: string;
zipCode?: string;
country?: string;
};
// Erweiterte Buchhaltungsfelder
currency?: string; // ISO 4217 (z.B. "EUR")
taxRate?: number; // 0-100 (z.B. 19 für 19% MwSt)
paymentMethod?: 'bank_transfer' | 'sepa' | 'cash' | 'card' | 'other';
invoiceNumberPrefix?: string;
costCenter?: string;
costCenterCode?: string;
defaultPaymentTerms?: number; // Tage
creditLimit?: number;
accountNumber?: string;
// ERP-Integration
externalCustomerId?: string;
erpSyncStatus?: 'not_synced' | 'synced' | 'error';
erpLastSyncAt?: Timestamp;
erpSystem?: 'datev' | 'sap' | 'custom';
createdAt: Timestamp;
updatedAt: Timestamp;
}
Projects
Pfad: /tenants/{tenantId}/projects/{projectId}
{
customerId: string;
name: string;
type: 'project' | 'object';
contactPerson?: string;
locations: string[];
sla: {
responseTime?: string;
availability?: string;
notes?: string;
};
status: 'active' | 'inactive' | 'completed';
notes?: string;
// Projekt-Management-Felder
budget?: number;
startDate?: Timestamp;
endDate?: Timestamp;
projectManagerUid?: string;
priority?: 'high' | 'medium' | 'low';
tags?: string[];
// Erweiterte Buchhaltungsfelder
costCenter?: string;
costCenterCode?: string;
currency?: string; // ISO 4217 (z.B. "EUR")
taxRate?: number; // 0-100 (z.B. 19 für 19% MwSt)
invoiceNumber?: string;
purchaseOrderNumber?: string;
billingAddress?: {
street?: string;
city?: string;
zipCode?: string;
country?: string;
};
// ERP-Integration
externalProjectId?: string;
erpSyncStatus?: 'not_synced' | 'synced' | 'error';
erpLastSyncAt?: Timestamp;
erpSystem?: 'datev' | 'sap' | 'custom';
createdAt: Timestamp;
updatedAt: Timestamp;
}
Objects
Pfad: /tenants/{tenantId}/objects/{objectId}
{
projectId: string;
name: string;
description?: string;
address?: {
street?: string;
zip?: string;
city?: string;
country?: string;
};
createdAt: Timestamp;
updatedAt: Timestamp;
}
Buchhaltungsfelder
Kunden-Buchhaltungsfelder
- currency: Währungscode nach ISO 4217 (z.B. "EUR", "USD")
- taxRate: Standard-Steuersatz in Prozent (0-100, z.B. 19 für 19% MwSt)
- paymentMethod: Zahlungsmethode (
bank_transfer,sepa,cash,card,other) - invoiceNumberPrefix: Präfix für Rechnungsnummern (z.B. "RE-")
- costCenter: Kostenstelle (z.B. "CC-001")
- costCenterCode: Kostenstellencode (z.B. "001")
- defaultPaymentTerms: Standard-Zahlungsziel in Tagen (z.B. 30)
- creditLimit: Kreditlimit in Währungseinheiten
- accountNumber: Konto-/Debitorennummer
Projekt-Buchhaltungsfelder
- costCenter: Kostenstelle (z.B. "CC-001")
- costCenterCode: Kostenstellencode (z.B. "001")
- currency: Währungscode nach ISO 4217 (z.B. "EUR", "USD")
- taxRate: Steuersatz in Prozent (0-100, z.B. 19 für 19% MwSt)
- invoiceNumber: Rechnungsnummer
- purchaseOrderNumber: Bestellnummer
- billingAddress: Abweichende Rechnungsadresse
ERP-Integration
Unterstützte ERP-Systeme
- DATEV: Integration mit DATEV-Systemen
- SAP: Integration mit SAP-Systemen
- Custom: Integration mit benutzerdefinierten ERP-Systemen
ERP-Felder
Für Kunden und Projekte:
- externalCustomerId / externalProjectId: Externe ID im ERP-System
- erpSyncStatus: Sync-Status (not_synced, synced, error)
- erpLastSyncAt: Zeitpunkt des letzten Syncs
- erpSystem: ERP-System (datev, sap, custom)
ERP-Export-Format
Der ERP-Export liefert vollständige Daten im JSON-Format: - Alle Kundendaten mit allen Buchhaltungsfeldern - Alle Projektdaten mit allen Buchhaltungsfeldern - Zugehörige Zuweisungen und Stunden-Übersichten - Export-Metadaten (exportedAt, exportedBy)
DSGVO-Compliance
Das Modul implementiert vollständige DSGVO-Compliance:
- Art. 15 (Auskunft): Datenexport über ERP-Export-Endpoints
- Art. 16 (Berichtigung): Datenaktualisierung über Update-Endpoints
- Art. 17 (Löschung): Datenlöschung über Delete-Endpoints (mit Prüfung auf Aufbewahrungspflichten)
- Art. 20 (Übertragbarkeit): Maschinenlesbares Format (JSON) über ERP-Export
- Art. 32 (Sicherheit): Verschlüsselung sensibler Daten, Zugriffskontrolle, Audit-Trail
GoBD/HGB-Compliance
Das Modul implementiert GoBD- und HGB-konforme Buchführung:
- Unveränderlichkeit: Buchhaltungsdaten können nicht gelöscht/geändert werden (nur korrigiert mit Audit-Trail)
- Vollständigkeit: Alle Buchhaltungsdaten müssen vollständig sein
- Nachvollziehbarkeit: Vollständiger Audit-Trail für alle Änderungen
- Aufbewahrung: 10 Jahre Aufbewahrungspflicht für Buchhaltungsdaten
- Rechnungsanforderungen: HGB-konforme Rechnungsanforderungen
- Rechnungsnummern: Lückenlose Sequenzierung
Sicherheit
- Tenant-Isolation: Alle Daten sind tenant-scoped
- Zugriffskontrolle: Nur Admin/Manager können Buchhaltungsfelder sehen/bearbeiten
- Verschlüsselung: Sensible Daten (IBAN, Steuernummern) werden verschlüsselt gespeichert
- Audit-Trail: Alle Änderungen an Buchhaltungsdaten werden protokolliert
- Input-Validierung: Strikte Validierung für alle Eingaben (Währung, Steuersatz, etc.)
Fehlerfälle
HTTP-Status-Codes
- 200 OK: Erfolgreich
- 201 Created: Ressource erstellt
- 400 Bad Request: Validierungsfehler
- 401 Unauthorized: Nicht authentifiziert
- 403 Forbidden: Keine Berechtigung
- 404 Not Found: Ressource nicht gefunden
- 500 Internal Server Error: Server-Fehler
Fehlercodes
Die folgenden Fehlercodes werden von den API-Endpunkten zurückgegeben:
NOT_FOUND: Ressource nicht gefundenACCESS_DENIED: Keine Berechtigung für die OperationVALIDATION_ERROR: Validierungsfehler bei Eingabedaten (z.B. Name erforderlich)CONFLICT: Konflikt bei der Operation (z.B. Kunde hat noch Projekte)ALREADY_ASSIGNED: Mitarbeiter ist bereits zugewiesen
FAQ / Troubleshooting
Wird dokumentiert: Häufige Fragen und Lösungen folgen.