This commit is contained in:
2025-05-23 18:45:35 +00:00
parent 17fce1255b
commit 85556d80cd

View File

@@ -201,86 +201,86 @@ COLUMN_MAP = {
# CRM-Daten Teil 1 (A-C) # CRM-Daten Teil 1 (A-C)
"ReEval Flag": 0, "CRM Name": 1, "CRM Kurzform": 2, "ReEval Flag": 0, "CRM Name": 1, "CRM Kurzform": 2,
# Parent Account Info (D, neue Spalte) # Parent Account Info (D)
"Parent Account Name": 3, # D (NEU) "Parent Account Name": 3, # D (NEU)
# CRM-Daten Teil 2 (E-P, alte D-M verschoben um +1) # CRM-Daten Teil 2 (E-N), alte D-M verschoben um +1
"CRM Website": 4, # E (vorher D) "CRM Website": 4, # E
"CRM Ort": 5, # F (vorher E) "CRM Ort": 5, # F
"CRM Land": 6, # G (vorher F) "CRM Land": 6, # G
"CRM Beschreibung": 7, # H (vorher G) "CRM Beschreibung": 7, # H
"CRM Branche": 8, # I (vorher H) "CRM Branche": 8, # I
"CRM Beschreibung Branche extern": 9, # J (vorher I) "CRM Beschreibung Branche extern": 9, # J
"CRM Anzahl Techniker": 10, # K (vorher J) "CRM Anzahl Techniker": 10, # K
"CRM Umsatz": 11, # L (vorher K) "CRM Umsatz": 11, # L
"CRM Anzahl Mitarbeiter": 12, # M (vorher L) "CRM Anzahl Mitarbeiter": 12, # M
"CRM Vorschlag Wiki URL": 13, # N (vorher M) "CRM Vorschlag Wiki URL": 13, # N
# System Vorschlag Parent & Status (O-P, neue Spalten) # System Vorschlag Parent & Status & Timestamp (O-Q)
"System Vorschlag Parent Account": 14, # O (NEU) "System Vorschlag Parent Account": 14, # O (NEU)
"Parent Vorschlag Status": 15, # P (NEU) "Parent Vorschlag Status": 15, # P (NEU)
"Parent Vorschlag Timestamp": 16, # Q (NEU)
# Wikipedia-Daten & -Status (Q-AF, alte N-AB verschoben um +2) # Wikipedia-Daten & -Status (R-AG), alte N-AB verschoben um +4
"Wiki URL": 16, # Q (vorher N) "Wiki URL": 17, # R
"Wiki Sitz Stadt": 17, # R (vorher O) "Wiki Sitz Stadt": 18, # S
"Wiki Sitz Land": 18, # S (vorher P) "Wiki Sitz Land": 19, # T
"Wiki Absatz": 19, # T (vorher Q) "Wiki Absatz": 20, # U
"Wiki Branche": 20, # U (vorher R) "Wiki Branche": 21, # V
"Wiki Umsatz": 21, # V (vorher S) "Wiki Umsatz": 22, # W
"Wiki Mitarbeiter": 22, # W (vorher T) "Wiki Mitarbeiter": 23, # X
"Wiki Kategorien": 23, # X (vorher U) "Wiki Kategorien": 24, # Y
"Wikipedia Timestamp": 24, # Y (vorher V) "Wikipedia Timestamp": 25, # Z
"Wiki Verif. Timestamp": 25, # Z (vorher W) "Wiki Verif. Timestamp": 26, # AA
"SerpAPI Wiki Search Timestamp": 26, # AA (vorher X) "SerpAPI Wiki Search Timestamp": 27, # AB
"Chat Wiki Konsistenzpruefung": 27, # AB (vorher Y) "Chat Wiki Konsistenzpruefung": 28, # AC
"Chat Begruendung Wiki Inkonsistenz": 28, # AC (vorher Z) "Chat Begruendung Wiki Inkonsistenz": 29, # AD
"Chat Vorschlag Wiki Artikel": 29, # AD (vorher AA) "Chat Vorschlag Wiki Artikel": 30, # AE
"Begruendung bei Abweichung": 30, # AE (vorher AB) "Begruendung bei Abweichung": 31, # AF
# Website-Daten (AG-AK, alte AC-AG verschoben um +3) # Website-Daten (AH-AL), alte AC-AG verschoben um +4
"Website Rohtext": 31, # AF (vorher AC) "Website Rohtext": 32, # AG
"Website Zusammenfassung": 32, # AG (vorher AD) "Website Zusammenfassung": 33, # AH
"Website Meta-Details": 33, # AH (vorher AE) "Website Meta-Details": 34, # AI
"Website Scrape Timestamp": 34, # AI (vorher AF) "Website Scrape Timestamp": 35, # AJ
"URL Prüfstatus": 35, # AJ (vorher AG) "URL Prüfstatus": 36, # AK
# ChatGPT Branchen- & weitere Schätzungen (AL-AX, alte AH-AT verschoben um +3) # ChatGPT Branchen- & weitere Schätzungen (AM-AY), alte AH-AT verschoben um +4
"Chat Vorschlag Branche": 36, # AK (vorher AH) "Chat Vorschlag Branche": 37, # AL
"Chat Branche Konfidenz": 37, # AL (vorher AI) "Chat Branche Konfidenz": 38, # AM
"Chat Konsistenz Branche": 38, # AM (vorher AJ) "Chat Konsistenz Branche": 39, # AN
"Chat Begruendung Abweichung Branche": 39, # AN (vorher AK) "Chat Begruendung Abweichung Branche": 40, # AO
"Chat Pruefung FSM Relevanz": 40, # AO (vorher AL) "Chat Pruefung FSM Relevanz": 41, # AP
"Chat Begruendung für FSM Relevanz": 41, # AP (vorher AM) "Chat Begruendung für FSM Relevanz": 42, # AQ
"Chat Schaetzung Anzahl Mitarbeiter": 42, # AQ (vorher AN) "Chat Schaetzung Anzahl Mitarbeiter": 43, # AR
"Chat Konsistenzprüfung Mitarbeiterzahl": 43, # AR (vorher AO) "Chat Konsistenzprüfung Mitarbeiterzahl": 44, # AS
"Chat Begruendung Abweichung Mitarbeiterzahl": 44, # AS (vorher AP) "Chat Begruendung Abweichung Mitarbeiterzahl": 45, # AT
"Chat Einschätzung Anzahl Servicetechniker": 45, # AT (vorher AQ) "Chat Einschätzung Anzahl Servicetechniker": 46, # AU
"Chat Begruendung Abweichung Anzahl Servicetechniker": 46, # AU (vorher AR) "Chat Begruendung Abweichung Anzahl Servicetechniker": 47, # AV
"Chat Schätzung Umsatz": 47, # AV (vorher AS) "Chat Schätzung Umsatz": 48, # AW
"Chat Begruendung Abweichung Umsatz": 48, # AW (vorher AT) "Chat Begruendung Abweichung Umsatz": 49, # AX
# LinkedIn-Kontakte (AY-BB, alte AU-AX verschoben um +3) # LinkedIn-Kontakte (AZ-BC), alte AU-AX verschoben um +4
"Linked Serviceleiter gefunden": 49, # AX (vorher AU) "Linked Serviceleiter gefunden": 50, # AY
"Linked It-Leiter gefunden": 50, # AY (vorher AV) "Linked It-Leiter gefunden": 51, # AZ
"Linked Management gefunden": 51, # AZ (vorher AW) "Linked Management gefunden": 52, # BA
"Linked Disponent gefunden": 52, # BA (vorher AX) "Linked Disponent gefunden": 53, # BB
# Konsolidierte Werte, Timestamps, Plausi & System (BC-BO) # Timestamps, Konsolidierte Werte, ML & Plausi (BD-BP)
# Reihenfolge von "Contact Search Timestamp" nach Ihren letzten Wünschen "Contact Search Timestamp": 54, # BC
"Contact Search Timestamp": 53, # BB (war AY in der 64-Spalten-Version) "Finaler Umsatz (Wiki>CRM)": 55, # BD
"Finaler Umsatz (Wiki>CRM)": 54, # BC (war AZ in der 64-Spalten-Version) "Finaler Mitarbeiter (Wiki>CRM)": 56, # BE
"Finaler Mitarbeiter (Wiki>CRM)": 55, # BD (war BA in der 64-Spalten-Version) "Geschaetzter Techniker Bucket": 57, # BF
"Geschaetzter Techniker Bucket": 56, # BE (war BB in der 64-Spalten-Version) "Plausibilität Umsatz": 58, # BG
"Plausibilität Umsatz": 57, # BF (war BC in der 64-Spalten-Version) "Plausibilität Mitarbeiter": 59, # BH
"Plausibilität Mitarbeiter": 58, # BG (war BD in der 64-Spalten-Version) "Plausibilität Umsatz/MA Ratio": 60, # BI
"Plausibilität Umsatz/MA Ratio": 59, # BH (war BE in der 64-Spalten-Version) "Abweichung Umsatz CRM/Wiki": 61, # BJ
"Abweichung Umsatz CRM/Wiki": 60, # BI (war BF in der 64-Spalten-Version) "Abweichung MA CRM/Wiki": 62, # BK
"Abweichung MA CRM/Wiki": 61, # BJ (war BG in der 64-Spalten-Version) "Plausibilität Begründung": 63, # BL
"Plausibilität Begründung": 62, # BK (war BH in der 64-Spalten-Version) "Plausibilität Prüfdatum": 64, # BM
"Plausibilität Prüfdatum": 63, # BL (war BI in der 64-Spalten-Version) "Timestamp letzte Pruefung": 65, # BN (ChatGPT Eval TS)
"Timestamp letzte Pruefung": 64, # BM (ChatGPT Eval TS, war BJ) "Version": 66, # BO
"Version": 65, # BN (war BK) "Tokens": 67, # BP
"Tokens": 66, # BO (war BL)
} }
# --- Globale Variablen fuer Branch Mapping (werden von load_target_schema() befuellt) --- # --- Globale Variablen fuer Branch Mapping (werden von load_target_schema() befuellt) ---
@@ -815,13 +815,8 @@ def get_numeric_filter_value(value_str, is_umsatz=False):
raw_value_str_original = str(value_str).strip() raw_value_str_original = str(value_str).strip()
if raw_value_str_original.lower() in ['k.a.', 'n/a', '-']: # "0"-Strings und "k.A." für Filterlogik als 0 behandeln
return 0.0 if is_umsatz else 0 if raw_value_str_original.lower() in ['k.a.', 'n/a', '-', '0', '0.0', '0,0', '0.00', '0,000', '0.000']:
# "0" als expliziter String wird hier für Filterzwecke wie 0 behandelt.
# Die Plausi-Logik wird "0" (falls es in die finale Spalte geschrieben wird)
# dann über _get_numeric_value_for_plausi als "unbekannt" interpretieren.
if raw_value_str_original in ['0', '0.0', '0,0', '0.00', '0,000', '0.000']:
return 0.0 if is_umsatz else 0 return 0.0 if is_umsatz else 0
try: try:
@@ -835,24 +830,69 @@ def get_numeric_filter_value(value_str, is_umsatz=False):
# Tausendertrenner entfernen (Apostroph, Punkt wenn nicht Dezimal) # Tausendertrenner entfernen (Apostroph, Punkt wenn nicht Dezimal)
# Komma zu Punkt für Dezimal machen # Komma zu Punkt für Dezimal machen
num_extraction_str = processed_value.replace("'", "") # Apostrophe immer entfernen num_extraction_str = processed_value.replace("'", "")
if '.' in num_extraction_str and ',' in num_extraction_str: # Enthält Punkt und Komma # Fall 1: Enthält Punkt UND Komma (z.B. 1.234,56 oder 1,234.56)
if '.' in num_extraction_str and ',' in num_extraction_str:
if num_extraction_str.rfind('.') > num_extraction_str.rfind(','): # US-Stil: 1,234.56 -> Kommas entfernen if num_extraction_str.rfind('.') > num_extraction_str.rfind(','): # US-Stil: 1,234.56 -> Kommas entfernen
num_extraction_str = num_extraction_str.replace(',', '') num_extraction_str = num_extraction_str.replace(',', '')
else: # EU-Stil: 1.234,56 -> Punkte entfernen, Komma zu Punkt else: # EU-Stil: 1.234,56 -> Punkte entfernen, Komma zu Punkt
num_extraction_str = num_extraction_str.replace('.', '').replace(',', '.') num_extraction_str = num_extraction_str.replace('.', '').replace(',', '.')
elif ',' in num_extraction_str: # Nur Kommas als Dezimaltrenner: 1234,56 -> 1234.56 # Fall 2: Enthält nur Komma (z.B. 1234,56) -> Komma zu Punkt
elif ',' in num_extraction_str:
num_extraction_str = num_extraction_str.replace(',', '.') num_extraction_str = num_extraction_str.replace(',', '.')
elif '.' in num_extraction_str: # Nur Punkte # Fall 3: Enthält nur Punkt(e) (z.B. 4.380 oder 123.45 oder 1.234.567)
# Wenn der String klar ein Tausenderformat hat (z.B. 1.234 oder 1.234.567), Punkte entfernen elif '.' in num_extraction_str:
if re.fullmatch(r'^\d{1,3}(\.\d{3})+$', num_extraction_str): # Wenn der String klar ein Tausenderformat hat (Endet nicht mit .XX und hat Punkte)
if re.fullmatch(r'^\d{1,3}(\.\d{3})+$', num_extraction_str) and not re.search(r'\.\d{1,2}$', num_extraction_str):
num_extraction_str = num_extraction_str.replace('.', '') num_extraction_str = num_extraction_str.replace('.', '')
# Ansonsten ist ein einzelner Punkt ein Dezimalpunkt (z.B. "123.45") oder es ist ungültig # Sonst ist ein einzelner Punkt ein Dezimalpunkt (z.B. "123.45")
elif num_extraction_str.count('.') > 1: # Mehrere Punkte nicht im Tausenderformat sind ungültig # Bei mehreren Punkten, die nicht Tausenderformat sind (z.B. 1.2.3), wird es später als Fehler behandelt.
elif num_extraction_str.count('.') > 1:
logger.debug(f"get_numeric_filter_value: Mehrere Punkte in '{num_extraction_str}' (nicht als Tausenderformat erkannt).") logger.debug(f"get_numeric_filter_value: Mehrere Punkte in '{num_extraction_str}' (nicht als Tausenderformat erkannt).")
return 0.0 if is_umsatz else 0 return 0.0 if is_umsatz else 0
match = re.search(r'([\d.\-]+)', num_extraction_str)
if not match:
return 0.0 if is_umsatz else 0
num_str_for_float = match.group(1)
if not num_str_for_float or num_str_for_float == '.' or num_str_for_float == '-' or \
(num_str_for_float.count('.') > 1) or \
(num_str_for_float.count('-') > 1) or \
(num_str_for_float.count('-') == 1 and not num_str_for_float.startswith('-')):
return 0.0 if is_umsatz else 0
num_as_float = float(num_str_for_float) # Dies ist der Wert, wie er im String steht (sollte Mio. € sein für Umsatz, wenn keine Einheit)
scaled_num = num_as_float
original_lower = raw_value_str_original.lower()
if is_umsatz: # Zielwert soll in Millionen sein
if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower):
scaled_num = num_as_float * 1000.0 # z.B. "2 Mrd" -> num_as_float=2 -> 2000 Mio
elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower):
scaled_num = num_as_float / 1000.0 # z.B. "500 Tsd" -> num_as_float=500 -> 0.5 Mio
# Ansonsten wird angenommen, dass num_as_float bereits den Wert in Mio. € darstellt (z.B. "173" aus CRM)
else: # Mitarbeiter (absolute Zahl)
if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower):
scaled_num = num_as_float * 1000000000.0
elif re.search(r'\bmio\s*\b|\bmillionen\s*\b|\bmill[.]?\s*\b', original_lower):
scaled_num = num_as_float * 1000000.0
elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower):
scaled_num = num_as_float * 1000.0
return scaled_num if scaled_num > 0 else (0.0 if is_umsatz else 0)
except ValueError as e:
logger.debug(f"get_numeric_filter_value: ValueError '{e}' bei Konvertierung von '{num_str_for_float if 'num_str_for_float' in locals() else raw_value_str_original[:30]}...'")
return 0.0 if is_umsatz else 0
except Exception as e_general:
logger.error(f"Unerwarteter Fehler in get_numeric_filter_value für '{raw_value_str_original[:50]}...': {e_general}")
logger.debug(traceback.format_exc())
return 0.0 if is_umsatz else 0
# Extrahiere die Zahl (kann jetzt einen Dezimalpunkt enthalten) # Extrahiere die Zahl (kann jetzt einen Dezimalpunkt enthalten)
match = re.search(r'([\d.\-]+)', num_extraction_str) match = re.search(r'([\d.\-]+)', num_extraction_str)
if not match: if not match:
@@ -2518,10 +2558,10 @@ def alignment_demo(sheet):
logger.info("Starte Alignment Demo für das Hauptblatt...") logger.info("Starte Alignment Demo für das Hauptblatt...")
new_headers = [ new_headers = [
[ # Zeile 1: Spaltenname (67 Spalten) [ # Zeile 1: Spaltenname (68 Spalten)
"ReEval Flag", "CRM Name", "CRM Kurzform", "ReEval Flag", "CRM Name", "CRM Kurzform", "Parent Account Name",
"Parent Account Name", "CRM Website", "CRM Ort", "CRM Land", "CRM Beschreibung", "CRM Branche", "CRM Beschreibung Branche extern", "CRM Anzahl Techniker", "CRM Umsatz", "CRM Anzahl Mitarbeiter", "CRM Vorschlag Wiki URL", "CRM Website", "CRM Ort", "CRM Land", "CRM Beschreibung", "CRM Branche", "CRM Beschreibung Branche extern", "CRM Anzahl Techniker", "CRM Umsatz", "CRM Anzahl Mitarbeiter", "CRM Vorschlag Wiki URL",
"System Vorschlag Parent Account", "Parent Vorschlag Status", "System Vorschlag Parent Account", "Parent Vorschlag Status", "Parent Vorschlag Timestamp",
"Wiki URL", "Wiki Sitz Stadt", "Wiki Sitz Land", "Wiki Absatz", "Wiki Branche", "Wiki Umsatz", "Wiki Mitarbeiter", "Wiki Kategorien", "Wikipedia Timestamp", "Wiki Verif. Timestamp", "SerpAPI Wiki Search Timestamp", "Chat Wiki Konsistenzpruefung", "Chat Begründung Wiki Inkonsistenz", "Chat Vorschlag Wiki Artikel", "Begründung bei Abweichung", "Wiki URL", "Wiki Sitz Stadt", "Wiki Sitz Land", "Wiki Absatz", "Wiki Branche", "Wiki Umsatz", "Wiki Mitarbeiter", "Wiki Kategorien", "Wikipedia Timestamp", "Wiki Verif. Timestamp", "SerpAPI Wiki Search Timestamp", "Chat Wiki Konsistenzpruefung", "Chat Begründung Wiki Inkonsistenz", "Chat Vorschlag Wiki Artikel", "Begründung bei Abweichung",
"Website Rohtext", "Website Zusammenfassung", "Website Meta-Details", "Website Scrape Timestamp", "URL Prüfstatus", "Website Rohtext", "Website Zusammenfassung", "Website Meta-Details", "Website Scrape Timestamp", "URL Prüfstatus",
"Chat Vorschlag Branche", "Chat Branche Konfidenz", "Chat Konsistenz Branche", "Chat Begruendung Abweichung Branche", "Chat Prüfung FSM Relevanz", "Chat Begründung für FSM Relevanz", "Chat Schätzung Anzahl Mitarbeiter", "Chat Konsistenzprüfung Mitarbeiterzahl", "Chat Begründung Abweichung Mitarbeiterzahl", "Chat Einschätzung Anzahl Servicetechniker", "Chat Begründung Abweichung Anzahl Servicetechniker", "Chat Schätzung Umsatz", "Chat Begründung Abweichung Umsatz", "Chat Vorschlag Branche", "Chat Branche Konfidenz", "Chat Konsistenz Branche", "Chat Begruendung Abweichung Branche", "Chat Prüfung FSM Relevanz", "Chat Begründung für FSM Relevanz", "Chat Schätzung Anzahl Mitarbeiter", "Chat Konsistenzprüfung Mitarbeiterzahl", "Chat Begründung Abweichung Mitarbeiterzahl", "Chat Einschätzung Anzahl Servicetechniker", "Chat Begründung Abweichung Anzahl Servicetechniker", "Chat Schätzung Umsatz", "Chat Begründung Abweichung Umsatz",
@@ -2531,42 +2571,38 @@ def alignment_demo(sheet):
"Plausibilität Prüfdatum", "Plausibilität Prüfdatum",
"Timestamp letzte Prüfung", "Version", "Tokens" "Timestamp letzte Prüfung", "Version", "Tokens"
], ],
[ # Zeile 2: Quelle der Daten (67 Spalten) [ # Zeile 2: Quelle der Daten (68 Spalten)
"CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM/Manuell",
"CRM/Manuell", # D: Parent Account Name "CRM", "CRM", "CRM/Manuell", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM",
"CRM", "CRM", "CRM/Manuell", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", "CRM", # E-N (alt D-M) "System", "Manuell/System", "System",
"System", "Manuell/System", # O-P: System Vorschlag Parent, Status "Wikipediascraper/SerpAPI/ChatGPT/Manuell", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "System", "System", "System", "ChatGPT API", "ChatGPT API", "ChatGPT API", "System/Manuell",
"Wikipediascraper/SerpAPI/ChatGPT/Manuell", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "Wikipediascraper", "System", "System", "System", "ChatGPT API", "ChatGPT API", "ChatGPT API", "System/Manuell", # Q-AE "Web Scraper", "ChatGPT API", "Web Scraper", "System", "System/Web Scraper",
"Web Scraper", "ChatGPT API", "Web Scraper", "System", "System/Web Scraper", # AF-AJ "ChatGPT API", "ChatGPT API", "System/ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API", "System/ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API",
"ChatGPT API", "ChatGPT API", "System/ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API", "System/ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API", "ChatGPT API", # AK-AW "LinkedIn (via SerpApi)", "LinkedIn (via SerpApi)", "LinkedIn (via SerpApi)", "LinkedIn (via SerpApi)",
"LinkedIn (via SerpApi)", "LinkedIn (via SerpApi)", "LinkedIn (via SerpApi)", "LinkedIn (via SerpApi)", # AX-BA "System", "Skript (Wiki/CRM Logik)", "Skript (Wiki/CRM Logik)", "ML Modell / Skript",
"System", # BB: Contact Search Timestamp "Skript (Plausi-Check)", "Skript (Plausi-Check)", "Skript (Plausi-Check)", "Skript (Plausi-Check)", "Skript (Plausi-Check)", "Skript (Plausi-Check)",
"Skript (Wiki/CRM Logik)", "Skript (Wiki/CRM Logik)", "ML Modell / Skript", # BC-BE "System (Plausi-Check TS)",
"Skript (Plausi-Check)", "Skript (Plausi-Check)", "Skript (Plausi-Check)", "Skript (Plausi-Check)", "Skript (Plausi-Check)", "Skript (Plausi-Check)", # BF-BK "System", "System", "System"
"System (Plausi-Check TS)", # BL
"System", "System", "System" # BM-BO
], ],
[ # Zeile 3: Feldkategorie (67 Spalten) [ # Zeile 3: Feldkategorie (68 Spalten)
"Prozess", "Firmenname", "Firmenname", "Prozess", "Firmenname", "Firmenname", "Konzernstruktur",
"Konzernstruktur", # D "Website", "Ort", "Land", "Beschreibung (Text)", "Branche", "Branche", "Anzahl Servicetechniker", "Umsatz", "Anzahl Mitarbeiter", "Wikipedia Artikel URL",
"Website", "Ort", "Land", "Beschreibung (Text)", "Branche", "Branche", "Anzahl Servicetechniker", "Umsatz", "Anzahl Mitarbeiter", "Wikipedia Artikel URL", # E-N "Konzernstruktur (Vorschlag)", "Konzernstruktur (Status)", "Timestamp",
"Konzernstruktur (Vorschlag)", "Konzernstruktur (Status)", # O-P "Wikipedia Artikel URL", "Ort", "Land", "Beschreibung (Text)", "Branche", "Umsatz", "Anzahl Mitarbeiter", "Kategorien (Text)", "Timestamp", "Timestamp", "Timestamp", "Verifizierung Wiki-Artikel", "Begründung Verifizierung", "Wikipedia Artikel URL (Vorschlag)", "Begründung URL-Abweichung",
"Wikipedia Artikel URL", "Ort", "Land", "Beschreibung (Text)", "Branche", "Umsatz", "Anzahl Mitarbeiter", "Kategorien (Text)", "Timestamp", "Timestamp", "Timestamp", "Verifizierung Wiki-Artikel", "Begründung Verifizierung", "Wikipedia Artikel URL (Vorschlag)", "Begründung URL-Abweichung", # Q-AE "Website-Content", "Website-Content (Zusammenfassung)", "Website-Content (Meta)", "Timestamp", "Prozess-Status",
"Website-Content", "Website-Content (Zusammenfassung)", "Website-Content (Meta)", "Timestamp", "Prozess-Status", # AF-AJ "Branche (Vorschlag KI)", "Branche (Konfidenz KI)", "Branche (Konsistenz)", "Branche (Begründung KI)", "FSM Relevanz (KI)", "FSM Relevanz (Begründung KI)", "Anzahl Mitarbeiter (KI)", "Anzahl Mitarbeiter (Konsistenz KI)", "Anzahl Mitarbeiter (Begründung KI)", "Anzahl Servicetechniker (KI)", "Anzahl Servicetechniker (Begründung KI)", "Umsatz (KI)", "Umsatz (Begründung KI)",
"Branche (Vorschlag KI)", "Branche (Konfidenz KI)", "Branche (Konsistenz)", "Branche (Begründung KI)", "FSM Relevanz (KI)", "FSM Relevanz (Begründung KI)", "Anzahl Mitarbeiter (KI)", "Anzahl Mitarbeiter (Konsistenz KI)", "Anzahl Mitarbeiter (Begründung KI)", "Anzahl Servicetechniker (KI)", "Anzahl Servicetechniker (Begründung KI)", "Umsatz (KI)", "Umsatz (Begründung KI)", # AK-AW "Kontakte (Anzahl)", "Kontakte (Anzahl)", "Kontakte (Anzahl)", "Kontakte (Anzahl)",
"Kontakte (Anzahl)", "Kontakte (Anzahl)", "Kontakte (Anzahl)", "Kontakte (Anzahl)", # AX-BA "Timestamp", "Umsatz (Konsolidiert)", "Anzahl Mitarbeiter (Konsolidiert)", "Anzahl Servicetechniker (Bucket ML)",
"Timestamp", # BB "Plausibilität", "Plausibilität", "Plausibilität", "Datenqualitäts-Indikator", "Datenqualitäts-Indikator", "Plausibilität (Text)",
"Umsatz (Konsolidiert)", "Anzahl Mitarbeiter (Konsolidiert)", "Anzahl Servicetechniker (Bucket ML)", # BC-BE "Timestamp (Plausi)",
"Plausibilität", "Plausibilität", "Plausibilität", "Datenqualitäts-Indikator", "Datenqualitäts-Indikator", "Plausibilität (Text)", # BF-BK "Timestamp", "Skript Version", "API Tokens"
"Timestamp (Plausi)", # BL
"Timestamp", "Skript Version", "API Tokens" # BM-BO
], ],
[ # Zeile 4: Kurze Beschreibung (67 Spalten - JETZT AUSFÜHRLICH) [ # Zeile 4: Kurze Beschreibung (68 Spalten - JETZT AUSFÜHRLICH)
"Systemspalte, irrelevant für den Prompt. Wird genutzt um die manuelle Neuprüfung dieses Accounts durchzuführen.", #A ReEval Flag "Systemspalte, irrelevant für den Prompt. Wird genutzt um die manuelle Neuprüfung dieses Accounts durchzuführen.", #A ReEval Flag
"Enthält den Firmennamen nach bestem Gewissen. Firmennamen sind manchmal herausfordernd, insbesondere was unterschiedliche Schreibweisen, Firmierung, Tochter/Mutterfirmen etc. anbelangt. Zur besseren Trefferquote in der Wikipedia-Suche normalisieren wir den Firmennamen und entfernen sämtliche Firmenformen, wie z.B. AG, GmbH, SE etc.", #B CRM Name "Enthält den Firmennamen nach bestem Gewissen. Firmennamen sind manchmal herausfordernd, insbesondere was unterschiedliche Schreibweisen, Firmierung, Tochter/Mutterfirmen etc. anbelangt. Zur besseren Trefferquote in der Wikipedia-Suche normalisieren wir den Firmennamen und entfernen sämtliche Firmenformen, wie z.B. AG, GmbH, SE etc.", #B CRM Name
"Enthält eine manuell gepflegte (normalisierte) Kurzform des Firmennamens, wie auch ein Mensch die Firma nennen würde. Dies bedeutet insbesondere, dass die Firmenform wie z.B. GmbH oder AG aus dem Namen entfernt wird. Meist entspricht die Kurzform den ersten beiden Worten des Firmennamens. Manchmal sind auch Worte nötig, wenn die ersten beiden worte zu wenig Aussagekraft haben. Beispiele dafür sind beispielsweise Firmen wie 'Schmidt & Söhne', bei denen 'Schmidt &' wenig Sinn machen würde, oder 'Philip Morris Tabakwaren' - weil in diesem Fall 'Philip Morris' zu generisch wäre bzw. wenig eindeutig.", #C CRM Kurzform "Enthält eine manuell gepflegte (normalisierte) Kurzform des Firmennamens, wie auch ein Mensch die Firma nennen würde. Dies bedeutet insbesondere, dass die Firmenform wie z.B. GmbH oder AG aus dem Namen entfernt wird. Meist entspricht die Kurzform den ersten beiden Worten des Firmennamens. Manchmal sind auch Worte nötig, wenn die ersten beiden worte zu wenig Aussagekraft haben. Beispiele dafür sind beispielsweise Firmen wie 'Schmidt & Söhne', bei denen 'Schmidt &' wenig Sinn machen würde, oder 'Philip Morris Tabakwaren' - weil in diesem Fall 'Philip Morris' zu generisch wäre bzw. wenig eindeutig.", #C CRM Kurzform
"Name der direkten Muttergesellschaft / des Hauptkonzerns (falls zutreffend). Manuell gepflegt oder aus CRM. Beeinflusst Konsolidierung und Plausi-Checks.", #D Parent Account Name (NEU) "Name der direkten Muttergesellschaft / des Hauptkonzerns (falls zutreffend). Manuell gepflegt oder aus CRM. Beeinflusst Konsolidierung und Plausi-Checks.", #D Parent Account Name
"Von uns ermittelte Website des Unternehmens, sofern verfügbar. Kann durch 'website_lookup' oder 'check_urls' aktualisiert werden.", #E CRM Website "Von uns ermittelte Website des Unternehmens, sofern verfügbar.", #E CRM Website
"von uns ermittelter Ort des Unternehmens", #F CRM Ort "von uns ermittelter Ort des Unternehmens", #F CRM Ort
"Land des Unternehmenssitzes laut CRM oder manueller Recherche. Wichtig für regionale Analysen (z.B. DACH).", #G CRM Land "Land des Unternehmenssitzes laut CRM oder manueller Recherche. Wichtig für regionale Analysen (z.B. DACH).", #G CRM Land
"Kurze Beschreibung der Haupttätigkeit des Unternehmens aus dem CRM-System. Dient als Input für KI-Analysen.", #H CRM Beschreibung "Kurze Beschreibung der Haupttätigkeit des Unternehmens aus dem CRM-System. Dient als Input für KI-Analysen.", #H CRM Beschreibung
@@ -2575,62 +2611,63 @@ def alignment_demo(sheet):
"Bekannte Anzahl der Servicetechniker des Unternehmens (aus CRM oder Recherche). Dient als Ground Truth für ML.", #K CRM Anzahl Techniker "Bekannte Anzahl der Servicetechniker des Unternehmens (aus CRM oder Recherche). Dient als Ground Truth für ML.", #K CRM Anzahl Techniker
"Umsatz des Unternehmens in Millionen Euro laut CRM oder Recherche.", #L CRM Umsatz "Umsatz des Unternehmens in Millionen Euro laut CRM oder Recherche.", #L CRM Umsatz
"Anzahl der Mitarbeiter des Unternehmens laut CRM oder Recherche.", #M CRM Anzahl Mitarbeiter "Anzahl der Mitarbeiter des Unternehmens laut CRM oder Recherche.", #M CRM Anzahl Mitarbeiter
"Enthält aus einer alten Recherche Vorschläge für die Wikipedia URL zum Unternehmen. Dieser muss aber nicht stimmen. Sollte als Ausgangs- und Vergleichspunkt für die nachgelagerte Wikipedia-Suche dienen.", #N CRM Vorschlag Wiki URL "Enthält aus einer alten Recherche Vorschläge für die Wikipedia URL zum Unternehmen. Dieser muss aber nicht stimmen. Sollte als Ausgangs- und Vergleichspunkt für die nachgelagerte Wikipedia-Suche dienen. Der Wert soll mit den üblichen Methoden geprüft werden z.B. kommt die normalisierte Website vor, Ähnlichkeitsprüfung des Firmennamens mit dem Artikelnamen von Wikipedia etc.", #N CRM Vorschlag Wiki URL
"Vom System heuristisch ermittelter Vorschlag für den Parent Account (basierend auf Namensähnlichkeiten, Wiki-Infos etc.).", #O System Vorschlag Parent Account (NEU) "Vom System heuristisch ermittelter Vorschlag für den Parent Account (basierend auf Namensähnlichkeiten, Wiki-Infos etc.).", #O System Vorschlag Parent Account
"Status des System-Vorschlags für Parent Account (z.B. 'x' für akzeptiert, '-' für abgelehnt, '?' für unklar zur manuellen Prüfung).", #P Parent Vorschlag Status (NEU) "Status des System-Vorschlags für Parent Account (z.B. 'x' für akzeptiert, '-' für abgelehnt, '?' für unklar zur manuellen Prüfung).", #P Parent Vorschlag Status
"Finale Wikipedia URL des Unternehmens. Quelle: Wikipedia-Scraper (Suche/Extraktion), SerpAPI (Neusuche), ChatGPT (Vorschlag AD nach Prüfung), oder manuelle Eingabe.", #Q Wiki URL "Zeitstempel der letzten Generierung/Änderung des Parent-Vorschlags/-Status.", #Q Parent Vorschlag Timestamp
"Aus Wikipedia-Infobox extrahierte Stadt des Unternehmenssitzes.", #R Wiki Sitz Stadt "Wikipedia URL aus der Recherche im laufenden Prozess", #R Wiki URL (alt M)
"Aus Wikipedia-Infobox extrahiertes Land des Unternehmenssitzes.", #S Wiki Sitz Land "Aus Wikipedia-Infobox extrahierte Stadt des Unternehmenssitzes.", #S Wiki Sitz Stadt (neu)
"Erster aussagekräftiger Absatz des Wikipedia-Artikels (Q).", #T Wiki Absatz "Aus Wikipedia-Infobox extrahiertes Land des Unternehmenssitzes.", #T Wiki Sitz Land (neu)
"Aus der Wikipedia-Infobox extrahierte Branche(n).", #U Wiki Branche "Erster Absatz des Wikipedia-Artikels", #U Wiki Absatz (alt N)
"Aus der Wikipedia-Infobox extrahierter Umsatz (normalisiert in Mio. €).", #V Wiki Umsatz "Branche aus Wikipedia-Artikel soweit verfügbar", #V Wiki Branche (alt O)
"Aus der Wikipedia-Infobox extrahierte Mitarbeiterzahl (normalisiert).", #W Wiki Mitarbeiter "Umsatz aus Wikipediaartikel soweit verfügbar.", #W Wiki Umsatz (alt P)
"Komma-separierte Liste der Kategorien, denen der Artikel in Wikipedia zugewiesen wurde. Hier ist auch häufig eine Branche enthalten, häufig auch noch weitere Informationen etwa zur Gründung, ob sie etwa im DAX gelistet ist etc. Guter Anhaltspunkt zur Differenzierung von Unternehmenseinträgen und Wikipedia-Seiten, die kein Unternehmen beschreiben und fälschlicherweise zugewiesen wurden. Bei jeder Unternehmensseite MUSS das Wort unternehmen in irgendeiner Art und Weise vorkommen. NEGATIVSIGNAL: EHEMALIGES UNTERNEHMEN -> Weist darauf hin, dass das Unternehmen nicht mehr besteht.", #X Wiki Kategorien "Anzahl Mitarbeiter laut Wikipedia sofern verfügbar.", #X Wiki Mitarbeiter (alt Q)
"Zeitstempel der letzten Wikipedia-Suche und Datenextraktion für diese Zeile (für Spalten Q-X).", #Y Wikipedia Timestamp "Komma-separierte Liste der Kategorien, denen der Artikel in Wikipedia zugewiesen wurde. Hier ist auch häufig eine Branche enthalten, häufig auch noch weitere Informationen etwa zur Gründung, ob sie etwa im DAX gelistet ist etc. Guter Anhaltspunkt zur Differenzierung von Unternehmenseinträgen und Wikipedia-Seiten, die kein Unternehmen beschreiben und fälschlicherweise zugewiesen wurden. \nBei jeder Unternehmensseite MUSS das Wort unternehmen in irgendeiner Art und Weise vorkommen.\nNEGATIVSIGNAL: EHEMALIGES UNTERNEHMEN -> Weist darauf hin, dass das Unternehmen nicht mehr besteht.", #Y Wiki Kategorien (alt R)
"Zeitstempel der letzten Wikipedia-Artikel-Verifizierung durch ChatGPT (Ergebnis in Spalten AB-AD).", #Z Wiki Verif. Timestamp "Zeitstempel der letzten Wikipedia-Suche und Datenextraktion für diese Zeile (jetzt für Spalten R-Y).", #Z Wikipedia Timestamp (alt AN)
"Zeitstempel des letzten Versuchs, eine fehlende Wiki-URL (Q) über SerpAPI zu suchen.", #AA SerpAPI Wiki Search Timestamp "Zeitstempel der letzten Wikipedia-Artikel-Verifizierung durch ChatGPT (Ergebnis in Spalten AC-AE).", #AA Wiki Verif. Timestamp (alt AX)
"Ergebnis der ChatGPT-Prüfung, ob der Wiki-Artikel (Q) zum Unternehmen passt. ('OK', 'X', '?', 'FEHLER', etc.)", #AB Chat Wiki Konsistenzpruefung "Zeitstempel des letzten Versuchs, eine fehlende Wiki-URL (R) über SerpAPI zu suchen.", #AB SerpAPI Wiki Search Timestamp (alt AY)
"Von ChatGPT generierte Begründung, falls der Wiki-Artikel (Q) als inkonsistent zum Unternehmen bewertet wurde.", #AC Chat Begründung Wiki Inkonsistenz "\"OK\" wird bei Firmen eingetragen, wo Firma und Wikipedia-Eintrag zusammenpassen. \"X\" wird bei Firmen eingetragen, wo Firma und Wikipedia-Eintrag nicht zusammenpassen.", #AC Chat Wiki Konsistenzpruefung (alt S)
"Von ChatGPT vorgeschlagene alternative Wikipedia-URL, falls der Artikel in Q als unpassend bewertet wurde.", #AD Chat Vorschlag Wiki Artikel "Begründung welche Inkonsistenz aus den Daten hervorgeht.", #AD Chat Begründung Wiki Inkonsistenz (alt T)
"Wird derzeit primär geleert. Ursprünglich für Begründung bei Abweichung CRM Vorschlag Wiki URL (N alt) vs. gefundener Wiki-URL (Q).", #AE Begründung bei Abweichung "URL des durch ChatGPT recherchierten Wikipedia-Artikels", #AE Chat Vorschlag Wiki Artikel (alt U)
"Roh extrahierter Textinhalt der Website. Basis für Zusammenfassung. Kann auch Fehlermeldungen oder Marker wie 'URL_CHECK_NEEDED' enthalten.", #AF Website Rohtext "XXX derzeit nicht verwendet, wird vermutlich gelöscht xxx", #AF Begründung bei Abweichung (alt V)
"KI-generierte Zusammenfassung des Website-Rohtextes (AF).", #AG Website Zusammenfassung "Roh extrahierter Textinhalt der Firmenwebsite. Basis für Zusammenfassung und KI-Analysen.", #AG Website Rohtext (neu)
"Extrahierte Meta-Daten der Website: Title, Meta-Description, H1-H3 Überschriften etc.", #AH Website Meta-Details "KI-generierte Zusammenfassung des Website-Rohtextes (AG). Input für Branchenbewertung.", #AH Website Zusammenfassung (neu)
"Zeitstempel des letzten Website-Scraping/Summarization-Versuchs (für AF, AG, AH).", #AI Website Scrape Timestamp "Extrahierte Meta-Daten der Website (Title, Description, H-Tags). Für schnelle Analyse & Validierung.", #AI Website Meta-Details (neu)
"Status der URL-Prüfung (z.B. 'URL_CHECK_NEEDED', 'URL_OK', 'FEHLER_SSL'). Wird von 'check_urls' Modus gesetzt/genutzt.", #AJ URL Prüfstatus "Zeitstempel des letzten Website-Scraping/Summarization-Versuchs (für AG-AI).", #AJ Website Scrape Timestamp (neu)
"Branchenvorschlag von ChatGPT basierend auf allen verfügbaren Informationen.", #AK Chat Vorschlag Branche "Status der URL-Prüfung (z.B. 'URL_CHECK_NEEDED', 'URL_OK', 'FEHLER_SSL'). Wird von 'check_urls' Modus gesetzt/genutzt.", #AK URL Prüfstatus (neu)
"Konfidenz des ChatGPT-Branchenvorschlags (AK), z.B. Hoch/Mittel/Niedrig.", #AL Chat Branche Konfidenz "Durch ChatGPT ermittelte Branche des Unternehmens", #AL Chat Vorschlag Branche (alt W)
"Konsistenzprüfung: 'ok', wenn ChatGPT-Vorschlag (AK) mit CRM-Branche (I) übereinstimmt (unter Berücksichtigung von Parent-Logik).", #AM Chat Konsistenz Branche "Konfidenz des ChatGPT-Branchenvorschlags (AL), z.B. Hoch/Mittel/Niedrig.", #AM Chat Branche Konfidenz (neu)
"Von ChatGPT generierte Begründung für den Branchenvorschlag (AK) oder bei Abweichung.", #AN Chat Begruendung Abweichung Branche "\"OK\" wird bei Firmen eingetragen, wo die Einschätzung zur Branche mit der CRM Branche übereinstimmt. \"X\" wird ausgegeben, wenn die Einschätzungen nicht zusammenpassen.", #AN Chat Konsistenz Branche (alt X)
"Bewertung der FSM-Relevanz durch ChatGPT. ('OK' für relevant, 'X' für irrelevant) (Platzhalter)", #AO Chat Prüfung FSM Relevanz "Begründung für Abweichung der Branche von CRM Branche", #AO Chat Begruendung Abweichung Branche (alt Y)
"Von ChatGPT generierte Begründung für die Einschätzung der FSM-Relevanz. (Platzhalter)", #AP Chat Begründung für FSM Relevanz "\"OK\" wird bei Firmen eingetragen, für die FSM relevant ist, \"X\" für Firmen, für die FSM irrelevant ist.", #AP Chat Prüfung FSM Relevanz (alt Z)
"Von ChatGPT geschätzte Anzahl der Mitarbeiter. (Platzhalter)", #AQ Chat Schaetzung Anzahl Mitarbeiter "Begründung für die Beurteilung in Spalte Chat Begründung für FSM Relevanz", #AQ Chat Begründung für FSM Relevanz (alt AA)
"Konsistenzprüfung der von ChatGPT geschätzten Mitarbeiterzahl (AQ). (Platzhalter)", #AR Chat Konsistenzprüfung Mitarbeiterzahl "Anzahl der Mitarbeiter durch ChatGPT geschätzt.", #AR Chat Schaetzung Anzahl Mitarbeiter (alt AB)
"Von ChatGPT generierte Begründung bei signifikanter Abweichung der geschätzten Mitarbeiterzahl. (Platzhalter)", #AS Chat Begründung Abweichung Mitarbeiterzahl "\"OK\" wird bei Firmen eingetragen, für die Anzahl der Mitarbeiter grob mit der aus Spalte CRM Anzahl Mitarbeiter bzw. der Spalte Wiki Mitarbeiter übereinstimmt. \"X\" für Firmen, bei denen dies nicht zutrifft.", #AS Chat Konsistenzprüfung Mitarbeiterzahl (alt AC)
"Anzahl der Servicetechniker geschätzt durch Chat GPT (z.B. 0, <50, >100). (Platzhalter)", #AT Chat Einschätzung Anzahl Servicetechniker "Begründung für Abweichende Mitarbeiterzahl", #AT Chat Begründung Abweichung Mitarbeiterzahl (alt AD)
"Begründung für Abweichungen der ChatGPT-Technikerschätzung zur CRM-Angabe. (Platzhalter)", #AU Chat Begründung Abweichung Anzahl Servicetechniker "Anzahl der Servicetechniker geschätzt durch Chat GPT", #AU Chat Einschätzung Anzahl Servicetechniker (alt AE)
"Umsatz durch ChatGPT geschätzt. (Platzhalter)", #AV Chat Schätzung Umsatz "Begründung für Abweichungen zur Anzahl der Techniker", #AV Chat Begründung Abweichung Anzahl Servicetechniker (alt AF)
"Begründung für Abweichungen des ChatGPT-Umsatzes zu CRM/Wiki. (Platzhalter)", #AW Chat Begründung Abweichung Umsatz "Umsatz durch ChatGTP geschätzt", #AW Chat Schätzung Umsatz (alt AG)
"Anzahl der Kontakte die zur Suche 'Serviceleiter', 'Leiter Service', 'technischer Leiter', 'Service Manager', 'Leiter Kundendienst' gefunden wurden.", #AX Linked Serviceleiter gefunden "Begründung für Abweichungen zum Umsatz", #AX Chat Begründung Abweichung Umsatz (alt AH)
"Anzahl der Kontakte die zur Suche 'Leiter IT', 'IT Leiter', 'Head of IT', 'IT-Leiter', 'CIO' gefunden wurden.", #AY Linked It-Leiter gefunden "Anzahl der Kontakte die zur Suche 'Serviceleiter', 'Leiter Service', 'technischer Leiter', 'Service Manager', 'Leiter Kundendienst' gefunden wurden", #AY Linked Serviceleiter gefunden (alt AI)
"Anzahl der Kontakte die zur Suche 'Geschäftsführer', 'Geschäftsführung', 'GF', 'CEO', 'Geschäftsführerin', 'Managing Director', 'Geschäftsführender Gesellschafter' gefunden wurden.", #AZ Linked Management gefunden "Anzahl der Kontakte die zur Suche 'Leiter IT', 'IT Leiter', 'Head of IT', 'IT-Leiter', 'CIO' gefunden wurden", #AZ Linked It-Leiter gefunden (alt AJ)
"Anzahl der Kontakte die zur Suche 'Disponent', 'Einsatzplaner' gefunden wurden.", #BA Linked Disponent gefunden "Anzahl der Kontakte die zur Suche 'Geschäftsführer', 'Geschäftsführung', 'GF', 'CEO', 'Geschäftsführerin', 'Managing Director', 'Geschäftsführender Gesellschafter' gefunden wurden", #BA Linked Management gefunden (alt AK)
"Timestamp des Zeitpunkts zu dem die Kontaktsuche via SerpAPI für diese Zeile fertiggestellt wurde.", #BB Contact Search Timestamp "Anzahl der Kontakte die zur Suche 'Disponent', 'Einsatzplaner' gefunden wurden", #BB Linked Disponent gefunden (alt AL)
"Konsolidierter Umsatzwert in Millionen Euro. Priorisiert Wiki (V) > CRM (L). Berücksichtigt Parent-Account (D).", #BC Finaler Umsatz (Wiki>CRM) "Timestamp des Zeitpunkts zu dem die Kontaktsuche fertiggestellt wurde", #BC Contact Search Timestamp (alt AM)
"Konsolidierte Mitarbeiterzahl (absolut). Priorisiert Wiki (W) > CRM (M). Berücksichtigt Parent-Account (D).", #BD Finaler Mitarbeiter (Wiki>CRM) "Konsolidierter Umsatzwert in Millionen Euro. Priorisiert Wiki (W) > CRM (L). Berücksichtigt Parent-Account (D).", #BD Finaler Umsatz (Wiki>CRM)
"Ergebnis der Schätzung durch das trainierte Machine-Learning-Modell (Techniker-Bucket).", #BE Geschaetzter Techniker Bucket "Konsolidierte Mitarbeiterzahl (absolut). Priorisiert Wiki (X) > CRM (M). Berücksichtigt Parent-Account (D).", #BE Finaler Mitarbeiter (Wiki>CRM)
"Plausibilitätsstatus für den finalen Umsatzwert (BC) (z.B. OK, WARNUNG_HOCH, FEHLER_FORMAT).", #BF Plausibilität Umsatz "Ergebnis der Schätzung durch das trainierte Machine-Learning-Modell (Techniker-Bucket).", #BF Geschaetzter Techniker Bucket
"Plausibilitätsstatus für die finale Mitarbeiterzahl (BD) (z.B. OK, WARNUNG_NIEDRIG).", #BG Plausibilität Mitarbeiter "Plausibilitätsstatus für den finalen Umsatzwert (BD) (z.B. OK, WARNUNG_HOCH, FEHLER_FORMAT).", #BG Plausibilität Umsatz
"Plausibilitätsstatus für die Umsatz-pro-Mitarbeiter-Ratio (BC/BD).", #BH Plausibilität Umsatz/MA Ratio "Plausibilitätsstatus für die finale Mitarbeiterzahl (BE) (z.B. OK, WARNUNG_NIEDRIG).", #BH Plausibilität Mitarbeiter
"Indikator für Abweichung (>30%) zwischen CRM-Umsatz (L) und Wiki-Umsatz (V). Berücksichtigt Parent-Logik.", #BI Abweichung Umsatz CRM/Wiki "Plausibilitätsstatus für die Umsatz-pro-Mitarbeiter-Ratio (BD/BE).", #BI Plausibilität Umsatz/MA Ratio
"Indikator für Abweichung (>30%) zwischen CRM-MA (M) und Wiki-MA (W). Berücksichtigt Parent-Logik.", #BJ Abweichung MA CRM/Wiki "Indikator für Abweichung (>30%) zwischen CRM-Umsatz (L) und Wiki-Umsatz (W). Berücksichtigt Parent-Logik.", #BJ Abweichung Umsatz CRM/Wiki
"Gesammelte Begründungen für Plausibilitätswarnungen oder -fehler aus den Spalten BF-BJ.", #BK Plausibilität Begründung "Indikator für Abweichung (>30%) zwischen CRM-MA (M) und Wiki-MA (X). Berücksichtigt Parent-Logik.", #BK Abweichung MA CRM/Wiki
"Zeitstempel des letzten Laufs der Plausibilitäts-Checks für diese Zeile.", #BL Plausibilität Prüfdatum "Gesammelte Begründungen für Plausibilitätswarnungen oder -fehler aus den Spalten BG-BK.", #BL Plausibilität Begründung
"Timestamp des Zeitpunkts zu dem die übergreifende Validierung/Schätzung durch ChatGPT (AK-AW) durchgeführt wurde.", #BM Timestamp letzte Prüfung "Zeitstempel des letzten Laufs der Plausibilitäts-Checks für diese Zeile.", #BM Plausibilität Prüfdatum
"Systemspalte zur Ausgabe der Skriptversion die das Ergebnis generiert hat.", #BN Version "Timestamp des Zeitpunkts zu dem die Validierung durch ChatGPT durchgeführt wurde", #BN Timestamp letzte Prüfung (alt AO)
"Zeigt an, wie viele Tokens für die OpenAI API-Requests dieser Zeile ungefähr benötigt wurden." #BO Tokens "Systemspalte zur Ausgabe der Skriptversion die das Ergebnis generiert hat", #BO Version (alt AP)
"Zeigt an, wie viele Tokens für den Request benötigt wurden" #BP Tokens (alt AQ)
], ],
[ # Zeile 5: Aufgabe / Funktion (67 Spalten - JETZT AUSFÜHRLICH) [ # Zeile 5: Aufgabe / Funktion (68 Spalten - JETZT AUSFÜHRLICH)
"Datenquelle/Prozesssteuerung: 'x' markiert Zeile für Re-Evaluation im Modus 'reeval'.", #A "Datenquelle/Prozesssteuerung: 'x' markiert Zeile für Re-Evaluation im Modus 'reeval'.", #A
"Datenquelle: Firmenname aus CRM.", #B "Datenquelle: Firmenname aus CRM.", #B
"Datenquelle: Manuell gepflegte Kurzform des Firmennamens, primär für API-Suchen (LinkedIn, SerpAPI) und Matching genutzt.", #C "Datenquelle: Manuell gepflegte Kurzform des Firmennamens, primär für API-Suchen (LinkedIn, SerpAPI) und Matching genutzt.", #C
@@ -2646,65 +2683,66 @@ def alignment_demo(sheet):
"Datenquelle: Mitarbeiterzahl aus CRM (absolut). Input für Konsolidierung, Plausi-Checks und ML.", #M "Datenquelle: Mitarbeiterzahl aus CRM (absolut). Input für Konsolidierung, Plausi-Checks und ML.", #M
"Datenquelle: Alte/vorgeschlagene Wiki-URL aus CRM. Dient als initialer Input oder Vergleichswert für den Wiki-Prozess.", #N "Datenquelle: Alte/vorgeschlagene Wiki-URL aus CRM. Dient als initialer Input oder Vergleichswert für den Wiki-Prozess.", #N
"Ziel/System: Vom Skript generierter Vorschlag für die Muttergesellschaft (basierend auf Heuristiken), zur manuellen Prüfung.", #O "Ziel/System: Vom Skript generierter Vorschlag für die Muttergesellschaft (basierend auf Heuristiken), zur manuellen Prüfung.", #O
"Prozesssteuerung/Manuell: Bestätigung ('x'), Ablehnung ('-') oder Unklarheit ('?') des System-Vorschlags für den Parent Account. Kann Übernahme in Spalte D steuern.", #P "Prozesssteuerung/Manuell: Bestätigung ('x'), Ablehnung ('-') oder Unklarheit ('?') des System-Vorschlags. Kann Übernahme in Spalte D steuern.", #P
"Ziel/Quelle: Finale, als relevant erachtete Wikipedia-URL. Quelle: Wikipedia-Scraper, SerpAPI, ChatGPT-Vorschlag (AD), oder manuelle Eingabe.", #Q "System: Zeitstempel für die Bearbeitung von Spalte O und P (Parent Vorschlag).", #Q
"Quelle: Aus Wikipedia-Infobox extrahierte Stadt des Unternehmenssitzes. Ziel: Geografische Analyse.", #R "Wird durch Wikipedia Scraper bereitgestellt", #R Wiki URL (alt M)
"Quelle: Aus Wikipedia-Infobox extrahiertes Land des Unternehmenssitzes. Ziel: Geografische Analyse (DACH).", #S "Quelle: Aus Wikipedia-Infobox extrahierte Stadt des Unternehmenssitzes. Ziel: Geografische Analyse.", #S Wiki Sitz Stadt
"Quelle: Erster aussagekräftiger Absatz des Wikipedia-Artikels (Q). Input für KI-Analysen (Wiki-Verifizierung, Branchen).", #T "Quelle: Aus Wikipedia-Infobox extrahiertes Land des Unternehmenssitzes. Ziel: Geografische Analyse (DACH).", #T Wiki Sitz Land
"Quelle: Aus der Wikipedia-Infobox extrahierte Branche(n). Input für KI-Branchenbewertung.", #U "Wird zunächst nicht verwendet, kann möglicherweise in einem späteren Schritt z.B. zum Vergleich mit der CRM Beschreibung genutzt werden, um auf Textähnlichkeit / Übereinstimmende Worte geprüft zu werden und damit eine Validierung des Artikels zum Account sicherzustellen.", #U Wiki Absatz (alt N)
"Quelle: Aus der Wikipedia-Infobox extrahierter Umsatz (in Mio. €). Input für Konsolidierung und Plausi-Checks.", #V "Wird u.a. zur finalen Ermittlung der Branche im Ziel-Branchenschema genutzt und mit der CRM Branche bzw. CRM Beschreibung Branche Extern verglichen. Stimmen alle drei Einstufungen grob überein, bestärkt dies die urpsrüngliche Einstufung. Laufen diese Branchen weit auseinander, soll, sofern der Wikipedia-Artikel verifiziert ist, die Branche von Wikipedia als zuverlässigste Quelle bewertet werden, danach folgen die CRM Beschreibung Branche Extern und die CRM Branche an dritter Stelle.", #V Wiki Branche (alt O)
"Quelle: Aus der Wikipedia-Infobox extrahierte Mitarbeiterzahl (absolut). Input für Konsolidierung und Plausi-Checks.", #W "Wird u.a. mit CRM Umsatz zur Validierung des Unternehmens verglichen bzw. zur Bewertung der größe / Einschätzung Anzahl der Techniker bzw. Bewertung der Relevanz für FSM genutzt.", #W Wiki Umsatz (alt P)
"Quelle: Wikipedia-Kategorien des Artikels (Q). Wichtiger Input für KI-Analysen (Wiki-Verifizierung, Branchenbewertung, Parent-Vorschlag).", #X "Wird u.a. mit CRM Anzahl Mitarbeiter zur Validierung des Unternehmens verglichen bzw. zur Bewertung der größe / Einschätzung Anzahl der Techniker bzw. Bewertung der Relevanz für FSM genutzt.", #X Wiki Mitarbeiter (alt Q)
"System: Timestamp der letzten Wikipedia-Suche/Datenextraktion (für Spalten Q-X). Steuert Wiederholung.", #Y "Wenn Wiki Branche nicht gepflegt ist, wird dieses Feld zur finalen Ermittlung der Branche im Ziel-Branchenschema genutzt und mit der CRM Branche bzw. CRM Beschreibung Branche Extern verglichen. Dabei muss aus dem Feld natürlich die Branche ermittelt werden, die auch hier nicht zwingend eingetragen ist. Stimmen alle drei Einstufungen grob überein, bestärkt dies die urpsrüngliche Einstufung. Laufen diese Branchen weit auseinander, soll, sofern der Wikipedia-Artikel verifiziert ist, die Branche von Wikipedia als zuverlässigste Quelle bewertet werden, danach folgen die CRM Beschreibung Branche Extern und die CRM Branche an dritter Stelle.", #Y Wiki Kategorien (alt R)
"System: Timestamp der letzten ChatGPT-Verifizierung des Wiki-Artikels (Q). Steuert Wiederholung der Verifizierung.", #Z "System: Timestamp der letzten Wikipedia-Suche/Datenextraktion (für Spalten R-Y). Steuert Wiederholung.", #Z Wikipedia Timestamp
"System: Timestamp des letzten Versuchs, eine fehlende Wiki-URL (Q) via SerpAPI zu suchen. Steuert Wiederholung.", #AA "System: Timestamp der letzten ChatGPT-Verifizierung des Wiki-Artikels (R). Steuert Wiederholung.", #AA Wiki Verif. Timestamp
"Ziel: Ergebnis der ChatGPT-Konsistenzprüfung für Wiki-Artikel (Q). Status '?' triggert erneute Prüfung.", #AB "System: Timestamp des letzten Versuchs, eine fehlende Wiki-URL (R) via SerpAPI zu suchen. Steuert Wiederholung.", #AB SerpAPI Wiki Search Timestamp
"Ziel: Begründung von ChatGPT, falls Wiki-Artikel (Q) als inkonsistent bewertet wurde.", #AC "\"Es soll durch ChatGPT geprüft werden, ob anhand der vorliegenden Daten bestätigt werden kann, dass der Wikipedia-Eintrag sicher das Unternehmen beschreibt. Hierzu können sämtliche Daten miteinander verglichen werden. u.a. stimmt die Website überein, ist der Umsatz in einer ähnlichen größenordnung, passt die mitarbeiterzahl etc. Bei allen daten darf eine gewisse Unschärfe zum Vergleich (+-30%) gelten.\n Es muss teilweise etwas großzügig bewertet werden, insbesondere bei Konzernstrukturen, wo oft Töchter keinen eigenen Wikipedia-Artikel haben, aber quasi am Umsatz der Mutter hängen und damit prinzipiell die gleichen Daten zur Bewertung herangezogen werden können wie für die Mutter.\nAbweichungen sollen in der Spalte Chat Begründung Wiki Inkonsistenz begründet werden.\"", #AC Chat Wiki Konsistenzpruefung (alt S)
"Ziel: Von ChatGPT vorgeschlagene alternative Wikipedia-URL. Wird von Modus 'update_wiki_suggestions' verarbeitet.", #AD "\"Liegt eine Inkonsistenz zwischen gefundenem Wikipedia-Artikel und dem Unternehmen vor, soll dies hier kurz begründet werden.\nWurde der Artikel als unpassend identifiziert, soll Chat GPT selbst einen passenden wikipedia-Artikel zum Unternehmen finden und diesen in Spalte Chat Vorschlag Wiki Artikel ausgeben.\"", #AD Chat Begründung Wiki Inkonsistenz (alt T)
"Ziel/Info: Begründung für manuelle oder systemische Abweichungen bei der finalen Wiki-URL-Wahl.", #AE "\"Sollte durch die Wikipedia-Suche kein Artikel gefunden werden, oder der Artikel von Chat GPT als nicht zum Unternehmen passend identifiziert werden, soll Chat GPT eigenständig nach einem Wikipedia-Artikel recherchieren. Auch dieser soll die gleichen Stufen zur Qualitätsprüfung durchlaufen wie bei der Wikipedia-Suche üblich.\nDer von ChatGPT gefundene Artikel muss vom als falsch bewerteten Artikel abweichen. Wurde kein passender Artikel gefunden, soll 'kein Artikel verfügbar' ausgegeben werden\"", #AE Chat Vorschlag Wiki Artikel (alt U)
"Ziel: Rohtext der Website (AF). Input für Zusammenfassung (AG).", #AF "XXX derzeit nicht verwendet, wird vermutlich gelöscht xxx", #AF Begründung bei Abweichung (alt V)
"Ziel: KI-generierte Zusammenfassung des Website-Rohtextes (AF). Input für Branchenbewertung.", #AG "Ziel: Rohtext der Website. Input für Zusammenfassung (AH).", #AG Website Rohtext
"Ziel: Strukturierte Meta-Daten der Website (Title, Description, H-Tags). Für schnelle Analyse & Validierung.", #AH "Ziel: KI-generierte Zusammenfassung des Website-Rohtextes (AG). Input für Branchenbewertung.", #AH Website Zusammenfassung
"System: Timestamp des letzten Website-Scraping/Summarization-Versuchs (für AF-AH). Steuert Wiederholung.", #AI "Ziel: Strukturierte Meta-Daten der Website. Für schnelle Analyse & Validierung.", #AI Website Meta-Details
"System/Ziel: Status der URL-Prüfung. 'URL_CHECK_NEEDED' triggert Neusuche im Modus 'check_urls'.", #AJ "System: Timestamp des letzten Website-Scraping/Summarization-Versuchs (für AG-AI).", #AJ Website Scrape Timestamp
"Ziel: Von ChatGPT final vorgeschlagene Branche gemäß Zielschema. Hauptziel der Branchenklassifizierung.", #AK "System/Ziel: Status der URL-Prüfung. 'URL_CHECK_NEEDED' triggert Neusuche.", #AK URL Prüfstatus
"Ziel: Von ChatGPT eingeschätzte Konfidenz (Hoch/Mittel/Niedrig) für den Branchenvorschlag (AK).", #AL "\"Chat GPT soll anhand der vorliegenden Informationen prüfen, welcher Branche des Ziel-Branchenschemas das Unternehmen am ehesten zugeordnet werden kann. Das Ziel-Branchenschema darf nicht verändert oder erweitert werden, sondern die Vorschläge müssen genau dem Ziel-Branchenschema entsprechen.\nDie Bewertung soll möglichst ohne Abgleich mit der CRM Branche bewertet werden, da diese falsch sein könnte. ChatGPT soll auch die Firmenwebsite und ähnliche Quellen zur Bewertung des Unernehmens heranziehen.\"", #AL Chat Vorschlag Branche (alt W)
"Ziel: Ergebnis des Abgleichs ('ok'/'X') zwischen KI-Branchenvorschlag (AK) und CRM-Branche (I).", #AM "Ziel: Von ChatGPT eingeschätzte Konfidenz (Hoch/Mittel/Niedrig) für den Branchenvorschlag (AL).", #AM Chat Branche Konfidenz
"Ziel: Von ChatGPT generierte Begründung für den Branchenvorschlag (AK) und/oder die Konsistenz (AM).", #AN "Die durch uns festgelegte Branche in Spalte CRM Branche soll mit der von ChatGPT ermittelten Branche in Spalte Chat Vorschlag Branche verglichen werden.", #AN Chat Konsistenz Branche (alt X)
"Ziel: Ergebnis der FSM-Relevanzprüfung durch ChatGPT. (Platzhalter)", #AO "Weicht die Branche von unserer Eisntufung in Spalte CRM Branche ab, soll ChatGPT die Abweichung kurz begründen.", #AO Chat Begruendung Abweichung Branche (alt Y)
"Ziel: Begründung von ChatGPT für die FSM-Relevanz. (Platzhalter)", #AP "Chat GPT soll anhand der vorliegenden Informationen sowie eigener Recherche prüfen, ob für das Unternehmen der Einsatz einer Fieldservice Management Lösung vorteilhaft ist. Sprich hat das Unternehmen mutmaßlich einen technischen Außendienst bzw. Disponenten die mit der Planung mobiler Resourcen beschäftigt sind.", #AP Chat Prüfung FSM Relevanz (alt Z)
"Ziel: Von ChatGPT geschätzte Mitarbeiterzahl. (Platzhalter)", #AQ "Die in Spalte Chat Begründung für FSM Relevanz soll begründet werden.", #AQ Chat Begründung für FSM Relevanz (alt AA)
"Ziel: Konsistenzprüfung der KI-Mitarbeiterschätzung. (Platzhalter)", #AR "Nur wenn kein Wikipedia-Eintrag vorliegt (Wiki URL = \"\") soll ChatGPT auf Basis öffentlich verfügbarer Informationen z.B. durch Auswertung der Firmen-Website herausfinden oder schätzen, wieviele Mitarbeiter das Unternehmen hat. Wenn keine Schätzung möglich ist, soll \"keine Schätzung möglich\" ausgegeben werden.", #AR Chat Schaetzung Anzahl Mitarbeiter (alt AB)
"Ziel: Begründung von ChatGPT bei Abweichung der Mitarbeiterschätzung. (Platzhalter)", #AS "Entspricht die durch ChatGPT ermittelte Mitarbeiterzahl der von uns ermittelten (Spalte CRM Anzahl Mitarbeiter) bzw. der durch Wikipedia ermittelten Mitarbeiterzahl (Spalte Wiki Mitarbeiter). Begründung bei Abweichung über +-30% in Spalte Chat Begründung Abweichung Mitarbeiter", #AS Chat Konsistenzprüfung Mitarbeiterzahl (alt AC)
"Ziel: Von ChatGPT geschätzte Anzahl Servicetechniker (Buckets). (Platzhalter)", #AT "Weicht die durch Chat GPT ermittelte Mitarbeiterzahl erheblich von der Anzahl der Mitarbeiter aus dem CRM (Spalte CRM Anzahl Mitarbeiter) bzw. der von Wikipedia ermittelten Anzahl (Spalte Wiki Mitarbeiter) ab, soll dies kurz begründet werden.", #AT Chat Begründung Abweichung Mitarbeiterzahl (alt AD)
"Ziel: Begründung von ChatGPT bei Abweichung der Technikerzahl-Schätzung. (Platzhalter)", #AU "Chat GPT soll auf basis öffentlich zugänglicher Information eine Schätzung abgeben, wieviele Servicetechniker das Unternehmen hat. Hierzu können auch Querverbindungen zwischen Anzahl der Mitarbeiter, Umsatz, Branche hergestellt werden, um eine möglichst solide Schätzung abgeben zu können. Die Schätzung soll in den Abstufungen 0, <50 , >100, >200, >500 Techniker abgegeben werden. In Entwicklung ist eine Aggegierung von branchenspezifischen Merkmalen (z.B. Umsatz, Mitarbeiterzahl) die für jede Gruppe typisch ist. In weiterer Zukunft kann hierzu möglicherweise auf ein RAG-System (Retrieval-Augmented Generation) zurückgegriffen werden. Abweichungen der Einschätzung von der durch uns ermittelten Anzahl Servicetechniker (die relativ zuverlässig ist) sollen in Spalte Chat Begründung Abweichung Anzahl Servicetechniker ausgegeben werden. Wenn die Einschätzung zu einem ähnlichen Ergebnis kommt, soll \"OK\" ausgegeben werden.", #AU Chat Einschätzung Anzahl Servicetechniker (alt AE)
"Ziel: Von ChatGPT geschätzter Umsatz. (Platzhalter)", #AV "Weicht die Einschätzung in Spalte Chat Einschätzung Anzahl Servicetechniker von den durch uns recherchierten Ergebnissen in Spalte CRM Anzahl Techniker ab, soll dies begründet werden.", #AV Chat Begründung Abweichung Anzahl Servicetechniker (alt AF)
"Ziel: Begründung von ChatGPT bei Abweichung der Umsatzschätzung. (Platzhalter)", #AW "Nur wenn kein wikipedia-Eintrag vorliegt (Wiki URL = \"\") soll ChatGPT den Umsatz auf Basis seiner Daten oder der Unternehmenswebsite ermitteln. Wenn keine Schätzung möglich ist, soll \"keine Schätzung möglich\" ausgegeben werden.", #AW Chat Schätzung Umsatz (alt AG)
"Ziel: Anzahl gefundener LinkedIn-Kontakte (Serviceleiter) via SerpAPI.", #AX "ChatGPT soll erhebliche Abweichungen beim Umsatz zwischen Chat Schätzung Umsatz, Wiki Umsatz und CRM Umsatz begründen. Sind alle Umsätze einigermaßen deckungsgleich (+-30%) soll \"OK\" ausgegeben werden.", #AX Chat Begründung Abweichung Umsatz (alt AH)
"Ziel: Anzahl gefundener LinkedIn-Kontakte (IT-Leiter) via SerpAPI.", #AY "über SerpAPI wird gemeinsam mit der Kurzform des Unternehmensnamens (Spalte CRM Kurzform) und der folgenden Liste per ODER verknüpfung gesucht.\n- 'Serviceleiter'\n- 'Leiter Service'\n- 'technischer Leiter'\n- 'Service Manager'\n- 'Leiter Kundendienst'", #AY Linked Serviceleiter gefunden (alt AI)
"Ziel: Anzahl gefundener LinkedIn-Kontakte (Management) via SerpAPI.", #AZ "über SerpAPI wird gemeinsam mit der Kurzform des Unternehmensnamens (Spalte CRM Kurzform) und der folgenden Liste per ODER verknüpfung gesucht.\n- 'Leiter IT'\n- 'IT Leiter'\n- 'Head of IT'\n- 'IT-Leiter'\n- 'CIO'", #AZ Linked It-Leiter gefunden (alt AJ)
"Ziel: Anzahl gefundener LinkedIn-Kontakte (Disponent) via SerpAPI.", #BA "über SerpAPI wird gemeinsam mit der Kurzform des Unternehmensnamens (Spalte CRM Kurzform) und der folgenden Liste per ODER verknüpfung gesucht.\n- 'Geschäftsführer'\n- 'Geschäftsführung'\n- 'GF'\n- 'CEO'\n- 'Geschäftsführerin'\n- 'Managing Director'\n- 'Geschäftsführender Gesellschafter'", #BA Linked Management gefunden (alt AK)
"System: Timestamp der letzten Kontaktsuche (Modus 'contacts'). Steuert Wiederholung.", #BB "über SerpAPI wird gemeinsam mit der Kurzform des Unternehmensnamens (Spalte CRM Kurzform) und der folgenden Liste per ODER verknüpfung gesucht.\n- 'Disponent'\n- 'Einsatzplaner'", #BB Linked Disponent gefunden (alt AL)
"Ziel: Konsolidierter Umsatz (Wiki > CRM), berücksichtigt Parent-Struktur. Input für ML und Plausi.", #BC "System: Timestamp der letzten Kontaktsuche. Steuert Wiederholung.", #BC Contact Search Timestamp (alt AM)
"Ziel: Konsolidierte Mitarbeiterzahl (Wiki > CRM), berücksichtigt Parent-Struktur. Input für ML und Plausi.", #BD "Ziel: Konsolidierter Umsatz (Mio. €), Wiki > CRM, berücksichtigt Parent. Input für ML/Plausi.", #BD Finaler Umsatz (Wiki>CRM)
"Ziel: Vom ML-Modell vorhergesagter Bucket für die Anzahl der Servicetechniker.", #BE "Ziel: Konsolidierte Mitarbeiterzahl, Wiki > CRM, berücksichtigt Parent. Input für ML/Plausi.", #BE Finaler Mitarbeiter (Wiki>CRM)
"Ziel: Kennzeichnung der Plausibilität des finalen Umsatzwertes (BC).", #BF "Ziel: Vom ML-Modell vorhergesagter Techniker-Bucket.", #BF Geschaetzter Techniker Bucket
"Ziel: Kennzeichnung der Plausibilität der finalen Mitarbeiterzahl (BD).", #BG "Ziel: Plausi-Flag für finalen Umsatz (BD).", #BG Plausibilität Umsatz
"Ziel: Kennzeichnung der Plausibilität der Umsatz-pro-Mitarbeiter-Verhältniszahl.", #BH "Ziel: Plausi-Flag für finale Mitarbeiterzahl (BE).", #BH Plausibilität Mitarbeiter
"Ziel: Indikator zur Datenqualität bezüglich Umsatz CRM (L) vs. Wiki (V), berücksichtigt Parent.", #BI "Ziel: Plausi-Flag für Umsatz/MA-Ratio.", #BI Plausibilität Umsatz/MA Ratio
"Ziel: Indikator zur Datenqualität bezüglich Mitarbeiter CRM (M) vs. Wiki (W), berücksichtigt Parent.", #BJ "Ziel: Datenqualitäts-Indikator Umsatz CRM vs. Wiki, berücksichtigt Parent.", #BJ Abweichung Umsatz CRM/Wiki
"Ziel: Zusammenfassung der Gründe für erkannte Plausibilitätsprobleme (aus BF-BJ).", #BK "Ziel: Datenqualitäts-Indikator MA CRM vs. Wiki, berücksichtigt Parent.", #BK Abweichung MA CRM/Wiki
"System: Timestamp des letzten Plausibilitäts-Checks. Steuert Wiederholung des Plausi-Modus.", #BL "Ziel: Zusammenfassung Plausi-Probleme.", #BL Plausibilität Begründung
"System: Timestamp der letzten übergreifenden ChatGPT-Evaluation (AK-AW). Steuert Wiederholung.", #BM "System: Timestamp letzter Plausi-Check. Steuert Wiederholung.", #BM Plausibilität Prüfdatum
"System: Skriptversion, die die Zeile zuletzt signifikant bearbeitet hat.", #BN "Wenn die ChatGPT Bewertung gestartet wird, wird der erste Eintrag ohne Zeitstempel in dieser Spalte gesucht und die Bearbeitung ab hier forgesetzt. Zeilen die bereits einen Zeitstempel haben werden bei der Bearbeitung übersprungen", #BN Timestamp letzte Prüfung (alt AO)
"System: Verbrauchte Tokens für OpenAI API-Aufrufe für diese Zeile (kumuliert)." #BO "Wird durch das System befüllt", #BO Version (alt AP)
"Wird durch Ticktokens berechnet" #BP Tokens (alt AQ)
] ]
] ]
num_cols = len(new_headers[0]) num_cols = len(new_headers[0])
if not all(len(row) == num_cols for row in new_headers): if not all(len(row) == num_cols for row in new_headers):
logger.critical(f"FEHLER in alignment_demo: Die Anzahl der Spalten in den Header-Zeilen ist nicht konsistent! Erwartet {num_cols} Spalten pro Zeile, aber Längen sind: {[len(row) for row in new_headers]}.") logger.critical(f"FEHLER in alignment_demo: Die Anzahl der Spalten in den Header-Zeilen ist nicht konsistent! Erwartet {num_cols} Spalten pro Zeile, aber Längen sind: {[len(row) for row in new_headers]}.")
num_cols = max(len(row) for row in new_headers) if new_headers and any(row for row in new_headers) else 0 # Sicherstellen, dass new_headers nicht komplett leer ist num_cols = max(len(row) for row in new_headers) if new_headers and any(row for row in new_headers) else 0
if num_cols == 0: if num_cols == 0:
logger.error("FEHLER: Konnte keine Spaltenanzahl für Alignment-Demo Header bestimmen.") logger.error("FEHLER: Konnte keine Spaltenanzahl für Alignment-Demo Header bestimmen.")
return return
@@ -2716,7 +2754,7 @@ def alignment_demo(sheet):
string = chr(65 + remainder) + string string = chr(65 + remainder) + string
return string return string
end_col_letter = colnum_string(num_cols) # Sollte "BO" für 67 Spalten sein end_col_letter = colnum_string(num_cols) # Sollte "BQ" für 68 Spalten sein
header_range = f"A1:{end_col_letter}{len(new_headers)}" header_range = f"A1:{end_col_letter}{len(new_headers)}"
logger.info(f"Schreibe Alignment-Demo Header in Bereich {header_range}...") logger.info(f"Schreibe Alignment-Demo Header in Bereich {header_range}...")
@@ -7920,18 +7958,14 @@ class DataProcessor:
# Innerhalb der DataProcessor Klasse # Innerhalb der DataProcessor Klasse
def _get_numeric_value_for_plausi(self, value_str, is_umsatz=False): def _get_numeric_value_for_plausi(self, value_str, is_umsatz=False):
# Diese Funktion ist jetzt sehr ähnlich zu get_numeric_filter_value, logger = logging.getLogger(__name__ + "._get_numeric_value_for_plausi") # Eigener Logger
# nur dass sie np.nan für "unbekannt" zurückgibt und den Umsatz immer in Euro.
if value_str is None or pd.isna(value_str): return np.nan if value_str is None or pd.isna(value_str): return np.nan
raw_value_str_clean = str(value_str).strip() raw_value_str_clean = str(value_str).strip()
# Explizit "0" und andere "unbekannt" Strings als NaN if raw_value_str_clean.lower() in ['', 'k.a.', 'n/a', '-', '0', '0.0', '0,00', '0.000', '0.00']:
if raw_value_str_clean.lower() in ['', 'k.a.', 'n/a', '-', '0', '0.0', '0,00', '0,000', '0.00']: # '.00' hinzugefügt logger.debug(f"Input '{raw_value_str_clean}' als 'unbekannt' (NaN) interpretiert.")
self.logger.debug(f"PlausiParse: Input '{raw_value_str_clean}' -> NaN (als 'unbekannt' interpretiert).")
return np.nan return np.nan
# Bereinigungslogik
temp_val = clean_text(raw_value_str_clean) temp_val = clean_text(raw_value_str_clean)
if temp_val.lower() in ['k.a.', 'n/a', '-']: return np.nan if temp_val.lower() in ['k.a.', 'n/a', '-']: return np.nan
@@ -7939,7 +7973,6 @@ class DataProcessor:
temp_val = re.sub(r'[€$£¥]', '', temp_val).strip() temp_val = re.sub(r'[€$£¥]', '', temp_val).strip()
temp_val = re.split(r'\s*(-||bis)\s*', temp_val, 1)[0].strip() temp_val = re.split(r'\s*(-||bis)\s*', temp_val, 1)[0].strip()
# Tausendertrenner und Dezimalzeichen normalisieren
num_extraction_str = temp_val.replace("'", "") num_extraction_str = temp_val.replace("'", "")
if '.' in num_extraction_str and ',' in num_extraction_str: if '.' in num_extraction_str and ',' in num_extraction_str:
if num_extraction_str.rfind('.') > num_extraction_str.rfind(','): if num_extraction_str.rfind('.') > num_extraction_str.rfind(','):
@@ -7949,15 +7982,15 @@ class DataProcessor:
elif ',' in num_extraction_str: elif ',' in num_extraction_str:
num_extraction_str = num_extraction_str.replace(',', '.') num_extraction_str = num_extraction_str.replace(',', '.')
elif '.' in num_extraction_str: elif '.' in num_extraction_str:
if re.fullmatch(r'^\d{1,3}(\.\d{3})+$', num_extraction_str): if re.fullmatch(r'^\d{1,3}(\.\d{3})+$', num_extraction_str) and not re.search(r'\.\d{1,2}$', num_extraction_str):
num_extraction_str = num_extraction_str.replace('.', '') num_extraction_str = num_extraction_str.replace('.', '')
elif num_extraction_str.count('.') > 1: elif num_extraction_str.count('.') > 1:
self.logger.debug(f"PlausiParse: Mehrere Punkte in '{num_extraction_str}' (nicht als Tausenderformat erkannt).") logger.debug(f"Mehrere Punkte in '{num_extraction_str}' (nicht als Tausenderformat erkannt).")
return np.nan return np.nan
match = re.search(r'([\d.\-]+)', num_extraction_str) match = re.search(r'([\d.\-]+)', num_extraction_str)
if not match: if not match:
self.logger.debug(f"PlausiParse: Kein numerischer Match in '{num_extraction_str}' (von '{raw_value_str_clean}') -> NaN.") logger.debug(f"Kein numerischer Match in '{num_extraction_str}' (von '{raw_value_str_clean}') -> NaN.")
return np.nan return np.nan
num_str_for_float = match.group(1) num_str_for_float = match.group(1)
@@ -7968,37 +8001,34 @@ class DataProcessor:
(num_str_for_float.count('-') == 1 and not num_str_for_float.startswith('-')): (num_str_for_float.count('-') == 1 and not num_str_for_float.startswith('-')):
raise ValueError("Ungültiger Zahlenstring nach Regex") raise ValueError("Ungültiger Zahlenstring nach Regex")
num_val = float(num_str_for_float) # Der reine Zahlenwert aus dem String num_val = float(num_str_for_float)
# Einheiten-Skalierung zum absoluten Wert
original_lower = raw_value_str_clean.lower() original_lower = raw_value_str_clean.lower()
final_num_absolute = num_val final_num_absolute = num_val
if is_umsatz: if is_umsatz: # Ziel ist der absolute Euro-Betrag
# Annahme: Input-String (value_str) ist bereits in Mio, wenn keine andere Einheit explizit genannt ist.
# Wir wollen hier den absoluten Euro-Betrag.
if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower): if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower):
final_num_absolute = num_val * 1000000000.0 # z.B. String "2 Mrd" -> num_val=2 -> 2 Mrd € final_num_absolute = num_val * 1000000000.0
elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower): elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower):
final_num_absolute = num_val * 1000.0 # z.B. String "500 Tsd" -> num_val=500 -> 500 Tsd € final_num_absolute = num_val * 1000.0
else: # Keine explizite andere Einheit, oder "Mio" steht da else: # Annahme: num_val ist bereits in Mio (z.B. "173" aus CRM), konvertiere zu absolutem Euro
final_num_absolute = num_val * 1000000.0 # z.B. String "173" -> num_val=173 -> 173 Mio € final_num_absolute = num_val * 1000000.0
else: # Mitarbeiter (absolute Zahl erwartet, außer bei expliziten Einheiten) else: # Mitarbeiter (absolute Zahl, außer bei expliziten Einheiten)
if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower): final_num_absolute = num_val * 1000000000.0 if re.search(r'\bmrd\s*\b|\bmilliarden\s*\b|\bbillion\s*\b', original_lower): final_num_absolute = num_val * 1000000000.0
elif re.search(r'\bmio\s*\b|\bmillionen\s*\b|\bmill[.]?\s*\b', original_lower): final_num_absolute = num_val * 1000000.0 elif re.search(r'\bmio\s*\b|\bmillionen\s*\b|\bmill[.]?\s*\b', original_lower): final_num_absolute = num_val * 1000000.0
elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower): final_num_absolute = num_val * 1000.0 elif re.search(r'\btsd\s*\b|\btausend\s*\b', original_lower): final_num_absolute = num_val * 1000.0
# Nach der Skalierung: Wenn das Ergebnis 0 ist, aber der Originalstring nicht explizit "0" war, ist 0 ein valider Wert. # Explizite "0"-Strings wurden oben bereits zu NaN.
# Explizite "0"-Strings wurden ganz am Anfang schon zu NaN. # Wenn final_num_absolute hier 0.0 ist, dann kam es von einer Berechnung (z.B. "0 Tsd").
# Diese Funktion soll den *berechneten* numerischen Wert zurückgeben. # Die Plausi-Checks können dann mit diesem numerischen Wert 0.0 arbeiten.
return final_num_absolute return final_num_absolute
except ValueError as e: except ValueError as e:
self.logger.debug(f"PlausiParse: ValueError '{e}' bei Konvertierung von '{num_str_for_float}' (von '{raw_value_str_clean}') -> NaN.") logger.debug(f"ValueError '{e}' bei Konvertierung von '{num_str_for_float}' (von '{raw_value_str_clean}') -> NaN.")
return np.nan return np.nan
except Exception as e_general: except Exception as e_general:
self.logger.error(f"Unerwarteter Fehler in _get_numeric_value_for_plausi für '{raw_value_str_clean[:50]}...': {e_general}") logger.error(f"Unerwarteter Fehler in _get_numeric_value_for_plausi für '{raw_value_str_clean[:50]}...': {e_general}")
self.logger.debug(traceback.format_exc()) logger.debug(traceback.format_exc())
return np.nan return np.nan