bugfix
This commit is contained in:
@@ -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} €).")
|
||||
|
||||
Reference in New Issue
Block a user