Use masterdata project scope column for assignment disambiguation
This commit is contained in:
1 parent
bd2c0d512a
commit
4dd320878d
5 files changed
+36
-16
No files matched your search
@@ -46,12 +46,23 @@ def _name_keys(name: str) -> set[str]:
|
||||
|
||||
|
||||
def _disambiguate_by_project_key(
|
||||
candidates: list,
|
||||
candidates: list[MasterDataRecord],
|
||||
project_key: str,
|
||||
) -> object:
|
||||
"""Return the single candidate whose Funktion contains the project key, or None."""
|
||||
key = project_key.strip().casefold()
|
||||
matched = [c for c in candidates if key in c.funktion.casefold()]
|
||||
) -> MasterDataRecord | None:
|
||||
"""Return the single candidate matching allocation project key via masterdata project_scope."""
|
||||
parts = [
|
||||
token.strip().casefold()
|
||||
for token in re.split(r"[/,;|]", project_key)
|
||||
if token.strip()
|
||||
]
|
||||
project_tokens = set(parts or [project_key.strip().casefold()])
|
||||
|
||||
matched = []
|
||||
for candidate in candidates:
|
||||
candidate_scope = (candidate.project_scope or "PS").strip().casefold()
|
||||
if candidate_scope in project_tokens:
|
||||
matched.append(candidate)
|
||||
|
||||
return matched[0] if len(matched) == 1 else None
|
||||
|
||||
|
||||
@@ -105,7 +116,7 @@ def match_assignments(
|
||||
if len(candidates) == 1:
|
||||
selected = candidates[0]
|
||||
else:
|
||||
# Multiple candidates: disambiguate by project key in Funktion
|
||||
# Multiple candidates: disambiguate by explicit project scope column.
|
||||
selected = _disambiguate_by_project_key(candidates, allocation.project_key)
|
||||
if selected is None:
|
||||
issues.append(
|
||||
@@ -114,8 +125,8 @@ def match_assignments(
|
||||
message=(
|
||||
f"Ambiguous master-data for '{allocation.employee_name}' / "
|
||||
f"'{allocation.project_key}': {len(candidates)} rows, "
|
||||
f"none or multiple match Funktion. "
|
||||
f"Funktionen: {[c.funktion for c in candidates]}"
|
||||
f"none or multiple match project_scope. "
|
||||
f"project_scope values: {[c.project_scope for c in candidates]}"
|
||||
),
|
||||
severity="error",
|
||||
context=allocation.employee_name,
|
||||
|
||||
@@ -19,6 +19,7 @@ class MasterDataRecord:
|
||||
antragsnummer: str
|
||||
name: str
|
||||
qualifikation: str
|
||||
project_scope: str
|
||||
stellenanteil_percent: float
|
||||
funktion: str
|
||||
taetigkeit: str
|
||||
|
||||
@@ -243,6 +243,7 @@ def parse_masterdata_records(
|
||||
antragsnummer_col = column_index_from_string(columns_cfg["antragsnummer"])
|
||||
name_col = column_index_from_string(columns_cfg["name"])
|
||||
qualifikation_col = column_index_from_string(columns_cfg["qualifikation"])
|
||||
project_scope_col = column_index_from_string(columns_cfg["project_scope"])
|
||||
stellenanteil_col = column_index_from_string(columns_cfg["stellenanteil"])
|
||||
funktion_col = column_index_from_string(columns_cfg["funktion"])
|
||||
taetigkeit_col = column_index_from_string(columns_cfg["taetigkeit"])
|
||||
@@ -254,12 +255,16 @@ def parse_masterdata_records(
|
||||
if not name:
|
||||
continue
|
||||
|
||||
stellenanteil = _parse_german_decimal(
|
||||
worksheet.cell(row=row_index, column=stellenanteil_col).value,
|
||||
field_name=f"stellenanteil row {row_index}",
|
||||
decimal_separator=decimal_cfg.get("decimal_separator", ","),
|
||||
thousands_separator=decimal_cfg.get("thousands_separator", "."),
|
||||
stellenanteil_raw = worksheet.cell(row=row_index, column=stellenanteil_col).value
|
||||
stellenanteil = _to_float_or_none(stellenanteil_raw)
|
||||
if stellenanteil is None:
|
||||
stellenanteil = 0.0
|
||||
|
||||
project_scope = _to_text(
|
||||
worksheet.cell(row=row_index, column=project_scope_col).value
|
||||
)
|
||||
if not project_scope:
|
||||
project_scope = "PS"
|
||||
|
||||
records.append(
|
||||
MasterDataRecord(
|
||||
@@ -271,6 +276,7 @@ def parse_masterdata_records(
|
||||
qualifikation=_to_text(
|
||||
worksheet.cell(row=row_index, column=qualifikation_col).value
|
||||
),
|
||||
project_scope=project_scope,
|
||||
stellenanteil_percent=stellenanteil,
|
||||
funktion=_to_text(worksheet.cell(row=row_index, column=funktion_col).value),
|
||||
taetigkeit=_to_text(
|
||||
|
||||
@@ -132,6 +132,7 @@ def validate_sources(
|
||||
master_cols["antragsnummer"],
|
||||
master_cols["name"],
|
||||
master_cols["qualifikation"],
|
||||
master_cols["project_scope"],
|
||||
master_cols["stellenanteil"],
|
||||
master_cols["funktion"],
|
||||
master_cols["taetigkeit"],
|
||||
|
||||
Reference in new issue
Block a user