diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 549798c5..cd9e0235 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -4667,195 +4667,183 @@ class DataProcessor: # --- 2. Wikipedia Handling (Search, Extraction, Status Reset) ========== run_wiki_step = 'wiki' in steps_to_run - wiki_processing_needed_based_on_status = self._needs_wiki_processing(row_data, force_reeval) # Prüft Z und AC + wiki_processing_needed_based_on_status = self._needs_wiki_processing(row_data, force_reeval) if run_wiki_step and wiki_processing_needed_based_on_status: - any_processing_done = True + any_processing_done = True # Markiere, dass in dieser Zeile etwas im Wiki-Teil getan wird - # --- KORREKTUR HIER --- + # ---- KORREKTE VARIABLENERSTELLUNG UND VERWENDUNG FÜR LOGGING ---- grund_message_parts_wiki = [] - if force_reeval: grund_message_parts_wiki.append('Re-Eval') + if force_reeval: + grund_message_parts_wiki.append('Re-Eval') + # Überprüfung des Wikipedia Timestamps (Spalte Z) if not self._get_cell_value_safe(row_data, "Wikipedia Timestamp").strip(): grund_message_parts_wiki.append('Z (Wikipedia Timestamp) leer') + # Überprüfung des Chat Wiki Konsistenzprüfung (Spalte AC) if self._get_cell_value_safe(row_data, "Chat Wiki Konsistenzpruefung").strip().upper() == "X (URL COPIED)": grund_message_parts_wiki.append("AC (Chat Wiki Konsistenzpruefung)='X (URL COPIED)'") - grund_message_wiki = ", ".join(filter(None, grund_message_parts_wiki)) # Erzeugt den String - if not grund_message_wiki: # Fallback, falls Liste leer war - grund_message_wiki = "Bedingungen für Wiki-Bearbeitung erfüllt (siehe Debug)" + # Baue die Log-Nachricht zusammen + grund_message_wiki = ", ".join(filter(None, grund_message_parts_wiki)) + if not grund_message_wiki: # Wenn die Liste leer war und join einen leeren String ergibt + grund_message_wiki = "Bedingung für Wiki-Bearbeitung erfüllt (Details im Debug-Log oder Status)" # Allgemeinerer Fallback - # Die Log-Zeile muss die Variable `grund_message_wiki` verwenden: + # Verwende die korrekte Variable `grund_message_wiki` self.logger.info(f"Zeile {row_num_in_sheet}: Fuehre WIKI Schritte aus (Grund: {grund_message_wiki})...") - # --- ENDE KORREKTUR --- + # ---- ENDE KORREKTUR ---- - current_wiki_url_r = self._get_cell_value_safe(row_data, "Wiki URL").strip() # Spalte R (Tochter) - system_suggested_parent_o = self._get_cell_value_safe(row_data, "System Vorschlag Parent Account").strip() # Spalte O - parent_name_d = self._get_cell_value_safe(row_data, "Parent Account Name").strip() # Spalte D - - url_for_extraction = None - source_of_wiki_data_origin_log_msg = "Tochter (Standard)" # Für Logging + # Hole aktuellen Wiki-URL der Tochter aus Spalte R + current_wiki_url_in_sheet_for_daughter = self._get_cell_value_safe(row_data, "Wiki URL").strip() + system_suggested_parent_name_o = self._get_cell_value_safe(row_data, "System Vorschlag Parent Account").strip() + # parent_account_name_d wird bereits weiter oben in der Funktion gelesen - # Priorität 1: Wenn Tochter-URL (R) leer/k.A. UND Parent (D) gesetzt ist - if (not current_wiki_url_r or current_wiki_url_r.lower() == 'k.a.') and \ - (parent_name_d and parent_name_d.lower() != 'k.a.'): - self.logger.info(f" Zeile {row_num_in_sheet}: R leer, D ('{parent_name_d}') gesetzt. Suche Wiki für Parent D.") + url_to_validate_and_extract = None + name_for_wiki_article_validation = company_name + source_of_wiki_data_origin_log_msg = "Tochter (Standard)" # Angepasst für Klarheit + additional_info_for_af_col = "" + artikel_ist_valide_fuer_extraktion = False + + # --- START: LOGIK FÜR PARENT-ACCOUNT (O oder D) UND WIKI-URL DER TOCHTER (R) --- + # (Hier folgt der Codeblock, den wir für die Parent-Wiki-Suche und Validierung entwickelt haben) + # Dieser Block sollte `url_to_validate_and_extract`, `name_for_wiki_article_validation`, + # `source_of_wiki_data_origin_log_msg` und `artikel_ist_valide_fuer_extraktion` setzen. + # Wichtig: Er muss `serp_wikipedia_lookup` verwenden, wie besprochen. + + # Beispielhafte Struktur (basierend auf unserem vereinfachten Ansatz): + # 1. Prüfung Parent D (manuell/CRM) + if (not current_wiki_url_in_sheet_for_daughter or current_wiki_url_in_sheet_for_daughter.lower() == 'k.a.') and \ + (parent_account_name_d and parent_account_name_d.lower() != 'k.a.'): + self.logger.info(f" Zeile {row_num_in_sheet}: R leer, D ('{parent_account_name_d}') gesetzt. Suche Wiki für Parent D.") try: - url_for_extraction = serp_wikipedia_lookup(parent_name_d, website=None) - if url_for_extraction: - source_of_wiki_data_origin_log_msg = f"Parent D ('{parent_name_d}')" - # Setze AC direkt auf INFO_PARENT_AUS_D, da wir diesem Pfad vertrauen + potential_url = serp_wikipedia_lookup(parent_account_name_d, website=None) + if potential_url and potential_url.lower() not in ["k.a.", "kein artikel gefunden"] and not potential_url.startswith("FEHLER"): + url_to_validate_and_extract = potential_url + name_for_wiki_article_validation = parent_account_name_d + source_of_wiki_data_origin_log_msg = f"Parent D ('{parent_account_name_d}')" + # Da wir dieser Quelle vertrauen, setzen wir Validierung für Extraktion direkt + artikel_ist_valide_fuer_extraktion = True + self.logger.info(f" -> Wiki-Artikel für Parent D '{parent_account_name_d}' gefunden und als valide angenommen: {url_to_validate_and_extract}") updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Wiki Konsistenzpruefung"] + 1)}{row_num_in_sheet}', 'values': [["INFO_PARENT_AUS_D"]]}) - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Begründung bei Abweichung"] + 1)}{row_num_in_sheet}', 'values': [[f"Wiki-Daten von Parent (aus D): {parent_name_d} übernommen."]]}) - except Exception as e_d_lookup: - self.logger.error(f"Fehler bei Wiki-Suche für Parent D '{parent_name_d}': {e_d_lookup}") - url_for_extraction = f"Fehler Suche Parent D: {str(e_d_lookup)[:50]}" + additional_info_for_af_col = f"INFO: Wiki-Daten von Parent (aus D): {parent_account_name_d} direkt übernommen. " + else: + self.logger.warning(f" -> Kein Wiki-Artikel für Parent D '{parent_account_name_d}' gefunden.") + except Exception as e_d_lookup_re: + self.logger.error(f"Fehler bei Wiki-Suche für Parent D '{parent_account_name_d}': {e_d_lookup_re}") - # Priorität 2: Wenn Tochter-URL (R) leer/k.A. UND (D leer ODER D-Suche fehlschlug) UND Parent-Vorschlag (O) gesetzt ist - if (url_for_extraction is None or url_for_extraction.startswith("Fehler")) and \ - (not current_wiki_url_r or current_wiki_url_r.lower() == 'k.a.') and \ - (system_suggested_parent_o and system_suggested_parent_o.lower() != 'k.a.'): - self.logger.info(f" Zeile {row_num_in_sheet}: R leer, D nicht genutzt/erfolglos, O ('{system_suggested_parent_o}') gesetzt. Suche Wiki für Parent O.") + # 2. Prüfung Parent O (Systemvorschlag), wenn D nicht erfolgreich oder leer war + if (url_to_validate_and_extract is None) and \ + (not current_wiki_url_in_sheet_for_daughter or current_wiki_url_in_sheet_for_daughter.lower() == 'k.a.') and \ + (system_suggested_parent_name_o and system_suggested_parent_name_o.lower() != 'k.a.'): + self.logger.info(f" Zeile {row_num_in_sheet}: R leer, D nicht genutzt/erfolglos, O ('{system_suggested_parent_name_o}') gesetzt. Suche Wiki für Parent O.") try: - url_for_extraction = serp_wikipedia_lookup(system_suggested_parent_o, website=None) - if url_for_extraction: - source_of_wiki_data_origin_log_msg = f"Parent O ('{system_suggested_parent_o}')" - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Wiki Konsistenzpruefung"] + 1)}{row_num_in_sheet}', 'values': [["INFO_PARENT_AUS_O"]]}) - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Begründung bei Abweichung"] + 1)}{row_num_in_sheet}', 'values': [[f"Wiki-Daten von Parent (aus O): {system_suggested_parent_o} übernommen."]]}) - except Exception as e_o_lookup: - self.logger.error(f"Fehler bei Wiki-Suche für Parent O '{system_suggested_parent_o}': {e_o_lookup}") - url_for_extraction = f"Fehler Suche Parent O: {str(e_o_lookup)[:50]}" - - # Priorität 3: Standard Tochter-Suche/Verwendung (wenn R leer war und Parent-Suchen nicht griffen, oder wenn R schon was hat und Re-Eval etc.) - if url_for_extraction is None or url_for_extraction.startswith("Fehler"): - self.logger.debug(f" Zeile {row_num_in_sheet}: Keine Parent-Wiki-URL ermittelt oder genutzt. Standard Wiki-Logik für Tochter '{company_name}' greift.") - # Hier die bisherige Logik aus _process_single_row für die Wiki-Suche/Validierung der Tochter - # (Diese Logik entscheidet, ob `current_wiki_url_r` verwendet, neu gesucht oder validiert wird) - # Am Ende dieser Logik sollte `url_for_extraction` die URL der Tochter oder einen Fehler/Signalwert enthalten. - # Beispielhaft (vereinfacht): - if force_reeval or not self._get_cell_value_safe(row_data, "Wikipedia Timestamp").strip() or self._get_cell_value_safe(row_data, "Chat Wiki Konsistenzpruefung").strip().upper() == "X (URL COPIED)": - if current_wiki_url_r and current_wiki_url_r.lower() not in ["k.a.", "kein artikel gefunden"] and not force_reeval and self._get_cell_value_safe(row_data, "Chat Wiki Konsistenzpruefung").strip().upper() != "X (URL COPIED)": - # Timestamp Z war leer, aber R hatte eine URL -> diese verwenden und validieren - url_for_extraction = current_wiki_url_r - source_of_wiki_data_origin_log_msg = "Tochter (aus R, Z leer)" - else: # Neu suchen - try: - page_obj_tochter = self.wiki_scraper.search_company_article(company_name, website_url) - if page_obj_tochter: - url_for_extraction = page_obj_tochter.url - source_of_wiki_data_origin_log_msg = "Tochter (Standard-Suche)" + potential_url = serp_wikipedia_lookup(system_suggested_parent_name_o, website=None) + if potential_url and potential_url.lower() not in ["k.a.", "kein artikel gefunden"] and not potential_url.startswith("FEHLER"): + url_to_validate_and_extract = potential_url + name_for_wiki_article_validation = system_suggested_parent_name_o + source_of_wiki_data_origin_log_msg = f"Parent O ('{system_suggested_parent_name_o}')" + # Hier validieren wir den gefundenen Artikel gegen den Namen aus O + page_obj_o = wikipedia.page(url=url_to_validate_and_extract, auto_suggest=False, preload=False) # oder title=, je nachdem was serp_lookup liefert + if self.wiki_scraper._validate_article(page_obj_o, name_for_wiki_article_validation, website_url, is_parent_context=True): + artikel_ist_valide_fuer_extraktion = True + url_to_validate_and_extract = page_obj_o.url # Kanonische URL + self.logger.info(f" -> Wiki-Artikel für Parent O '{system_suggested_parent_name_o}' gefunden und validiert: {url_to_validate_and_extract}") + updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Wiki Konsistenzpruefung"] + 1)}{row_num_in_sheet}', 'values': [["INFO_PARENT_AUS_O"]]}) + additional_info_for_af_col = f"INFO: Wiki-Daten von Parent (aus O): {system_suggested_parent_name_o} übernommen. " + else: + self.logger.warning(f" -> Gefundener Wiki-Artikel für Parent O '{system_suggested_parent_name_o}' ({url_to_validate_and_extract}) nicht validiert.") + additional_info_for_af_col = f"WARNUNG: Artikel für Parent O '{url_to_validate_and_extract}' nicht valide. " + final_wiki_data['url'] = url_to_validate_and_extract # URL speichern, aber nicht extrahieren + # ... Rest auf k.A. setzen ... + wiki_data_updated_in_this_run = True # Da URL in R geschrieben wird + url_to_validate_and_extract = None # Verhindert Extraktion + else: + self.logger.warning(f" -> Kein Wiki-Artikel für Parent O '{system_suggested_parent_name_o}' gefunden.") + except Exception as e_o_lookup_re: + self.logger.error(f"Fehler bei Wiki-Suche/Validierung für Parent O '{system_suggested_parent_name_o}': {e_o_lookup_re}") + url_to_validate_and_extract = f"Fehler Suche Parent O: {str(e_o_lookup_re)[:50]}" + + + # 3. Standard Tochter-Wiki-Logik (wenn url_to_validate_and_extract immer noch None ist) + if url_to_validate_and_extract is None or url_to_validate_and_extract.startswith("Fehler"): + self.logger.debug(f" Zeile {row_num_in_sheet}: Keine gültige Parent-Wiki-URL. Standard Tochter-Wiki-Logik...") + # ... (Ihre bestehende Logik, um url_to_validate_and_extract für die Tochter zu setzen) + # Diese Logik muss name_for_wiki_article_validation = company_name und + # source_of_wiki_data_origin = "Tochter (...)" setzen. + # Und am Ende muss artikel_ist_valide_fuer_extraktion gesetzt werden. + # Beispiel (sehr vereinfacht): + if current_wiki_url_in_sheet_for_daughter and current_wiki_url_in_sheet_for_daughter.lower() not in ['k.a.'] and not current_wiki_url_in_sheet_for_daughter.startswith("Fehler"): + url_to_validate_and_extract = current_wiki_url_in_sheet_for_daughter + # ... Validierung für Tochter ... + else: # Neue Suche für Tochter + try: + page_obj_tochter = self.wiki_scraper.search_company_article(company_name, website_url) + if page_obj_tochter: + url_to_validate_and_extract = page_obj_tochter.url + # Validierung hier: + if self.wiki_scraper._validate_article(page_obj_tochter, company_name, website_url, is_parent_context=False): + artikel_ist_valide_fuer_extraktion = True + source_of_wiki_data_origin_log_msg = "Tochter (Suche & Valide)" else: - url_for_extraction = "Kein Artikel gefunden" - except Exception as e_tochter_suche: - url_for_extraction = f"Fehler Suche Tochter: {str(e_tochter_suche)[:50]}" - elif current_wiki_url_r and current_wiki_url_r.lower() not in ["k.a.", "kein artikel gefunden"]: - url_for_extraction = current_wiki_url_r # R hat was und Timestamp Z ist gesetzt - source_of_wiki_data_origin_log_msg = "Tochter (aus R, unverändert)" + # ... Behandlung wenn Tochter-Artikel nicht valide ... + pass + else: + url_to_validate_and_extract = "Kein Artikel gefunden" + except Exception as e_tochter_suche_re: + url_to_validate_and_extract = f"Fehler Suche Tochter: {str(e_tochter_suche_re)[:50]}" - # Datenextraktion, wenn eine URL bestimmt wurde (egal ob Parent oder Tochter) - if url_for_extraction and isinstance(url_for_extraction, str) and \ - url_for_extraction.lower() not in ["k.a.", "kein artikel gefunden"] and \ - not url_for_extraction.startswith("FEHLER"): - self.logger.info(f" -> Extrahiere Wiki-Daten von URL ({source_of_wiki_data_origin_log_msg}): {url_for_extraction[:100]}...") + # --- DATENEXTRAKTION (nur wenn artikel_ist_valide_fuer_extraktion True ist) --- + if artikel_ist_valide_fuer_extraktion and url_to_validate_and_extract and \ + not url_to_validate_and_extract.lower() in ["k.a.", "kein artikel gefunden"] and \ + not url_to_validate_and_extract.startswith("FEHLER"): + self.logger.debug(f" -> Extrahiere Wiki-Daten von validierter URL ({source_of_wiki_data_origin_log_msg}): {url_to_validate_and_extract[:100]}...") try: - # Für Parent-Artikel wird hier KEINE strenge Validierung mehr durchgeführt, - # wir nehmen an, serp_lookup war gut genug. Für Tochter-Artikel - # hat search_company_article bereits validiert. - extracted_data = self.wiki_scraper.extract_company_data(url_for_extraction) - - if extracted_data and isinstance(extracted_data, dict) and extracted_data.get('url') != 'k.A.': + extracted_data = self.wiki_scraper.extract_company_data(url_to_validate_and_extract) + # ... (Rest der Extraktionslogik und Updates für final_wiki_data) ... + if extracted_data and extracted_data.get('url') != 'k.A.': final_wiki_data = extracted_data wiki_data_updated_in_this_run = True - self.logger.info(f" -> Datenextraktion von {url_for_extraction[:100]}... erfolgreich.") - # Wenn Daten von Parent stammen, wurde AC ggf. schon oben gesetzt. - # Wenn es eine Tochter-URL war, muss AC+AA ggf. für ChatGPT-Verif. zurückgesetzt werden. - if not source_of_wiki_data_origin_log_msg.startswith("Parent") and \ - (force_reeval or current_wiki_url_r != url_for_extraction or self._get_cell_value_safe(row_data, "Chat Wiki Konsistenzpruefung").strip().upper() == "X (URL COPIED)"): - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Chat Wiki Konsistenzpruefung"] + 1)}{row_num_in_sheet}', 'values': [['?']]}) - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Wiki Verif. Timestamp"] + 1)}{row_num_in_sheet}', 'values': [['']]}) - # ... (Rest der Fehlerbehandlung für Extraktion) - except Exception as e_wiki_extract_final_simple: - # ... (Fehlerbehandlung) - final_wiki_data['url'] = url_for_extraction # Zumindest die URL speichern - # ... (Rest auf k.A. setzen) - wiki_data_updated_in_this_run = True - elif url_for_extraction: # War "Kein Artikel..." oder "Fehler..." - final_wiki_data['url'] = url_for_extraction + # ... (Logik für AC-Status Reset, wenn Tochter-URL geändert oder Re-Eval) ... + except Exception as e_extract_final: + self.logger.error(f"FEHLER bei Wikipedia Datenextraktion von {url_to_validate_and_extract[:100]}...: {e_extract_final}") + # ... (Fehlerbehandlung für final_wiki_data) ... + elif url_to_validate_and_extract: # War "Kein Artikel..." oder "Fehler..." oder nicht valide + final_wiki_data['url'] = url_to_validate_and_extract for key_to_clear in ['sitz_stadt', 'sitz_land', 'first_paragraph', 'branche', 'umsatz', 'mitarbeiter', 'categories']: final_wiki_data[key_to_clear] = 'k.A.' wiki_data_updated_in_this_run = True - - # Updates für R-Y und Z + + # Updates für R-Y und Z (immer ausführen, wenn wiki_data_updated_in_this_run) if wiki_data_updated_in_this_run: - # ... (Updates für Spalten R bis Y mit final_wiki_data) ... + # ... (Schreiben von final_wiki_data und Timestamps Z, AB, AF und Reset von AC, AA, AD, AE) ... + updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Wiki URL"] + 1)}{row_num_in_sheet}', 'values': [[final_wiki_data.get('url', 'k.A.')]]}) + # usw. für R-Y updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Wikipedia Timestamp"] + 1)}{row_num_in_sheet}', 'values': [[now_timestamp]]}) # Z - # Ggf. SerpAPI Timestamp (AB) setzen, wenn eine der Suchen (Parent D/O oder Tochter) via serp_wikipedia_lookup lief - if source_of_wiki_data_origin_log_msg.endswith("(O via SerpAPI)") or \ - source_of_wiki_data_origin_log_msg.endswith("(D via SerpAPI)") or \ - (source_of_wiki_data_origin_log_msg == "Tochter (Standard-Suche)" and "serp_wikipedia_lookup" in str(self.wiki_scraper.search_company_article)): # Heuristik - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["SerpAPI Wiki Search Timestamp"] + 1)}{row_num_in_sheet}', 'values': [[now_timestamp]]}) - # --- 2b. System Vorschlag Parent Account (O, P, Q) --- - # ... (Dieser Block bleibt wie im vorherigen Vorschlag, ruft _suggest_parent_account) ... - # _suggest_parent_account muss jetzt auch mit den potentiell vom Parent stammenden final_wiki_data umgehen können. - - # ... (Rest von _process_single_row: ChatGPT-Eval, ML, etc.) ... - - # --- 2b. System Vorschlag Parent Account (Spalte O, P, Q) --- - # Dieser Schritt wird ausgeführt, wenn 'wiki' in steps_to_run enthalten ist (oder ein spezifischer 'parent_suggest'-Schritt) - run_parent_suggest_step = 'wiki' in steps_to_run # Oder ein dedizierter Schritt-Key - - system_vorschlag_parent_o_value = self._get_cell_value_safe(row_data, "System Vorschlag Parent Account").strip() - parent_vorschlag_status_p_value = self._get_cell_value_safe(row_data, "Parent Vorschlag Status").strip() - - needs_parent_suggestion = (not system_vorschlag_parent_o_value or system_vorschlag_parent_o_value.lower() == 'k.a.') and parent_vorschlag_status_p_value != '-' - if force_reeval and parent_vorschlag_status_p_value != '-': - needs_parent_suggestion = True # Auch wenn O schon gefüllt war, aber nicht abgelehnt + # (Dieser Block bleibt wie im vorherigen Vorschlag, ruft Ihre _suggest_parent_account_openai_task über eine Batch-Methode + # oder, falls Sie es direkt in _process_single_row wollen, eine adaptierte Version davon auf) + # Wichtig: Wenn Sie Parent-Vorschläge *innerhalb* des Wiki-Schritts von _process_single_row machen wollen, + # dann muss die Logik für den Aufruf von _suggest_parent_account_openai_task hier platziert werden. + # Mein vorheriger Vorschlag war, dies in einem separaten Batch-Modus zu machen. + # Für _process_single_row, wenn wir es hier machen wollen würden (nicht empfohlen für viele Zeilen): - if run_parent_suggest_step and needs_parent_suggestion: - any_processing_done = True # Zählt als Verarbeitung - self.logger.info(f" Zeile {row_num_in_sheet}: Versuche Parent-Account vorzuschlagen...") - try: - # _suggest_parent_account braucht jetzt auch CRM-Daten und die aktuellen Wiki-Daten als Input - suggested_parent_info = self._suggest_parent_account( - company_name=company_name, - website_url=website_url, - crm_beschreibung=crm_beschreibung, - # final_wiki_data enthält hier die möglicherweise vom Parent (O) stammenden Wiki-Daten, - # was für die Heuristik relevant sein kann (z.B. um nicht sich selbst vorzuschlagen). - # Es ist wichtig, dass _suggest_parent_account dies berücksichtigt. - wiki_data_dict=final_wiki_data - ) - - if suggested_parent_info and suggested_parent_info.get("parent_name"): - # Nur schreiben, wenn der Vorschlag sich vom aktuellen Wert in D unterscheidet (falls D gesetzt) - # oder D leer ist. Und wenn der Vorschlag nicht der Firmenname selbst ist. - if suggested_parent_info["parent_name"].strip().lower() != company_name.strip().lower() and \ - (not parent_account_name_d or suggested_parent_info["parent_name"].strip().lower() != parent_account_name_d.strip().lower()): - - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["System Vorschlag Parent Account"] + 1)}{row_num_in_sheet}', 'values': [[suggested_parent_info["parent_name"]]]}) # Spalte O - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Parent Vorschlag Status"] + 1)}{row_num_in_sheet}', 'values': [['?']]}) # Spalte P, initial '?' - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Parent Vorschlag Timestamp"] + 1)}{row_num_in_sheet}', 'values': [[now_timestamp]]}) # Spalte Q - self.logger.info(f" -> Parent-Vorschlag für O: '{suggested_parent_info['parent_name']}' (Grund: {suggested_parent_info.get('reason', 'N/A')})") - else: - self.logger.info(f" -> Parent-Vorschlag '{suggested_parent_info['parent_name']}' ist identisch mit Firma oder D. Kein Update für O.") - # Optional: Timestamp trotzdem setzen, dass versucht wurde? - if system_vorschlag_parent_o_value.lower() == 'k.a.' or not system_vorschlag_parent_o_value: # Wenn O vorher leer war - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Parent Vorschlag Timestamp"] + 1)}{row_num_in_sheet}', 'values': [[now_timestamp]]}) - - - elif suggested_parent_info and suggested_parent_info.get("status") == "NO_SUGGESTION": - self.logger.info(f" -> Kein Parent-Vorschlag gemacht (Grund: {suggested_parent_info.get('reason', 'N/A')}). P/Q nicht geändert, falls O leer war.") - # Wenn O vorher leer war, Timestamp setzen, dass es versucht wurde. - if system_vorschlag_parent_o_value.lower() == 'k.a.' or not system_vorschlag_parent_o_value: - updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["Parent Vorschlag Timestamp"] + 1)}{row_num_in_sheet}', 'values': [[now_timestamp]]}) - - else: - self.logger.info(f" -> Kein Parent-Vorschlag von _suggest_parent_account erhalten oder ungültiges Format.") - except Exception as e_suggest_parent: - self.logger.error(f" -> Fehler bei _suggest_parent_account für Zeile {row_num_in_sheet}: {e_suggest_parent}") - # --- ENDE: 2b. Parent-Account-Vorschlag --- + # if 'parent_suggest' in steps_to_run: # Wenn ein spezifischer Schritt dafür da ist + # system_vorschlag_parent_o_value = self._get_cell_value_safe(row_data, "System Vorschlag Parent Account").strip() + # parent_vorschlag_status_p_value = self._get_cell_value_safe(row_data, "Parent Vorschlag Status").strip() + # needs_parent_suggestion_in_psr = (not system_vorschlag_parent_o_value or system_vorschlag_parent_o_value.lower() == 'k.a.') and parent_vorschlag_status_p_value != '-' + # if force_reeval and parent_vorschlag_status_p_value != '-': needs_parent_suggestion_in_psr = True + # + # if needs_parent_suggestion_in_psr: + # self.logger.info(f" Zeile {row_num_in_sheet}: Versuche Parent-Account vorzuschlagen (via OpenAI Task)...") + # task_data_for_o = { # Daten für _suggest_parent_account_openai_task zusammenstellen + # "row_num": row_num_in_sheet, "crm_name": company_name, ... + # } + # # Direkter, synchroner Aufruf hier (nicht ideal für Performance) + # # openai_semaphore_dummy = threading.Semaphore(1) # Dummy-Semaphore für direkten Aufruf + # # parent_suggestion_result = self._suggest_parent_account_openai_task(task_data_for_o, openai_semaphore_dummy) + # # ... (Ergebnis verarbeiten und O, P, Q updaten) ... + # # Besser: Dies in einem eigenen Batch-Modus belassen (process_parent_suggestion_batch) # --- Ende des Wikipedia-Blocks --- # Der nächste Block wäre ChatGPT-Evaluationen