v1.3.5 FSM & Servicetechniker-Explanation, Sheet-Update-Check Auto Log

Der Dekorator retry_on_failure wurde oben im Code definiert.

Wikipedia-Artikelvorschlag aus Spalte K wird bevorzugt genutzt.

Nach dem Schreiben der Wiki-Daten wird geprüft, ob das Update abgeschlossen ist, mit einer 3‑Sekunden-Pause.

Der FSM-Eignungsparser wurde flexibler angepasst, sodass auch freie Antworten erkannt werden.

Bei Abweichungen in der Servicetechniker-Schätzung wird jetzt zusätzlich eine detaillierte Erklärung von ChatGPT angefordert.

Die Spalten AF und AG werden mit "XX" befüllt.

Alle Debug-Ausgaben werden automatisch in einer Log-Datei im Ordner "Log" gespeichert, deren Name Datum, Uhrzeit und Versionsnummer enthält.
This commit is contained in:
2025-04-02 14:06:58 +00:00
parent e0e9987516
commit b206ef9767

View File

@@ -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))