HR Document Router
Sole builder · 2026
A rules-engine script that sorted 20,000+ orphaned HR documents into per-employee folders after an HRIS migration.
Impact
Sorted 20,000+ flat exported documents across 1,100+ employees into 14 category folders with 99.8% auto-placement, fully auditable and re-runnable.
Systems
HR areas
The problem
A legacy HRIS export dumped every uploaded employee document — signed offer letters, compliance forms, ID scans, training certificates — into one flat directory of 20,000+ files, named only by employee ID and a free-text title. There was no per-employee folder structure, and the titles weren't reliable enough to trust at a glance: a meaningful chunk were camera filenames or truncated strings.
What I built
A Python categorization engine that reads each filename, extracts the employee ID and document title, and routes the file into <Category>/<employee>/<original filename> using an ordered, precedence-based keyword ruleset — tuned iteratively against the real export until it stopped misfiling edge cases (a training certificate landing in "Legal ID," a termination letter landing in "Offer Letters," and similar near-misses that only show up at scale).
- Every run produces a full manifest CSV — every file, its destination, and why it was routed there — so the categorization is auditable, not a black box.
- Files that don't match any rule land in a clearly labeled fallback bucket rather than silently defaulting somewhere wrong.
- Default mode copies rather than moves, so a bad run costs nothing to re-do.
- A
--names-frommode plans the entire run from a filename list alone, so the ruleset could be tuned without ever opening a single document — important when the documents contain passports, SSNs, and medical records.
Why it mattered
This turned a genuinely unusable flat export into a browsable, per-employee document archive — 99.8% of files placed automatically, with a clean audit trail for the rest — without anyone having to hand-sort 20,000 files or open documents that didn't need to be opened.