From 8cc2efbf2142c7dea9c093dad7c9f9ce45009a5a Mon Sep 17 00:00:00 2001 From: Rudy Mizrahi Celekli <47457359+rudycelekli@users.noreply.github.com> Date: Sun, 18 Oct 2026 01:14:26 -0400 Subject: [PATCH] fix(salary): prefer exact workbook identity headers (#571) * fix(salary): prefer exact workbook identity headers * docs(changelog): record fix for #571 --- CHANGELOG.md | 2 + tests/test_salary_company_header_cli.py | 53 +++++++++++++++++++++++++ tools/convert_salary_excel.py | 6 +++ 3 files changed, 61 insertions(+) create mode 100644 tests/test_salary_company_header_cli.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 01bda175..b63db985 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -211,6 +211,8 @@ per-file diff commands. RFC 9309 section 2.2.3, `$` is an end anchor only at the end of the pattern, and internal `$` characters are now matched literally. +- **Salary workbook conversion prefers exact identity headers** (#571) - exact company column names take precedence over incidental substring matches in other headers. + - **CV template guidance aligns geometry scale with master template** (#553, `.claude/skills/job-application-assistant/05-cv-templates.md`, `tests/test_latex_guidance.py`) - the preamble snippet in `05-cv-templates.md` specified `\usepackage[scale=0.77]{geometry}`, diff --git a/tests/test_salary_company_header_cli.py b/tests/test_salary_company_header_cli.py new file mode 100644 index 00000000..a9f87b86 --- /dev/null +++ b/tests/test_salary_company_header_cli.py @@ -0,0 +1,53 @@ +"""A salary category must not steal the workbook's company-name column.""" +import json +import subprocess +import sys +import unittest +from pathlib import Path +from tempfile import TemporaryDirectory + +try: + import openpyxl +except ImportError: + openpyxl = None + +TOOL = Path(__file__).resolve().parent.parent / "tools" / "convert_salary_excel.py" + + +@unittest.skipUnless(openpyxl, "requires optional openpyxl (installed in CI)") +class CompanyHeaderCLI(unittest.TestCase): + def convert(self, header): + with TemporaryDirectory() as directory: + root = Path(directory) + workbook, output = root / "salary.xlsx", root / "salary.json" + book = openpyxl.Workbook() + try: + book.active.append(header) + book.active.append(["Acme Corp", "Berlin", 25, 108.5]) + book.save(workbook) + finally: + book.close() + result = subprocess.run( + [sys.executable, str(TOOL), str(workbook), "--output", str(output)], + capture_output=True, text=True, encoding="utf-8", + ) + self.assertEqual(result.returncode, 0, result.stderr) + return json.loads(output.read_text(encoding="utf-8"))["companies"] + + def test_company_prefixed_salary_columns_do_not_replace_the_company(self): + self.assertEqual(self.convert(["Company", "City", "Company Count", "Company Index"]), [ + {"company": "Acme Corp", "city": "Berlin", "categories": { + "company": {"count": 25, "index": 108.5}}} + ]) + + def test_existing_named_category_control(self): + self.assertEqual(self.convert(["Company Name", "City", "Engineering Count", "Engineering Index"]), [ + {"company": "Acme Corp", "city": "Berlin", "categories": { + "engineering": {"count": 25, "index": 108.5}}} + ]) + + def test_city_prefixed_salary_columns_do_not_replace_the_city(self): + self.assertEqual(self.convert(["Company", "City", "City Count", "City Index"]), [ + {"company": "Acme Corp", "city": "Berlin", "categories": { + "city": {"count": 25, "index": 108.5}}} + ]) diff --git a/tools/convert_salary_excel.py b/tools/convert_salary_excel.py index 7c02ad2e..1f2b3529 100644 --- a/tools/convert_salary_excel.py +++ b/tools/convert_salary_excel.py @@ -191,6 +191,12 @@ def parse_sheet(ws, sheet_label=None): elif header_matches(h, CITY_PATTERNS): city_col = i + # A qualified salary header such as "Company Index" may also contain a + # metadata token. Prefer an unqualified metadata column when one exists, + # leaving the qualified column available as salary data. + company_col = next((i for i, h in enumerate(headers) if h.lower() in COMPANY_PATTERNS), company_col) + city_col = next((i for i, h in enumerate(headers) if h.lower() in CITY_PATTERNS), city_col) + if company_col is None: print(f"Warning: Could not find company column in sheet '{ws.title}'.", file=sys.stderr) return []