New CustomerInventory,
New Mitgliederverwaltung für Vereine New Bank Auto Complete
This commit is contained in:
95
backend/scripts/generate-de-bank-codes.ts
Normal file
95
backend/scripts/generate-de-bank-codes.ts
Normal file
@@ -0,0 +1,95 @@
|
||||
import fs from "node:fs/promises"
|
||||
import path from "node:path"
|
||||
import https from "node:https"
|
||||
|
||||
const DEFAULT_SOURCE_URL =
|
||||
"https://www.bundesbank.de/resource/blob/602632/bec25ca5df1eb62fefadd8325dafe67c/472B63F073F071307366337C94F8C870/blz-aktuell-txt-data.txt"
|
||||
|
||||
const OUTPUT_NAME_FILE = path.resolve("src/utils/deBankCodes.ts")
|
||||
const OUTPUT_BIC_FILE = path.resolve("src/utils/deBankBics.ts")
|
||||
|
||||
function fetchBuffer(url: string): Promise<Buffer> {
|
||||
return new Promise((resolve, reject) => {
|
||||
https
|
||||
.get(url, (res) => {
|
||||
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
||||
return resolve(fetchBuffer(res.headers.location))
|
||||
}
|
||||
|
||||
if (res.statusCode !== 200) {
|
||||
return reject(new Error(`Download failed with status ${res.statusCode}`))
|
||||
}
|
||||
|
||||
const chunks: Buffer[] = []
|
||||
res.on("data", (chunk) => chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)))
|
||||
res.on("end", () => resolve(Buffer.concat(chunks)))
|
||||
res.on("error", reject)
|
||||
})
|
||||
.on("error", reject)
|
||||
})
|
||||
}
|
||||
|
||||
function escapeTsString(value: string) {
|
||||
return value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const source = process.env.BLZ_SOURCE_URL || DEFAULT_SOURCE_URL
|
||||
const sourceFile = process.env.BLZ_SOURCE_FILE
|
||||
let raw: Buffer
|
||||
|
||||
if (sourceFile) {
|
||||
console.log(`Reading BLZ source file: ${sourceFile}`)
|
||||
raw = await fs.readFile(sourceFile)
|
||||
} else {
|
||||
console.log(`Downloading BLZ source: ${source}`)
|
||||
raw = await fetchBuffer(source)
|
||||
}
|
||||
const content = raw.toString("latin1")
|
||||
|
||||
const lines = content.split(/\r?\n/)
|
||||
const nameMap = new Map<string, string>()
|
||||
const bicMap = new Map<string, string>()
|
||||
|
||||
for (const line of lines) {
|
||||
if (!line || line.length < 150) continue
|
||||
const blz = line.slice(0, 8).trim()
|
||||
const name = line.slice(9, 67).trim()
|
||||
const bic = line.slice(139, 150).trim()
|
||||
|
||||
if (!/^\d{8}$/.test(blz) || !name) continue
|
||||
if (!nameMap.has(blz)) nameMap.set(blz, name)
|
||||
if (bic && !bicMap.has(blz)) bicMap.set(blz, bic)
|
||||
}
|
||||
|
||||
const sortedNames = [...nameMap.entries()].sort(([a], [b]) => a.localeCompare(b))
|
||||
const sortedBics = [...bicMap.entries()].sort(([a], [b]) => a.localeCompare(b))
|
||||
|
||||
const nameOutputLines = [
|
||||
"// Lokale Bankleitzahl-zu-Institut Zuordnung (DE).",
|
||||
"// Quelle: Deutsche Bundesbank, BLZ-Datei (vollstaendig).",
|
||||
"export const DE_BANK_CODE_TO_NAME: Record<string, string> = {",
|
||||
...sortedNames.map(([blz, name]) => ` "${blz}": "${escapeTsString(name)}",`),
|
||||
"}",
|
||||
"",
|
||||
]
|
||||
|
||||
const bicOutputLines = [
|
||||
"// Lokale Bankleitzahl-zu-BIC Zuordnung (DE).",
|
||||
"// Quelle: Deutsche Bundesbank, BLZ-Datei (vollstaendig).",
|
||||
"export const DE_BANK_CODE_TO_BIC: Record<string, string> = {",
|
||||
...sortedBics.map(([blz, bic]) => ` "${blz}": "${escapeTsString(bic)}",`),
|
||||
"}",
|
||||
"",
|
||||
]
|
||||
|
||||
await fs.writeFile(OUTPUT_NAME_FILE, nameOutputLines.join("\n"), "utf8")
|
||||
await fs.writeFile(OUTPUT_BIC_FILE, bicOutputLines.join("\n"), "utf8")
|
||||
console.log(`Wrote ${sortedNames.length} bank names to ${OUTPUT_NAME_FILE}`)
|
||||
console.log(`Wrote ${sortedBics.length} bank BICs to ${OUTPUT_BIC_FILE}`)
|
||||
}
|
||||
|
||||
main().catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
Reference in New Issue
Block a user