diff --git a/data_processor.py b/data_processor.py index 1d6429e7..6f824177 100644 --- a/data_processor.py +++ b/data_processor.py @@ -984,7 +984,7 @@ class DataProcessor: rows_to_process = all_data[start_row_idx : end_row_idx + 1] - processed_count = 0 + processed_count_in_batch = 0 total_processed_since_start = 0 all_updates = [] @@ -1011,7 +1011,6 @@ class DataProcessor: now_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - # Updates für diese eine Zeile sammeln updates_for_row = [ {'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Wiki Konsistenzpruefung"] + 1)}{current_row_num}', 'values': [[verification_result.get("consistency")]]}, {'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Begründung Wiki Inkonsistenz"] + 1)}{current_row_num}', 'values': [[verification_result.get("justification")]]}, @@ -1020,98 +1019,34 @@ class DataProcessor: ] all_updates.extend(updates_for_row) - processed_count += 1 + processed_count_in_batch += 1 total_processed_since_start += 1 - # Wenn Batch-Größe erreicht, schreiben und zurücksetzen - if processed_count >= BATCH_SIZE: + if processed_count_in_batch >= BATCH_SIZE: self.logger.info(f"Batch-Größe ({BATCH_SIZE}) erreicht. Schreibe {len(all_updates)} Zell-Updates...") self.sheet_handler.batch_update_cells(all_updates) self.logger.info("Batch erfolgreich geschrieben.") - all_updates = [] # Liste für den nächsten Batch leeren - processed_count = 0 # Zähler für den nächsten Batch zurücksetzen + all_updates = [] + processed_count_in_batch = 0 - time.sleep(1) # API-Pause + time.sleep(1) + except KeyError as ke: + self.logger.critical(f"FATALER KEY_ERROR in Zeile {current_row_num}: Die Spalte '{ke}' existiert nicht im COLUMN_MAP in config.py! Breche Verarbeitung dieser Zeile ab.", exc_info=False) + continue # Mache mit der nächsten Zeile weiter except Exception as e: self.logger.error(f"Unerwarteter Fehler bei Verarbeitung von Zeile {current_row_num}: {e}", exc_info=True) else: self.logger.debug(f"Zeile {current_row_num}: Übersprungen (Timestamp vorhanden oder keine URL).") - # Schreibe die restlichen gesammelten Updates am Ende des Laufs if all_updates: - self.logger.info(f"Schleife beendet. Schreibe die letzten {len(all_updates)} Zell-Updates für {processed_count} Zeilen...") + self.logger.info(f"Schleife beendet. Schreibe die letzten {len(all_updates)} Zell-Updates für {processed_count_in_batch} Zeilen...") self.sheet_handler.batch_update_cells(all_updates) self.logger.info("Finaler Batch erfolgreich geschrieben.") self.logger.info(f"Wiki-Verifizierung abgeschlossen. {total_processed_since_start} Zeilen insgesamt verarbeitet.") - - # NEU: Spalten definieren, die vor der Neubewertung geleert werden sollen - cols_to_clear_keys = [ - # WICHTIG: "Wiki URL" (R) und "CRM Vorschlag Wiki URL" (N) werden NICHT mehr geleert, - # um manuelle Einträge zu schützen. - "Wiki Sitz Stadt", "Wiki Sitz Land", "Wiki Absatz", "Wiki Branche", - "Wiki Umsatz", "Wiki Mitarbeiter", "Wiki Kategorien", "Wikipedia Timestamp", - "Wiki Verif. Timestamp", "SerpAPI Wiki Search Timestamp", "Chat Wiki Konsistenzpruefung", - "Chat Begruendung Wiki Inkonsistenz", "Chat Vorschlag Wiki Artikel", "Begruendung bei Abweichung", - "Website Rohtext", "Website Zusammenfassung", "Website Meta-Details", "Website Scrape Timestamp", "URL Prüfstatus", - "Chat Vorschlag Branche", "Chat Branche Konfidenz", "Chat Konsistenz Branche", - "Chat Begruendung Abweichung Branche", "Finaler Umsatz (Wiki>CRM)", "Finaler Mitarbeiter (Wiki>CRM)", - "Geschaetzter Techniker Bucket", "Plausibilität Umsatz", "Plausibilität Mitarbeiter", - "Plausibilität Umsatz/MA Ratio", "Abweichung Umsatz CRM/Wiki", "Abweichung MA CRM/Wiki", - "Plausibilität Begründung", "Plausibilität Prüfdatum", "Timestamp letzte Pruefung", "Version", "Tokens", - # Der FSM Pitch und sein Timestamp sollten auch geleert werden - "FSM Pitch", "FSM Pitch Timestamp" - ] - - clear_updates = [] - for task in rows_to_process: - row_num = task['row_num'] - for key in cols_to_clear_keys: - col_idx = COLUMN_MAP.get(key) - if col_idx is not None: - col_letter = self.sheet_handler._get_col_letter(col_idx + 1) - clear_updates.append({'range': f'{col_letter}{row_num}', 'values': [['']]}) - - if clear_updates: - self.logger.info(f"Leere {len(clear_updates)} Zellen für {found_count} Re-Eval-Zeilen zur Vorbereitung...") - self.sheet_handler.batch_update_cells(clear_updates) - self.logger.info("Vorbereitung abgeschlossen. Starte eigentliche Verarbeitung...") - time.sleep(2) - self.sheet_handler.load_data() - all_data = self.sheet_handler.get_all_data_with_headers() - - # Bestehende Logik zur Verarbeitung der Zeilen - processed_count_actual = 0 - steps_to_run_set = set(key for key, value in {'wiki': process_wiki_steps, 'chat': process_chatgpt_steps, 'web': process_website_steps, 'ml_predict': process_ml_steps}.items() if value) - - # NEU: all_data nach dem Leeren der Zellen aktualisieren - fresh_data = self.sheet_handler.get_all_data_with_headers() - - for task in rows_to_process: - if row_limit is not None and processed_count_actual >= row_limit: - self.logger.info(f"Zeilenlimit ({row_limit}) fuer Re-Evaluation erreicht.") - break - - # Holen der (jetzt geleerten) Daten für die Verarbeitung aus den frisch geladenen Daten - current_row_data = fresh_data[task['row_num'] - 1] - self.logger.info(f"Bearbeite Re-Eval Zeile {task['row_num']}...") - processed_count_actual += 1 - try: - self._process_single_row( - row_num_in_sheet=task['row_num'], - row_data=current_row_data, - steps_to_run=steps_to_run_set, - force_reeval=True, - clear_x_flag=clear_flag - ) - except Exception as e_proc_reval: - self.logger.exception(f"FEHLER bei Re-Evaluation von Zeile {task['row_num']}: {e_proc_reval}") - - self.logger.info(f"Re-Evaluierung abgeschlossen. {processed_count_actual} Zeilen verarbeitet.") - def process_fsm_pitch(self, start_sheet_row=None, end_sheet_row=None, limit=None): """ Generiert FSM-Pitches für alle Zeilen, bei denen der Pitch oder der Timestamp fehlt.