From 15e97b6bdb5ee3dbf8be02878093593e1bb0a9b5 Mon Sep 17 00:00:00 2001 From: Floke Date: Mon, 12 May 2025 19:14:57 +0000 Subject: [PATCH] bugfix --- brancheneinstufung.py | 277 ++++++++++++++++++++++++++++++++---------- 1 file changed, 213 insertions(+), 64 deletions(-) diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 69c7883e..668d7efe 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -7970,10 +7970,14 @@ class DataProcessor: def _check_financial_plausibility(self, row_data_dict): + """ + Prüft die Plausibilität der finalen Umsatz- und Mitarbeiterzahlen + sowie deren Ratio und den Abgleich mit CRM-Daten. + """ results = { - "plaus_umsatz_flag": "NICHT_PRUEFBAR", # Default, wenn Wert NaN ist - "plaus_ma_flag": "NICHT_PRUEFBAR", # Default, wenn Wert NaN ist - "plaus_ratio_flag": "NICHT_PRUEFBAR",# Default + "plaus_umsatz_flag": "NICHT_PRUEFBAR", + "plaus_ma_flag": "NICHT_PRUEFBAR", + "plaus_ratio_flag": "NICHT_PRUEFBAR", "abweichung_umsatz_flag": "N/A", "abweichung_ma_flag": "N/A", "begruendungen": [] @@ -7982,7 +7986,6 @@ class DataProcessor: final_umsatz_str = row_data_dict.get("Finaler Umsatz (Wiki>CRM)", "k.A.") final_ma_str = row_data_dict.get("Finaler Mitarbeiter (Wiki>CRM)", "k.A.") - # DEBUG-Ausgabe für die Einganswerte der Funktion self.logger.debug(f" _check_financial_plausibility Input: final_umsatz_str='{final_umsatz_str}', final_ma_str='{final_ma_str}'") umsatz_num = self._get_numeric_value_for_plausi(final_umsatz_str, is_umsatz=True) @@ -7992,18 +7995,129 @@ class DataProcessor: # 1. Plausibilität Umsatz if pd.isna(umsatz_num): - # Wenn der Originalstring nicht schon 'k.A.' oder leer war (was bereits NaN ergibt), dann ist es ein Formatfehler - if final_umsatz_str.lower().strip() not in ['k.a.', '', 'n/a', '-']: + # --- BEGINN DEBUG-BLOCK FÜR UMSATZ-FORMAT --- + self.logger.debug(f" Format-Check Umsatz: final_umsatz_str='{final_umsatz_str}' (Typ: {type(final_umsatz_str)})") + self.logger.debug(f" Format-Check Umsatz: umsatz_num ist NaN? {pd.isna(umsatz_num)}") + exclusion_list_umsatz = ['k.a.', '', 'n/a', '-', '0', '0.0', '0,00', '0.000'] # Explizite "0"-Strings sind KEIN Formatfehler + is_excluded_umsatz = final_umsatz_str.lower().strip() in exclusion_list_umsatz + self.logger.debug(f" Format-Check Umsatz: '{final_umsatz_str.lower().strip()}' in exclusion_list_umsatz? {is_excluded_umsatz}") + # --- ENDE DEBUG-BLOCK FÜR UMSATZ-FORMAT --- + + if not is_excluded_umsatz: # Nur wenn der String nicht in der Ausschlussliste war results["plaus_umsatz_flag"] = "FEHLER_FORMAT" - results["begruendungen"].append(f"Finaler Umsatz ('{final_umsatz_str}') konnte nicht als Zahl interpretiert werden.") - # else: Flag bleibt "NICHT_PRUEFBAR" - else: # umsatz_num ist eine gültige Zahl (kann auch 0 sein) - results["plaus_umsatz_flag"] = "OK" # Initialannahme für numerische Werte - if umsatz_num == 0: + results["begruendungen"].append(f"Finaler Umsatz ('{final_umsatz_str}') konnte nicht als gültige Zahl interpretiert werden (und war kein 'k.A.' oder expliziter '0'-Wert).") + # else: Flag bleibt "NICHT_PRUEFBAR", da es 'k.A.' oder ein expliziter '0'-String war + else: # umsatz_num ist eine gültige Zahl (kann auch 0 sein,Abs wenn aus "0 Tsd" etc.) + results["plaus_umsatz_flag"] = "OK" + olut! Entschuldigung, ich hätte den Kontext direkt mitliefern sollen. + +Hier ist dieif 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"]. **gesamte `_check_financial_plausibility`-Methode** mit dem erweiterten Debugging für die Formatappend(f"Finaler Umsatz ist numerisch 0 (ursprünglicher Wert im Sheet war: '{final_umsatz_str-Prüfung des Umsatzes. Sie können Ihre bestehende Methode durch diese ersetzen: + +```python +# Innerhalb der}').") + elif umsatz_num < getattr(Config, 'PLAUSI_UMSATZ_MIN_WARNUNG', DataProcessor Klasse + + def _check_financial_plausibility(self, row_data_dict): + """ + Pr50000): + results["plaus_umsatz_flag"] = "WARNUNG_NIEDRIG" + results["begruendungen"].append(f"Finaler Umsatz ({umsatz_num:,.0f}üft die Plausibilität der finalen Umsatz- und Mitarbeiterzahlen + sowie deren Ratio und den Abgleich mit CRM-Daten. + + €) < {getattr(Config, 'PLAUSI_UMSATZ_MIN_WARNUNG', 50000):,.0f} €.") + elif umsatz_num > getattr(Config, 'PLAUSI Args: + row_data_dict (dict): Ein Dictionary mit den relevanten Werten der Zeile._UMSATZ_MAX_WARNUNG', 200000000000): + results["plaus_umsatz_flag"] = "WARNUNG_HOCH" + results["begruendungen"].append(f"Finaler Umsatz ({umsatz_num:,.0f} €) + Returns: + dict: Ein Dictionary mit Plausibilitäts-Flags und einer Begründung. + """ + results = { + "plaus_umsatz_flag": "NICHT_PRUEFBAR", + "plaus_ma_flag": "NICHT_PRUEFBAR", + "pl > {getattr(Config, 'PLAUSI_UMSATZ_MAX_WARNUNG', 200000000000):,.0f} €.") + + # 2. Plausibilitätaus_ratio_flag": "NICHT_PRUEFBAR", + "abweichung_umsatz_flag": "N/A", + "abweichung_ma_flag": "N/A", + " Mitarbeiter + if pd.isna(ma_num): + # --- BEGINN DEBUG-BLOCK FÜR MA-FORMAT --- + self.logger.debug(f" Format-Check MA: final_ma_str='{finalbegruendungen": [] + } + + final_umsatz_str = row_data_dict.get("Finaler Umsatz (Wiki>CRM)", "k.A.") + final_ma_str = row_data_dict.get("_ma_str}' (Typ: {type(final_ma_str)})") + self.logger.debug(f" Format-Check MA: ma_num ist NaN? {pd.isna(ma_num)}")Finaler Mitarbeiter (Wiki>CRM)", "k.A.") + + self.logger.debug(f" _check_financial_plausibility Input: final_umsatz_str='{final_umsatz_str}', final_ma_str='{final_ma_str}'") + + umsatz_num = self._get_numeric_value_for_plaus + exclusion_list_ma = ['k.a.', '', 'n/a', '-', '0', '0.0', '0,00', '0.000'] + is_excluded_ma = final_ma_str.lower().strip() in exclusion_list_ma + self.logger.debug(fi(final_umsatz_str, is_umsatz=True) + ma_num = self._get_numeric_value_for_plausi(final_ma_str, is_umsatz=False" Format-Check MA: '{final_ma_str.lower().strip()}' in exclusion_list_ma? {is) + + self.logger.debug(f" _check_financial_plausibility Numerisch: umsatz_num={umsatz_num}, ma_num={ma_num}") + + # 1. Plausibilität Umsatz + if pd_excluded_ma}") + # --- ENDE DEBUG-BLOCK FÜR MA-FORMAT --- + if not is_excluded_ma: +.isna(umsatz_num): + # =========== BEGINN DEBUG-BLOCK FÜR UMSATZ FORMAT results["plaus_ma_flag"] = "FEHLER_FORMAT" + results["begruendungen"].append(f"Finale MA-Zahl ('{final_ma_str}') konnte nicht als gültige Zahl interpretiert werden (und war kein 'k.A.' oder expliziter '0'-Wert).") + -CHECK =========== + self.logger.debug(f" Format-Check Umsatz: final_umsatz_str='{finalelse: + results["plaus_ma_flag"] = "OK" + if ma_num == 0:_umsatz_str}' (Typ: {type(final_umsatz_str)})") + self. + results["plaus_ma_flag"] = "WARNUNG_NULL_WERT" + results["begruendungen"].logger.debug(f" Format-Check Umsatz: umsatz_num ist NaN? {pd.isna(umsappend(f"Finale MA-Zahl ist numerisch 0 (ursprünglicher Wert im Sheet war: '{final_ma_str}').") + elif ma_num < getattr(Config, 'PLAUSI_MA_MIN_WARNUNGatz_num)}") + exclusion_list_umsatz = ['k.a.', '', 'n/a', '-', '0', '0.0', '0,00', '0.000'] # Explizite Strings,_ABS', 1): + results["plaus_ma_flag"] = "WARNUNG_NIEDRIG" + results["begruendungen"].append(f"Finale MA-Zahl ({ma_num:.0f}) < {getattr die NaN in umsatz_num erzeugen, aber KEIN Formatfehler sind + is_excluded_umsatz = final(Config, 'PLAUSI_MA_MIN_WARNUNG_ABS', 1)}.") + elif ma_num >_umsatz_str.lower().strip() in exclusion_list_umsatz + self.logger.debug(f" Format-Check getattr(Config, 'PLAUSI_MA_MAX_WARNUNG', 1000000 Umsatz: '{final_umsatz_str.lower().strip()}' in exclusion_list_umsatz? {is_excluded_): + results["plaus_ma_flag"] = "WARNUNG_HOCH" + results["begruendungen"].append(f"Finale MA-Zahl ({ma_num:.0f}) > {getattr(Config, 'PLAUSumsatz}") + + if not is_excluded_umsatz: # Nur wenn der String nicht in der ExklI_MA_MAX_WARNUNG', 1000000)}.") + + if not pd.isna(umsatz_num) and umsatz_num > getattr(Config, 'PLAUSI_UMSATZ_MIN_SCHWELLE_FUER_MA_CHECK', 1000000) andusionsliste ist, ist es ein Formatfehler + # =========== ENDE DEBUG-BLOCK FÜR UMSATZ FORMAT-CHECK ( \ + ma_num !=0 and ma_num < getattr(Config, 'PLAUSI_MA_MIN_WARNUNG_BEI_UMSATZ', 3) : + if results["plaus_ma_flag"]Bedingung angepasst) =========== + results["plaus_umsatz_flag"] = "FEHLER_FORMAT == "OK": results["plaus_ma_flag"] = "WARNUNG_RATIO_IMPL" + results["begruendungen"].append(f"Wenige MA ({ma_num:.0f}) bei" + results["begruendungen"].append(f"Finaler Umsatz ('{final_umsatz_str}') konnte nicht als gültige Zahl interpretiert werden (und war kein bekannter 'Unbekannt'-Wert wie k.A. oder '0').") + # signifikantem Umsatz ({umsatz_num:,.0f} €).") + + # 3. Umsatz/MA Ratio + if not pd.isna(umsatz_num) and not pd.isna(ma_num): + if ma_num > 0: + ratio = umsatz_num / ma_num + results["plaus_ratio_flag"] = "OK" + if ratio < getattr(Config, 'PLAUSI_ else: Flag bleibt "NICHT_PRUEFBAR", da der Input ein bekannter "Unbekannt"-Wert war + else: # umsatz_num ist eine gültige Zahl (kann auch 0 sein) + results["plaus_umsatz_flag"] = "OK" + if umsatz_num == 0: + RATIO_UMSATZ_PRO_MA_MIN', 25000): + results["plaus_ratio_flag"] = "WARNUNG_RATIO_NIEDRIG" + results["begruendungen"].append(f"Umsatz/MA Ratio ({ratio:,.0f} €/MA) < {getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MINresults["plaus_umsatz_flag"] = "WARNUNG_NULL_WERT" results["begruendungen"].append(f"Finaler Umsatz ist numerisch 0 (aus '{final_umsatz_str}').") elif umsatz_num < getattr(Config, 'PLAUSI_UMSATZ_MIN_WARNUNG', 50000): results["plaus_umsatz_flag"] = "WARNUNG_NIEDRIG" + results["beg', 25000):,.0f}.") + elif ratio > getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MAX', 1500000): + results["plaus_ratio_flag"] = "WARNUNG_RATIO_HOCH" + results["begruendungen"].append(f"Umsatz/MA Ratio ({ratio:,.0f} €/MA) > {getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MAX', 1500000):,.0f}.") + elif umsatz_num > 0 and ma_num == 0: + results["plaus_ratio_flag"] = "FEHLER_RATIO_MA_NULL" results["begruendungen"].append(f"Finaler Umsatz ({umsatz_num:,.0f} €) < {getattr(Config, 'PLAUSI_UMSATZ_MIN_WARNUNG', 50000):,.0f} €.") elif umsatz_num > getattr(Config, 'PLAUSI_UMSATZ_MAX_WARNUNG', 200000000000): results["plaus_umsatz_flag"] = "WARNUNG_HOCH" @@ -8011,52 +8125,25 @@ class DataProcessor: # 2. Plausibilität Mitarbeiter if pd.isna(ma_num): - if final_ma_str.lower().strip() not in ['k.a.', '', 'n/a', '-']: - results["plaus_ma_flag"] = "FEHLER_FORMAT" - results["begruendungen"].append(f"Finale MA-Zahl ('{final_ma_str}') konnte nicht als Zahl interpretiert werden.") - # else: Flag bleibt "NICHT_PRUEFBAR" - else: # ma_num ist eine gültige Zahl - results["plaus_ma_flag"] = "OK" # Initialannahme - if ma_num == 0: # Explizit numerisch 0 - results["plaus_ma_flag"] = "WARNUNG_NULL_WERT" - results["begruendungen"].append(f"Finale MA-Zahl ist numerisch 0 (aus '{final_ma_str}').") - elif ma_num < getattr(Config, 'PLAUSI_MA_MIN_WARNUNG_ABS', 1): - results["plaus_ma_flag"] = "WARNUNG_NIEDRIG" - results["begruendungen"].append(f"Finale MA-Zahl ({ma_num:.0f}) < {getattr(Config, 'PLAUSI_MA_MIN_WARNUNG_ABS', 1)}.") - elif ma_num > getattr(Config, 'PLAUSI_MA_MAX_WARNUNG', 1000000): - results["plaus_ma_flag"] = "WARNUNG_HOCH" - results["begruendungen"].append(f"Finale MA-Zahl ({ma_num:.0f}) > {getattr(Config, 'PLAUSI_MA_MAX_WARNUNG', 1000000)}.") - - if not pd.isna(umsatz_num) and umsatz_num > getattr(Config, 'PLAUSI_UMSATZ_MIN_SCHWELLE_FUER_MA_CHECK', 1000000) and \ - ma_num !=0 and ma_num < getattr(Config, 'PLAUSI_MA_MIN_WARNUNG_BEI_UMSATZ', 3) : - if results["plaus_ma_flag"] == "OK": results["plaus_ma_flag"] = "WARNUNG_RATIO_IMPL" - results["begruendungen"].append(f"Wenige MA ({ma_num:.0f}) bei signifikantem Umsatz ({umsatz_num:,.0f} €).") - - # 3. Umsatz/MA Ratio - if not pd.isna(umsatz_num) and not pd.isna(ma_num): - if ma_num > 0: - ratio = umsatz_num / ma_num - results["plaus_ratio_flag"] = "OK" # Initialannahme - if ratio < getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MIN', 25000): - results["plaus_ratio_flag"] = "WARNUNG_RATIO_NIEDRIG" - results["begruendungen"].append(f"Umsatz/MA Ratio ({ratio:,.0f} €/MA) < {getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MIN', 25000):,.0f}.") - elif ratio > getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MAX', 1500000): - results["plaus_ratio_flag"] = "WARNUNG_RATIO_HOCH" - results["begruendungen"].append(f"Umsatz/MA Ratio ({ratio:,.0f} €/MA) > {getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MAX', 1500000):,.0f}.") - elif umsatz_num > 0 and ma_num == 0: # Umsatz da, aber MA ist numerisch 0 - results["plaus_ratio_flag"] = "FEHLER_RATIO_MA_NULL" - results["begruendungen"].append("Ratio nicht berechenbar: Umsatz > 0, aber MA=0.") + # =========== BEGINN DEBUG-BLOCK FÜR MAruendungen"].append("Ratio nicht berechenbar: Umsatz > 0, aber MA=0.") if results["plaus_ma_flag"] == "OK" or results["plaus_ma_flag"] == "WARNUNG_NULL_WERT": - results["plaus_ma_flag"] = "WARNUNG_NULL_BEI_UMSATZ" # Spezifischere Warnung - # Wenn ma_num NaN ist oder umsatz_num NaN ist, bleibt der Flag "NICHT_PRUEFBAR" + results["plaus_ma_flag"] = "WARNUNG_NULL_BEI_UMSATZ" - # ... (Rest der Funktion für Abweichung CRM/Wiki bleibt gleich) ... + # 4. Abgleich CRM vs. Wiki (Logik bleibt wie im letzten Vorschlag) crm_umsatz_str = row_data_dict.get("CRM Umsatz", "k.A.") wiki_umsatz_str = row_data_dict.get("Wiki Umsatz", "k.A.") crm_ma_str = row_data_dict.get("CRM Anzahl Mitarbeiter", "k.A.") wiki_ma_str = row_data_dict.get("Wiki Mitarbeiter", "k.A.") - crm_u = self._get_numeric_value_for_plausi(crm_umsatz_str, True) + crm_u = self._get_numeric_value_for_plausi(crm_umsatz_str, True FORMAT-CHECK =========== + self.logger.debug(f" Format-Check MA: final_ma_str='{final_ma_str}' (Typ: {type(final_ma_str)})") + self.logger.debug(f" Format-Check MA: ma_num ist NaN? {pd.isna(ma_num)}") + exclusion_list_ma = ['k.a.', '', 'n/a', '-', '0', '0.0', '0,00', '0.000'] # Explizite Strings, die NaN in ma_num erzeugen, aber KEIN Formatfehler sind + is_excluded_ma = final_ma_str.lower().strip() in exclusion_list_ma + self.logger.debug(f" Format-Check MA: '{final_ma_str.lower().strip()}' in exclusion_list_ma? {is_excluded_ma}") + + if not is_excluded_ma: # Nur wenn der String nicht in der Exklusionsliste ist, ist es ein Formatfehler + ) wiki_u = self._get_numeric_value_for_plausi(wiki_umsatz_str, True) crm_m = self._get_numeric_value_for_plausi(crm_ma_str, False) wiki_m = self._get_numeric_value_for_plausi(wiki_ma_str, False) @@ -8065,30 +8152,92 @@ class DataProcessor: if not pd.isna(crm_u) and not pd.isna(wiki_u): if crm_u == 0 and wiki_u == 0: results["abweichung_umsatz_flag"] = "OK_BEIDE_NULL" - elif crm_u > 0 and wiki_u > 0 : - diff = abs(crm_u - wiki_u); max_val = max(crm_u, wiki_u) - if max_val > 0 and (diff / max_val) > abweichung_prozent: + elif crm_u >= 0 and wiki_u >= 0 : # >= 0 um auch den Fall # =========== ENDE DEBUG-BLOCK FÜR MA FORMAT-CHECK (Bedingung angepasst) =========== + results["plaus_ma_flag"] = "FEHLER_FORMAT" + results["begruendungen"].append(f"Finale MA-Zahl ('{final_ma_str}') konnte nicht als gültige Zahl interpretiert werden (und war kein bekannter 'Unbekannt'-Wert wie k.A. oder '0').") + # else: Flag bleibt "NICHT_PRUEFBAR" + else: # ma_num ist eine gültige Zahl + results["plaus_ma_flag"] = "OK" + if ma_num == 0: + results["plaus_ma_flag"] = "WARNUNG_NULL_WERT" + results["begruendungen"].append(f"Finale MA-Zahl ist0 vs positive Zahl zu erwischen + # Wenn einer der Werte 0 ist und der andere nicht (und nicht klein), ist es signifikant + if (crm_u == 0 and wiki_u > getattr(Config, 'PLAUSI_UMSATZ_MIN_WARNUNG', 50000)/10) or \ + (wiki_u == 0 and crm_u > getattr(Config, 'PLAUSI_UMSATZ_MIN_WARNUNG', 50000)/10): results["abweichung_umsatz_flag"] = "WARNUNG_SIGNIFIKANT" - results["begruendungen"].append(f"Umsatz CRM ({crm_u:,.0f}) vs. Wiki ({wiki_u:,.0f}) weicht >{abweichung_prozent*100:.0f}% ab.") - else: results["abweichung_umsatz_flag"] = "OK" - else: results["abweichung_umsatz_flag"] = "INFO_EINER_NULL" - elif pd.isna(crm_u) and not pd.isna(wiki_u): results["abweichung_umsatz_flag"] = "CRM_FEHLT" + results["begruendungen"].append(f"Umsatz CRM numerisch 0 (aus '{final_ma_str}').") + elif ma_num < getattr(Config, 'PLAUSI_MA_MIN_WARNUNG_ABS', 1): + results["plaus_ma_flag"] = "WARNUNG_NIEDRIG" + results["begruendungen"].append(f"Finale MA-Zahl ({ma_num:.0f}) < {getattr(Config, 'PLAUSI_MA_MIN_WARNUNG_ABS', 1)}.") + elif ma_num > getattr(Config, 'PLAUSI_MA_MAX_WARNUNG', ({crm_u:,.0f}) vs. Wiki ({wiki_u:,.0f}) weicht signifikant ab (einer ist 0).") + elif crm_u > 0 and wiki_u > 0: # Nur wenn beide positiv sind, prozentuale Abweichung berechnen + diff = abs(crm_u - wiki_u); max_val = max(crm_u, wiki_u) + if max_val > 0 and (diff1000000): + results["plaus_ma_flag"] = "WARNUNG_HOCH" + results["begruendungen"].append(f"Finale MA-Zahl ({ma_num:.0f}) > {getattr(Config, 'PLAUSI_MA_MAX_WARNUNG', 1000000)}.") + + if not pd.isna(umsatz_num) and umsatz_num > getattr(Config, 'PLAUSI_UMSATZ_MIN_SCHWELLE_FUER_MA_CHECK', 1000000) and \ + ma_num !=0 and ma_num < getattr(Config, 'PLAUSI / max_val) > abweichung_prozent: + results["abweichung_umsatz_flag"] = "WARNUNG_SIGNIFIKANT" + results["begruendungen"].append(f"Umsatz CRM ({crm_u:,.0f}) vs. Wiki ({wiki_u:,.0f}) weicht >{abweichung_prozent*100:.0f}% ab.") + else: results["abweichung_umsatz_flag"] = "OK" + _MA_MIN_WARNUNG_BEI_UMSATZ', 3) : + if results["plaus_ma_flag"] == "OK": results["plaus_ma_flag"] = "WARNUNG_RATIO_IMPL" + results["begruendungen"].append(f"Wenige MA ({ma_num:.0f}) bei signifikantem Umsatz ({umsatz_num:,.0f} €).") + + # 3. Umsatz/else: results["abweichung_umsatz_flag"] = "OK" # Wenn beide nahe 0 sind oder einer 0 und der andere klein + else: results["abweichung_umsatz_flag"] = "INFO_NEGMA Ratio + # ... (Rest der Funktion wie im vorherigen Vorschlag, da dieser Teil weniger problematisch schATIV_WERT" # Sollte nicht vorkommen, da _get_numeric... >=0 liefert + elif pd.isna(ien) + if not pd.isna(umsatz_num) and not pd.isna(ma_num): + if macrm_u) and not pd.isna(wiki_u): results["abweichung_umsatz_flag"] = "CRM_num > 0: + ratio = umsatz_num / ma_num + results["plaus_ratio_FEHLT" elif not pd.isna(crm_u) and pd.isna(wiki_u): results["abweichung_umsatz_flag"] = "WIKI_FEHLT" - if not pd.isna(crm_m) and not pd.isna(wiki_m): +_flag"] = "OK" + if ratio < getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MIN', 25000): + results["plaus_ratio_ if not pd.isna(crm_m) and not pd.isna(wiki_m): if crm_m == 0 and wiki_m == 0: results["abweichung_ma_flag"] = "OK_BEIDE_NULL" - elif crm_m >= 0 and wiki_m >= 0: # Erlaube 0 MA für Vergleich, wenn nicht NaN - # Spezialfall: wenn einer 0 ist und der andere nicht, ist es eine große Abweichung, es sei denn beide sind sehr klein - if (crm_m == 0 and wiki_m > 5) or (wiki_m == 0 and crm_m > 5) or (crm_m > 0 and wiki_m > 0 and (abs(crm_m - wiki_m) / max(crm_m, wiki_m)) > abweichung_prozent): + elif crm_m >= 0 and wiki_m >=flag"] = "WARNUNG_RATIO_NIEDRIG" + results["begruendungen"].append(f"Umsatz/MA Ratio ({ratio:,.0f} €/MA) < {getattr(Config, 'PLAUSI_RATIO_UM 0: + if (crm_m == 0 and wiki_m > getattr(Config, 'PLAUSISATZ_PRO_MA_MIN', 25000):,.0f}.") + elif ratio > getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MAX', 15000_MA_MIN_WARNUNG_BEI_UMSATZ', 3)*2) or \ + (wiki_m == 0 and crm_m > getattr(Config, 'PLAUSI_MA_MIN_00): + results["plaus_ratio_flag"] = "WARNUNG_RATIO_HOCH" + results["begruendungen"].append(f"Umsatz/MA Ratio ({ratio:,.0f} €/MA) > {getattr(Config, 'PLAUSI_RATIO_UMSATZ_PRO_MA_MAX',WARNUNG_BEI_UMSATZ', 3)*2): # Faktor 2 für kleine Zahlen results["abweichung_ma_flag"] = "WARNUNG_SIGNIFIKANT" - results["begruendungen"].append(f"MA CRM ({crm_m:.0f}) vs. Wiki ({wiki_m:.0f}) weicht signifikant ab.") - else: results["abweichung_ma_flag"] = "OK" + results["begruendungen"].append(f"MA 1500000):,.0f}.") + elif umsatz_num > 0 and ma_num == 0: + results["plaus_ratio_flag"] = "FEHLER_RATIO_MA CRM ({crm_m:.0f}) vs. Wiki ({wiki_m:.0f}) weicht signifikant ab (einer ist 0).") + elif crm_m > 0 and wiki_m > 0: + _NULL" + results["begruendungen"].append("Ratio nicht berechenbar: Umsatz > 0, aber MA=0.") + if results["plaus_ma_flag"] == "OK" or results["plaus_ma_flag"] == "diff = abs(crm_m - wiki_m); max_val = max(crm_m, wiki_m) + if max_val > 0 and (diff / max_val) > abweichung_prozent: + WARNUNG_NULL_WERT": + results["plaus_ma_flag"] = "WARNUNG_NULL_BEI_UMresults["abweichung_ma_flag"] = "WARNUNG_SIGNIFIKANT" + results["begruendungen"].append(f"MA CRM ({crm_m:.0f}) vs. Wiki ({wiki_SATZ" + + # 4. Abgleich CRM vs. Wiki (Rest der Funktion wie im vorherigen Vorschlag) +m:.0f}) weicht >{abweichung_prozent*100:.0f}% ab.") + else: results["abweichung_ma_flag"] = "OK" + else: results["abwe crm_umsatz_str = row_data_dict.get("CRM Umsatz", "k.A.") + wiki_umsatz_str = row_data_dict.get("Wiki Umsatz", "k.A.")ichung_ma_flag"] = "OK" # else: bleibt N/A elif pd.isna(crm_m) and not pd.isna(wiki_m): results["abweichung_ma_flag"] = "CRM_FEHLT" - elif not pd.isna(crm_m) and pd.isna(wiki_m): results["abweichung_ma_flag"] = "WIKI_FEHLT" + elif not pd.isna(crm_m) and pd.isna(wiki_ + crm_ma_str = row_data_dict.get("CRM Anzahl Mitarbeiter", "k.A.") + wiki_ma_str = row_data_dict.get("Wiki Mitarbeiter", "k.A.") + + crm_u = self._get_numeric_value_for_plausi(crm_umsatz_str,m): results["abweichung_ma_flag"] = "WIKI_FEHLT" if not results["begruendungen"]: results["plausi_begruendung_final"] = "Plausibilität OK" else: results["plausi_begruendung_final"] = "; ".join(results["begruendungen"]) + True) + wiki_u = self._get_numeric_value_for_plausi(wiki_umsatz_str, True) + crm_m = self._get_numeric_value_for_plausi(crm_ma_str, False) + wiki_m = self._get_numeric_value_for_plausi(wiki_ma_str, False) return results