Add robust company slug for job-offer blacklist matching

Company matching relied on normText(), which kept legal-form suffixes,
spacing and umlaut spelling — so "Bosch GmbH", "Bosch AG" and "bosch gmbh"
did not match the same entry, making the blacklist unreliable.

Introduce firmaSlug(): transliterate German umlauts, strip diacritics and
trailing legal-form tokens (GmbH/AG/SE/KG/…), then kebab-join. Add a
firma_slug field to jobangebote_blacklist (schema + ALTER/backfill migration)
and match on it for typ firma/firma_stelle/auto, falling back to firma_norm
for legacy rows. POST /joboffers rejects blacklisted offers via matchBlacklist
automatically since offerSignature now carries the slug.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-06 22:25:59 +02:00
co-authored by Claude Opus 4.8
parent 4e5933890f
commit f935e00b53
3 changed files with 76 additions and 8 deletions
+20
View File
@@ -815,6 +815,7 @@ function initializeDatabase() {
quelle TEXT,
external_id TEXT,
firma_norm TEXT,
firma_slug TEXT,
stelle_norm TEXT,
ort_norm TEXT,
firma TEXT,
@@ -824,6 +825,25 @@ function initializeDatabase() {
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
`, () => {});
// Add + backfill firma_slug on pre-existing installs. The slug is a
// legal-form/umlaut-robust company key that the blacklist now matches
// on; backfill from the stored original company name so old company
// entries start blocking reliably too.
db.run('ALTER TABLE jobangebote_blacklist ADD COLUMN firma_slug TEXT', () => {
db.all(
`SELECT id, firma, firma_norm FROM jobangebote_blacklist
WHERE firma_slug IS NULL AND (firma IS NOT NULL OR firma_norm IS NOT NULL)`,
(err, rows) => {
if (err || !rows) return;
for (const r of rows) {
const slug = blacklist.firmaSlug(r.firma || r.firma_norm || '');
if (slug) {
db.run('UPDATE jobangebote_blacklist SET firma_slug = ? WHERE id = ?', [slug, r.id], () => {});
}
}
}
);
});
// Remember the last recipient address per application (prefill).
db.run('ALTER TABLE bewerbungen ADD COLUMN email_empfaenger TEXT', () => {});