const Database = require('better-sqlite3') const path = require('path') const { v4: uuidv4 } = require('uuid') // Open database const dbPath = path.join(__dirname, '..', 'skillmate.dev.encrypted.db') const db = new Database(dbPath) // Enable foreign keys db.pragma('foreign_keys = ON') console.log('🏢 Seeding LKA NRW Organizational Structure...') const now = new Date().toISOString() // Helper function to insert organizational unit function insertUnit(code, name, type, level, parentId = null, options = {}) { const id = uuidv4() db.prepare(` INSERT OR REPLACE INTO organizational_units ( id, code, name, type, level, parent_id, color, order_index, has_fuehrungsstelle, fuehrungsstelle_name, is_active, created_at, updated_at ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) `).run( id, code, name, type, level, parentId, options.color || null, options.orderIndex || 0, options.hasFuehrungsstelle || 0, options.fuehrungsstelleName || null, 1, now, now ) return id } // Clear existing data console.log('Clearing existing organizational data...') db.prepare('DELETE FROM deputy_delegations').run() db.prepare('DELETE FROM deputy_assignments').run() db.prepare('DELETE FROM special_positions').run() db.prepare('DELETE FROM employee_unit_assignments').run() db.prepare('DELETE FROM organizational_units').run() // Create Direktor const direktorId = insertUnit('DIR', 'Direktor LKA NRW', 'direktion', 0, null, { color: '#1e3a8a', orderIndex: 0 }) // Create Leitungsstab const leitungsstabId = insertUnit('LStab', 'Leitungsstab', 'stabsstelle', 1, direktorId, { color: '#6b7280', orderIndex: 1 }) // Leitungsstab Sub-units insertUnit('LStab 1', 'Grundsatzangelegenheiten, Gremien, internationale polizeiliche Zusammenarbeit', 'sachgebiet', 2, leitungsstabId) insertUnit('LStab 2', 'Strategische Steuerung, Qualitätsmanagement, Controlling', 'sachgebiet', 2, leitungsstabId) insertUnit('LStab 3', 'Presse- und Öffentlichkeitsarbeit', 'sachgebiet', 2, leitungsstabId) // Create Special Units (Beauftragte) const personalratId = insertUnit('PR', 'Personalrat', 'sondereinheit', 1, direktorId, { color: '#059669', orderIndex: 2 }) const schwerbehindertenId = insertUnit('SBV', 'Schwerbehindertenvertretung', 'sondereinheit', 1, direktorId, { color: '#059669', orderIndex: 3 }) // Create Abteilungen with color gradients const abteilungen = [ { code: 'Abt 1', name: 'Organisierte Kriminalität', color: '#dc2626' }, { code: 'Abt 2', name: 'Terrorismusbekämpfung und Staatsschutz', color: '#ea580c' }, { code: 'Abt 3', name: 'Strategische Kriminalitätsbekämpfung', color: '#0891b2' }, { code: 'Abt 4', name: 'Cybercrime (CCCC)', color: '#7c3aed' }, { code: 'Abt 5', name: 'Kriminalwissenschaftliches und -technisches Institut', color: '#0d9488' }, { code: 'Abt 6', name: 'Fachaufsicht und Ermittlungsunterstützung', color: '#be185d' }, { code: 'ZA', name: 'Zentralabteilung', color: '#6b7280' } ] const abteilungIds = {} abteilungen.forEach((abt, index) => { abteilungIds[abt.code] = insertUnit(abt.code, abt.name, 'abteilung', 1, direktorId, { color: abt.color, orderIndex: 10 + index * 10, hasFuehrungsstelle: abt.code !== 'ZA' ? 1 : 0, fuehrungsstelleName: abt.code !== 'ZA' ? `Führungsstelle ${abt.code}` : null }) }) // Create Dezernate for Abteilung 1 (Organisierte Kriminalität) const dezernate1 = [ { code: '11', name: 'Ermittlungen OK, OK Rauschgift' }, { code: '12', name: 'Wirtschaftskriminalität' }, { code: '13', name: 'Finanzermittlungen' }, { code: '14', name: 'Auswerte- und Analysestelle OK' }, { code: '15', name: 'Korruption, Umweltkriminalität' }, { code: '16', name: 'Finanzierung Organisierter Kriminalität und Terrorismus' } ] dezernate1.forEach((dez, index) => { const dezId = insertUnit(`Dezernat ${dez.code}`, dez.name, 'dezernat', 2, abteilungIds['Abt 1'], { orderIndex: index }) // Add sample Sachgebiete if (dez.code === '11') { insertUnit('SG 11.1', 'Grundsatzfragen/Koordination/Auswertung', 'sachgebiet', 3, dezId) } if (dez.code === '12') { insertUnit('SG 12.1', 'Grundsatzfragen/Koordination/Auswertung', 'sachgebiet', 3, dezId) } if (dez.code === '13') { insertUnit('SG 13.1', 'GFG 1', 'sachgebiet', 3, dezId) insertUnit('SG 13.2', 'GFG 2', 'sachgebiet', 3, dezId) insertUnit('SG 13.3', 'Verfahrensintegrierte Finanzermittlungen/Vermögensabschöpfung', 'sachgebiet', 3, dezId) insertUnit('SG 13.4', 'Zentrale Informations- und Koordinierungsstelle Finanzermittlung', 'sachgebiet', 3, dezId) } if (dez.code === '14') { insertUnit('TD 14.1', 'Operative Auswertung und Analyse', 'teildezernat', 3, dezId) insertUnit('SG 14.2', 'Strategische Auswertung und Analyse', 'sachgebiet', 3, dezId) insertUnit('SG 14.3', 'Technische Informationssysteme', 'sachgebiet', 3, dezId) insertUnit('SG 14.4', 'Auswertung und Analyse Rockerkriminalität', 'sachgebiet', 3, dezId) insertUnit('SG 14.5', 'Auswertung und Analyse Clankriminalität', 'sachgebiet', 3, dezId) } if (dez.code === '15') { insertUnit('SG 15.1', 'Grundsatzangelegenheiten, Korruption', 'sachgebiet', 3, dezId) insertUnit('SG 15.2', 'Vernetzungsstelle Umweltkriminalität', 'sachgebiet', 3, dezId) } if (dez.code === '16') { insertUnit('SG 16.1', 'Grundsatzfragen/Auswertung/Analyse', 'sachgebiet', 3, dezId) } }) // Create Dezernate for Abteilung 2 (Terrorismusbekämpfung) const dezernate2 = [ { code: '21', name: 'Ermittlungen' }, { code: '22', name: 'Auswertung/Analyse, ZMI, OSINT, Wissenschaftlicher Dienst PMK' }, { code: '23', name: 'PMK Rechts und PMK SZ' }, { code: '24', name: 'PMK Religiöse Ideologie' }, { code: '25', name: 'PMK Links, Ausländische Ideologie, ZSÜ' } ] dezernate2.forEach((dez, index) => { const dezId = insertUnit(`Dezernat ${dez.code}`, dez.name, 'dezernat', 2, abteilungIds['Abt 2'], { orderIndex: index }) if (dez.code === '21') { insertUnit('TD 21.1', 'Ermittlungskommissionen VSTGB', 'teildezernat', 3, dezId) } if (dez.code === '22') { insertUnit('SG 22.1', 'Auswertung/Analyse, ZMI', 'sachgebiet', 3, dezId) insertUnit('TD 22.2', 'Open Source Intelligence (OSINT)', 'teildezernat', 3, dezId) insertUnit('TD 22.3', 'Wissenschaftlicher Dienst PMK', 'teildezernat', 3, dezId) insertUnit('SG 22.4', 'PMK Meldedienste, KPMD', 'sachgebiet', 3, dezId) } if (dez.code === '23') { insertUnit('SG 23.1', 'KoSt Gefährder, GETZ-Rechts', 'sachgebiet', 3, dezId) insertUnit('SG 23.2', 'Prüffallbearbeitung, Gefahrensachverhalte', 'sachgebiet', 3, dezId) insertUnit('TD 23.3', 'PMK SZ, Spionage', 'teildezernat', 3, dezId) } if (dez.code === '24') { insertUnit('SG 24.1', 'KoST Gefährder, SiKo', 'sachgebiet', 3, dezId) insertUnit('TD 24.2', 'Gemeinsames Terrorismusabwehrzentrum (GTAZ) NRW', 'teildezernat', 3, dezId) insertUnit('SG 24.3', 'Prüffallbearbeitung, islamistisch-terroristisches Personenpotential', 'sachgebiet', 3, dezId) } if (dez.code === '25') { insertUnit('SG 25.1', 'KoSt Gefährder Links', 'sachgebiet', 3, dezId) insertUnit('SG 25.2', 'KoSt Gefährder Ausländische Ideologie', 'sachgebiet', 3, dezId) insertUnit('SG 25.3', 'Zentrale Stelle NRW für ZSÜ', 'sachgebiet', 3, dezId) } }) // Create Dezernate for Abteilung 3 (Strategische Kriminalitätsbekämpfung) const dezernate3 = [ { code: '31', name: 'Kriminalitätsauswertung und Analyse' }, { code: '32', name: 'Kriminalprävention, KKF, Evaluation' }, { code: '33', name: 'Fahndung, Datenaustausch, Kriminalaktenhaltung' }, { code: '34', name: 'Digitalstrategie, Polizeifachliche IT' }, { code: '35', name: 'Verhaltensanalyse und Risikomanagement' } ] dezernate3.forEach((dez, index) => { const dezId = insertUnit(`Dezernat ${dez.code}`, dez.name, 'dezernat', 2, abteilungIds['Abt 3'], { orderIndex: index }) if (dez.code === '31') { insertUnit('SG 31.1', 'Grundsatzangelegenheiten/KoST MAfEx', 'sachgebiet', 3, dezId) insertUnit('SG 31.2', 'Auswertung und Analyse 1', 'sachgebiet', 3, dezId) insertUnit('SG 31.3', 'Auswertung/Analyse 2', 'sachgebiet', 3, dezId) insertUnit('SG 31.4', 'Polizeiliche Kriminalstatistik (PKS)', 'sachgebiet', 3, dezId) } if (dez.code === '32') { insertUnit('SG 32.1', 'Kriminalprävention und Opferschutz', 'sachgebiet', 3, dezId) insertUnit('TD 32.2', 'Kriminalistisch-Kriminologische Forschungsstelle (KKF)', 'teildezernat', 3, dezId) insertUnit('SG 32.3', 'Zentralstelle Evaluation (ZEVA)', 'sachgebiet', 3, dezId) } if (dez.code === '33') { insertUnit('SG 33.1', 'Datenstation, Polizeiliche Beobachtung', 'sachgebiet', 3, dezId) insertUnit('SG 33.2', 'Datenaustausch Polizei/Justiz', 'sachgebiet', 3, dezId) insertUnit('SG 33.3', 'Rechtshilfe, PNR, internationale Fahndung', 'sachgebiet', 3, dezId) } if (dez.code === '34') { insertUnit('TD 34.1', 'Grundsatz, Gremien, Fachliche IT-Projekte', 'teildezernat', 3, dezId) insertUnit('TD 34.2', 'Zentralstelle Polizei 2020', 'teildezernat', 3, dezId) insertUnit('TD 34.3', 'IT FaKo Fachbereich Kriminalität', 'teildezernat', 3, dezId) } if (dez.code === '35') { insertUnit('SG 35.1', 'Zentralstelle KURS NRW', 'sachgebiet', 3, dezId) insertUnit('SG 35.2', 'Operative Fallanalyse (OFA/ViCLAS)', 'sachgebiet', 3, dezId) insertUnit('SG 35.3', 'Zentralstelle PeRiskoP', 'sachgebiet', 3, dezId) } }) // Create Dezernate for Abteilung 4 (Cybercrime) const dezernate4 = [ { code: '41', name: 'Zentrale Ansprechstelle Cybercrime, Grundsatz, Digitale Forensik' }, { code: '42', name: 'Cyber-Recherche- und Fahndungszentrum' }, { code: '43', name: 'Zentrale Auswertungs- und Sammelstelle (ZASt)' }, { code: '44', name: 'Telekommunikationsüberwachung (TKÜ)' } ] dezernate4.forEach((dez, index) => { const dezId = insertUnit(`Dezernat ${dez.code}`, dez.name, 'dezernat', 2, abteilungIds['Abt 4'], { orderIndex: index }) if (dez.code === '41') { insertUnit('SG 41.1', 'Grundsatzangelegenheiten, Prävention', 'sachgebiet', 3, dezId) insertUnit('TD 41.2', 'Software und KI-Entwicklung', 'teildezernat', 3, dezId) insertUnit('SG 41.3', 'Forensik Desktop Strategie', 'sachgebiet', 3, dezId) insertUnit('SG 41.4', 'Forensik Desktop Datenaufbereitung', 'sachgebiet', 3, dezId) insertUnit('TD 41.5', 'Forensik Desktop Betrieb', 'teildezernat', 3, dezId) } if (dez.code === '42') { insertUnit('SG 42.1', 'Personenorientierte Recherche in Datennetzen', 'sachgebiet', 3, dezId) insertUnit('SG 42.2', 'Sachorientierte Recherche in Datennetzen', 'sachgebiet', 3, dezId) insertUnit('TD 42.3', 'Interventionsteams Digitale Tatorte', 'teildezernat', 3, dezId) } if (dez.code === '43') { insertUnit('SG 43.1', 'ZASt Grundsatz', 'sachgebiet', 3, dezId) insertUnit('SG 43.2', 'ZASt NCMEC/Landeszentrale Bewertung 1', 'sachgebiet', 3, dezId) insertUnit('SG 43.3', 'ZASt NCMEC/Landeszentrale Bewertung 2', 'sachgebiet', 3, dezId) insertUnit('SG 43.4', 'ZASt NCMEC/Landeszentrale Bewertung 3', 'sachgebiet', 3, dezId) } if (dez.code === '44') { insertUnit('SG 44.1', 'Grundsatzaufgaben, operative TKÜ', 'sachgebiet', 3, dezId) insertUnit('SG 44.2', 'TKÜ Betrieb und Service', 'sachgebiet', 3, dezId) insertUnit('TD 44.3', 'Digitale Forensik, IUK-Ermittlungsunterstützung', 'teildezernat', 3, dezId) } }) // Create Dezernate for Abteilung 5 (Kriminalwissenschaftliches Institut) const dezernate5 = [ { code: '51', name: 'Chemie, Physik' }, { code: '52', name: 'Serologie, DNA-Analytik' }, { code: '53', name: 'Biologie, Materialspuren, Urkunden' }, { code: '54', name: 'Zentralstelle Kriminaltechnik, Forensische Medientechnik' }, { code: '55', name: 'Waffen und Werkzeug, DNA-Analyse-Datei' }, { code: '56', name: 'Daktyloskopie, Gesichts- und Sprechererkennung' } ] dezernate5.forEach((dez, index) => { const dezId = insertUnit(`Dezernat ${dez.code}`, dez.name, 'dezernat', 2, abteilungIds['Abt 5'], { orderIndex: index }) if (dez.code === '51') { insertUnit('TD 51.1', 'Schussspuren, Explosivstoffe, Brand', 'teildezernat', 3, dezId) insertUnit('TD 51.2', 'Betäubungsmittel', 'teildezernat', 3, dezId) } if (dez.code === '52') { insertUnit('TD 52.1', 'DNA-Probenbearbeitung', 'teildezernat', 3, dezId) insertUnit('TD 52.2', 'DNA-Spurenbearbeitung II', 'teildezernat', 3, dezId) insertUnit('TD 52.3', 'DNA-Spurenbearbeitung III', 'teildezernat', 3, dezId) insertUnit('TD 52.4', 'DNA-Spurenbearbeitung IV', 'teildezernat', 3, dezId) } if (dez.code === '53') { insertUnit('TD 53.1', 'Forensische Textilkunde, Botanik', 'teildezernat', 3, dezId) insertUnit('SG 53.2', 'Urkunden, Handschriften', 'sachgebiet', 3, dezId) } if (dez.code === '54') { insertUnit('SG 54.1', 'Zentralstelle Kriminaltechnik', 'sachgebiet', 3, dezId) insertUnit('SG 54.2', 'Tatortvermessung, Rekonstruktion und XR-Lab', 'sachgebiet', 3, dezId) insertUnit('SG 54.3', 'Entschärfung von USBV', 'sachgebiet', 3, dezId) } if (dez.code === '55') { insertUnit('SG 55.1', 'Waffen und Munition', 'sachgebiet', 3, dezId) insertUnit('SG 55.2', 'Werkzeug-, Form-, Passspuren', 'sachgebiet', 3, dezId) insertUnit('SG 55.3', 'DNA-Analyse-Datei', 'sachgebiet', 3, dezId) } if (dez.code === '56') { insertUnit('SG 56.1', 'Daktyloskopisches Labor', 'sachgebiet', 3, dezId) insertUnit('SG 56.2', 'AFIS I/Daktyloskopische Gutachten', 'sachgebiet', 3, dezId) insertUnit('SG 56.3', 'AFIS II/Daktyloskopische Gutachten', 'sachgebiet', 3, dezId) insertUnit('TD 56.4', 'Gesichts- und Sprechererkennung', 'teildezernat', 3, dezId) } }) // Create Dezernate for Abteilung 6 (Fachaufsicht) const dezernate6 = [ { code: '61', name: 'Kriminalitätsangelegenheiten der KPB, Fachcontrolling' }, { code: '62', name: 'Fahndungsgruppe Staatsschutz' }, { code: '63', name: 'Verdeckte Ermittlungen, Zeugenschutz' }, { code: '64', name: 'Mobiles Einsatzkommando, TEG, Zielfahndung' } ] dezernate6.forEach((dez, index) => { const dezId = insertUnit(`Dezernat ${dez.code}`, dez.name, 'dezernat', 2, abteilungIds['Abt 6'], { orderIndex: index }) if (dez.code === '61') { insertUnit('TD 61.1', 'Kriminalitätsangelegenheiten der KPB', 'teildezernat', 3, dezId) insertUnit('SG 61.2', 'Lagedienst', 'sachgebiet', 3, dezId) } if (dez.code === '62') { for (let i = 1; i <= 9; i++) { if (i === 9) { insertUnit(`SG 62.${i}`, 'Technische Gruppe', 'sachgebiet', 3, dezId) } else { insertUnit(`SG 62.${i}`, `Fahndungsgruppe ${i}`, 'sachgebiet', 3, dezId) } } } if (dez.code === '63') { insertUnit('SG 63.1', 'Einsatz VE 1', 'sachgebiet', 3, dezId) insertUnit('SG 63.2', 'Einsatz VE 2', 'sachgebiet', 3, dezId) insertUnit('SG 63.3', 'Scheinkäufer, Logistik', 'sachgebiet', 3, dezId) insertUnit('SG 63.4', 'VP-Führung, Koordinierung VP', 'sachgebiet', 3, dezId) insertUnit('TD 63.5', 'Zeugenschutz, OpOS', 'teildezernat', 3, dezId) } if (dez.code === '64') { insertUnit('SG 64.1', 'MEK 1', 'sachgebiet', 3, dezId) insertUnit('SG 64.2', 'MEK 2', 'sachgebiet', 3, dezId) insertUnit('SG 64.3', 'Technische Einsatzgruppe', 'sachgebiet', 3, dezId) insertUnit('SG 64.4', 'Zielfahndung', 'sachgebiet', 3, dezId) } }) // Create Dezernate for Zentralabteilung const dezernateZA = [ { code: 'ZA 1', name: 'Haushalts-, Wirtschafts-, Liegenschaftsmanagement' }, { code: 'ZA 2', name: 'Personalangelegenheiten, Gleichstellungsbeauftragte' }, { code: 'ZA 3', name: 'Informationstechnik und Anwenderunterstützung' }, { code: 'ZA 4', name: 'Vereins- und Waffenrecht, Innenrevision' }, { code: 'ZA 5', name: 'Polizeiärztlicher Dienst' } ] dezernateZA.forEach((dez, index) => { const dezId = insertUnit(`Dezernat ${dez.code}`, dez.name, 'dezernat', 2, abteilungIds['ZA'], { orderIndex: index }) if (dez.code === 'ZA 1') { insertUnit('SG ZA 1.1', 'Haushalts- und Wirtschaftsangelegenheiten', 'sachgebiet', 3, dezId) insertUnit('SG ZA 1.2', 'Liegenschaftsmanagement', 'sachgebiet', 3, dezId) insertUnit('SG ZA 1.3', 'Zentrale Vergabestelle', 'sachgebiet', 3, dezId) } if (dez.code === 'ZA 2') { insertUnit('SG ZA 2.1', 'Personalentwicklung, Arbeitszeit', 'sachgebiet', 3, dezId) insertUnit('SG ZA 2.2', 'Personalverwaltung Beamte', 'sachgebiet', 3, dezId) insertUnit('TD ZA 2.3', 'Personalverwaltung Regierungsbeschäftigte', 'teildezernat', 3, dezId) insertUnit('SG ZA 2.4', 'Fortbildung', 'sachgebiet', 3, dezId) } if (dez.code === 'ZA 3') { insertUnit('SG ZA 3.1', 'IT-Grundsatz, Planung und Koordinierung', 'sachgebiet', 3, dezId) insertUnit('SG ZA 3.2', 'Netzwerk/TK-Anlage', 'sachgebiet', 3, dezId) insertUnit('SG ZA 3.3', 'Server/Client, Logistik', 'sachgebiet', 3, dezId) insertUnit('SG ZA 3.4', 'Kfz-, Waffen- und Geräteangelegenheiten', 'sachgebiet', 3, dezId) } }) console.log('✅ LKA NRW Organizational Structure seeded successfully!') // Close database db.close() console.log('🎉 Done! Run the backend to see the organizational structure.')