mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-09-17 08:36:25 +00:00
Fix salary tool edge cases (#75)
* fix: handle salary tool edge cases * fix: preserve Danish salary compounds
This commit is contained in:
+5
-2
@@ -204,12 +204,15 @@ def format_entry(entry, metadata):
|
|||||||
count = data.get("count")
|
count = data.get("count")
|
||||||
index = data.get("index")
|
index = data.get("index")
|
||||||
if count is not None or index is not None:
|
if count is not None or index is not None:
|
||||||
count_str = str(count) if count else "-"
|
count_str = str(count) if count is not None else "-"
|
||||||
if index is not None:
|
if isinstance(index, (int, float)):
|
||||||
diff = index - baseline
|
diff = index - baseline
|
||||||
sign = "+" if diff >= 0 else ""
|
sign = "+" if diff >= 0 else ""
|
||||||
index_str = f"{index:.1f}"
|
index_str = f"{index:.1f}"
|
||||||
diff_str = f"{sign}{diff:.1f}%"
|
diff_str = f"{sign}{diff:.1f}%"
|
||||||
|
elif index is not None:
|
||||||
|
index_str = str(index)
|
||||||
|
diff_str = ""
|
||||||
else:
|
else:
|
||||||
index_str = "N/A*"
|
index_str = "N/A*"
|
||||||
diff_str = ""
|
diff_str = ""
|
||||||
|
|||||||
@@ -37,6 +37,13 @@ class DetectColumnTypeTests(unittest.TestCase):
|
|||||||
with self.subTest(header=header):
|
with self.subTest(header=header):
|
||||||
self.assertEqual(detect_column_type(header), "count")
|
self.assertEqual(detect_column_type(header), "count")
|
||||||
|
|
||||||
|
def test_count_inside_word_does_not_make_count_header(self):
|
||||||
|
self.assertIsNone(detect_column_type("Accounting Total"))
|
||||||
|
self.assertEqual(detect_column_type("Accounting Index"), "index")
|
||||||
|
|
||||||
|
def test_danish_compound_headers_still_match(self):
|
||||||
|
self.assertEqual(detect_column_type("Lønindeks"), "index")
|
||||||
|
|
||||||
def test_parse_sheet_preserves_category_name_with_letter_n(self):
|
def test_parse_sheet_preserves_category_name_with_letter_n(self):
|
||||||
ws = FakeWorksheet([
|
ws = FakeWorksheet([
|
||||||
("Company", "Engineering Count", "Engineering Index"),
|
("Company", "Engineering Count", "Engineering Index"),
|
||||||
@@ -47,6 +54,16 @@ class DetectColumnTypeTests(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(companies[0]["categories"]["engineering"], {"count": 12, "index": 105.5})
|
self.assertEqual(companies[0]["categories"]["engineering"], {"count": 12, "index": 105.5})
|
||||||
|
|
||||||
|
def test_parse_sheet_groups_accounting_count_index_pair(self):
|
||||||
|
ws = FakeWorksheet([
|
||||||
|
("Company", "Accounting Count", "Accounting Index"),
|
||||||
|
("Example Corp", 12, 105.5),
|
||||||
|
])
|
||||||
|
|
||||||
|
companies = parse_sheet(ws)
|
||||||
|
|
||||||
|
self.assertEqual(companies[0]["categories"]["accounting"], {"count": 12, "index": 105.5})
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
import unittest
|
||||||
|
|
||||||
|
from salary_lookup import format_entry
|
||||||
|
|
||||||
|
|
||||||
|
class FormatEntryTests(unittest.TestCase):
|
||||||
|
def test_zero_count_is_displayed_as_zero(self):
|
||||||
|
entry = {
|
||||||
|
"company": "Example Corp",
|
||||||
|
"city": "",
|
||||||
|
"categories": {
|
||||||
|
"public_data": {
|
||||||
|
"count": 0,
|
||||||
|
"index": 100.0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rendered = format_entry(entry, {"index_baseline": 100, "index_label": "Index"})
|
||||||
|
|
||||||
|
self.assertRegex(rendered, r"Public Data\s+0\s+100\.0")
|
||||||
|
|
||||||
|
def test_text_index_does_not_crash(self):
|
||||||
|
entry = {
|
||||||
|
"company": "Example Corp",
|
||||||
|
"city": "",
|
||||||
|
"categories": {
|
||||||
|
"sample": {
|
||||||
|
"count": 3,
|
||||||
|
"index": "private",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rendered = format_entry(entry, {"index_baseline": 100, "index_label": "Index"})
|
||||||
|
|
||||||
|
self.assertIn("private", rendered)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -42,6 +42,7 @@ COMPANY_PATTERNS = {"firma", "company", "virksomhed", "employer", "arbejdsgiver"
|
|||||||
CITY_PATTERNS = {"by", "city", "kommune", "location", "lokation", "sted"}
|
CITY_PATTERNS = {"by", "city", "kommune", "location", "lokation", "sted"}
|
||||||
COUNT_PATTERNS = {"antal", "count", "number", "n", "employees", "medarbejdere"}
|
COUNT_PATTERNS = {"antal", "count", "number", "n", "employees", "medarbejdere"}
|
||||||
INDEX_PATTERNS = {"indeks", "index", "idx", "salary", "løn", "median", "average", "gennemsnit"}
|
INDEX_PATTERNS = {"indeks", "index", "idx", "salary", "løn", "median", "average", "gennemsnit"}
|
||||||
|
DANISH_COMPOUND_PATTERNS = {"antal", "indeks", "løn", "gennemsnit", "medarbejdere"}
|
||||||
|
|
||||||
|
|
||||||
def header_matches(header, patterns):
|
def header_matches(header, patterns):
|
||||||
@@ -50,10 +51,9 @@ def header_matches(header, patterns):
|
|||||||
tokens = set(re.findall(r"[a-zæøåöäü0-9]+", h))
|
tokens = set(re.findall(r"[a-zæøåöäü0-9]+", h))
|
||||||
|
|
||||||
for p in patterns:
|
for p in patterns:
|
||||||
if len(p) == 1:
|
|
||||||
if p in tokens:
|
if p in tokens:
|
||||||
return True
|
return True
|
||||||
elif p in h:
|
if p in DANISH_COMPOUND_PATTERNS and p in h:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@@ -62,10 +62,7 @@ def strip_type_patterns(header, patterns):
|
|||||||
"""Remove count/index words from a header to derive a category name."""
|
"""Remove count/index words from a header to derive a category name."""
|
||||||
name = header.lower()
|
name = header.lower()
|
||||||
for p in patterns:
|
for p in patterns:
|
||||||
if len(p) == 1:
|
name = re.sub(rf"(?<![a-zæøåöäü0-9]){re.escape(p)}(?![a-zæøåöäü0-9])", "", name)
|
||||||
name = re.sub(rf"\b{re.escape(p)}\b", "", name)
|
|
||||||
else:
|
|
||||||
name = name.replace(p, "")
|
|
||||||
return name.strip(" _-")
|
return name.strip(" _-")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user