diff --git a/brancheneinstufung.py b/brancheneinstufung.py index aaf0e133..1fc81f5f 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -8109,6 +8109,11 @@ class DataProcessor: def run_plausibility_checks_batch(self, start_sheet_row=None, end_sheet_row=None, limit=None): self.logger.info(f"Starte Modus 'Plausibilitäts-Checks'. Bereich: {start_sheet_row if start_sheet_row is not None else 'Datenstart'} bis {end_sheet_row if end_sheet_row else 'Sheet-Ende'}, Limit: {limit if limit is not None else 'Unbegrenzt'}") + plausi_ts_key = "Plausibilität Prüfdatum" # Schlüssel für den neuen Timestamp + if plausi_ts_key not in COLUMN_MAP: + self.logger.error(f"FEHLER: Schlüssel '{plausi_ts_key}' nicht in COLUMN_MAP. Kann Timestamp nicht setzen. Abbruch.") + return + if not self.sheet_handler.load_data(): self.logger.error("Konnte Sheet-Daten nicht laden für Plausi-Checks. Abbruch.") return @@ -8116,28 +8121,32 @@ class DataProcessor: all_data = self.sheet_handler.get_all_data_with_headers() header_offset = self.sheet_handler._header_rows - # Benötigte Spalten für den Input des Plausi-Checks required_input_keys = [ "Finaler Umsatz (Wiki>CRM)", "Finaler Mitarbeiter (Wiki>CRM)", "CRM Umsatz", "Wiki Umsatz", "CRM Anzahl Mitarbeiter", "Wiki Mitarbeiter" ] - # Spalten für den Output - output_keys = [ + output_keys_flags = [ "Plausibilität Umsatz", "Plausibilität Mitarbeiter", "Plausibilität Umsatz/MA Ratio", - "Abweichung Umsatz CRM/Wiki", "Abweichung MA CRM/Wiki", "Plausibilität Begründung" + "Abweichung Umsatz CRM/Wiki", "Abweichung MA CRM/Wiki" ] + begruendung_key = "Plausibilität Begründung" - # Prüfen, ob alle Keys da sind (vereinfacht) - if not all(key in COLUMN_MAP for key in required_input_keys + output_keys): - self.logger.error("Nicht alle benötigten Spalten für Plausi-Checks in COLUMN_MAP. Abbruch.") + # Sicherstellen, dass alle benötigten Schlüssel vorhanden sind + all_req_keys_for_plausi = required_input_keys + output_keys_flags + [begruendung_key, plausi_ts_key] + if not all(key in COLUMN_MAP for key in all_req_keys_for_plausi): + missing_k = [k for k in all_req_keys_for_plausi if k not in COLUMN_MAP] + self.logger.error(f"Nicht alle benötigten Spalten ({missing_k}) für Plausi-Checks in COLUMN_MAP. Abbruch.") return updates_fuer_sheet = [] processed_rows_count = 0 + now_timestamp_str = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # Einmal pro Lauf für Konsistenz innerhalb des Laufs effective_start_row = start_sheet_row if start_sheet_row is not None else header_offset + 1 effective_end_row = end_sheet_row if end_sheet_row is not None else len(all_data) + self.logger.info(f"Prüfe Zeilen {effective_start_row} bis {effective_end_row} für Plausi-Checks.") + for row_num_sheet in range(effective_start_row, effective_end_row + 1): if limit is not None and processed_rows_count >= limit: self.logger.info(f"Limit von {limit} Zeilen für Plausi-Checks erreicht.") @@ -8147,46 +8156,58 @@ class DataProcessor: if row_list_idx >= len(all_data): break row_data = all_data[row_list_idx] - # Hole die Input-Daten für den Plausi-Check plausi_input_data = {} valid_input_for_check = True for key in required_input_keys: val = self._get_cell_value_safe(row_data, key) plausi_input_data[key] = val - # Einfache Prüfung: Wenn die Haupt-Inputwerte (Finaler U/MA) fehlen, nicht prüfen - if key in ["Finaler Umsatz (Wiki>CRM)", "Finaler Mitarbeiter (Wiki>CRM)"] and (not val or str(val).lower() == 'k.a.'): + if key in ["Finaler Umsatz (Wiki>CRM)", "Finaler Mitarbeiter (Wiki>CRM)"] and (not val or str(val).lower() == 'k.a.' or str(val).upper().startswith("FEHLER")): valid_input_for_check = False if not valid_input_for_check: - # self.logger.debug(f"Zeile {row_num_sheet}: Übersprungen, finale U/MA fehlen für Plausi-Check.") continue processed_rows_count +=1 + current_row_updates = [] # Updates für DIESE Zeile try: plausi_results = self._check_financial_plausibility(plausi_input_data) - updates_fuer_sheet.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Plausibilität Umsatz"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("plaus_umsatz_flag", "FEHLER")]]}) - # ... (alle anderen Plausi-Spalten hinzufügen) ... - updates_fuer_sheet.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Plausibilität Mitarbeiter"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("plaus_ma_flag", "FEHLER")]]}) - updates_fuer_sheet.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Plausibilität Umsatz/MA Ratio"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("plaus_ratio_flag", "FEHLER")]]}) - updates_fuer_sheet.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Abweichung Umsatz CRM/Wiki"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("abweichung_umsatz_flag", "FEHLER")]]}) - updates_fuer_sheet.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Abweichung MA CRM/Wiki"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("abweichung_ma_flag", "FEHLER")]]}) - updates_fuer_sheet.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Plausibilität Begründung"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("plausi_begruendung_final", "Fehler Begr.")]]}) + + current_row_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Plausibilität Umsatz"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("plaus_umsatz_flag", "ERR_FLAG")]]}) + current_row_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Plausibilität Mitarbeiter"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("plaus_ma_flag", "ERR_FLAG")]]}) + current_row_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Plausibilität Umsatz/MA Ratio"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("plaus_ratio_flag", "ERR_FLAG")]]}) + current_row_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Abweichung Umsatz CRM/Wiki"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("abweichung_umsatz_flag", "ERR_FLAG")]]}) + current_row_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Abweichung MA CRM/Wiki"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("abweichung_ma_flag", "ERR_FLAG")]]}) + current_row_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Plausibilität Begründung"] + 1)}{row_num_sheet}', 'values': [[plausi_results.get("plausi_begruendung_final", "Fehler Begr.")]]}) + + # --- KORREKTUR: Timestamp HINZUFÜGEN --- + current_row_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP[plausi_ts_key] + 1)}{row_num_sheet}', 'values': [[now_timestamp_str]]}) + # --------------------------------------- + + updates_fuer_sheet.extend(current_row_updates) except Exception as e_plausi_run: self.logger.error(f"Fehler im Plausi-Check Lauf für Zeile {row_num_sheet}: {e_plausi_run}") - # ... (Fehlerwerte in Plausi-Spalten schreiben) ... + error_updates_for_row = [] + err_val = [['FEHLER_CHECK_RUNTIME']] + for key in output_keys_flags: # Nur die Flag-Spalten + error_updates_for_row.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP[key] + 1)}{row_num_sheet}', 'values': err_val}) + error_updates_for_row.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP[begruendung_key] + 1)}{row_num_sheet}', 'values': [[f"Systemfehler Plausi-Check: {str(e_plausi_run)[:100]}"]]}) + # Auch bei Fehler den Timestamp setzen, um zu zeigen, dass es versucht wurde + error_updates_for_row.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP[plausi_ts_key] + 1)}{row_num_sheet}', 'values': [[now_timestamp_str]]}) + updates_fuer_sheet.extend(error_updates_for_row) - if len(updates_fuer_sheet) >= getattr(Config, 'UPDATE_BATCH_ROW_LIMIT', 50) * 6: # 6 Spalten - self.logger.info(f"Sende Plausi-Check Batch-Update ({len(updates_fuer_sheet)//6} Zeilen)...") + # Batch-Update Logik (Anzahl der Updates pro Zeile ist jetzt 7: 6 Plausi + 1 TS) + if len(updates_fuer_sheet) >= getattr(Config, 'UPDATE_BATCH_ROW_LIMIT', 50) * (len(output_keys_flags) + 2): # +2 für Begründung und TS + self.logger.info(f"Sende Plausi-Check Batch-Update ({len(updates_fuer_sheet)//(len(output_keys_flags)+2)} Zeilen)...") self.sheet_handler.batch_update_cells(updates_fuer_sheet) updates_fuer_sheet = [] if updates_fuer_sheet: - self.logger.info(f"Sende finalen Plausi-Check Batch-Update ({len(updates_fuer_sheet)//6} Zeilen)...") + self.logger.info(f"Sende finalen Plausi-Check Batch-Update ({len(updates_fuer_sheet)//(len(output_keys_flags)+2)} Zeilen)...") self.sheet_handler.batch_update_cells(updates_fuer_sheet) - self.logger.info(f"Plausibilitäts-Check-Lauf beendet. {processed_rows_count} Zeilen geprüft.") + self.logger.info(f"Plausibilitäts-Check-Lauf beendet. {processed_rows_count} Zeilen geprüft und ggf. aktualisiert.") # ========================================================================== # === Utility Methods (ML Data Prep & Training) ============================