From 110e83bee52ddf45373a4c4ed05e8254349ce79d Mon Sep 17 00:00:00 2001 From: Floke Date: Wed, 16 Apr 2025 13:23:32 +0000 Subject: [PATCH] bugfix --- brancheneinstufung.py | 313 +++++++++++++++++++++++++++--------------- 1 file changed, 204 insertions(+), 109 deletions(-) diff --git a/brancheneinstufung.py b/brancheneinstufung.py index dd15e590..b22a89f9 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -1847,11 +1847,18 @@ def evaluate_umsatz_chatgpt(company_name, wiki_umsatz): def _process_batch(sheet, batches, row_numbers): """ Hilfsfunktion für process_verification_only: Verarbeitet einen Batch von Wikipedia-Verifizierungsanfragen. - Aktualisiert Spalten S-Y sowie Zeitstempel (AO) und Version (AP). + Aktualisiert NUR die Spalten S bis Y. Zeitstempel (AN, AO, AP) werden von + der aufrufenden Funktion oder anderen Prozessen gesetzt. + + Args: + sheet (gspread.Worksheet): Das Worksheet-Objekt zum Schreiben. + batches (list): Liste der Prompt-Teile für den Batch. + row_numbers (list): Liste der zugehörigen Zeilennummern. """ if not batches: return + # --- Prompt Erstellung (wie gehabt) --- aggregated_prompt = ( "Du bist ein Experte in der Verifizierung von Wikipedia-Artikeln für Unternehmen. " "Für jeden der folgenden Einträge prüfe, ob der vorhandene Wikipedia-Artikel (URL, Absatz, Kategorien) plausibel zum Firmennamen und zur Beschreibung passt. " @@ -1861,32 +1868,27 @@ def _process_batch(sheet, batches, row_numbers): "- 'OK' (wenn der Artikel gut passt)\n" "- 'X | Alternativer Artikel: | Begründung: ' (wenn der Artikel nicht passt, aber ein besserer gefunden wurde)\n" "- 'X | Kein passender Artikel gefunden | Begründung: ' (wenn der Artikel nicht passt und kein besserer gefunden wurde)\n" - "- 'Kein Wikipedia-Eintrag vorhanden.' (wenn initial keine URL angegeben wurde und keine Suche erfolgreich war - dieser Fall sollte selten sein, da die Suche vorher stattfindet)\n\n" + "- 'Kein Wikipedia-Eintrag vorhanden.' (wenn initial keine URL angegeben wurde und keine Suche erfolgreich war)\n\n" "Einträge:\n" "----------\n" ) aggregated_prompt += "".join(batches) # Join ohne zusätzliches \n aggregated_prompt += "----------\nBitte nur die 'Eintrag X: Antwort'-Zeilen ausgeben." - debug_print(f"Verarbeite Verifizierungs-Batch für Zeilen {row_numbers[0]} bis {row_numbers[-1]}.") - + debug_print(f"Verarbeite Verifizierungs-Batch für Zeilen {row_numbers[0]} bis {row_numbers[-1]} (nur S-Y)...") # Hinweis angepasst + # Token Count für den Prompt prompt_tokens = token_count(aggregated_prompt) debug_print(f"Token-Zahl für Verifizierungs-Batch: {prompt_tokens}") - # Optional: Prüfung auf Token-Limit vor dem Senden - # if prompt_tokens > 3800: # Beispiel-Limit für gpt-3.5-turbo (4096 gesamt) - # debug_print(f"WARNUNG: Prompt für Batch {row_numbers[0]}-{row_numbers[-1]} überschreitet möglicherweise Token-Limit ({prompt_tokens}). Überspringe Batch.") - # # Hier könnte man den Batch aufteilen - # return + # --- ChatGPT Aufruf (wie gehabt) --- chat_response = call_openai_chat(aggregated_prompt, temperature=0.0) if not chat_response: debug_print(f"Fehler: Keine Antwort von OpenAI für Verifizierungs-Batch {row_numbers[0]}-{row_numbers[-1]}.") - # Optional: Markiere Zeilen als fehlerhaft return - # Parse die aggregierte Antwort + # --- Antwort parsen (wie gehabt) --- answers = {} lines = chat_response.strip().split('\n') for line in lines: @@ -1896,70 +1898,72 @@ def _process_batch(sheet, batches, row_numbers): answer_text = match.group(2).strip() if row_num in row_numbers: answers[row_num] = answer_text - else: - debug_print(f"Warnung: Antwort für unerwartete Zeilennummer {row_num} im Batch erhalten: {answer_text}") + # else: # Weniger Lärm im Log + # debug_print(f"Warnung: Antwort für unerwartete Zeilennummer {row_num} im Batch erhalten: {answer_text}") - # Bereite Batch-Update für Google Sheet vor + # --- Batch-Update vorbereiten (NUR S bis Y) --- updates = [] - current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") - current_version = Config.VERSION + # Timestamps und Version werden HIER NICHT mehr hinzugefügt for row_num in row_numbers: answer = answers.get(row_num, "k.A. (Keine Antwort im Batch)") # Fallback - debug_print(f"Zeile {row_num} Verifizierungsantwort: '{answer}'") - wiki_confirm = "" # Spalte S - alt_article = "" # Spalte T - wiki_explanation = "" # Spalte U - # Spalten V-Y bleiben vorerst leer oder werden hier gesetzt - v_val, w_val, x_val, y_val = "", "", "", "" # Beispiel + # Variablen für die Spalten S-Y initialisieren + wiki_confirm = "" # Spalte S + alt_article = "" # Spalte T + wiki_explanation = "" # Spalte U + v_val, w_val, x_val, y_val = "", "", "", "" # Spalten V-Y + # Logik zur Bestimmung der Werte für S, T, U basierend auf 'answer' (wie gehabt) if answer.upper() == "OK": wiki_confirm = "OK" elif answer.upper() == "KEIN WIKIPEDIA-EINTRAG VORHANDEN.": - wiki_confirm = "X" # Markieren, da eigentlich einer da sein sollte + wiki_confirm = "X" alt_article = "Kein Wikipedia-Eintrag vorhanden." wiki_explanation = "Ursprünglich keine URL oder Suche erfolglos." elif answer.startswith("X |"): - parts = answer.split("|", 2) # Splitte maximal 2 mal + parts = answer.split("|", 2) wiki_confirm = "X" if len(parts) > 1: detail = parts[1].strip() if detail.startswith("Alternativer Artikel:"): alt_article = detail.split(":", 1)[1].strip() elif detail == "Kein passender Artikel gefunden": - alt_article = "Kein passender Artikel gefunden" - else: # Fallback, falls Format unerwartet - alt_article = detail + alt_article = detail + else: + alt_article = detail if len(parts) > 2: reason_part = parts[2].strip() if reason_part.startswith("Begründung:"): wiki_explanation = reason_part.split(":", 1)[1].strip() - else: # Fallback + else: wiki_explanation = reason_part else: # Unerwartetes Format wiki_confirm = "?" wiki_explanation = f"Unerwartetes Format: {answer}" - # Füge Updates für diese Zeile zur Liste hinzu + # Füge Updates NUR für S-Y zur Liste hinzu updates.append({'range': f'S{row_num}', 'values': [[wiki_confirm]]}) updates.append({'range': f'T{row_num}', 'values': [[alt_article]]}) updates.append({'range': f'U{row_num}', 'values': [[wiki_explanation]]}) - # Setze V-Y zurück/leer updates.append({'range': f'V{row_num}:Y{row_num}', 'values': [[v_val, w_val, x_val, y_val]]}) - # Zeitstempel und Version - updates.append({'range': f'AO{row_num}', 'values': [[current_timestamp]]}) - updates.append({'range': f'AP{row_num}', 'values': [[current_version]]}) - # Führe das Batch-Update für alle Zeilen dieses Batches durch + # --- Führe das Batch-Update für S-Y durch --- if updates: - GoogleSheetHandler().batch_update_cells(updates) # Nutze die zentrale Update-Funktion - debug_print(f"Verifizierungs-Batch {row_numbers[0]}-{row_numbers[-1]} erfolgreich in Google Sheet aktualisiert.") + try: + # Verwende das übergebene sheet-Objekt direkt + sheet.batch_update(updates, value_input_option='USER_ENTERED') + debug_print(f"Verifizierungs-Batch {row_numbers[0]}-{row_numbers[-1]} (S-Y) erfolgreich in Google Sheet aktualisiert.") + except Exception as e: + # Gib eine spezifischere Fehlermeldung aus + debug_print(f"FEHLER beim Batch-Update (S-Y) für Zeilen {row_numbers[0]}-{row_numbers[-1]}: {type(e).__name__} - {e}") + # Optional: Fehler weitergeben, wenn retry gewünscht wird (nicht empfohlen für Sheet-Updates hier) + # raise e else: - debug_print(f"Keine Updates für Verifizierungs-Batch {row_numbers[0]}-{row_numbers[-1]} generiert.") + debug_print(f"Keine Updates (S-Y) für Verifizierungs-Batch {row_numbers[0]}-{row_numbers[-1]} generiert.") - # Kurze Pause nach jedem Batch-API-Call - time.sleep(Config.RETRY_DELAY) + # KEINE Pause hier mehr, wird in der aufrufenden Funktion gemacht + # time.sleep(Config.RETRY_DELAY) def process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_index_in_sheet): @@ -1969,8 +1973,21 @@ def process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_i """ debug_print(f"Starte Wikipedia-Verifizierungsmodus (Batch) für Zeilen {start_row_index_in_sheet} bis {end_row_index_in_sheet}...") + # Lade aktuelle Daten direkt hier all_data = sheet_handler.get_all_data_with_headers() - timestamp_col_index = COLUMN_MAP["Wikipedia Timestamp"] # Prüfe Spalte AN + if not all_data or len(all_data) <= 5: # Check ob Daten vorhanden sind + debug_print("FEHLER/WARNUNG: Keine Daten zum Verarbeiten in process_verification_only gefunden.") + return + + # Hole Index für AN Timestamp + timestamp_col_key = "Wikipedia Timestamp" + timestamp_col_index = COLUMN_MAP.get(timestamp_col_key) + ts_col_letter = sheet_handler._get_col_letter(timestamp_col_index + 1) if timestamp_col_index is not None else "FEHLER" + + + if timestamp_col_index is None: + debug_print(f"FEHLER: Spaltenschlüssel '{timestamp_col_key}' nicht in COLUMN_MAP gefunden. Breche Wiki-Verifizierung ab.") + return batch_size = Config.BATCH_SIZE current_batch = [] @@ -1980,26 +1997,38 @@ def process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_i for i in range(start_row_index_in_sheet, end_row_index_in_sheet + 1): row_index_in_list = i - 1 - if row_index_in_list >= len(all_data): # Sicherheitscheck - debug_print(f"Warnung: Zeilenindex {row_index_in_list} außerhalb des Datenbereichs ({len(all_data)} Zeilen).") + if row_index_in_list >= len(all_data): + debug_print(f"Warnung (Wiki): Zeilenindex {row_index_in_list} außerhalb des Datenbereichs ({len(all_data)} Zeilen).") continue - + row = all_data[row_index_in_list] - # --- NEU: Timestamp-Prüfung für jede Zeile --- - if len(row) > timestamp_col_index and row[timestamp_col_index].strip(): - debug_print(f"Zeile {i}: Überspringe Wiki-Verifizierung (Timestamp AN bereits vorhanden: '{row[timestamp_col_index]}').") + # --- DEBUGGING Timestamp-Prüfung AN --- + ts_value_an = "INDEX_FEHLER" + ts_an_is_set = False + if len(row) > timestamp_col_index: + ts_value_an = row[timestamp_col_index] + ts_an_is_set = bool(str(ts_value_an).strip()) # Prüfe, ob Wert nach strip nicht leer ist + # Logge für die ersten 5 geprüften und letzte 5 geprüfte Zeilen im Range, oder wenn es sich ändert + log_debug = (i < start_row_index_in_sheet + 5 or i > end_row_index_in_sheet - 5 or i % 500 == 0) + if log_debug: + debug_print(f"Zeile {i} (Wiki Check): Prüfe Timestamp {ts_col_letter} (Index {timestamp_col_index}). Rohwert='{ts_value_an}', Strip='{str(ts_value_an).strip()}', Bedingung ist: {ts_an_is_set}") + # --- Ende DEBUGGING --- + + if ts_an_is_set: + # Weniger Lärm im Log, nur zählen skipped_count += 1 + if skipped_count == 1 or skipped_count % 100 == 0: # Logge den ersten und jeden 100. übersprungenen + debug_print(f"Zeile {i}: Überspringe Wiki-Verifizierung (Timestamp {ts_col_letter} vorhanden: '{ts_value_an.strip()}'). ({skipped_count} gesamt übersprungen)") continue # --- Ende Timestamp-Prüfung --- - # Erstelle Text für den Prompt (wie zuvor) + # (Restliche Logik zum Erstellen von entry_text wie zuvor) company_name = row[COLUMN_MAP["CRM Name"]] if len(row) > COLUMN_MAP["CRM Name"] else '' crm_desc = row[COLUMN_MAP["CRM Beschreibung"]] if len(row) > COLUMN_MAP["CRM Beschreibung"] else '' wiki_url = row[COLUMN_MAP["Wiki URL"]] if len(row) > COLUMN_MAP["Wiki URL"] and row[COLUMN_MAP["Wiki URL"]].strip() not in ['', 'k.A.'] else 'k.A.' wiki_paragraph = row[COLUMN_MAP["Wiki Absatz"]] if len(row) > COLUMN_MAP["Wiki Absatz"] else 'k.A.' wiki_categories = row[COLUMN_MAP["Wiki Kategorien"]] if len(row) > COLUMN_MAP["Wiki Kategorien"] else 'k.A.' - entry_text = ( f"Eintrag {i}:\n" f" Firmenname: {company_name}\n" @@ -2014,27 +2043,26 @@ def process_verification_only(sheet_handler, start_row_index_in_sheet, end_row_i processed_count += 1 # Wenn Batch voll oder letzte Zeile erreicht - if len(current_batch) == batch_size or i == end_row_index_in_sheet: - if current_batch: # Nur wenn etwas im Batch ist - # _process_batch schreibt S-Y, AO, AP. AN wird *nicht* von _process_batch geschrieben! - # Wir müssen AN separat setzen oder _process_batch anpassen. - # Einfacher: Setzen AN hier *vor* dem Aufruf für die bearbeiteten Zeilen. - - # Erstelle Updates für den AN-Timestamp + if len(current_batch) >= batch_size or i == end_row_index_in_sheet: + if current_batch: + # Setze zuerst den AN Timestamp für die bearbeiteten Zeilen wiki_ts_updates = [] current_wiki_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") for row_num in current_row_numbers: - wiki_ts_updates.append({'range': f'AN{row_num}', 'values': [[current_wiki_timestamp]]}) - - # Setze zuerst den AN Timestamp - if wiki_ts_updates: - sheet_handler.batch_update_cells(wiki_ts_updates) - debug_print(f"Wiki-Timestamp AN für Batch {current_row_numbers[0]}-{current_row_numbers[-1]} gesetzt.") + # Verwende Spaltenbuchstaben dynamisch + wiki_ts_updates.append({'range': f'{ts_col_letter}{row_num}', 'values': [[current_wiki_timestamp]]}) + + if wiki_ts_updates: + success_ts = sheet_handler.batch_update_cells(wiki_ts_updates) + if success_ts: + debug_print(f"Wiki-Timestamp {ts_col_letter} für Batch {current_row_numbers[0]}-{current_row_numbers[-1]} gesetzt.") + else: + debug_print(f"FEHLER beim Setzen des Wiki-Timestamps {ts_col_letter} für Batch.") + + # Rufe dann _process_batch auf, das S-Y schreibt + _process_batch(sheet_handler.sheet, current_batch, current_row_numbers) + time.sleep(Config.RETRY_DELAY) # Pause nach API Calls - # Rufe dann _process_batch auf, das S-Y, AO, AP schreibt - _process_batch(sheet_handler.sheet, current_batch, current_row_numbers) # Nutzt noch alten Timestamp AO! Das müssen wir ändern. - - # Reset für nächsten Batch current_batch = [] current_row_numbers = [] @@ -2139,10 +2167,17 @@ def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index """Batch-Prozess für Website-Scraping (Rohtext & Zusammenfassung).""" debug_print(f"Starte Website-Scraping (Batch) für Zeilen {start_row_index_in_sheet} bis {end_row_index_in_sheet}...") + # Lade aktuelle Daten direkt hier all_data = sheet_handler.get_all_data_with_headers() - sheet = sheet_handler.sheet - # HIER KORRIGIERT: Sicherstellen, dass der Index für AT verwendet wird - timestamp_col_index = COLUMN_MAP.get("Website Scrape Timestamp") + if not all_data or len(all_data) <= 5: + debug_print("FEHLER/WARNUNG: Keine Daten zum Verarbeiten in process_website_batch gefunden.") + return + + sheet = sheet_handler.sheet # Zugriff auf gspread sheet Objekt + + # Hole Indizes aus COLUMN_MAP + timestamp_col_key = "Website Scrape Timestamp" + timestamp_col_index = COLUMN_MAP.get(timestamp_col_key) website_col_index = COLUMN_MAP.get("CRM Website") rohtext_col_index = COLUMN_MAP.get("Website Rohtext") summary_col_index = COLUMN_MAP.get("Website Zusammenfassung") @@ -2153,27 +2188,44 @@ def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index debug_print("FEHLER: Mindestens ein benötigter Spaltenindex für process_website_batch fehlt in COLUMN_MAP.") return + ts_col_letter = sheet_handler._get_col_letter(timestamp_col_index + 1) + rohtext_col_letter = sheet_handler._get_col_letter(rohtext_col_index + 1) + summary_col_letter = sheet_handler._get_col_letter(summary_col_index + 1) + version_col_letter = sheet_handler._get_col_letter(version_col_index + 1) + processed_count = 0 skipped_count = 0 for i in range(start_row_index_in_sheet, end_row_index_in_sheet + 1): row_index_in_list = i - 1 - if row_index_in_list >= len(all_data): continue + if row_index_in_list >= len(all_data): + debug_print(f"Warnung (Website): Zeilenindex {row_index_in_list} außerhalb des Datenbereichs ({len(all_data)} Zeilen).") + continue + row = all_data[row_index_in_list] - # --- KORRIGIERTE Timestamp-Prüfung für jede Zeile --- - if len(row) > timestamp_col_index and row[timestamp_col_index].strip(): - # Optional: Weniger Lärm im Log, nur alle X Zeilen loggen - # if skipped_count % 100 == 0: - # debug_print(f"Zeile {i}: Überspringe Website-Scraping (Timestamp AT vorhanden: '{row[timestamp_col_index]}')...") + # --- DEBUGGING Timestamp-Prüfung AT --- + ts_value_at = "INDEX_FEHLER" + ts_at_is_set = False + if len(row) > timestamp_col_index: + ts_value_at = row[timestamp_col_index] + ts_at_is_set = bool(str(ts_value_at).strip()) + log_debug = (i < start_row_index_in_sheet + 5 or i > end_row_index_in_sheet - 5 or i % 500 == 0) + if log_debug: + debug_print(f"Zeile {i} (Website Check): Prüfe Timestamp {ts_col_letter} (Index {timestamp_col_index}). Rohwert='{ts_value_at}', Strip='{str(ts_value_at).strip()}', Bedingung ist: {ts_at_is_set}") + # --- Ende DEBUGGING --- + + if ts_at_is_set: skipped_count += 1 + if skipped_count == 1 or skipped_count % 100 == 0: + debug_print(f"Zeile {i}: Überspringe Website-Scraping (Timestamp {ts_col_letter} vorhanden: '{ts_value_at.strip()}'). ({skipped_count} gesamt übersprungen)") continue # --- Ende Timestamp-Prüfung --- website_url = row[website_col_index] if len(row) > website_col_index else "" if not website_url or website_url.strip().lower() == "k.a.": # debug_print(f"Zeile {i}: Kein gültiger Website-Eintrag, überspringe Website-Scraping.") - skipped_count += 1 + skipped_count += 1 # Zähle auch diese als übersprungen continue # debug_print(f"Zeile {i}: Verarbeite Website {website_url}...") # Weniger Lärm @@ -2185,12 +2237,6 @@ def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") current_version = Config.VERSION - # Spaltenbuchstaben für die Ranges ermitteln - rohtext_col_letter = sheet_handler._get_col_letter(rohtext_col_index + 1) - summary_col_letter = sheet_handler._get_col_letter(summary_col_index + 1) - ts_col_letter = sheet_handler._get_col_letter(timestamp_col_index + 1) - version_col_letter = sheet_handler._get_col_letter(version_col_index + 1) - updates.append({'range': f'{rohtext_col_letter}{i}', 'values': [[raw_text]]}) updates.append({'range': f'{summary_col_letter}{i}', 'values': [[summary]]}) updates.append({'range': f'{ts_col_letter}{i}', 'values': [[current_timestamp]]}) # AT Timestamp @@ -2200,13 +2246,11 @@ def process_website_batch(sheet_handler, start_row_index_in_sheet, end_row_index if updates: success = sheet_handler.batch_update_cells(updates) if not success: - debug_print(f"FEHLER beim Schreiben der Updates für Zeile {i}.") - # Weniger Lärm im Log bei Erfolg: - # else: debug_print(f"Zeile {i}: Website-Daten aktualisiert...") + debug_print(f"FEHLER beim Schreiben der Website-Updates für Zeile {i}.") + # Weniger Lärm im Log bei Erfolg + # else: debug_print(f"Zeile {i}: Website-Daten aktualisiert.") - - # Pause zwischen den Zeilen/Websites - time.sleep(Config.RETRY_DELAY) + time.sleep(Config.RETRY_DELAY) # Pause *nach* der Verarbeitung einer Zeile debug_print(f"Website-Scraping (Batch) abgeschlossen. {processed_count} Websites gescraped, {skipped_count} Zeilen übersprungen.") @@ -2215,39 +2259,86 @@ def process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_ """Batch-Prozess für Brancheneinschätzung.""" debug_print(f"Starte Brancheneinschätzung (Batch) für Zeilen {start_row_index_in_sheet} bis {end_row_index_in_sheet}...") + # Lade aktuelle Daten direkt hier all_data = sheet_handler.get_all_data_with_headers() + if not all_data or len(all_data) <= 5: + debug_print("FEHLER/WARNUNG: Keine Daten zum Verarbeiten in process_branch_batch gefunden.") + return + sheet = sheet_handler.sheet - timestamp_col_index = COLUMN_MAP["Timestamp letzte Prüfung"] # Prüfe Spalte AO + + # Hole Indizes aus COLUMN_MAP + timestamp_col_key = "Timestamp letzte Prüfung" + timestamp_col_index = COLUMN_MAP.get(timestamp_col_key) + branche_crm_idx = COLUMN_MAP.get("CRM Branche") + beschreibung_idx = COLUMN_MAP.get("CRM Beschreibung") + branche_wiki_idx = COLUMN_MAP.get("Wiki Branche") + kategorien_wiki_idx = COLUMN_MAP.get("Wiki Kategorien") + summary_web_idx = COLUMN_MAP.get("Website Zusammenfassung") + version_col_index = COLUMN_MAP.get("Version") + # Indizes für Ergebnisspalten W, X, Y + branch_w_idx = COLUMN_MAP.get("Chat Vorschlag Branche") + branch_x_idx = COLUMN_MAP.get("Chat Konsistenz Branche") + branch_y_idx = COLUMN_MAP.get("Chat Begründung Abweichung Branche") + + # Fehlerprüfung für Indizes + required_indices = [timestamp_col_index, branche_crm_idx, beschreibung_idx, branche_wiki_idx, + kategorien_wiki_idx, summary_web_idx, version_col_index, branch_w_idx, + branch_x_idx, branch_y_idx] + if None in required_indices: + debug_print("FEHLER: Mindestens ein benötigter Spaltenindex für process_branch_batch fehlt in COLUMN_MAP.") + return + + ts_col_letter = sheet_handler._get_col_letter(timestamp_col_index + 1) + version_col_letter = sheet_handler._get_col_letter(version_col_index + 1) + branch_w_letter = sheet_handler._get_col_letter(branch_w_idx + 1) + branch_x_letter = sheet_handler._get_col_letter(branch_x_idx + 1) + branch_y_letter = sheet_handler._get_col_letter(branch_y_idx + 1) + processed_count = 0 skipped_count = 0 # Stelle sicher, dass das Branchenschema geladen ist if not ALLOWED_TARGET_BRANCHES: - load_target_schema() # Versuch es zu laden + load_target_schema() if not ALLOWED_TARGET_BRANCHES: debug_print("FEHLER: Ziel-Branchenschema konnte nicht geladen werden. Breche Branch-Batch ab.") return for i in range(start_row_index_in_sheet, end_row_index_in_sheet + 1): row_index_in_list = i - 1 - if row_index_in_list >= len(all_data): continue + if row_index_in_list >= len(all_data): + debug_print(f"Warnung (Branch): Zeilenindex {row_index_in_list} außerhalb des Datenbereichs ({len(all_data)} Zeilen).") + continue + row = all_data[row_index_in_list] - # --- NEU: Timestamp-Prüfung für jede Zeile --- - if len(row) > timestamp_col_index and row[timestamp_col_index].strip(): - debug_print(f"Zeile {i}: Überspringe Branchen-Einschätzung (Timestamp AO bereits vorhanden: '{row[timestamp_col_index]}').") + # --- DEBUGGING Timestamp-Prüfung AO --- + ts_value_ao = "INDEX_FEHLER" + ts_ao_is_set = False + if len(row) > timestamp_col_index: + ts_value_ao = row[timestamp_col_index] + ts_ao_is_set = bool(str(ts_value_ao).strip()) + log_debug = (i < start_row_index_in_sheet + 5 or i > end_row_index_in_sheet - 5 or i % 500 == 0) + if log_debug: + debug_print(f"Zeile {i} (Branch Check): Prüfe Timestamp {ts_col_letter} (Index {timestamp_col_index}). Rohwert='{ts_value_ao}', Strip='{str(ts_value_ao).strip()}', Bedingung ist: {ts_ao_is_set}") + # --- Ende DEBUGGING --- + + if ts_ao_is_set: skipped_count += 1 + if skipped_count == 1 or skipped_count % 100 == 0: + debug_print(f"Zeile {i}: Überspringe Branchen-Einschätzung (Timestamp {ts_col_letter} vorhanden: '{ts_value_ao.strip()}'). ({skipped_count} gesamt übersprungen)") continue # --- Ende Timestamp-Prüfung --- - # Hole benötigte Daten aus der Zeile (wie zuvor) - crm_branche = row[COLUMN_MAP["CRM Branche"]] if len(row) > COLUMN_MAP["CRM Branche"] else "" - beschreibung = row[COLUMN_MAP["CRM Beschreibung"]] if len(row) > COLUMN_MAP["CRM Beschreibung"] else "" - wiki_branche = row[COLUMN_MAP["Wiki Branche"]] if len(row) > COLUMN_MAP["Wiki Branche"] else "" - wiki_kategorien = row[COLUMN_MAP["Wiki Kategorien"]] if len(row) > COLUMN_MAP["Wiki Kategorien"] else "" - website_summary = row[COLUMN_MAP["Website Zusammenfassung"]] if len(row) > COLUMN_MAP["Website Zusammenfassung"] else "" + # Hole benötigte Daten aus der Zeile + crm_branche = row[branche_crm_idx] if len(row) > branche_crm_idx else "" + beschreibung = row[beschreibung_idx] if len(row) > beschreibung_idx else "" + wiki_branche = row[branche_wiki_idx] if len(row) > branche_wiki_idx else "" + wiki_kategorien = row[kategorien_wiki_idx] if len(row) > kategorien_wiki_idx else "" + website_summary = row[summary_web_idx] if len(row) > summary_web_idx else "" - debug_print(f"Zeile {i}: Starte Brancheneinschätzung...") + # debug_print(f"Zeile {i}: Starte Brancheneinschätzung...") # Weniger Lärm result = evaluate_branche_chatgpt(crm_branche, beschreibung, wiki_branche, wiki_kategorien, website_summary) processed_count += 1 @@ -2255,19 +2346,23 @@ def process_branch_batch(sheet_handler, start_row_index_in_sheet, end_row_index_ current_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") current_version = Config.VERSION - updates.append({'range': f'W{i}', 'values': [[result.get("branch", "Fehler")]]}) # Spalte W - updates.append({'range': f'X{i}', 'values': [[result.get("consistency", "Fehler")]]}) # Spalte X - updates.append({'range': f'Y{i}', 'values': [[result.get("justification", "Fehler")]]})# Spalte Y - updates.append({'range': f'AO{i}', 'values': [[current_timestamp]]}) # Spalte AO (Timestamp letzte Prüfung) - updates.append({'range': f'AP{i}', 'values': [[current_version]]}) # Spalte AP (Version) + updates.append({'range': f'{branch_w_letter}{i}', 'values': [[result.get("branch", "Fehler")]]}) + updates.append({'range': f'{branch_x_letter}{i}', 'values': [[result.get("consistency", "Fehler")]]}) + updates.append({'range': f'{branch_y_letter}{i}', 'values': [[result.get("justification", "Fehler")]]}) + updates.append({'range': f'{ts_col_letter}{i}', 'values': [[current_timestamp]]}) # AO Timestamp + updates.append({'range': f'{version_col_letter}{i}', 'values': [[current_version]]}) # AP Version # Führe Batch-Update für diese eine Zeile durch if updates: - sheet_handler.batch_update_cells(updates) - debug_print(f"Zeile {i}: Branch-Einschätzung aktualisiert: {result['branch']} ({result['consistency']}) | Zeitstempel AO: {current_timestamp}, Version: {current_version}") + success = sheet_handler.batch_update_cells(updates) + if success: + # Weniger Lärm im Log bei Erfolg + # debug_print(f"Zeile {i}: Branch-Einschätzung aktualisiert: {result['branch']} ({result['consistency']}) | Zeitstempel AO: {current_timestamp}, Version: {current_version}") + pass + else: + debug_print(f"FEHLER beim Schreiben der Branch-Updates für Zeile {i}.") - # Pause zwischen den API-Aufrufen - time.sleep(Config.RETRY_DELAY) + time.sleep(Config.RETRY_DELAY) # Pause *nach* der Verarbeitung debug_print(f"Brancheneinschätzung (Batch) abgeschlossen. {processed_count} Zeilen eingeschätzt, {skipped_count} Zeilen übersprungen.")