diff --git a/brancheneinstufung.py b/brancheneinstufung.py index 01477359..a383d0ab 100644 --- a/brancheneinstufung.py +++ b/brancheneinstufung.py @@ -14,7 +14,7 @@ import csv # ==================== KONFIGURATION ==================== class Config: - VERSION = "v1.3.5" # v1.3.5: FSM-Prüfung mit flexiblem Parser, Servicetechniker-Explanation, Log-Datei, Warten bis Sheet-Update. + VERSION = "v1.3.5" # v1.3.5: FSM-Eignungsprüfung & Servicetechniker-Explanation, Sheet-Update-Check, automatische Log-Datei. LANG = "de" CREDENTIALS_FILE = "service_account.json" SHEET_URL = "https://docs.google.com/spreadsheets/d/1u_gHr9JUfmV1-iviRzbSe3575QEp7KLhK5jFV_gJcgo" @@ -26,7 +26,19 @@ class Config: WIKIPEDIA_SEARCH_RESULTS = 5 HTML_PARSER = "html.parser" -# Log-Datei vorbereiten +# ==================== RETRY-DECORATOR ==================== +def retry_on_failure(func): + def wrapper(*args, **kwargs): + for attempt in range(Config.MAX_RETRIES): + try: + return func(*args, **kwargs) + except Exception as e: + print(f"⚠️ Fehler bei {func.__name__} (Versuch {attempt+1}): {str(e)[:100]}") + time.sleep(Config.RETRY_DELAY) + return None + return wrapper + +# ==================== LOGGING & HELPER FUNCTIONS ==================== if not os.path.exists("Log"): os.makedirs("Log") LOG_FILE = os.path.join("Log", f"{datetime.now().strftime('%d-%m-%Y_%H-%M')}_{Config.VERSION.replace('.', '')}.txt") @@ -209,7 +221,6 @@ def evaluate_fsm_suitability(company_name, company_data): ) result = response.choices[0].message.content.strip() debug_print(f"FSM-Eignungsantwort ChatGPT: '{result}'") - # Flexibler Parser: Falls keine Zeilen mit ":" vorhanden sind, nimm den ersten Satz. suitability = "k.A." justification = "" lines = result.split("\n") @@ -618,7 +629,6 @@ class WikipediaScraper: } @retry_on_failure def search_company_article(self, company_name, website): - # Zuerst prüfen: Gibt es in Spalte K bereits einen Wikipedia-Vorschlag? search_terms = self._generate_search_terms(company_name, website) for term in search_terms: try: @@ -701,11 +711,10 @@ class DataProcessor: company_data.get('categories', 'k.A.') ] self.sheet_handler.sheet.update(values=[wiki_values], range_name=wiki_update_range) - # Warten, bis das Update im Sheet übernommen wurde (prüfe Zelle K{row_num}) wait_for_sheet_update(self.sheet_handler.sheet, f"K{row_num}", wiki_values[0]) time.sleep(3) - # Umsatz-Schätzung (Spalte AF soll "XX" erhalten) + # Umsatz-Schätzung: Spalte AF soll "XX" erhalten self.sheet_handler.sheet.update(values=[["XX"]], range_name=chatgpt_range) # Umsatz-Abgleich (Spalte AG) @@ -743,14 +752,13 @@ class DataProcessor: internal_value = row_data[7] if len(row_data) > 7 else "k.A." internal_category = map_internal_technicians(internal_value) if internal_value != "k.A." else "k.A." if internal_category != "k.A." and st_estimate != internal_category: - # Hole detaillierte Erklärung von ChatGPT, warum die Schätzung so ist. explanation = evaluate_servicetechnicians_explanation(company_name, st_estimate, company_data) discrepancy = explanation else: discrepancy = "ok" self.sheet_handler.sheet.update(values=[[discrepancy]], range_name=f"AE{row_num}") - # Spalten AF und AG sollen "XX" enthalten + # Spalten AF und AG: "XX" self.sheet_handler.sheet.update(values=[["XX"]], range_name="AF" + str(row_num)) self.sheet_handler.sheet.update(values=[["XX"]], range_name="AG" + str(row_num))