diff --git a/MODULES_ROADMAP.md b/MODULES_ROADMAP.md new file mode 100644 index 0000000..a6fc7ee --- /dev/null +++ b/MODULES_ROADMAP.md @@ -0,0 +1,251 @@ +# SeCu Module Roadmap + +## Modulares Preismodell + +### 🆓 Basis (kostenlos/Grundpreis) +- Mitarbeiterverwaltung +- Benutzerverwaltung (Chef, Disponent, Mitarbeiter) +- Einstellungen & Profil +- Hilfe-System + +### 💰 Premium-Module (Aufpreis) + +| Modul | Priorität | Beschreibung | +|-------|-----------|--------------| +| **Aufträge** | ⭐⭐⭐ | Auftragsverwaltung, Zuweisung | +| **Stundenzettel** | ⭐⭐⭐ | Zeiterfassung, Foto-Upload, Genehmigung | +| **Verfügbarkeiten** | ⭐⭐⭐ | Einsatzplanung, Kalender | +| **Qualifikationen** | ⭐⭐⭐ | Zertifikate, §34a, Ablauf-Tracking | +| **Objektverwaltung** | ⭐⭐⭐ | Wachobjekte, Standorte, Kontakte | +| **Schichtplanung** | ⭐⭐ | Dienstpläne, Wochenpläne, Vertretungen | +| **Wächterkontrolle** | ⭐⭐ | QR/NFC-Checkpoints, Rundgänge, GPS | +| **Vorfallberichte** | ⭐⭐ | Incidents, Fotos, Kategorien | +| **Fahrzeuge** | ⭐ | Firmenwagen, Kilometer, Wartung | +| **Dokumente** | ⭐ | Verträge, Policies, Uploads | +| **Kunden/CRM** | ⭐ | Kundenverwaltung, Kontakte | +| **Abrechnung** | ⭐ | Rechnungen, Export | +| **Partnerschaften** | ⭐ | Subunternehmer, Stundenzettel-Austausch | + +--- + +## Modul-Details + +### 1. Qualifikationen & Zertifikate ⭐⭐⭐ +**Status:** 🔨 In Entwicklung + +**Datenmodell:** +- `qualifications` - Verfügbare Qualifikationstypen +- `employee_qualifications` - Zuordnung MA ↔ Qualifikation + +**Qualifikationstypen:** +- §34a Sachkundenachweis (Pflicht!) +- §34a Unterrichtungsnachweis +- Waffensachkunde +- Waffenschein (grün/gelb) +- Erste-Hilfe-Zertifikat +- Brandschutzhelfer +- Evakuierungshelfer +- Führerschein Klasse B/C/D +- Personenschutz-Ausbildung +- Hundeführerschein +- Sprachen (Englisch, etc.) + +**Features:** +- Ablaufdatum-Tracking +- Automatische Erinnerungen (E-Mail/Push) +- Dokument-Upload (Scan des Zertifikats) +- Qualifikations-Matrix (wer hat was) +- Bei Auftragszuweisung: Prüfung ob MA qualifiziert +- Ablaufende Qualifikationen im Dashboard + +--- + +### 2. Objektverwaltung ⭐⭐⭐ +**Status:** 📋 Geplant + +**Datenmodell:** +- `objects` - Wachobjekte/Standorte +- `object_contacts` - Ansprechpartner pro Objekt +- `object_instructions` - Dienstanweisungen +- `object_documents` - Lagepläne, Schlüssellisten + +**Features:** +- Objektdetails (Adresse, Typ, Größe) +- Mehrere Ansprechpartner +- Dienstanweisungen (PDF/Text) +- Schlüsselverwaltung +- Zugangsregeln +- Notfallpläne +- Objekt-spezifische Checklisten +- Verknüpfung mit Aufträgen + +--- + +### 3. Schichtplanung ⭐⭐ +**Status:** 📋 Geplant + +**Datenmodell:** +- `shifts` - Schichtdefinitionen +- `shift_assignments` - Wer arbeitet wann +- `shift_templates` - Wiederkehrende Muster + +**Features:** +- Wochenansicht / Monatsansicht +- Drag & Drop Planung +- Verfügbarkeits-Check +- Qualifikations-Check +- Vertretungsanfragen +- Push-Benachrichtigung bei Änderungen +- Export (PDF, iCal) +- Arbeitszeitkonto + +--- + +### 4. Wächterkontrollsystem ⭐⭐ +**Status:** 📋 Geplant + +**Datenmodell:** +- `checkpoints` - QR/NFC Kontrollpunkte +- `patrol_routes` - Rundgang-Routen +- `patrol_logs` - Erfasste Rundgänge + +**Features:** +- QR-Code Generator für Checkpoints +- NFC-Tag Unterstützung +- GPS-Koordinaten bei Scan +- Pflicht-Reihenfolge definierbar +- Zeitfenster für Rundgänge +- Abweichungs-Alarme +- Rundgang-Historie +- Berichte für Kunden + +--- + +### 5. Vorfallberichte ⭐⭐ +**Status:** 📋 Geplant + +**Datenmodell:** +- `incidents` - Vorfälle +- `incident_categories` - Kategorien +- `incident_attachments` - Fotos, Dokumente + +**Kategorien:** +- Einbruch/Einbruchsversuch +- Vandalismus +- Hausfriedensbruch +- Technische Störung +- Brand/Brandgefahr +- Unfall +- Sonstiges + +**Features:** +- Schnell-Erfassung (Mobile-optimiert) +- Foto-Upload (vor Ort) +- Kategorisierung +- Schweregrad +- Beteiligte Personen +- Maßnahmen dokumentieren +- PDF-Export für Kunden +- Eskalations-Workflow + +--- + +### 6. Fahrzeugverwaltung ⭐ +**Status:** 📋 Geplant + +**Datenmodell:** +- `vehicles` - Fahrzeuge +- `vehicle_bookings` - Buchungen +- `vehicle_logs` - Fahrten, Tanken +- `vehicle_maintenance` - Wartungen + +**Features:** +- Fahrzeugpool +- Buchungssystem +- Kilometerstand-Tracking +- Tankbelege +- Wartungserinnerungen (TÜV, Inspektion) +- Schadensmeldungen +- Führerschein-Kontrolle + +--- + +### 7. Dokumentenverwaltung ⭐ +**Status:** 📋 Geplant + +**Features:** +- Arbeitsverträge +- Datenschutzerklärungen +- Dienstanweisungen +- Schulungsunterlagen +- Versionierung +- Lesebestätigung durch MA + +--- + +### 8. Kunden/CRM ⭐ +**Status:** 📋 Geplant + +**Features:** +- Kundenstammdaten +- Ansprechpartner +- Vertragsübersicht +- Kommunikationshistorie +- Umsatz pro Kunde + +--- + +### 9. Abrechnung ⭐ +**Status:** 📋 Geplant + +**Features:** +- Stundensätze pro Kunde/Objekt +- Automatische Rechnungserstellung +- PDF-Export +- DATEV-Export +- Mahnwesen + +--- + +## Entwicklungsreihenfolge + +1. ✅ Basis (Benutzer, Auth, Dashboard) +2. ✅ Aufträge +3. ✅ Stundenzettel +4. ✅ Verfügbarkeiten +5. ✅ Hilfe-System +6. 🔨 **Qualifikationen** ← AKTUELL +7. 📋 Objektverwaltung +8. 📋 Schichtplanung +9. 📋 Wächterkontrolle +10. 📋 Vorfallberichte +11. 📋 Fahrzeuge +12. 📋 Dokumente +13. 📋 CRM +14. 📋 Abrechnung + +--- + +## Technische Umsetzung + +### Modul-System (Backend) +```typescript +// modules Tabelle erweitern +{ + key: 'qualifications', + name: 'Qualifikationen', + description: 'Zertifikate & Nachweise verwalten', + icon: '🎓', + price_monthly: 29.00, + price_yearly: 290.00, + is_premium: true +} +``` + +### Feature-Flags (Frontend) +```typescript +// Modul-Check vor Anzeige +if (orgStore.hasModule('qualifications')) { + // Zeige Menüpunkt +} +``` diff --git a/db/migrations/003_qualifications.sql b/db/migrations/003_qualifications.sql new file mode 100644 index 0000000..8b0a99c --- /dev/null +++ b/db/migrations/003_qualifications.sql @@ -0,0 +1,182 @@ +-- Migration: 003_qualifications.sql +-- Qualifikationen & Zertifikate Modul + +-- Verfügbare Qualifikationstypen (System-weit) +CREATE TABLE IF NOT EXISTS qualification_types ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + key VARCHAR(50) UNIQUE NOT NULL, + name VARCHAR(100) NOT NULL, + description TEXT, + category VARCHAR(50) NOT NULL DEFAULT 'general', + has_expiry BOOLEAN DEFAULT true, + validity_months INTEGER, -- Standard-Gültigkeit in Monaten + is_required BOOLEAN DEFAULT false, -- Pflicht für alle MA? + icon VARCHAR(10) DEFAULT '📜', + sort_order INTEGER DEFAULT 0, + is_system BOOLEAN DEFAULT true, -- System-vorgegeben oder custom + created_at TIMESTAMPTZ DEFAULT NOW() +); + +-- Standard-Qualifikationstypen einfügen +INSERT INTO qualification_types (key, name, description, category, has_expiry, validity_months, is_required, icon, sort_order, is_system) VALUES +-- Gesetzliche Pflicht +('sachkunde_34a', '§34a Sachkundenachweis', 'Sachkundeprüfung nach §34a GewO - Pflicht für Bewachungsgewerbe', 'legal', false, NULL, true, '📋', 1, true), +('unterrichtung_34a', '§34a Unterrichtungsnachweis', '40-Stunden Unterrichtung nach §34a GewO', 'legal', false, NULL, false, '📋', 2, true), + +-- Waffen +('waffensachkunde', 'Waffensachkunde', 'Sachkundenachweis für Waffenbesitz', 'weapons', false, NULL, false, '🔫', 10, true), +('waffenschein_gruen', 'Waffenschein (grün)', 'Waffenschein für Schusswaffen', 'weapons', true, 36, false, '🟢', 11, true), +('waffenschein_gelb', 'Waffenschein (gelb)', 'Kleiner Waffenschein', 'weapons', true, 36, false, '🟡', 12, true), + +-- Erste Hilfe & Sicherheit +('erste_hilfe', 'Erste-Hilfe-Kurs', 'Erste-Hilfe-Ausbildung (9 UE)', 'safety', true, 24, false, '🏥', 20, true), +('brandschutzhelfer', 'Brandschutzhelfer', 'Ausbildung zum Brandschutzhelfer', 'safety', true, 36, false, '🔥', 21, true), +('evakuierungshelfer', 'Evakuierungshelfer', 'Ausbildung zum Evakuierungshelfer', 'safety', true, 24, false, '🚪', 22, true), +('defibrillator', 'AED/Defibrillator', 'Einweisung Automatisierter Externer Defibrillator', 'safety', true, 24, false, '💓', 23, true), + +-- Führerscheine +('fuehrerschein_b', 'Führerschein Klasse B', 'PKW Führerschein', 'driving', true, NULL, false, '🚗', 30, true), +('fuehrerschein_c', 'Führerschein Klasse C', 'LKW Führerschein', 'driving', true, 60, false, '🚛', 31, true), +('fuehrerschein_d', 'Führerschein Klasse D', 'Bus Führerschein', 'driving', true, 60, false, '🚌', 32, true), + +-- Spezial-Ausbildungen +('personenschutz', 'Personenschutz', 'Ausbildung zum Personenschützer', 'special', false, NULL, false, '🛡️', 40, true), +('hundefuehrer', 'Diensthundeführer', 'Ausbildung zum Diensthundeführer', 'special', true, 12, false, '🐕', 41, true), +('intervention', 'Interventionskraft', 'Ausbildung zur Interventionskraft (IK)', 'special', false, NULL, false, '⚡', 42, true), +('nsk', 'NSK (Notruf-Service-Kraft)', 'Notruf- und Service-Leitstelle', 'special', false, NULL, false, '📞', 43, true), + +-- Sprachen +('sprache_englisch', 'Englisch', 'Englischkenntnisse', 'language', false, NULL, false, '🇬🇧', 50, true), +('sprache_franzoesisch', 'Französisch', 'Französischkenntnisse', 'language', false, NULL, false, '🇫🇷', 51, true), +('sprache_russisch', 'Russisch', 'Russischkenntnisse', 'language', false, NULL, false, '🇷🇺', 52, true), +('sprache_tuerkisch', 'Türkisch', 'Türkischkenntnisse', 'language', false, NULL, false, '🇹🇷', 53, true), +('sprache_arabisch', 'Arabisch', 'Arabischkenntnisse', 'language', false, NULL, false, '🇸🇦', 54, true) + +ON CONFLICT (key) DO NOTHING; + +-- Custom Qualifikationstypen pro Organisation +CREATE TABLE IF NOT EXISTS org_qualification_types ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, + key VARCHAR(50) NOT NULL, + name VARCHAR(100) NOT NULL, + description TEXT, + category VARCHAR(50) DEFAULT 'custom', + has_expiry BOOLEAN DEFAULT true, + validity_months INTEGER, + icon VARCHAR(10) DEFAULT '📜', + sort_order INTEGER DEFAULT 100, + created_at TIMESTAMPTZ DEFAULT NOW(), + UNIQUE(org_id, key) +); + +-- Mitarbeiter-Qualifikationen +CREATE TABLE IF NOT EXISTS employee_qualifications ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, + org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, + + -- Entweder System-Typ oder Custom-Typ + qualification_type_id UUID REFERENCES qualification_types(id), + org_qualification_type_id UUID REFERENCES org_qualification_types(id), + + -- Daten + issued_date DATE, -- Ausstellungsdatum + expiry_date DATE, -- Ablaufdatum (falls zutreffend) + issuer VARCHAR(255), -- Ausstellende Stelle + certificate_number VARCHAR(100), -- Zertifikatsnummer + + -- Level/Stufe (optional) + level VARCHAR(50), -- z.B. "A1", "B2" für Sprachen + + -- Dokument + document_url TEXT, -- Scan des Zertifikats + document_name VARCHAR(255), + + -- Status + status VARCHAR(20) DEFAULT 'active', -- active, expired, revoked, pending + verified_by UUID REFERENCES users(id), -- Wer hat verifiziert + verified_at TIMESTAMPTZ, + + -- Notizen + notes TEXT, + + created_at TIMESTAMPTZ DEFAULT NOW(), + updated_at TIMESTAMPTZ DEFAULT NOW(), + + -- Constraint: Entweder System-Typ oder Custom-Typ + CONSTRAINT chk_qualification_type CHECK ( + (qualification_type_id IS NOT NULL AND org_qualification_type_id IS NULL) OR + (qualification_type_id IS NULL AND org_qualification_type_id IS NOT NULL) + ) +); + +-- Index für schnelle Abfragen +CREATE INDEX IF NOT EXISTS idx_emp_qual_user ON employee_qualifications(user_id); +CREATE INDEX IF NOT EXISTS idx_emp_qual_org ON employee_qualifications(org_id); +CREATE INDEX IF NOT EXISTS idx_emp_qual_expiry ON employee_qualifications(expiry_date); +CREATE INDEX IF NOT EXISTS idx_emp_qual_status ON employee_qualifications(status); + +-- Erinnerungen für ablaufende Qualifikationen +CREATE TABLE IF NOT EXISTS qualification_reminders ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + employee_qualification_id UUID NOT NULL REFERENCES employee_qualifications(id) ON DELETE CASCADE, + reminder_date DATE NOT NULL, + days_before INTEGER NOT NULL, -- 30, 14, 7, 1 + sent BOOLEAN DEFAULT false, + sent_at TIMESTAMPTZ, + created_at TIMESTAMPTZ DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_qual_reminder_date ON qualification_reminders(reminder_date, sent); + +-- View: Qualifikationen mit Details +CREATE OR REPLACE VIEW v_employee_qualifications AS +SELECT + eq.id, + eq.user_id, + eq.org_id, + u.first_name, + u.last_name, + u.email, + COALESCE(qt.key, oqt.key) as qualification_key, + COALESCE(qt.name, oqt.name) as qualification_name, + COALESCE(qt.category, oqt.category) as category, + COALESCE(qt.icon, oqt.icon) as icon, + COALESCE(qt.has_expiry, oqt.has_expiry) as has_expiry, + eq.issued_date, + eq.expiry_date, + eq.issuer, + eq.certificate_number, + eq.level, + eq.document_url, + eq.status, + eq.verified_by, + eq.verified_at, + eq.notes, + eq.created_at, + -- Berechnete Felder + CASE + WHEN eq.expiry_date IS NULL THEN 'no_expiry' + WHEN eq.expiry_date < CURRENT_DATE THEN 'expired' + WHEN eq.expiry_date < CURRENT_DATE + INTERVAL '30 days' THEN 'expiring_soon' + ELSE 'valid' + END as expiry_status, + CASE + WHEN eq.expiry_date IS NOT NULL + THEN eq.expiry_date - CURRENT_DATE + ELSE NULL + END as days_until_expiry +FROM employee_qualifications eq +JOIN users u ON eq.user_id = u.id +LEFT JOIN qualification_types qt ON eq.qualification_type_id = qt.id +LEFT JOIN org_qualification_types oqt ON eq.org_qualification_type_id = oqt.id; + +-- Modul in modules Tabelle einfügen +INSERT INTO modules (key, name, description, icon, is_premium, price_monthly, price_yearly, sort_order) VALUES +('qualifications', 'Qualifikationen', 'Zertifikate, Nachweise & Ablauf-Tracking', '🎓', true, 29.00, 290.00, 10) +ON CONFLICT (key) DO UPDATE SET + name = EXCLUDED.name, + description = EXCLUDED.description, + price_monthly = EXCLUDED.price_monthly, + price_yearly = EXCLUDED.price_yearly;