From de486aeab05c8d1ed40caaf00cd94295ef1b4af2 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Sun, 8 Mar 2026 23:53:52 +0100 Subject: [PATCH] =?UTF-8?q?feat(sdk):=20Step=206=20nach=20Abteilungen=20+?= =?UTF-8?q?=20aktivit=C3=A4tsspezifische=20Datenkategorien?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Verarbeitungstätigkeiten nach 11+ Abteilungen gruppiert (Personal, Finanzen, Vertrieb, Marketing, IT, Recht, Einkauf, Produktion, Logistik, Kundenservice, Facility) - Branchenspezifische Abteilungen (E-Commerce, Gesundheit, Finanz, Bildung, Immobilien) - 3-Stufen Datenkategorien: primär (sichtbar), weitere (aufklappbar), Art. 9 (rot, nur wenn plausibel relevant) - Bundesland/Kanton-Dropdown für DE (16), AT (9), CH (26) statt Freitext Co-Authored-By: Claude Opus 4.6 --- .../app/sdk/company-profile/page.tsx | 688 +++++++++++------- 1 file changed, 433 insertions(+), 255 deletions(-) diff --git a/admin-compliance/app/sdk/company-profile/page.tsx b/admin-compliance/app/sdk/company-profile/page.tsx index 8b69a93..0c47762 100644 --- a/admin-compliance/app/sdk/company-profile/page.tsx +++ b/admin-compliance/app/sdk/company-profile/page.tsx @@ -382,9 +382,37 @@ function StepLocations({ } } - const stateLabel = data.headquartersCountry === 'CH' ? 'Kanton' : - data.headquartersCountry === 'AT' ? 'Bundesland' : - data.headquartersCountry === 'DE' ? 'Bundesland' : 'Region / Provinz' + const STATES_BY_COUNTRY: Record = { + DE: { + label: 'Bundesland', + options: [ + 'Baden-Württemberg', 'Bayern', 'Berlin', 'Brandenburg', 'Bremen', + 'Hamburg', 'Hessen', 'Mecklenburg-Vorpommern', 'Niedersachsen', + 'Nordrhein-Westfalen', 'Rheinland-Pfalz', 'Saarland', 'Sachsen', + 'Sachsen-Anhalt', 'Schleswig-Holstein', 'Thüringen', + ], + }, + AT: { + label: 'Bundesland', + options: [ + 'Burgenland', 'Kärnten', 'Niederösterreich', 'Oberösterreich', + 'Salzburg', 'Steiermark', 'Tirol', 'Vorarlberg', 'Wien', + ], + }, + CH: { + label: 'Kanton', + options: [ + 'Aargau', 'Appenzell Ausserrhoden', 'Appenzell Innerrhoden', + 'Basel-Landschaft', 'Basel-Stadt', 'Bern', 'Freiburg', 'Genf', + 'Glarus', 'Graubünden', 'Jura', 'Luzern', 'Neuenburg', 'Nidwalden', + 'Obwalden', 'Schaffhausen', 'Schwyz', 'Solothurn', 'St. Gallen', + 'Tessin', 'Thurgau', 'Uri', 'Waadt', 'Wallis', 'Zug', 'Zürich', + ], + }, + } + + const countryStates = data.headquartersCountry ? STATES_BY_COUNTRY[data.headquartersCountry] : null + const stateLabel = countryStates?.label || 'Region / Provinz' return (
@@ -464,13 +492,26 @@ function StepLocations({ {/* State / Bundesland / Kanton */}
- onChange({ headquartersState: e.target.value })} - placeholder={data.headquartersCountry === 'CH' ? 'z.B. Zürich' : data.headquartersCountry === 'AT' ? 'z.B. Wien' : 'z.B. Bayern'} - className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" - /> + {countryStates ? ( + + ) : ( + onChange({ headquartersState: e.target.value })} + placeholder="Region / Provinz" + className="w-full px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent" + /> + )}
@@ -596,7 +637,7 @@ function StepDataProtection({ // ============================================================================= // DSGVO-Standard Datenkategorien -const DATA_CATEGORIES = [ +const ALL_DATA_CATEGORIES = [ { id: 'stammdaten', label: 'Stammdaten', desc: 'Name, Geburtsdatum, Geschlecht' }, { id: 'kontaktdaten', label: 'Kontaktdaten', desc: 'E-Mail, Telefon, Adresse' }, { id: 'vertragsdaten', label: 'Vertragsdaten', desc: 'Vertragsnummer, Laufzeit, Konditionen' }, @@ -609,7 +650,7 @@ const DATA_CATEGORIES = [ { id: 'bewerberdaten', label: 'Bewerberdaten', desc: 'Lebenslauf, Zeugnisse, Anschreiben' }, ] as const -const SPECIAL_DATA_CATEGORIES = [ +const ALL_SPECIAL_CATEGORIES = [ { id: 'gesundheit', label: 'Gesundheitsdaten', desc: 'Krankheitstage, Atteste, Diagnosen' }, { id: 'biometrie', label: 'Biometrische Daten', desc: 'Fingerabdruck, Gesichtserkennung' }, { id: 'religion', label: 'Religiöse Überzeugungen', desc: 'Konfession, Feiertage' }, @@ -625,68 +666,188 @@ const LEGAL_BASES = [ { id: 'interest', label: 'Berechtigtes Interesse (Art. 6 Abs. 1f)' }, ] as const -// Verarbeitungstätigkeiten-Vorlagen nach Branche -interface ProcessingActivityTemplate { +// Verarbeitungstätigkeiten mit aktivitätsspezifischen Datenkategorien +interface ActivityTemplate { id: string name: string purpose: string - default_categories: string[] + primary_categories: string[] // Sichtbar + vorausgewählt + art9_relevant: string[] // Art. 9 Kategorien die plausibel relevant sind default_legal_basis: string } -const COMMON_ACTIVITIES: ProcessingActivityTemplate[] = [ - { id: 'personal', name: 'Personalverwaltung', purpose: 'Verwaltung von Mitarbeiterdaten, Gehaltsabrechnung, Arbeitszeitverwaltung', default_categories: ['stammdaten', 'kontaktdaten', 'beschaeftigtendaten', 'zahlungsdaten'], default_legal_basis: 'contract' }, - { id: 'buchhaltung', name: 'Buchhaltung / Rechnungswesen', purpose: 'Rechnungsstellung, Zahlungsabwicklung, Steuerliche Pflichten', default_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten', 'zahlungsdaten'], default_legal_basis: 'legal' }, - { id: 'bewerbung', name: 'Bewerbermanagement', purpose: 'Verwaltung von Bewerbungen und Auswahlverfahren', default_categories: ['stammdaten', 'kontaktdaten', 'bewerberdaten'], default_legal_basis: 'consent' }, - { id: 'website', name: 'Website-Betrieb', purpose: 'Bereitstellung der Unternehmenswebsite, Analytics, Kontaktformulare', default_categories: ['nutzungsdaten', 'kontaktdaten'], default_legal_basis: 'interest' }, - { id: 'email', name: 'E-Mail-Kommunikation', purpose: 'Geschäftliche E-Mail-Korrespondenz', default_categories: ['stammdaten', 'kontaktdaten', 'kommunikation'], default_legal_basis: 'interest' }, -] - -const INDUSTRY_ACTIVITIES: Record = { - 'Technologie / IT': [ - { id: 'crm', name: 'CRM / Kundenverwaltung', purpose: 'Pflege von Kundenbeziehungen, Vertriebspipeline', default_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten', 'kommunikation'], default_legal_basis: 'contract' }, - { id: 'support', name: 'Support / Ticketsystem', purpose: 'Kundenanfragen bearbeiten, Fehlerbehebung', default_categories: ['stammdaten', 'kontaktdaten', 'kommunikation', 'nutzungsdaten'], default_legal_basis: 'contract' }, - { id: 'saas', name: 'SaaS-Plattform / Nutzerkonten', purpose: 'Bereitstellung der Software, Nutzerverwaltung', default_categories: ['stammdaten', 'kontaktdaten', 'nutzungsdaten', 'vertragsdaten'], default_legal_basis: 'contract' }, - ], - 'E-Commerce / Handel': [ - { id: 'bestellung', name: 'Bestellabwicklung', purpose: 'Bestellannahme, Zahlungsabwicklung, Versand', default_categories: ['stammdaten', 'kontaktdaten', 'zahlungsdaten', 'vertragsdaten', 'standortdaten'], default_legal_basis: 'contract' }, - { id: 'kundenkonto', name: 'Kundenkonto-Verwaltung', purpose: 'Registrierung, Login, Bestellhistorie', default_categories: ['stammdaten', 'kontaktdaten', 'nutzungsdaten'], default_legal_basis: 'contract' }, - { id: 'newsletter', name: 'Newsletter / Marketing', purpose: 'E-Mail-Marketing, Werbeaktionen', default_categories: ['stammdaten', 'kontaktdaten', 'nutzungsdaten'], default_legal_basis: 'consent' }, - ], - 'Finanzdienstleistungen': [ - { id: 'konto', name: 'Kontoverwaltung', purpose: 'Kontoeröffnung, KYC, Kontopflege', default_categories: ['stammdaten', 'kontaktdaten', 'zahlungsdaten', 'vertragsdaten'], default_legal_basis: 'contract' }, - { id: 'compliance_fin', name: 'Regulatorische Pflichten', purpose: 'Geldwäscheprävention, Meldepflichten', default_categories: ['stammdaten', 'zahlungsdaten'], default_legal_basis: 'legal' }, - ], - 'Gesundheitswesen': [ - { id: 'patient', name: 'Patientenverwaltung', purpose: 'Aufnahme, Behandlung, Dokumentation', default_categories: ['stammdaten', 'kontaktdaten', 'gesundheit'], default_legal_basis: 'contract' }, - { id: 'termin', name: 'Terminplanung', purpose: 'Terminvergabe und -verwaltung', default_categories: ['stammdaten', 'kontaktdaten'], default_legal_basis: 'contract' }, - { id: 'abrechnung_kv', name: 'Abrechnung / KV', purpose: 'Kassenärztliche Abrechnung, Privatliquidation', default_categories: ['stammdaten', 'zahlungsdaten', 'gesundheit'], default_legal_basis: 'legal' }, - ], - 'Beratung / Consulting': [ - { id: 'crm', name: 'CRM / Kundenverwaltung', purpose: 'Pflege von Kundenbeziehungen, Projekthistorie', default_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten', 'kommunikation'], default_legal_basis: 'contract' }, - { id: 'projekt', name: 'Projektmanagement', purpose: 'Projektverwaltung, Zeiterfassung, Dokumentation', default_categories: ['stammdaten', 'beschaeftigtendaten', 'kommunikation'], default_legal_basis: 'contract' }, - ], - 'Bildung': [ - { id: 'schueler', name: 'Schüler-/Teilnehmerverwaltung', purpose: 'Verwaltung von Lernenden, Noten, Anwesenheit', default_categories: ['stammdaten', 'kontaktdaten', 'nutzungsdaten'], default_legal_basis: 'contract' }, - { id: 'lernplattform', name: 'Lernplattform / LMS', purpose: 'Bereitstellung von Lernmaterialien, Prüfungen', default_categories: ['stammdaten', 'nutzungsdaten', 'kommunikation'], default_legal_basis: 'contract' }, - ], - 'Marketing / Agentur': [ - { id: 'crm', name: 'CRM / Kundenverwaltung', purpose: 'Pflege von Kundenbeziehungen, Kampagnen', default_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten', 'kommunikation'], default_legal_basis: 'contract' }, - { id: 'campaign', name: 'Kampagnen / Analytics', purpose: 'Werbekampagnen, Tracking, Auswertung', default_categories: ['nutzungsdaten', 'kontaktdaten', 'standortdaten'], default_legal_basis: 'consent' }, - ], - 'Produktion / Industrie': [ - { id: 'lieferanten', name: 'Lieferantenverwaltung', purpose: 'Bestellungen, Lieferantenqualifizierung', default_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten', 'zahlungsdaten'], default_legal_basis: 'contract' }, - { id: 'zutrittskontrolle', name: 'Zutrittskontrolle', purpose: 'Werksgelände-Zugang, Besuchermanagement', default_categories: ['stammdaten', 'standortdaten', 'bilddaten'], default_legal_basis: 'interest' }, - ], +interface ActivityDepartment { + id: string + name: string + icon: string + activities: ActivityTemplate[] } -// Get processing activity templates for the selected industry -function getActivityTemplates(industry: string): ProcessingActivityTemplate[] { - const industrySpecific = INDUSTRY_ACTIVITIES[industry] || [] - // Merge common + industry-specific, avoiding duplicate IDs - const existingIds = new Set(industrySpecific.map(a => a.id)) - const common = COMMON_ACTIVITIES.filter(a => !existingIds.has(a.id)) - return [...industrySpecific, ...common] +// ── Universelle Abteilungen (immer sichtbar) ── + +const UNIVERSAL_DEPARTMENTS: ActivityDepartment[] = [ + { + id: 'personal', name: 'Personal / HR', icon: '👥', + activities: [ + { id: 'personalverwaltung', name: 'Personalverwaltung', purpose: 'Verwaltung von Beschäftigtendaten für das Arbeitsverhältnis', primary_categories: ['stammdaten', 'kontaktdaten', 'beschaeftigtendaten', 'zahlungsdaten'], art9_relevant: ['gesundheit', 'religion', 'gewerkschaft'], default_legal_basis: 'contract' }, + { id: 'lohnbuchhaltung', name: 'Lohn- und Gehaltsabrechnung', purpose: 'Berechnung und Auszahlung von Löhnen und Gehältern', primary_categories: ['beschaeftigtendaten', 'zahlungsdaten', 'stammdaten'], art9_relevant: ['gesundheit', 'religion'], default_legal_basis: 'legal' }, + { id: 'bewerbermanagement', name: 'Bewerbermanagement', purpose: 'Entgegennahme, Prüfung und Bearbeitung von Bewerbungen', primary_categories: ['bewerberdaten', 'stammdaten', 'kontaktdaten', 'kommunikation'], art9_relevant: ['gesundheit'], default_legal_basis: 'consent' }, + { id: 'arbeitszeiterfassung', name: 'Arbeitszeiterfassung', purpose: 'Erfassung und Dokumentation der Arbeitszeiten', primary_categories: ['beschaeftigtendaten'], art9_relevant: [], default_legal_basis: 'legal' }, + { id: 'weiterbildung', name: 'Fort- und Weiterbildung', purpose: 'Verwaltung von Schulungen und Weiterbildungsmaßnahmen', primary_categories: ['beschaeftigtendaten', 'stammdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + ], + }, + { + id: 'finanzen', name: 'Finanzen / Buchhaltung', icon: '💰', + activities: [ + { id: 'finanzbuchhaltung', name: 'Finanzbuchhaltung', purpose: 'Buchführung, Rechnungsstellung, steuerliche Dokumentation', primary_categories: ['stammdaten', 'zahlungsdaten', 'vertragsdaten', 'kontaktdaten'], art9_relevant: [], default_legal_basis: 'legal' }, + { id: 'zahlungsverkehr', name: 'Zahlungsverkehr', purpose: 'Abwicklung von ein- und ausgehenden Zahlungen', primary_categories: ['zahlungsdaten', 'stammdaten', 'kontaktdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'mahnwesen', name: 'Mahnwesen / Inkasso', purpose: 'Überwachung offener Forderungen und Mahnverfahren', primary_categories: ['stammdaten', 'kontaktdaten', 'zahlungsdaten', 'vertragsdaten'], art9_relevant: [], default_legal_basis: 'interest' }, + { id: 'reisekostenabrechnung', name: 'Reisekostenabrechnung', purpose: 'Abrechnung und Erstattung von Dienstreisekosten', primary_categories: ['beschaeftigtendaten', 'zahlungsdaten', 'standortdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + ], + }, + { + id: 'vertrieb', name: 'Vertrieb / Sales', icon: '📈', + activities: [ + { id: 'crm', name: 'CRM / Kundenverwaltung', purpose: 'Verwaltung von Kundenbeziehungen, Kontakthistorie, Verkaufschancen', primary_categories: ['stammdaten', 'kontaktdaten', 'kommunikation', 'vertragsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'angebotserstellung', name: 'Angebotserstellung', purpose: 'Erstellung und Nachverfolgung von Angeboten', primary_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'vertragsmanagement', name: 'Vertragsmanagement', purpose: 'Verwaltung, Archivierung und Nachverfolgung von Verträgen', primary_categories: ['vertragsdaten', 'stammdaten', 'kontaktdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + ], + }, + { + id: 'marketing', name: 'Marketing', icon: '📣', + activities: [ + { id: 'newsletter', name: 'Newsletter / E-Mail-Marketing', purpose: 'Versand von Newslettern und E-Mail-Marketing an Abonnenten', primary_categories: ['kontaktdaten', 'nutzungsdaten', 'stammdaten'], art9_relevant: [], default_legal_basis: 'consent' }, + { id: 'website_tracking', name: 'Website-Tracking / Analytics', purpose: 'Analyse des Nutzerverhaltens auf der Website mittels Tracking-Tools', primary_categories: ['nutzungsdaten', 'standortdaten'], art9_relevant: [], default_legal_basis: 'consent' }, + { id: 'social_media', name: 'Social-Media-Marketing', purpose: 'Betrieb von Unternehmensprofilen und Werbekampagnen', primary_categories: ['kontaktdaten', 'nutzungsdaten', 'kommunikation'], art9_relevant: [], default_legal_basis: 'consent' }, + { id: 'consent_management', name: 'Consent-Management (Cookies)', purpose: 'Verwaltung der Einwilligungen für Cookies und Tracking', primary_categories: ['nutzungsdaten'], art9_relevant: [], default_legal_basis: 'consent' }, + ], + }, + { + id: 'it', name: 'IT / Administration', icon: '🖥️', + activities: [ + { id: 'zugangsverwaltung', name: 'Zugangsverwaltung (IAM)', purpose: 'Verwaltung von Benutzerkonten, Passwörtern und Zugriffsrechten', primary_categories: ['beschaeftigtendaten', 'stammdaten', 'nutzungsdaten'], art9_relevant: ['biometrie'], default_legal_basis: 'contract' }, + { id: 'email_kommunikation', name: 'E-Mail-Kommunikation', purpose: 'Geschäftliche E-Mail-Korrespondenz', primary_categories: ['kontaktdaten', 'kommunikation', 'stammdaten'], art9_relevant: [], default_legal_basis: 'interest' }, + { id: 'datensicherung', name: 'Datensicherung / Backup', purpose: 'Sicherung von Unternehmensdaten zum Schutz vor Datenverlust', primary_categories: ['nutzungsdaten', 'beschaeftigtendaten'], art9_relevant: [], default_legal_basis: 'interest' }, + { id: 'website_betrieb', name: 'Website-Betrieb', purpose: 'Bereitstellung der Unternehmenswebsite und Kontaktformulare', primary_categories: ['nutzungsdaten', 'kontaktdaten'], art9_relevant: [], default_legal_basis: 'interest' }, + { id: 'it_sicherheit', name: 'IT-Sicherheit / Logging', purpose: 'Überwachung der IT-Sicherheit, Log-Analyse, Vorfallbehandlung', primary_categories: ['nutzungsdaten', 'beschaeftigtendaten'], art9_relevant: [], default_legal_basis: 'interest' }, + ], + }, + { + id: 'recht', name: 'Recht / Compliance', icon: '⚖️', + activities: [ + { id: 'datenschutzanfragen', name: 'Betroffenenrechte (DSGVO)', purpose: 'Bearbeitung von Auskunfts-, Lösch- und Berichtigungsanfragen', primary_categories: ['stammdaten', 'kontaktdaten', 'kommunikation'], art9_relevant: [], default_legal_basis: 'legal' }, + { id: 'auftragsverarbeitung', name: 'Auftragsverarbeitung (AVV)', purpose: 'Dokumentation und Verwaltung von Auftragsverarbeitungsverhältnissen', primary_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten'], art9_relevant: [], default_legal_basis: 'legal' }, + { id: 'whistleblowing', name: 'Hinweisgebersystem', purpose: 'Entgegennahme und Bearbeitung von Meldungen nach HinSchG', primary_categories: ['stammdaten', 'kontaktdaten', 'kommunikation'], art9_relevant: [], default_legal_basis: 'legal' }, + ], + }, +] + +// ── Abteilungen die je nach Kontext relevant sind ── + +const OPTIONAL_DEPARTMENTS: ActivityDepartment[] = [ + { + id: 'einkauf', name: 'Einkauf / Beschaffung', icon: '🛒', + activities: [ + { id: 'lieferantenverwaltung', name: 'Lieferantenverwaltung', purpose: 'Erfassung und Pflege von Lieferantenstammdaten', primary_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten', 'zahlungsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'bestellwesen', name: 'Bestellwesen', purpose: 'Abwicklung von Bestellungen bei Lieferanten', primary_categories: ['stammdaten', 'vertragsdaten', 'zahlungsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'lieferantenbewertung', name: 'Lieferantenbewertung', purpose: 'Bewertung und Qualifizierung von Lieferanten', primary_categories: ['stammdaten', 'kontaktdaten'], art9_relevant: [], default_legal_basis: 'interest' }, + ], + }, + { + id: 'produktion', name: 'Produktion / Fertigung', icon: '🏭', + activities: [ + { id: 'produktionsplanung', name: 'Produktionsplanung', purpose: 'Planung und Steuerung von Produktionsprozessen inkl. Personalzuordnung', primary_categories: ['beschaeftigtendaten', 'stammdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'qualitaetskontrolle', name: 'Qualitätskontrolle', purpose: 'Prüfung und Dokumentation der Produktqualität', primary_categories: ['beschaeftigtendaten', 'stammdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'arbeitssicherheit', name: 'Arbeitssicherheit / Arbeitsschutz', purpose: 'Dokumentation von Arbeitsschutzmaßnahmen, Unfällen, Gefährdungsbeurteilungen', primary_categories: ['beschaeftigtendaten'], art9_relevant: ['gesundheit'], default_legal_basis: 'legal' }, + { id: 'schichtplanung', name: 'Schichtplanung', purpose: 'Erstellung und Verwaltung von Schichtplänen', primary_categories: ['beschaeftigtendaten'], art9_relevant: [], default_legal_basis: 'contract' }, + ], + }, + { + id: 'logistik', name: 'Logistik / Versand', icon: '🚚', + activities: [ + { id: 'versandabwicklung', name: 'Versandabwicklung', purpose: 'Verarbeitung von Empfänger- und Versanddaten für den Warenversand', primary_categories: ['stammdaten', 'kontaktdaten', 'standortdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'lieferverfolgung', name: 'Lieferverfolgung / Sendungstracking', purpose: 'Nachverfolgung von Sendungen und Zustellung', primary_categories: ['stammdaten', 'kontaktdaten', 'standortdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'lagerverwaltung', name: 'Lagerverwaltung', purpose: 'Verwaltung von Lagerbeständen und Warenbewegungen', primary_categories: ['stammdaten', 'beschaeftigtendaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'retouren', name: 'Retourenmanagement', purpose: 'Bearbeitung von Warenrücksendungen', primary_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + ], + }, + { + id: 'kundenservice', name: 'Kundenservice / Support', icon: '🎧', + activities: [ + { id: 'ticketsystem', name: 'Ticketsystem / Support', purpose: 'Erfassung und Bearbeitung von Kundenanfragen und Supportfällen', primary_categories: ['stammdaten', 'kontaktdaten', 'kommunikation'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'beschwerdemanagement', name: 'Beschwerdemanagement', purpose: 'Bearbeitung und Dokumentation von Kundenbeschwerden', primary_categories: ['stammdaten', 'kontaktdaten', 'kommunikation'], art9_relevant: [], default_legal_basis: 'contract' }, + ], + }, + { + id: 'facility', name: 'Facility Management', icon: '🏢', + activities: [ + { id: 'zutrittskontrolle', name: 'Zutrittskontrolle', purpose: 'Kontrolle und Protokollierung des Zutritts zu Gebäuden und Räumen', primary_categories: ['beschaeftigtendaten', 'stammdaten', 'bilddaten'], art9_relevant: ['biometrie'], default_legal_basis: 'interest' }, + { id: 'videoueberwachung', name: 'Videoüberwachung', purpose: 'Überwachung von Gebäuden und Geländen mittels Videokameras', primary_categories: ['bilddaten', 'beschaeftigtendaten'], art9_relevant: ['biometrie'], default_legal_basis: 'interest' }, + { id: 'besuchermanagement', name: 'Besuchermanagement', purpose: 'Erfassung und Verwaltung von Besucherdaten', primary_categories: ['stammdaten', 'kontaktdaten'], art9_relevant: [], default_legal_basis: 'interest' }, + ], + }, +] + +// ── Branchenspezifische Abteilungen ── + +const INDUSTRY_DEPARTMENTS: Record = { + 'E-Commerce / Handel': [{ + id: 'ecommerce', name: 'E-Commerce / Webshop', icon: '🛍️', + activities: [ + { id: 'bestellabwicklung', name: 'Bestellabwicklung (Webshop)', purpose: 'Verarbeitung von Kundenbestellungen im Online-Shop', primary_categories: ['stammdaten', 'kontaktdaten', 'zahlungsdaten', 'vertragsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'kundenkonto', name: 'Kundenkonto-Verwaltung', purpose: 'Verwaltung registrierter Kundenkonten im Online-Shop', primary_categories: ['stammdaten', 'kontaktdaten', 'nutzungsdaten', 'zahlungsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'webshop_analyse', name: 'Webshop-Analyse / Conversion', purpose: 'Analyse des Kaufverhaltens und Conversion-Rates', primary_categories: ['nutzungsdaten', 'standortdaten'], art9_relevant: [], default_legal_basis: 'consent' }, + { id: 'produktbewertungen', name: 'Produktbewertungen / Reviews', purpose: 'Verwaltung von Kundenrezensionen und Produktbewertungen', primary_categories: ['stammdaten', 'kontaktdaten', 'kommunikation'], art9_relevant: [], default_legal_basis: 'consent' }, + ], + }], + 'Gesundheitswesen': [{ + id: 'gesundheit_dept', name: 'Medizin / Patientenversorgung', icon: '🏥', + activities: [ + { id: 'patientenverwaltung', name: 'Patientenverwaltung', purpose: 'Verwaltung von Patientenstammdaten und Krankengeschichte', primary_categories: ['stammdaten', 'kontaktdaten', 'zahlungsdaten'], art9_relevant: ['gesundheit', 'genetik'], default_legal_basis: 'contract' }, + { id: 'terminplanung_med', name: 'Terminplanung (Patienten)', purpose: 'Vergabe und Verwaltung von Patiententerminen', primary_categories: ['stammdaten', 'kontaktdaten'], art9_relevant: ['gesundheit'], default_legal_basis: 'contract' }, + { id: 'kv_abrechnung', name: 'KV-Abrechnung', purpose: 'Abrechnung von Leistungen gegenüber Kassenärztlichen Vereinigungen', primary_categories: ['stammdaten', 'zahlungsdaten'], art9_relevant: ['gesundheit'], default_legal_basis: 'legal' }, + { id: 'med_dokumentation', name: 'Medizinische Dokumentation', purpose: 'Dokumentation von Diagnosen, Therapien und Behandlungsverläufen', primary_categories: ['stammdaten'], art9_relevant: ['gesundheit', 'genetik'], default_legal_basis: 'legal' }, + ], + }], + 'Finanzdienstleistungen': [{ + id: 'finanz_dept', name: 'Regulatorik / Finanzaufsicht', icon: '🏦', + activities: [ + { id: 'kyc', name: 'Know Your Customer (KYC)', purpose: 'Identifizierung und Verifizierung von Kunden gemäß GwG', primary_categories: ['stammdaten', 'kontaktdaten', 'bilddaten'], art9_relevant: [], default_legal_basis: 'legal' }, + { id: 'kontoverwaltung', name: 'Kontoverwaltung', purpose: 'Verwaltung von Kundenkonten und Kontobewegungen', primary_categories: ['stammdaten', 'kontaktdaten', 'zahlungsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'geldwaeschepraevention', name: 'Geldwäscheprävention (AML)', purpose: 'Überwachung verdächtiger Transaktionen nach GwG', primary_categories: ['stammdaten', 'zahlungsdaten'], art9_relevant: [], default_legal_basis: 'legal' }, + ], + }], + 'Bildung': [{ + id: 'bildung_dept', name: 'Bildung / Lehre', icon: '🎓', + activities: [ + { id: 'schuelerverwaltung', name: 'Schüler-/Teilnehmerverwaltung', purpose: 'Verwaltung von Lernenden, Noten, Anwesenheit', primary_categories: ['stammdaten', 'kontaktdaten', 'nutzungsdaten'], art9_relevant: ['gesundheit', 'religion'], default_legal_basis: 'contract' }, + { id: 'lernplattform', name: 'Lernplattform / LMS', purpose: 'Bereitstellung und Nutzung digitaler Lernplattformen', primary_categories: ['stammdaten', 'nutzungsdaten', 'kommunikation'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'pruefungsverwaltung', name: 'Prüfungsverwaltung', purpose: 'Verwaltung und Dokumentation von Prüfungen und Noten', primary_categories: ['stammdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + ], + }], + 'Immobilien': [{ + id: 'immobilien_dept', name: 'Immobilienverwaltung', icon: '🏠', + activities: [ + { id: 'mieterverwaltung', name: 'Mieterverwaltung', purpose: 'Verwaltung von Mietverträgen und Mieterdaten', primary_categories: ['stammdaten', 'kontaktdaten', 'vertragsdaten', 'zahlungsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + { id: 'nebenkostenabrechnung', name: 'Nebenkostenabrechnung', purpose: 'Erstellung und Versand von Nebenkostenabrechnungen', primary_categories: ['stammdaten', 'zahlungsdaten'], art9_relevant: [], default_legal_basis: 'contract' }, + ], + }], +} + +// Compute which departments to show based on company context +function getRelevantDepartments(industry: string, businessModel: string | undefined, companySize: string | undefined): ActivityDepartment[] { + const departments: ActivityDepartment[] = [...UNIVERSAL_DEPARTMENTS] + + // Always show optional departments — user can choose + departments.push(...OPTIONAL_DEPARTMENTS) + + // Add industry-specific departments + const industryDepts = INDUSTRY_DEPARTMENTS[industry] + if (industryDepts) { + departments.push(...industryDepts) + } + + return departments } interface ProcessingActivity { @@ -695,6 +856,7 @@ interface ProcessingActivity { purpose: string data_categories: string[] legal_basis: string + department?: string custom?: boolean } @@ -705,6 +867,15 @@ interface AISystem { processes_personal_data: boolean } +// Helper: find template for an activity ID across all departments +function findTemplate(departments: ActivityDepartment[], activityId: string): ActivityTemplate | null { + for (const dept of departments) { + const t = dept.activities.find(a => a.id === activityId) + if (t) return t + } + return null +} + function StepProcessingAndAI({ data, onChange, @@ -716,12 +887,13 @@ function StepProcessingAndAI({ const aiSystems: AISystem[] = (data as any).aiSystems || [] const industry = data.industry || '' const [expandedActivity, setExpandedActivity] = useState(null) + const [collapsedDepts, setCollapsedDepts] = useState>(new Set()) + const [showExtraCategories, setShowExtraCategories] = useState>(new Set()) - // Get suggested templates based on industry - const templates = getActivityTemplates(industry) + const departments = getRelevantDepartments(industry, data.businessModel, data.companySize) const activeIds = new Set(activities.map(a => a.id)) - const toggleActivity = (template: ProcessingActivityTemplate) => { + const toggleActivity = (template: ActivityTemplate, deptId: string) => { if (activeIds.has(template.id)) { onChange({ processingSystems: activities.filter(a => a.id !== template.id) }) } else { @@ -730,8 +902,9 @@ function StepProcessingAndAI({ id: template.id, name: template.name, purpose: template.purpose, - data_categories: [...template.default_categories], + data_categories: [...template.primary_categories], legal_basis: template.default_legal_basis, + department: deptId, }], }) } @@ -752,6 +925,22 @@ function StepProcessingAndAI({ updateActivity(activityId, { data_categories: cats }) } + const toggleDeptCollapse = (deptId: string) => { + setCollapsedDepts(prev => { + const next = new Set(prev) + if (next.has(deptId)) next.delete(deptId); else next.add(deptId) + return next + }) + } + + const toggleExtraCategories = (activityId: string) => { + setShowExtraCategories(prev => { + const next = new Set(prev) + if (next.has(activityId)) next.delete(activityId); else next.add(activityId) + return next + }) + } + const addCustomActivity = () => { const id = `custom_${Date.now()}` onChange({ @@ -772,6 +961,10 @@ function StepProcessingAndAI({ if (expandedActivity === id) setExpandedActivity(null) } + // Count active activities per department + const deptActivityCount = (dept: ActivityDepartment) => + dept.activities.filter(a => activeIds.has(a.id)).length + // AI Systems const addAISystem = () => { onChange({ aiSystems: [...aiSystems, { name: '', vendor: '', purpose: '', processes_personal_data: false }] }) @@ -785,126 +978,189 @@ function StepProcessingAndAI({ onChange({ aiSystems: updated }) } + // Render activity detail panel (shared between template and custom) + const renderActivityDetail = (activity: ProcessingActivity, template: ActivityTemplate | null) => { + const primaryIds = new Set(template?.primary_categories || []) + const art9Ids = new Set(template?.art9_relevant || []) + const primaryCats = ALL_DATA_CATEGORIES.filter(c => primaryIds.has(c.id)) + const extraCats = ALL_DATA_CATEGORIES.filter(c => !primaryIds.has(c.id)) + const relevantArt9 = ALL_SPECIAL_CATEGORIES.filter(c => art9Ids.has(c.id)) + const otherArt9 = ALL_SPECIAL_CATEGORIES.filter(c => !art9Ids.has(c.id)) + const showingExtra = showExtraCategories.has(activity.id) + // For custom activities, show all categories + const isCustom = !template || activity.custom + + return ( +
+ {/* Custom: name + purpose fields */} + {isCustom && ( +
+ updateActivity(activity.id, { name: e.target.value })} placeholder="Name der Verarbeitungstätigkeit" className="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-purple-500 focus:border-transparent" /> + updateActivity(activity.id, { purpose: e.target.value })} placeholder="Zweck der Verarbeitung" className="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-purple-500 focus:border-transparent" /> +
+ )} + + {/* Primary Data Categories */} +
+ +
+ {(isCustom ? ALL_DATA_CATEGORIES : primaryCats).map(cat => ( + + ))} +
+
+ + {/* Extra categories (expandable, only for template-based) */} + {!isCustom && extraCats.length > 0 && ( +
+ + {showingExtra && ( +
+ {extraCats.map(cat => ( + + ))} +
+ )} +
+ )} + + {/* Art. 9 Special Categories — only show if relevant for this activity */} + {(isCustom ? ALL_SPECIAL_CATEGORIES.length > 0 : relevantArt9.length > 0) && ( +
+ +
+ {(isCustom ? ALL_SPECIAL_CATEGORIES : relevantArt9).map(cat => ( + + ))} +
+ {/* Show remaining Art. 9 categories if expanded */} + {!isCustom && otherArt9.length > 0 && showingExtra && ( +
+ {otherArt9.map(cat => ( + + ))} +
+ )} +
+ )} + + {/* Legal Basis */} +
+ + +
+ + +
+ ) + } + return (
- {/* Processing Activities */} + {/* Processing Activities grouped by department */}

Verarbeitungstätigkeiten

- Wählen Sie aus, welche Verarbeitungstätigkeiten in Ihrem Unternehmen stattfinden. Diese bilden die Grundlage für Ihr Verarbeitungsverzeichnis (VVT) nach Art. 30 DSGVO. + Wählen Sie pro Abteilung aus, welche Verarbeitungen stattfinden. Diese bilden die Grundlage für Ihr Verarbeitungsverzeichnis (VVT) nach Art. 30 DSGVO.

- {/* Template checkboxes */} -
- {templates.map(template => { - const isActive = activeIds.has(template.id) - const activity = activities.find(a => a.id === template.id) - const isExpanded = expandedActivity === template.id +
+ {departments.map(dept => { + const isCollapsed = collapsedDepts.has(dept.id) + const activeCount = deptActivityCount(dept) return ( -
-
{ - if (!isActive) { - toggleActivity(template) - setExpandedActivity(template.id) - } else { - setExpandedActivity(isExpanded ? null : template.id) - } - }} +
+ {/* Department header */} +
+ + + + - {/* Expanded detail: data categories + legal basis */} - {isActive && isExpanded && activity && ( -
- {/* Data Categories */} -
- -
- {DATA_CATEGORIES.map(cat => ( -
+ ) + })}
)}
@@ -914,12 +1170,12 @@ function StepProcessingAndAI({ {/* Custom activities */} {activities.filter(a => a.custom).map(activity => ( -
+
setExpandedActivity(expandedActivity === activity.id ? null : activity.id)} > - + +
{activity.name || 'Neue Verarbeitungstätigkeit'}
@@ -927,85 +1183,7 @@ function StepProcessingAndAI({
- - {expandedActivity === activity.id && ( -
-
- updateActivity(activity.id, { name: e.target.value })} - placeholder="Name der Verarbeitungstätigkeit" - className="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-purple-500 focus:border-transparent" - /> - updateActivity(activity.id, { purpose: e.target.value })} - placeholder="Zweck der Verarbeitung" - className="px-3 py-2 border border-gray-300 rounded-lg text-sm focus:ring-2 focus:ring-purple-500 focus:border-transparent" - /> -
- - {/* Data Categories */} -
- -
- {DATA_CATEGORIES.map(cat => ( - - ))} -
-
- - {/* Special Categories */} -
- -
- {SPECIAL_DATA_CATEGORIES.map(cat => ( - - ))} -
-
- - {/* Legal Basis */} -
- - -
- - -
- )} + {expandedActivity === activity.id && renderActivityDetail(activity, null)}
))} @@ -1013,7 +1191,7 @@ function StepProcessingAndAI({