diff --git a/brancheneinstufung.py b/brancheneinstufung.py index fb07e52e..a5572d8d 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -3478,129 +3478,193 @@ class DataProcessor: logging.info(f"Modus 'find_wiki_serp' abgeschlossen. {processed_rows_count} Tasks erstellt, {found_urls_count} URLs gefunden, {skipped_timestamp_ay_count} AY gesetzt, {skipped_size_count} Größe, {skipped_m_filled_count} M gefüllt.") # process_wiki_updates_from_chatgpt Methode - def process_wiki_updates_from_chatgpt(self, row_limit=None): # <<< Methode in DataProcessor + def process_wiki_updates_from_chatgpt(self, row_limit=None): # <<< Methode in DataProcessor """ Identifiziert Zeilen (S nicht OK/Updated/Copied/Invalid), prüft ob U eine *valide* und *andere* Wiki-URL ist. - - Wenn ja: Kopiert U->M, markiert S='X (URL Copied)', U='URL übernommen', löscht TS/Version, setzt ReEval-Flag A. - - Wenn nein (U keine URL, U==M, oder U ungültig): LÖSCHT den Inhalt von U und markiert S als 'X (Invalid Suggestion)'. + - Wenn ja: Kopiert U->M, markiert S='X (URL Copied)', U='URL übernommen', + löscht TS/Version, setzt ReEval-Flag A. + - Wenn nein (U keine URL, U==M, oder U ungültig): LÖSCHT den Inhalt von U + und markiert S als 'X (Invalid Suggestion)'. Verarbeitet maximal row_limit Zeilen. """ - logging.info(f"Starte Modus: Wiki-Updates (URL-Validierung & Löschen ungültiger Vorschläge). Limit: {limit if limit is not None else 'Unbegrenzt'}"); - if not self.sheet_handler.load_data(): return logging.error("FEHLER beim Laden der Daten."); + logging.info( + f"Starte Modus: Wiki-Updates (URL-Validierung & Löschen ungültiger Vorschläge). " + f"Limit: {row_limit if row_limit is not None else 'Unbegrenzt'}" + ) + if not self.sheet_handler.load_data(): + return logging.error("FEHLER beim Laden der Daten.") - # KORRIGIERTE ZEILEN: Trenne Zuweisung und If-Statement - header_rows = 5 # Zuweisung auf eigener Zeile (z.B. 8 Leerzeichen) - # if-Statement beginnt auf neuer Zeile und ist eingerückt (z.B. 8 Leerzeichen) - if not self.sheet_handler.get_all_data_with_headers() or len(self.sheet_handler.get_all_data_with_headers()) <= header_rows: - # Die folgenden Zeilen gehören zum If-Block und müssen weiter eingerückt sein (z.B. 12 Leerzeichen) - logging.warning("Keine Daten gefunden oder nur Header."); # Geändert von "Keine Daten gefunden." - return # continue oder return je nach Logik, hier return + # Header-Zeilen überspringen + header_rows = 5 + if (not self.sheet_handler.get_all_data_with_headers() + or len(self.sheet_handler.get_all_data_with_headers()) <= header_rows): + logging.warning("Keine Daten gefunden oder nur Header.") + return - # Diese Zeilen gehören zum normalen Fluss der Methode, nach dem if-Block - # Sie sind auf der gleichen Ebene wie das if darüber (z.B. 8 Leerzeichen) - all_data = self.sheet_handler.get_all_data_with_headers(); - data_rows = all_data[header_rows:]; - required_keys = [ "Chat Wiki Konsistenzprüfung", "Chat Vorschlag Wiki Artikel", "Wiki URL", "Wikipedia Timestamp", "Wiki Verif. Timestamp", "Timestamp letzte Prüfung", "Version", "ReEval Flag", "Wiki Absatz", "Wiki Branche", "Wiki Umsatz", "Wiki Mitarbeiter", "Wiki Kategorien", "Begründung bei Abweichung" ]; - col_indices = {}; + # Daten und Spalten-Indizes vorbereiten + all_data = self.sheet_handler.get_all_data_with_headers() + data_rows = all_data[header_rows:] + required_keys = [ + "Chat Wiki Konsistenzprüfung", "Chat Vorschlag Wiki Artikel", "Wiki URL", + "Wikipedia Timestamp", "Wiki Verif. Timestamp", "Timestamp letzte Prüfung", + "Version", "ReEval Flag", "Wiki Absatz", "Wiki Branche", "Wiki Umsatz", + "Wiki Mitarbeiter", "Wiki Kategorien", "Begründung bei Abweichung" + ] + col_indices = {} - # KORRIGIERTE ZEILEN: Trenne Zuweisung und For-Schleife - all_keys_found = True # <- Zuweisung auf eigener Zeile (z.B. 8 Leerzeichen) - # Die For-Schleife beginnt auf der nächsten Zeile und ist eingerückt - for key in required_keys: # <- For-Schleife beginnt hier, eingerückt unter all_keys_found - # Die folgenden Zeilen gehören zum Körper der For-Schleife und sind weiter eingerückt - idx = COLUMN_MAP.get(key); - col_indices[key] = idx; - if idx is None: # <- If innerhalb der For-Schleife - # <- Code unter dem If, weiter eingerückt - logging.critical(f"FEHLER: Schlüssel '{key}' nicht in COLUMN_MAP gefunden! Modus abgebrochen."); - all_keys_found = False; # <- Zuweisung unter dem If - # Hier endet die For-Schleife. + all_keys_found = True + for key in required_keys: + idx = COLUMN_MAP.get(key) + col_indices[key] = idx + if idx is None: + logging.critical(f"FEHLER: Schlüssel '{key}' nicht in COLUMN_MAP gefunden! Modus abgebrochen.") + all_keys_found = False - - # Diese Zeilen gehören zum normalen Fluss der Methode, nach dem if not all_keys_found Block if not all_keys_found: - return; # Abbruch, wenn nicht alle Schlüssel gefunden + return - # Diese Zeilen sind auf der gleichen Ebene wie das if darüber (z.B. 8 Leerzeichen) - all_sheet_updates = []; processed_rows_count = 0; updated_url_count = 0; cleared_suggestion_count = 0; + all_sheet_updates = [] + processed_rows_count = 0 + updated_url_count = 0 + cleared_suggestion_count = 0 + # Durch alle Datenzeilen iterieren + for idx, row in enumerate(data_rows): + row_num_in_sheet = idx + header_rows + 1 + if row_limit is not None and processed_rows_count >= row_limit: + logging.info(f"Limit ({row_limit}) erreicht.") + break -for idx, row in enumerate(data_rows): - row_num_in_sheet = idx + header_rows + 1; - if limit is not None and processed_rows_count >= limit: logging.info(f"Limit ({limit}) erreicht."); break; - - # KORRIGIERTE ZEILEN: Trenne Zuweisung und If-Statement - max_needed_idx = max(col_indices.values()); # Zuweisung auf eigener Zeile (z.B. 12 Leerzeichen) - # if-Statement beginnt auf neuer Zeile und ist eingerückt (z.B. 12 Leerzeichen) + # Zeile übersprungen, wenn zu kurz + max_needed_idx = max(col_indices.values()) if len(row) <= max_needed_idx: - # Die folgenden Zeilen gehören zum If-Block und müssen weiter eingerückt sein (z.B. 16 Leerzeichen) - logging.debug(f"Zeile {row_num_in_sheet}: Übersprungen (Zeile zu kurz)."); - continue; # continue gehört unter das if + logging.debug(f"Zeile {row_num_in_sheet}: Übersprungen (Zeile zu kurz).") + continue - # Nutze private Helfermethode _get_cell_value + # Zellenwerte holen konsistenz_s = self._get_cell_value(row, "Chat Wiki Konsistenzprüfung").strip() vorschlag_u = self._get_cell_value(row, "Chat Vorschlag Wiki Artikel").strip() url_m = self._get_cell_value(row, "Wiki URL").strip() konsistenz_s_upper = konsistenz_s.upper() - is_candidate_for_check = bool(konsistenz_s_upper) and konsistenz_s_upper not in ["OK", "X (UPDATED)", "X (URL COPIED)", "X (INVALID SUGGESTION)", "?"] + is_candidate_for_check = ( + bool(konsistenz_s_upper) + and konsistenz_s_upper not in ["OK", "X (UPDATED)", "X (URL COPIED)", "X (INVALID SUGGESTION)", "?"] + ) if is_candidate_for_check or (konsistenz_s_upper == "?" and not vorschlag_u): - logging.debug(f"Zeile {row_num_in_sheet}: Kandidat für Wiki-Update-Prüfung (Status S = '{konsistenz_s}'). Vorschlag U = '{vorschlag_u}'") - processed_rows_count += 1 + logging.debug( + f"Zeile {row_num_in_sheet}: Kandidat für Wiki-Update-Prüfung " + f"(Status S = '{konsistenz_s}'). Vorschlag U = '{vorschlag_u}'" + ) + processed_rows_count += 1 - is_update_candidate = False; new_url = "" - condition2_u_is_wiki_url = vorschlag_u.lower().startswith(("http://", "https://")) and "wikipedia.org/wiki/" in vorschlag_u.lower() + # Update-Kandidat prüfen + is_update_candidate = False + new_url = "" + condition2_u_is_wiki_url = ( + vorschlag_u.lower().startswith(("http://", "https://")) + and "wikipedia.org/wiki/" in vorschlag_u.lower() + ) - if condition2_u_is_wiki_url: - new_url = vorschlag_u - condition3_u_differs_m = simple_normalize_url(new_url) != simple_normalize_url(url_m) # Globale Funktion + if condition2_u_is_wiki_url: + new_url = vorschlag_u + condition3_u_differs_m = ( + simple_normalize_url(new_url) != simple_normalize_url(url_m) + ) - if condition3_u_differs_m: - logging.debug(f" -> Prüfe Validität der neuen URL: {new_url}...") - try: condition4_u_is_valid = is_valid_wikipedia_article_url(new_url); # Globale Funktion mit Retry - except Exception as e_valid: logging.error(f" -> Fehler bei Validierung der URL '{new_url}': {e_valid}. Behandle als ungültig."); condition4_u_is_valid = False + if condition3_u_differs_m: + logging.debug(f" -> Prüfe Validität der neuen URL: {new_url}...") + try: + condition4_u_is_valid = is_valid_wikipedia_article_url(new_url) + except Exception as e_valid: + logging.error( + f" -> Fehler bei Validierung der URL '{new_url}': {e_valid}. " + "Behandle als ungültig." + ) + condition4_u_is_valid = False - if condition4_u_is_valid: is_update_candidate = True; logging.debug(f" -> URL '{new_url}' ist ein valider Artikel.") - else: logging.debug(f" -> URL '{new_url}' ist KEIN valider Artikel laut API Check.") - else: logging.debug(f" -> Vorschlag U ist identisch mit URL M.") - else: logging.debug(f" -> Vorschlag U ist keine Wikipedia URL ('{vorschlag_u}').") + if condition4_u_is_valid: + is_update_candidate = True + logging.debug(f" -> URL '{new_url}' ist ein valider Artikel.") + else: + logging.debug(f" -> URL '{new_url}' ist KEIN valider Artikel laut API Check.") + else: + logging.debug(f" -> Vorschlag U ist identisch mit URL M.") + else: + logging.debug(f" -> Vorschlag U ist keine Wikipedia URL ('{vorschlag_u}').") -if is_update_candidate: - logging.info(f"Zeile {row_num_in_sheet}: Update-Kandidat VALIDIERUNG ERFOLGREICH. Setze ReEval-Flag 'x' und bereite Updates vor für URL: {new_url}"); - updated_url_count += 1; - m_l=self.sheet_handler._get_col_letter(col_indices["Wiki URL"]+1); s_l=self.sheet_handler._get_col_letter(col_indices["Chat Wiki Konsistenzprüfung"]+1); u_l=self.sheet_handler._get_col_letter(col_indices["Chat Vorschlag Wiki Artikel"]+1); - a_l=self.sheet_handler._get_col_letter(col_indices["ReEval Flag"]+1); - n_idx = col_indices["Wiki Absatz"]; v_idx = col_indices["Begründung bei Abweichung"]; n_l=self.sheet_handler._get_col_letter(n_idx+1); v_l=self.sheet_handler._get_col_letter(v_idx+1); - an_l=self.sheet_handler._get_col_letter(col_indices["Wikipedia Timestamp"]+1); ax_l=self.sheet_handler._get_col_letter(col_indices["Wiki Verif. Timestamp"]+1); ao_l=self.sheet_handler._get_col_letter(col_indices["Timestamp letzte Prüfung"]+1); ap_l=self.sheet_handler._get_col_letter(col_indices["Version"]+1); + # Je nach Ergebnis Update oder Cleanup anlegen + if is_update_candidate: + logging.info( + f"Zeile {row_num_in_sheet}: Update-Kandidat VALIDIERUNG ERFOLGREICH. " + f"Setze ReEval-Flag 'x' und bereite Updates vor für URL: {new_url}" + ) + updated_url_count += 1 - all_sheet_updates.extend([ - {'range': f'{m_l}{row_num_in_sheet}', 'values': [[new_url]]}, {'range': f'{s_l}{row_num_in_sheet}', 'values': [["X (URL Copied)"]]}, {'range': f'{u_l}{row_num_in_sheet}', 'values': [["URL übernommen"]]}, - {'range': f'{n_l}{row_num_in_sheet}:{v_l}{row_num_in_sheet}', 'values': [[''] * (v_idx - n_idx + 1)]}, - {'range': f'{an_l}{row_num_in_sheet}', 'values': [['']]}, {'range': f'{ax_l}{row_num_in_sheet}', 'values': [['']]}, - {'range': f'{ao_l}{row_num_in_sheet}', 'values': [['']]}, {'range': f'{ap_l}{row_num_in_sheet}', 'values': [['']]}, - {'range': f'{a_l}{row_num_in_sheet}', 'values': [["x"]]}, - ]); -else: # <= ZEILE 3583 - # <<< Die folgenden Zeilen müssen EINE EBENE TIEFER als das "else:" eingerückt sein (z.B. 16 Leerzeichen) - logging.info(f"Zeile {row_num_in_sheet}: Vorschlag U ('{vorschlag_u}') ist ungültig/identisch. Lösche U und setze Status S."); # <= ZEILE 3584 (korrekt eingerückt) - cleared_suggestion_count += 1; # <= ZEILE 3585 (korrekt eingerückt) - s_l=self.sheet_handler._get_col_letter(col_indices["Chat Wiki Konsistenzprüfung"]+1); u_l=self.sheet_handler._get_col_letter(col_indices["Chat Vorschlag Wiki Artikel"]+1); # <= ZEILE 3586 (korrekt eingerückt) - all_sheet_updates.extend([ # <= ZEILE 3587 (korrekt eingerückt) - {'range': f'{s_l}{row_num_in_sheet}', 'values': [["X (Invalid Suggestion)"]]}, # Neuer Status in S - {'range': f'{u_l}{row_num_in_sheet}', 'values': [[""]]} # Vorschlag U löschen - ]); # <= ZEILE 3590 (korrekt eingerückt) + # Spaltenbuchstaben bestimmen + m_l = self.sheet_handler._get_col_letter(col_indices["Wiki URL"] + 1) + s_l = self.sheet_handler._get_col_letter(col_indices["Chat Wiki Konsistenzprüfung"] + 1) + u_l = self.sheet_handler._get_col_letter(col_indices["Chat Vorschlag Wiki Artikel"] + 1) + a_l = self.sheet_handler._get_col_letter(col_indices["ReEval Flag"] + 1) - # else: Status war OK, X(Updated), X(Copied), X(Invalid Suggestion) oder leer -> Kein Kandidat <= ZEILE 3591 (Gehört zum if is_candidate_for_check) + n_idx = col_indices["Wiki Absatz"] + v_idx = col_indices["Begründung bei Abweichung"] + n_l = self.sheet_handler._get_col_letter(n_idx + 1) + v_l = self.sheet_handler._get_col_letter(v_idx + 1) + an_l = self.sheet_handler._get_col_letter(col_indices["Wikipedia Timestamp"] + 1) + ax_l = self.sheet_handler._get_col_letter(col_indices["Wiki Verif. Timestamp"]+ 1) + ao_l = self.sheet_handler._get_col_letter(col_indices["Timestamp letzte Prüfung"]+1) + ap_l = self.sheet_handler._get_col_letter(col_indices["Version"] + 1) + all_sheet_updates.extend([ + {'range': f'{m_l}{row_num_in_sheet}', 'values': [[ new_url ]]}, + {'range': f'{s_l}{row_num_in_sheet}', 'values': [[ "X (URL Copied)" ]]}, + {'range': f'{u_l}{row_num_in_sheet}', 'values': [[ "URL übernommen" ]]}, + { + 'range': f'{n_l}{row_num_in_sheet}:{v_l}{row_num_in_sheet}', + 'values': [[''] * (v_idx - n_idx + 1)] + }, + {'range': f'{an_l}{row_num_in_sheet}', 'values': [['']]}, + {'range': f'{ax_l}{row_num_in_sheet}', 'values': [['']]}, + {'range': f'{ao_l}{row_num_in_sheet}', 'values': [['']]}, + {'range': f'{ap_l}{row_num_in_sheet}', 'values': [['']]}, + {'range': f'{a_l}{row_num_in_sheet}', 'values': [[ "x" ]]}, + ]) + else: + logging.info( + f"Zeile {row_num_in_sheet}: Vorschlag U ('{vorschlag_u}') ist ungültig/identisch. " + "Lösche U und setze Status S." + ) + cleared_suggestion_count += 1 + + s_l = self.sheet_handler._get_col_letter(col_indices["Chat Wiki Konsistenzprüfung"] + 1) + u_l = self.sheet_handler._get_col_letter(col_indices["Chat Vorschlag Wiki Artikel"] + 1) + + all_sheet_updates.extend([ + {'range': f'{s_l}{row_num_in_sheet}', 'values': [[ "X (Invalid Suggestion)" ]]}, + {'range': f'{u_l}{row_num_in_sheet}', 'values': [[ "" ]]}, + ]) + + # Nach der Schleife: Batch-Update senden, falls nötig if all_sheet_updates: - logging.info(f"Sende Batch-Update für {processed_rows_count} geprüfte Zeilen ({len(all_sheet_updates)} Zellen)...") - success = self.sheet_handler.batch_update_cells(all_sheet_updates) - if success: logging.info(f"Sheet-Update für Wiki-Updates erfolgreich.") - else: logging.error("FEHLER beim Sheet-Update für Wiki-Updates.") - else: logging.info("Keine Zeilen gefunden, die eine Wiki-URL-Korrektur oder Vorschlagsbereinigung benötigen.") + logging.info( + f"Sende Batch-Update für {processed_rows_count} geprüfte Zeilen " + f"({len(all_sheet_updates)} Zellen)..." + ) + success = self.sheet_handler.batch_update_cells(all_sheet_updates) + if success: + logging.info("Sheet-Update für Wiki-Updates erfolgreich.") + else: + logging.error("FEHLER beim Sheet-Update für Wiki-Updates.") + else: + logging.info("Keine Zeilen gefunden, die eine Wiki-URL-Korrektur oder Vorschlagsbereinigung benötigen.") - logging.info(f"Wiki-Updates abgeschlossen. {processed_rows_count} Zeilen geprüft. {updated_url_count} URLs kopiert & für ReEval markiert, {cleared_suggestion_count} ungültige Vorschläge gelöscht/markiert.") + logging.info( + f"Wiki-Updates abgeschlossen. {processed_rows_count} Zeilen geprüft. " + f"{updated_url_count} URLs kopiert & für ReEval markiert, " + f"{cleared_suggestion_count} ungültige Vorschläge gelöscht/markiert." + ) # --- Private Helfer für Timestamp/Status Checks ---