Füge Skripte zum Aufteilen von Namen in firstName und lastName für Mitglieder und Bewerbungen hinzu, einschließlich Backup-Funktionalität.
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 51s
Some checks failed
Code Analysis (JS/Vue) / analyze (push) Failing after 51s
This commit is contained in:
25
scripts/README-split-names.md
Normal file
25
scripts/README-split-names.md
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
Split-Name Scripts
|
||||||
|
|
||||||
|
Diese Scripts helfen, das Feld `name` in `firstName` und `lastName` zu splitten, für verschiedene Datenquellen im Projekt.
|
||||||
|
|
||||||
|
Available scripts:
|
||||||
|
|
||||||
|
- `scripts/split-names-in-users.js` (CommonJS)
|
||||||
|
- Splittet `server/data/users.json` und ergänzt fehlende `firstName`/`lastName`.
|
||||||
|
- Erstellt ein Backup `users.json.bak.<timestamp>` falls Änderungen gemacht werden.
|
||||||
|
- Ausführen: `node scripts/split-names-in-users.js`
|
||||||
|
|
||||||
|
- `scripts/split-names-in-members.js` (ESM)
|
||||||
|
- Liest `members.json` über `server/utils/members.js` (beachtet Verschlüsselung), führt Dry-Run by default.
|
||||||
|
- Mit `--apply` werden Änderungen geschrieben und ein Backup erstellt.
|
||||||
|
- Ausführen (dry-run): `node scripts/split-names-in-members.js`
|
||||||
|
- Ausführen (apply): `node scripts/split-names-in-members.js --apply`
|
||||||
|
|
||||||
|
- `scripts/split-names-in-membership-apps.js` (CommonJS)
|
||||||
|
- Bearbeitet alle JSON-Dateien in `server/data/membership-applications/` und erstellt `.bak` Backups pro Datei.
|
||||||
|
- Ausführen: `node scripts/split-names-in-membership-apps.js`
|
||||||
|
|
||||||
|
Hinweis:
|
||||||
|
- Die Scripts sind vorsichtig: sie erstellen Backups bevor sie schreiben (außer beim Dry-Run für members.js).
|
||||||
|
- `split-names-in-members.js` nutzt die vorhandenen `readMembers`/`writeMembers` Utilities, um Verschlüsselung zu respektieren.
|
||||||
|
- Teste zuerst mit DRY-RUN oder in einer Kopie des Datenverzeichnisses.
|
||||||
80
scripts/split-names-in-members.js
Normal file
80
scripts/split-names-in-members.js
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
import fs from 'fs'
|
||||||
|
import { promises as fsp } from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
import { readMembers, writeMembers } from '../server/utils/members.js'
|
||||||
|
|
||||||
|
// Script to split `name` into firstName/lastName for members.json.
|
||||||
|
// Usage:
|
||||||
|
// node scripts/split-names-in-members.js # dry-run, no writes
|
||||||
|
// node scripts/split-names-in-members.js --apply # apply changes and create backup
|
||||||
|
|
||||||
|
const MEMBERS_FILE_PATH = path.join(process.cwd(), 'server/data/members.json')
|
||||||
|
|
||||||
|
function extractNames(name) {
|
||||||
|
if (!name || typeof name !== 'string') return { firstName: '', lastName: '' }
|
||||||
|
const parts = name.trim().split(/\s+/)
|
||||||
|
if (parts.length === 1) return { firstName: parts[0], lastName: '' }
|
||||||
|
return { firstName: parts[0], lastName: parts.slice(1).join(' ') }
|
||||||
|
}
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const apply = process.argv.includes('--apply')
|
||||||
|
|
||||||
|
console.log('Reading members via server utils (handles encryption)...')
|
||||||
|
const members = await readMembers()
|
||||||
|
if (!Array.isArray(members)) {
|
||||||
|
console.error('Unerwartetes Format von members:', typeof members)
|
||||||
|
process.exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
let changed = false
|
||||||
|
for (const m of members) {
|
||||||
|
if ((!m.firstName || !m.lastName) && m.name) {
|
||||||
|
const { firstName, lastName } = extractNames(m.name)
|
||||||
|
if (!m.firstName) m.firstName = firstName
|
||||||
|
if (!m.lastName) m.lastName = lastName
|
||||||
|
changed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!changed) {
|
||||||
|
console.log('Keine Änderungen erforderlich. Alle Mitglieder haben firstName/lastName.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Gefundene Änderungen: Mitglieder mit ergänztenn Namen werden ${apply ? 'angewendet' : 'nur angezeigt (dry-run)'}.`)
|
||||||
|
|
||||||
|
if (!apply) {
|
||||||
|
console.log('Vorschau der Änderungen (erstes 10 geänderte Mitglieder):')
|
||||||
|
let count = 0
|
||||||
|
for (const m of members) {
|
||||||
|
if (m.firstName || m.lastName) {
|
||||||
|
console.log('-', m.id || '(keine id)', m.firstName, m.lastName, '-', m.name)
|
||||||
|
count++
|
||||||
|
if (count >= 10) break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log('\nFühre das Skript mit --apply aus, um die Änderungen dauerhaft zu schreiben (Backup wird erstellt).')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create backup of raw file (may be encrypted)
|
||||||
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
|
||||||
|
const backupPath = MEMBERS_FILE_PATH + `.bak.${timestamp}`
|
||||||
|
try {
|
||||||
|
await fsp.copyFile(MEMBERS_FILE_PATH, backupPath)
|
||||||
|
console.log('Backup erstellt:', backupPath)
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Konnte kein Backup anlegen (Datei evtl. nicht vorhanden):', err.message)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write members using writeMembers (will handle encryption)
|
||||||
|
await writeMembers(members)
|
||||||
|
console.log('Mitglieder erfolgreich aktualisiert und verschlüsselt gespeichert.')
|
||||||
|
}
|
||||||
|
|
||||||
|
main().catch(err => {
|
||||||
|
console.error('Fehler:', err)
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
57
scripts/split-names-in-membership-apps.js
Normal file
57
scripts/split-names-in-membership-apps.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
// Script to split name field in membership application JSON files under server/data/membership-applications/
|
||||||
|
// It will create backups for each modified file.
|
||||||
|
|
||||||
|
const fs = require('fs')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
|
const APPS_DIR = path.join(__dirname, '../server/data/membership-applications')
|
||||||
|
|
||||||
|
function extractNames(name) {
|
||||||
|
if (!name || typeof name !== 'string') return { firstName: '', lastName: '' }
|
||||||
|
const parts = name.trim().split(/\s+/)
|
||||||
|
if (parts.length === 1) return { firstName: parts[0], lastName: '' }
|
||||||
|
return { firstName: parts[0], lastName: parts.slice(1).join(' ') }
|
||||||
|
}
|
||||||
|
|
||||||
|
function main() {
|
||||||
|
if (!fs.existsSync(APPS_DIR)) {
|
||||||
|
console.error('membership-applications Verzeichnis nicht gefunden:', APPS_DIR)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const files = fs.readdirSync(APPS_DIR).filter(f => f.endsWith('.json'))
|
||||||
|
if (files.length === 0) {
|
||||||
|
console.log('Keine Bewerbungsdateien gefunden.')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let modified = 0
|
||||||
|
for (const file of files) {
|
||||||
|
const p = path.join(APPS_DIR, file)
|
||||||
|
let data
|
||||||
|
try {
|
||||||
|
data = JSON.parse(fs.readFileSync(p, 'utf8'))
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Fehler beim Lesen von', p, err.message)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!data.firstName || !data.lastName) && data.name) {
|
||||||
|
const { firstName, lastName } = extractNames(data.name)
|
||||||
|
data.firstName = data.firstName || firstName
|
||||||
|
data.lastName = data.lastName || lastName
|
||||||
|
|
||||||
|
// Backup
|
||||||
|
const backup = p + '.bak'
|
||||||
|
fs.copyFileSync(p, backup)
|
||||||
|
fs.writeFileSync(p, JSON.stringify(data, null, 2))
|
||||||
|
modified++
|
||||||
|
console.log('Updated', p, '-> backup at', backup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('Done. Modified files:', modified)
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user