fix(scope): Evaluierung crasht (answerValue→value), Profil-Persistenz, Block-Umbenennungen
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-ai-compliance (push) Failing after 36s
CI / test-python-backend-compliance (push) Successful in 42s
CI / test-python-document-crawler (push) Successful in 27s
CI / test-python-dsms-gateway (push) Successful in 25s

- compliance-scope-engine: answerValue→value (Property existierte nicht, Crash bei Evaluierung)
- company-profile: saveProfileDraft synct jetzt Redux-State (Daten bleiben bei Navigation)
- Scope-Bloecke umbenannt: Kunden & Nutzer, Datenverarbeitung, Hosting & Verarbeitung, Website und Services
- org_cert_target + data_volume als Hidden Scoring Questions (Duplikate entfernt)
- ai_risk_assessment: boolean→single mit Ja/Nein/Noch nicht
- 6 neue Abteilungs-Datenkategorien: IT, Recht, Produktion, Logistik, Einkauf, Facility

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-10 16:33:59 +01:00
parent ee6743c7c6
commit 579fe1b5e1
5 changed files with 216 additions and 64 deletions

View File

@@ -2608,6 +2608,8 @@ export default function CompanyProfilePage() {
headers: { 'Content-Type': 'application/json' }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(buildProfilePayload(false)), body: JSON.stringify(buildProfilePayload(false)),
}) })
// Sync draft to Redux so it persists across navigation
setCompanyProfile({ ...formData, isComplete: false, completedAt: null } as CompanyProfile)
setDraftSaveStatus('saved') setDraftSaveStatus('saved')
// Reset status after 3 seconds // Reset status after 3 seconds
if (draftSaveTimerRef.current) clearTimeout(draftSaveTimerRef.current) if (draftSaveTimerRef.current) clearTimeout(draftSaveTimerRef.current)

View File

@@ -580,7 +580,13 @@ const DEPT_VALUE_TO_KEY: Record<string, string[]> = {
finanzen: ['dept_finance'], finanzen: ['dept_finance'],
vertrieb: ['dept_sales'], vertrieb: ['dept_sales'],
marketing: ['dept_marketing'], marketing: ['dept_marketing'],
it: ['dept_it'],
recht: ['dept_recht'],
kundenservice: ['dept_support'], kundenservice: ['dept_support'],
produktion: ['dept_produktion'],
logistik: ['dept_logistik'],
einkauf: ['dept_einkauf'],
facility: ['dept_facility'],
} }
/** Mapping department key → scope question ID for Block 9 */ /** Mapping department key → scope question ID for Block 9 */
@@ -591,6 +597,12 @@ const DEPT_KEY_TO_QUESTION: Record<string, string> = {
dept_sales: 'dk_dept_sales', dept_sales: 'dk_dept_sales',
dept_marketing: 'dk_dept_marketing', dept_marketing: 'dk_dept_marketing',
dept_support: 'dk_dept_support', dept_support: 'dk_dept_support',
dept_it: 'dk_dept_it',
dept_recht: 'dk_dept_recht',
dept_produktion: 'dk_dept_produktion',
dept_logistik: 'dk_dept_logistik',
dept_einkauf: 'dk_dept_einkauf',
dept_facility: 'dk_dept_facility',
} }
function DatenkategorienBlock9({ function DatenkategorienBlock9({

View File

@@ -1062,32 +1062,32 @@ export class ComplianceScopeEngine {
* Bestimmt den Multiplikator für eine Antwort (0.0 - 1.0) * Bestimmt den Multiplikator für eine Antwort (0.0 - 1.0)
*/ */
private getAnswerMultiplier(answer: ScopeProfilingAnswer): number { private getAnswerMultiplier(answer: ScopeProfilingAnswer): number {
const { questionId, answerValue } = answer const { questionId, value } = answer
// Boolean // Boolean
if (typeof answerValue === 'boolean') { if (typeof value === 'boolean') {
return answerValue ? 1.0 : 0.0 return value ? 1.0 : 0.0
} }
// Number // Number
if (typeof answerValue === 'number') { if (typeof value === 'number') {
return this.normalizeNumericAnswer(questionId, answerValue) return this.normalizeNumericAnswer(questionId, value)
} }
// Single choice // Single choice
if (typeof answerValue === 'string') { if (typeof value === 'string') {
const multipliers = ANSWER_MULTIPLIERS[questionId] const multipliers = ANSWER_MULTIPLIERS[questionId]
if (multipliers && multipliers[answerValue] !== undefined) { if (multipliers && multipliers[value] !== undefined) {
return multipliers[answerValue] return multipliers[value]
} }
return 0.5 // Fallback return 0.5 // Fallback
} }
// Multi choice // Multi choice
if (Array.isArray(answerValue)) { if (Array.isArray(value)) {
if (answerValue.length === 0) return 0.0 if (value.length === 0) return 0.0
// Simplified: count selected items // Simplified: count selected items
return Math.min(answerValue.length / 5, 1.0) return Math.min(value.length / 5, 1.0)
} }
return 0.0 return 0.0
@@ -1110,7 +1110,7 @@ export class ComplianceScopeEngine {
*/ */
evaluateHardTriggers(answers: ScopeProfilingAnswer[], companyProfile?: CompanyProfile | null): TriggeredHardTrigger[] { evaluateHardTriggers(answers: ScopeProfilingAnswer[], companyProfile?: CompanyProfile | null): TriggeredHardTrigger[] {
const triggered: TriggeredHardTrigger[] = [] const triggered: TriggeredHardTrigger[] = []
const answerMap = new Map(answers.map((a) => [a.questionId, a.answerValue])) const answerMap = new Map(answers.map((a) => [a.questionId, a.value]))
for (const rule of HARD_TRIGGER_RULES) { for (const rule of HARD_TRIGGER_RULES) {
const isTriggered = this.checkTriggerCondition(rule, answerMap, answers, companyProfile) const isTriggered = this.checkTriggerCondition(rule, answerMap, answers, companyProfile)
@@ -1186,39 +1186,39 @@ export class ComplianceScopeEngine {
} }
// Standard answer-based triggers // Standard answer-based triggers
const answerValue = answerMap.get(rule.questionId) const value = answerMap.get(rule.questionId)
if (answerValue === undefined) return false if (value === undefined) return false
// Basis-Check // Basis-Check
let baseCondition = false let baseCondition = false
switch (rule.condition) { switch (rule.condition) {
case 'EQUALS': case 'EQUALS':
baseCondition = answerValue === rule.conditionValue baseCondition = value === rule.conditionValue
break break
case 'CONTAINS': case 'CONTAINS':
if (Array.isArray(answerValue)) { if (Array.isArray(value)) {
baseCondition = answerValue.includes(rule.conditionValue) baseCondition = value.includes(rule.conditionValue)
} else if (typeof answerValue === 'string') { } else if (typeof value === 'string') {
baseCondition = answerValue.includes(rule.conditionValue) baseCondition = value.includes(rule.conditionValue)
} }
break break
case 'IN': case 'IN':
if (Array.isArray(rule.conditionValue)) { if (Array.isArray(rule.conditionValue)) {
baseCondition = rule.conditionValue.includes(answerValue) baseCondition = rule.conditionValue.includes(value)
} }
break break
case 'GREATER_THAN': case 'GREATER_THAN':
if (typeof answerValue === 'number' && typeof rule.conditionValue === 'number') { if (typeof value === 'number' && typeof rule.conditionValue === 'number') {
baseCondition = answerValue > rule.conditionValue baseCondition = value > rule.conditionValue
} else if (typeof answerValue === 'string') { } else if (typeof value === 'string') {
// Parse employee count from string like "1000+" // Parse employee count from string like "1000+"
const parsed = this.parseEmployeeCount(answerValue) const parsed = this.parseEmployeeCount(value)
baseCondition = parsed > (rule.conditionValue as number) baseCondition = parsed > (rule.conditionValue as number)
} }
break break
case 'NOT_EQUALS': case 'NOT_EQUALS':
baseCondition = answerValue !== rule.conditionValue baseCondition = value !== rule.conditionValue
break break
} }
@@ -1404,7 +1404,7 @@ export class ComplianceScopeEngine {
level: ComplianceDepthLevel level: ComplianceDepthLevel
): RiskFlag[] { ): RiskFlag[] {
const flags: RiskFlag[] = [] const flags: RiskFlag[] = []
const answerMap = new Map(answers.map((a) => [a.questionId, a.answerValue])) const answerMap = new Map(answers.map((a) => [a.questionId, a.value]))
// Process Maturity Gaps (Kategorie I Trigger) // Process Maturity Gaps (Kategorie I Trigger)
const maturityRules = HARD_TRIGGER_RULES.filter((r) => r.category === 'process_maturity') const maturityRules = HARD_TRIGGER_RULES.filter((r) => r.category === 'process_maturity')
@@ -1503,7 +1503,7 @@ export class ComplianceScopeEngine {
level: ComplianceDepthLevel level: ComplianceDepthLevel
): ScopeGap[] { ): ScopeGap[] {
const gaps: ScopeGap[] = [] const gaps: ScopeGap[] = []
const answerMap = new Map(answers.map((a) => [a.questionId, a.answerValue])) const answerMap = new Map(answers.map((a) => [a.questionId, a.value]))
// DSFA Gap (bei L3+) // DSFA Gap (bei L3+)
if (getDepthLevelNumeric(level) >= 3) { if (getDepthLevelNumeric(level) >= 3) {

View File

@@ -21,14 +21,16 @@ export const PROFILE_AUTOFILL_QUESTION_IDS = [
'org_industry', 'org_industry',
'org_business_model', 'org_business_model',
'org_has_dsb', 'org_has_dsb',
'org_cert_target',
'data_volume',
'prod_type', 'prod_type',
'prod_webshop', 'prod_webshop',
] as const ] as const
const BLOCK_1_ORGANISATION: ScopeQuestionBlock = { const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
id: 'organisation', id: 'organisation',
title: 'Organisation & Reife', title: 'Kunden & Nutzer',
description: 'Grundlegende Informationen zu Ihrer Organisation und Compliance-Zielen', description: 'Informationen zu Ihren Kunden und Nutzern',
order: 1, order: 1,
questions: [ questions: [
{ {
@@ -46,22 +48,6 @@ const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
], ],
scoreWeights: { risk: 6, complexity: 7, assurance: 6 }, scoreWeights: { risk: 6, complexity: 7, assurance: 6 },
}, },
{
id: 'org_cert_target',
type: 'multi',
question: 'Welche Zertifizierungen streben Sie an oder besitzen Sie bereits?',
helpText: 'Mehrfachauswahl möglich. Zertifizierungen erhöhen den Assurance-Bedarf',
required: false,
options: [
{ value: 'ISO27001', label: 'ISO 27001 (Informationssicherheit)' },
{ value: 'ISO27701', label: 'ISO 27701 (Datenschutz-Erweiterung)' },
{ value: 'TISAX', label: 'TISAX (Automotive)' },
{ value: 'SOC2', label: 'SOC 2 (US-Standard)' },
{ value: 'BSI-Grundschutz', label: 'BSI IT-Grundschutz' },
{ value: 'Keine', label: 'Keine Zertifizierung geplant' },
],
scoreWeights: { risk: 3, complexity: 5, assurance: 10 },
},
], ],
} }
@@ -70,7 +56,7 @@ const BLOCK_1_ORGANISATION: ScopeQuestionBlock = {
*/ */
const BLOCK_2_DATA: ScopeQuestionBlock = { const BLOCK_2_DATA: ScopeQuestionBlock = {
id: 'data', id: 'data',
title: 'Daten & Betroffene', title: 'Datenverarbeitung',
description: 'Art und Umfang der verarbeiteten personenbezogenen Daten', description: 'Art und Umfang der verarbeiteten personenbezogenen Daten',
order: 2, order: 2,
questions: [ questions: [
@@ -131,21 +117,6 @@ const BLOCK_2_DATA: ScopeQuestionBlock = {
mapsToVVTQuestion: 'dept_finance', mapsToVVTQuestion: 'dept_finance',
mapsToLFQuestion: 'data-buchhaltung', mapsToLFQuestion: 'data-buchhaltung',
}, },
{
id: 'data_volume',
type: 'single',
question: 'Wie viele Personendatensätze verarbeiten Sie insgesamt?',
helpText: 'Schätzen Sie die Gesamtzahl betroffener Personen',
required: true,
options: [
{ value: '<1000', label: 'Unter 1.000' },
{ value: '1000-10000', label: '1.000 bis 10.000' },
{ value: '10000-100000', label: '10.000 bis 100.000' },
{ value: '100000-1000000', label: '100.000 bis 1 Mio.' },
{ value: '>1000000', label: 'Über 1 Mio.' },
],
scoreWeights: { risk: 7, complexity: 6, assurance: 6 },
},
], ],
} }
@@ -224,7 +195,7 @@ const BLOCK_3_PROCESSING: ScopeQuestionBlock = {
*/ */
const BLOCK_4_TECH: ScopeQuestionBlock = { const BLOCK_4_TECH: ScopeQuestionBlock = {
id: 'tech', id: 'tech',
title: 'Technik, Hosting & Transfers', title: 'Hosting & Verarbeitung',
description: 'Technische Infrastruktur und Datenübermittlung', description: 'Technische Infrastruktur und Datenübermittlung',
order: 4, order: 4,
questions: [ questions: [
@@ -354,7 +325,7 @@ const BLOCK_5_PROCESSES: ScopeQuestionBlock = {
*/ */
const BLOCK_6_PRODUCT: ScopeQuestionBlock = { const BLOCK_6_PRODUCT: ScopeQuestionBlock = {
id: 'product', id: 'product',
title: 'Produktkontext', title: 'Website und Services',
description: 'Spezifische Merkmale Ihrer Produkte und Services', description: 'Spezifische Merkmale Ihrer Produkte und Services',
order: 6, order: 6,
questions: [ questions: [
@@ -433,6 +404,20 @@ export const HIDDEN_SCORING_QUESTIONS: ScopeProfilingQuestion[] = [
required: false, required: false,
scoreWeights: { risk: 5, complexity: 3, assurance: 6 }, scoreWeights: { risk: 5, complexity: 3, assurance: 6 },
}, },
{
id: 'org_cert_target',
type: 'multi',
question: 'Zertifizierungen (aus Profil)',
required: false,
scoreWeights: { risk: 3, complexity: 5, assurance: 10 },
},
{
id: 'data_volume',
type: 'single',
question: 'Personendatensaetze (aus Profil)',
required: false,
scoreWeights: { risk: 7, complexity: 6, assurance: 6 },
},
{ {
id: 'prod_type', id: 'prod_type',
type: 'multi', type: 'multi',
@@ -494,10 +479,15 @@ const BLOCK_7_AI_SYSTEMS: ScopeQuestionBlock = {
}, },
{ {
id: 'ai_risk_assessment', id: 'ai_risk_assessment',
type: 'boolean', type: 'single',
question: 'Haben Sie eine KI-Risikobewertung nach EU AI Act durchgeführt?', question: 'Haben Sie eine KI-Risikobewertung nach EU AI Act durchgeführt?',
helpText: 'Risikoeinstufung der KI-Systeme (verboten / hochriskant / begrenzt / minimal)', helpText: 'Risikoeinstufung der KI-Systeme (verboten / hochriskant / begrenzt / minimal)',
required: false, required: false,
options: [
{ value: 'yes', label: 'Ja' },
{ value: 'no', label: 'Nein' },
{ value: 'not_yet', label: 'Noch nicht' },
],
scoreWeights: { risk: -5, complexity: 3, assurance: 8 }, scoreWeights: { risk: -5, complexity: 3, assurance: 8 },
}, },
], ],
@@ -668,6 +658,84 @@ const BLOCK_9_DATENKATEGORIEN: ScopeQuestionBlock = {
scoreWeights: { risk: 5, complexity: 3, assurance: 4 }, scoreWeights: { risk: 5, complexity: 3, assurance: 4 },
mapsToVVTQuestion: 'dept_support_categories', mapsToVVTQuestion: 'dept_support_categories',
}, },
{
id: 'dk_dept_it',
type: 'multi',
question: 'Welche Datenkategorien verarbeitet Ihre IT-Abteilung?',
helpText: 'Waehlen Sie alle zutreffenden Datenkategorien fuer IT / Administration',
required: false,
options: DEPARTMENT_DATA_CATEGORIES.dept_it.categories.map(c => ({
value: c.id,
label: `${c.label}${c.isArt9 ? ' (Art. 9)' : ''}`,
})),
scoreWeights: { risk: 7, complexity: 5, assurance: 6 },
mapsToVVTQuestion: 'dept_it_categories',
},
{
id: 'dk_dept_recht',
type: 'multi',
question: 'Welche Datenkategorien verarbeitet Ihre Rechtsabteilung?',
helpText: 'Waehlen Sie alle zutreffenden Datenkategorien fuer Recht / Compliance',
required: false,
options: DEPARTMENT_DATA_CATEGORIES.dept_recht.categories.map(c => ({
value: c.id,
label: `${c.label}${c.isArt9 ? ' (Art. 9)' : ''}`,
})),
scoreWeights: { risk: 6, complexity: 4, assurance: 6 },
mapsToVVTQuestion: 'dept_recht_categories',
},
{
id: 'dk_dept_produktion',
type: 'multi',
question: 'Welche Datenkategorien verarbeitet Ihre Produktion?',
helpText: 'Waehlen Sie alle zutreffenden Datenkategorien fuer Produktion / Fertigung',
required: false,
options: DEPARTMENT_DATA_CATEGORIES.dept_produktion.categories.map(c => ({
value: c.id,
label: `${c.label}${c.isArt9 ? ' (Art. 9)' : ''}`,
})),
scoreWeights: { risk: 6, complexity: 4, assurance: 5 },
mapsToVVTQuestion: 'dept_produktion_categories',
},
{
id: 'dk_dept_logistik',
type: 'multi',
question: 'Welche Datenkategorien verarbeitet Ihre Logistik?',
helpText: 'Waehlen Sie alle zutreffenden Datenkategorien fuer Logistik / Versand',
required: false,
options: DEPARTMENT_DATA_CATEGORIES.dept_logistik.categories.map(c => ({
value: c.id,
label: `${c.label}${c.isArt9 ? ' (Art. 9)' : ''}`,
})),
scoreWeights: { risk: 5, complexity: 3, assurance: 4 },
mapsToVVTQuestion: 'dept_logistik_categories',
},
{
id: 'dk_dept_einkauf',
type: 'multi',
question: 'Welche Datenkategorien verarbeitet Ihr Einkauf?',
helpText: 'Waehlen Sie alle zutreffenden Datenkategorien fuer Einkauf / Beschaffung',
required: false,
options: DEPARTMENT_DATA_CATEGORIES.dept_einkauf.categories.map(c => ({
value: c.id,
label: `${c.label}${c.isArt9 ? ' (Art. 9)' : ''}`,
})),
scoreWeights: { risk: 4, complexity: 3, assurance: 4 },
mapsToVVTQuestion: 'dept_einkauf_categories',
},
{
id: 'dk_dept_facility',
type: 'multi',
question: 'Welche Datenkategorien verarbeitet Ihr Facility Management?',
helpText: 'Waehlen Sie alle zutreffenden Datenkategorien fuer Facility Management',
required: false,
options: DEPARTMENT_DATA_CATEGORIES.dept_facility.categories.map(c => ({
value: c.id,
label: `${c.label}${c.isArt9 ? ' (Art. 9)' : ''}`,
})),
scoreWeights: { risk: 5, complexity: 3, assurance: 4 },
mapsToVVTQuestion: 'dept_facility_categories',
},
], ],
} }

View File

@@ -380,6 +380,76 @@ export const DEPARTMENT_DATA_CATEGORIES: Record<string, DepartmentDataConfig> =
{ id: 'TECHNICAL_DATA', label: 'Technische Daten', info: 'Systeminfos, Logdateien, Screenshots bei Fehlermeldungen' }, { id: 'TECHNICAL_DATA', label: 'Technische Daten', info: 'Systeminfos, Logdateien, Screenshots bei Fehlermeldungen' },
] ]
}, },
dept_it: {
label: 'IT / Administration',
icon: '💻',
categories: [
{ id: 'USER_ACCOUNTS', label: 'Benutzerkonten', info: 'Benutzernamen, Passwort-Hashes, Rollen, Berechtigungen', isTypical: true },
{ id: 'LOG_DATA', label: 'Log-/Protokolldaten', info: 'System-Logs, Zugriffsprotokolle, Fehlerprotokolle, IP-Adressen', isTypical: true },
{ id: 'DEVICE_DATA', label: 'Geraetedaten', info: 'Inventar, Seriennummern, MAC-Adressen, zugewiesene Geraete', isTypical: true },
{ id: 'NETWORK_DATA', label: 'Netzwerkdaten', info: 'IP-Adressen, VPN-Verbindungen, Firewall-Logs', isTypical: true },
{ id: 'EMAIL_DATA', label: 'E-Mail-/Kommunikation', info: 'E-Mail-Konten, Verteiler, Archivierung', isTypical: true },
{ id: 'BACKUP_DATA', label: 'Backup-Daten', info: 'Sicherungskopien mit personenbezogenen Inhalten' },
{ id: 'MONITORING_DATA', label: 'Monitoring-Daten', info: 'Systemueberwachung, Performance-Metriken mit Nutzerbezug' },
]
},
dept_recht: {
label: 'Recht / Compliance',
icon: '⚖️',
categories: [
{ id: 'CONTRACT_DATA', label: 'Vertragsdaten', info: 'Vertraege, NDAs, AVVs, Rahmenvereinbarungen', isTypical: true },
{ id: 'NAME', label: 'Ansprechpartner', info: 'Namen, Kontaktdaten von Vertragspartnern und Anwaelten', isTypical: true },
{ id: 'COMPLIANCE_DATA', label: 'Compliance-Daten', info: 'Datenschutzanfragen, Meldungen, Audit-Ergebnisse', isTypical: true },
{ id: 'INCIDENT_DATA', label: 'Vorfallsdaten', info: 'Datenschutzvorfaelle, Beschwerden, Meldungen an Aufsichtsbehoerden' },
{ id: 'CONSENT_DATA', label: 'Einwilligungsdaten', info: 'Consent-Nachweise, Widerrufe, Opt-in/Opt-out-Protokolle' },
{ id: 'CRIMINAL_DATA', label: 'Strafrechtliche Daten', info: 'Fuehrungszeugnisse, Compliance-Pruefungen (Art. 10 DSGVO)', isArt9: true },
]
},
dept_produktion: {
label: 'Produktion / Fertigung',
icon: '🏭',
categories: [
{ id: 'EMPLOYMENT_DATA', label: 'Schichtplaene', info: 'Schichtzuordnung, Arbeitszeiten, Anwesenheitslisten', isTypical: true },
{ id: 'NAME', label: 'Mitarbeiterstammdaten', info: 'Name, Personalnummer, Qualifikation, Maschinenberechtigungen', isTypical: true },
{ id: 'HEALTH_DATA', label: 'Arbeitsschutzdaten', info: 'Arbeitsmedizinische Vorsorge, Unfallmeldungen, Gefahrstoff-Expositionen', isArt9: true },
{ id: 'ACCESS_DATA', label: 'Zugangsdaten', info: 'Zutrittskontrolle, Badge-Protokolle, Bereichsberechtigungen', isTypical: true },
{ id: 'QUALITY_DATA', label: 'Qualitaetsdaten', info: 'Pruefprotokolle mit Pruefernamen, Fehlerberichte' },
{ id: 'PHOTO_VIDEO', label: 'Bild-/Videodaten', info: 'Kameraueberwachung in Produktionsbereichen' },
]
},
dept_logistik: {
label: 'Logistik / Versand',
icon: '🚚',
categories: [
{ id: 'NAME', label: 'Empfaengerdaten', info: 'Name, Lieferadresse, Telefon fuer Zustellung', isTypical: true },
{ id: 'ADDRESS', label: 'Versandadressen', info: 'Liefer-/Abholadressen, Paketshop-Zuordnung', isTypical: true },
{ id: 'TRACKING_DATA', label: 'Sendungsverfolgung', info: 'Tracking-Nummern, Zustellstatus, Lieferzeitfenster', isTypical: true },
{ id: 'DRIVER_DATA', label: 'Fahrerdaten', info: 'Fahrerlaubnis, Touren, GPS-Standortdaten', isTypical: true },
{ id: 'CUSTOMS_DATA', label: 'Zolldaten', info: 'Zollerklaerungen, EORI-Nummern bei internationalem Versand' },
]
},
dept_einkauf: {
label: 'Einkauf / Beschaffung',
icon: '🛒',
categories: [
{ id: 'NAME', label: 'Lieferantenkontakte', info: 'Ansprechpartner, E-Mail, Telefon der Lieferanten', isTypical: true },
{ id: 'CONTRACT_DATA', label: 'Vertragsdaten', info: 'Rahmenvertraege, Bestellungen, Konditionen, Laufzeiten', isTypical: true },
{ id: 'BANK_ACCOUNT', label: 'Bankverbindungen', info: 'IBAN, BIC der Lieferanten fuer Zahlungsabwicklung', isTypical: true },
{ id: 'TAX_ID', label: 'Steuer-IDs', info: 'USt-IdNr., Steuernummer der Lieferanten', isTypical: true },
{ id: 'COMPLIANCE_DATA', label: 'Lieferantenbewertung', info: 'Qualitaetsbewertungen, Audit-Ergebnisse, Zertifizierungen' },
]
},
dept_facility: {
label: 'Facility Management',
icon: '🏢',
categories: [
{ id: 'ACCESS_DATA', label: 'Zutrittsdaten', info: 'Schluesselausgaben, Badge-Protokolle, Zutrittslisten', isTypical: true },
{ id: 'NAME', label: 'Dienstleisterkontakte', info: 'Reinigung, Wartung, Sicherheitsdienst — Namen und Kontaktdaten', isTypical: true },
{ id: 'PHOTO_VIDEO', label: 'Videoueberwachung', info: 'Kameraaufnahmen in/an Gebaeuden, Parkplaetzen', isTypical: true },
{ id: 'VISITOR_DATA', label: 'Besucherdaten', info: 'Name, Firma, Besuchsgrund, Ein-/Austrittszeiten', isTypical: true },
{ id: 'HEALTH_DATA', label: 'Gesundheits-/Sicherheitsdaten', info: 'Unfallmeldungen, Evakuierungslisten, Ersthelfer-Register', isArt9: true },
]
},
} }
// ============================================================================= // =============================================================================