Blacklist: Firmen schreibweisen-robust matchen (eine Firma nur einmal)

sameCompany() vergleicht Firmen-Slugs jetzt per Gleichheit ODER führendem
Bindestrich-Präfix (>=2 Tokens), sodass Kurzname und voller Firmenname
derselben Firma als gleich gelten (z. B. "it-problemloeser" =
"it-problemloeser-verwaltungs-und-handels", "stadtwerke-essen" =
"stadtwerke-essen-netz"). firmaMatch() nutzt das für die Blacklist-Typen
firma/firma_stelle/auto. Distinkte Firmen mit nur gleichem ersten Wort
("meyer-it" vs "meyer-logistik") bleiben getrennt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 07:25:04 +00:00
co-authored by Claude Opus 4.8
parent 7e0c27341a
commit 4e1043897d
+27 -3
View File
@@ -107,6 +107,27 @@ function firmaSlug(s) {
return (kept.length ? kept : words).join('-');
}
// Do two company slugs refer to the SAME employer? True when they are equal, or
// when the shorter one's hyphen tokens are a leading prefix of the longer one's.
// The prefix rule collapses "short name" vs "full legal name" spellings of one
// firm — e.g. "it-problemloeser" vs "it-problemloeser-verwaltungs-und-handels",
// or "stadtwerke-essen" vs "stadtwerke-essen-netz". To avoid merging distinct
// firms that merely share a first word ("meyer-it" vs "meyer-logistik"), a pure
// prefix match requires the shorter slug to carry at least two tokens; a
// single-token slug only matches an identical one.
function sameCompany(a, b) {
if (!a || !b) return false;
if (a === b) return true;
const ta = String(a).split('-').filter(Boolean);
const tb = String(b).split('-').filter(Boolean);
const [short, long] = ta.length <= tb.length ? [ta, tb] : [tb, ta];
if (short.length < 2) return false; // single distinctive token → exact only
for (let i = 0; i < short.length; i++) {
if (short[i] !== long[i]) return false;
}
return true;
}
// Normalise a company / job-title string for fuzzy identity matching:
// unescape, lowercase, drop gender markers like "(m/w/d)", collapse anything
// non-alphanumeric to single spaces.
@@ -138,10 +159,12 @@ function offerSignature(offer) {
};
}
// Company identity match: prefer the robust slug, fall back to firma_norm for
// legacy rows written before firma_slug existed (or not yet backfilled).
// Company identity match: prefer the robust slug (equal or prefix — see
// sameCompany, which absorbs spelling / legal-form / umlaut variants of one
// employer), fall back to firma_norm for legacy rows written before firma_slug
// existed (or not yet backfilled).
function firmaMatch(row, sig) {
if (row.firma_slug && sig.firma_slug) return row.firma_slug === sig.firma_slug;
if (row.firma_slug && sig.firma_slug) return sameCompany(row.firma_slug, sig.firma_slug);
return !!row.firma_norm && row.firma_norm === sig.firma_norm;
}
@@ -259,6 +282,7 @@ module.exports = {
urlDomain,
normText,
firmaSlug,
sameCompany,
offerSignature,
rowMatches,
matchBlacklist,