Zum Inhalt

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

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:

  1. Firebase ID Token (Standard für Web-App)
  2. 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:

{
  "message": "Kunde gelöscht"
}

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:

{
  "message": "Projekt gelöscht"
}

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:

{
  "projectId": "project123",
  "memberUid": "user123"
}

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:

{
  "status": "accepted"
}

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:

{
  "message": "Zuweisung entfernt"
}

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:

{
  "message": "Abmeldung erfolgreich"
}

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:

{
  "erpSystem": "datev"
}

Response:

{
  "message": "Kunde als ERP-synchronisiert markiert"
}

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:

{
  "erpSystem": "sap"
}

Response:

{
  "message": "Projekt als ERP-synchronisiert markiert"
}

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 gefunden
  • ACCESS_DENIED: Keine Berechtigung für die Operation
  • VALIDATION_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.