diff --git a/lib/blacklist.js b/lib/blacklist.js index 7b127bd..fefc72e 100644 --- a/lib/blacklist.js +++ b/lib/blacklist.js @@ -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,