This commit is contained in:
2025-05-12 18:45:56 +00:00
parent cd1faeb46c
commit f797dab1a8

View File

@@ -7895,56 +7895,69 @@ class DataProcessor:
def _get_numeric_value_for_plausi(self, value_str, is_umsatz=False):
"""
Hilfsfunktion, um einen String in einen numerischen Wert (float) für Plausi-Checks umzuwandeln.
Gibt np.nan zurück, wenn der Wert nicht numerisch oder 'k.A.' ist.
Unterscheidet sich von get_numeric_filter_value, da es float/nan für interne Berechnungen liefert.
"""
if value_str is None or pd.isna(value_str) or str(value_str).strip().lower() in ['', 'k.a.', 'n/a', '-']:
if value_str is None or pd.isna(value_str):
return np.nan
# Nutze die bestehende Logik von extract_numeric_value, aber sorge für float/nan Output
# extract_numeric_value gibt Strings oder "k.A." zurück. Wir brauchen hier Zahlen.
# Temporäre (vereinfachte) Konvertierung, die verbessert werden könnte,
# um die volle Logik von extract_numeric_value (Einheiten etc.) zu nutzen,
# aber sicherstellt, dass ein float oder np.nan zurückkommt.
# Erster Versuch, die Logik von extract_numeric_value zu adaptieren:
raw_value_str_clean = str(value_str).strip()
if not raw_value_str_clean: return np.nan
processed_value = clean_text(raw_value_str_clean) # Globale Funktion
if processed_value.lower() in ['k.a.', 'n/a', '-']: return np.nan
# Fall 1: Explizit "unbekannt" oder leer
if raw_value_str_clean.lower() in ['', 'k.a.', 'n/a', '-']:
self.logger.debug(f"_get_numeric_value_for_plausi: Input '{raw_value_str_clean}' als 'unbekannt/leer' (NaN) interpretiert.")
return np.nan
# Fall 2: Versuche, als Zahl zu interpretieren
# (Hier sollte die volle Logik von extract_numeric_value für Einheiten etc. stehen)
# Für dieses Beispiel eine vereinfachte Version, die Tausendertrenner und Komma als Dezimal behandelt:
temp_val = clean_text(raw_value_str_clean) # Bereinigen
if temp_val.lower() in ['k.a.', 'n/a', '-']: return np.nan
processed_value = re.sub(r'(?i)^\s*(ca\.?|circa|rund|etwa|ueber|unter|mehr als|weniger als|bis zu)\s+', '', processed_value)
processed_value = re.sub(r'[€$£¥]', '', processed_value).strip()
processed_value = re.split(r'\s*(-||bis)\s*', processed_value, 1)[0].strip()
# Entferne Nicht-Zahlen-Zeichen außer Punkt und Komma und Minus am Anfang
temp_val = re.sub(r'[^\d.,\-]', '', temp_val)
processed_value_no_thousands = processed_value.replace('.', '').replace("'", "")
processed_value_final = processed_value_no_thousands.replace(',', '.')
match = re.search(r'([\d.]+)', processed_value_final)
if not match: return np.nan
num_str = match.group(1)
# Wenn nach Bereinigung leer
if not temp_val: return np.nan
# Behandlung von Tausenderpunkten und Dezimalkomma
if '.' in temp_val and ',' in temp_val: # z.B. 1.234,56 oder 1,234.56
if temp_val.rfind('.') > temp_val.rfind(','): # US-Stil: 1,234.56
temp_val = temp_val.replace(',', '')
else: # EU-Stil: 1.234,56
temp_val = temp_val.replace('.', '').replace(',', '.')
elif ',' in temp_val: # Nur Komma: 1234,56 -> 1234.56
temp_val = temp_val.replace(',', '.')
# Wenn nur Punkte: 1.234.567 -> 1234567 (Annahme: Tausendertrenner)
# Dies ist heikel, wenn es sich um IP-Adressen oder Versionsnummern handelt.
# Aber für Finanzdaten ist es oft so.
elif temp_val.count('.') > 1:
temp_val = temp_val.replace('.', '')
try:
if not num_str or num_str == '.' or num_str.count('.') > 1: raise ValueError
num = float(num_str)
num = float(temp_val)
# Einheiten-Skalierung (vereinfacht aus extract_numeric_value)
original_lower = raw_value_str_clean.lower()
multiplier = 1.0
if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower): multiplier = 1000000000.0
elif re.search(r'\bmio\s*\b|\bmillionen\s*\b|\bmill[.]?\s*\b', original_lower): multiplier = 1000000.0
elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower): multiplier = 1000.0
num = num * multiplier
return num if num > 0 else np.nan # Nur positive Werte, sonst NaN
final_num = num * multiplier
# Gemäß Ihrer Regel: Wenn der *ursprüngliche String* "0" (oder Ähnliches) war, soll es als "unbekannt" (NaN) gelten.
if final_num == 0.0 and raw_value_str_clean.strip() in ['0', '0.0', '0,0', '0.00', '0,000', '0.000']:
self.logger.debug(f"_get_numeric_value_for_plausi: Input '{raw_value_str_clean}' ist explizit '0', als 'unbekannt' (NaN) interpretiert.")
return np.nan
# self.logger.debug(f"_get_numeric_value_for_plausi: Input '{raw_value_str_clean}' erfolgreich zu {final_num} konvertiert.")
return final_num # Gibt die Zahl zurück, auch wenn es 0.0 ist (aus z.B. "0 Tsd")
except ValueError:
self.logger.debug(f"_get_numeric_value_for_plausi: Konnte '{raw_value_str_clean}' (verarbeitet als '{temp_val}') nicht zu float konvertieren.")
return np.nan
def _check_financial_plausibility(self, row_data_dict):
"""
Prüft die Plausibilität der finalen Umsatz- und Mitarbeiterzahlen
@@ -7973,19 +7986,22 @@ class DataProcessor:
umsatz_num = self._get_numeric_value_for_plausi(final_umsatz_str, is_umsatz=True)
ma_num = self._get_numeric_value_for_plausi(final_ma_str, is_umsatz=False)
# 1. Format-Plausibilität (wird durch _get_numeric_value_for_plausi schon behandelt)
if pd.isna(umsatz_num) and final_umsatz_str.lower() not in ['k.a.', '', None]:
# 1. Format-Plausibilität
# Wird gesetzt, wenn der Originalstring nicht k.A./leer/explizit "0" war, aber die Konvertierung trotzdem zu NaN führte.
if pd.isna(umsatz_num) and final_umsatz_str.lower().strip() not in ['k.a.', '', 'n/a', '-', '0', '0.0', '0,00', '0.000']:
results["plaus_umsatz_flag"] = "FEHLER_FORMAT"
results["begruendungen"].append(f"Finaler Umsatz ('{final_umsatz_str}') nicht numerisch.")
if pd.isna(ma_num) and final_ma_str.lower() not in ['k.a.', '', None]:
results["begruendungen"].append(f"Finaler Umsatz ('{final_umsatz_str}') konnte nicht als gültige Zahl interpretiert werden.")
if pd.isna(ma_num) and final_ma_str.lower().strip() not in ['k.a.', '', 'n/a', '-', '0', '0.0', '0,00', '0.000']:
results["plaus_ma_flag"] = "FEHLER_FORMAT"
results["begruendungen"].append(f"Finale MA-Zahl ('{final_ma_str}') nicht numerisch.")
results["begruendungen"].append(f"Finale MA-Zahl ('{final_ma_str}') konnte nicht als gültige Zahl interpretiert werden.")
# Nur weiter prüfen, wenn Werte numerisch sind
if not pd.isna(umsatz_num):
if umsatz_num < getattr(Config, 'PLAUSI_UMSATZ_MIN_WARNUNG', 50000):
results["plaus_umsatz_flag"] = "WARNUNG_NIEDRIG"
results["begruendungen"].append(f"Finaler Umsatz ({umsatz_num:,.0f} €) sehr niedrig (< {getattr(Config, 'PLAUSI_UMSATZ_MIN_WARNUNG', 50000):,.0f}).")
if umsatz_num == 0: # Gilt für Fälle, wo z.B. "0 Tsd" zu 0.0 wird
results["plaus_umsatz_flag"] = "WARNUNG_NULL_WERT"
results["begruendungen"].append(f"Finaler Umsatz ist numerisch 0 (ursprünglicher Wert: '{final_umsatz_str}').")
elif umsatz_num < getattr(Config, 'PLAUSI_UMSATZ_MIN_WARNUNG', 50000):
if umsatz_num > getattr(Config, 'PLAUSI_UMSATZ_MAX_WARNUNG', 200000000000):
results["plaus_umsatz_flag"] = "WARNUNG_HOCH"
results["begruendungen"].append(f"Finaler Umsatz ({umsatz_num:,.0f} €) sehr hoch (> {getattr(Config, 'PLAUSI_UMSATZ_MAX_WARNUNG', 200000000000):,.0f} €).")