diff --git a/data_processor.py b/data_processor.py index 86f3112e..451ea473 100644 --- a/data_processor.py +++ b/data_processor.py @@ -529,34 +529,34 @@ class DataProcessor: }) # --- NEUER SCHRITT: FSM Pitch generieren --- - self.logger.info(f" Zeile {row_num_in_sheet}: Generiere FSM Pitch...") - try: - # Hole die konsolidierten Mitarbeiter- und bekannten Technikerzahlen für den Pitch - final_ma_val = self._get_cell_value_safe(row_data, "Finaler Mitarbeiter (Wiki>CRM)") - crm_techniker_val = self._get_cell_value_safe(row_data, "CRM Anzahl Techniker") - - # Verwende die validierte Branche aus dem vorherigen Schritt - validierte_branche_fuer_pitch = branch_result.get("branch", crm_branche) - if "FEHLER" in validierte_branche_fuer_pitch: validierte_branche_fuer_pitch = crm_branche + if 'fsm_pitch' in chat_steps_to_run and self._needs_fsm_pitch(row_data, force_reeval): + self.logger.info(f" -> Generiere FSM Pitch...") + try: + # Daten für den Pitch sammeln, die in diesem Durchlauf relevant sind + # Priorisiere die frisch generierte Branche, falle zurück auf Sheet-Daten + ki_branche = branch_result.get("branch") if branch_result else self._get_cell_value_safe(row_data, "Chat Vorschlag Branche") + if not ki_branche or "FEHLER" in ki_branche: + ki_branche = self._get_cell_value_safe(row_data, "CRM Branche") - fsm_pitch_text = generate_fsm_argument( - company_name, - validierte_branche_fuer_pitch, - website_summary, - final_wiki_data.get('first_paragraph', 'k.A.'), - final_ma_val, - crm_techniker_val - ) - updates.append({ - 'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch"] + 1)}{row_num_in_sheet}', - 'values': [[fsm_pitch_text]] - }) - except Exception as e_fsm_pitch: - self.logger.error(f"FEHLER bei FSM-Pitch-Generierung für Zeile {row_num_in_sheet}: {e_fsm_pitch}") - updates.append({ - 'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch"] + 1)}{row_num_in_sheet}', - 'values': [['k.A. (Fehler bei Generierung)']] - }) + # Rufe die neue, verbesserte Pitch-Funktion auf + fsm_pitch_text = generate_fsm_pitch( + company_name=self._get_cell_value_safe(row_data, "CRM Name"), + company_short_name=self._get_cell_value_safe(row_data, "CRM Kurzform"), + ki_branche=ki_branche, + website_summary=self._get_cell_value_safe(row_data, "Website Zusammenfassung"), + wiki_absatz=final_wiki_data.get('first_paragraph'), # Nutze die frischen Wiki-Daten + anzahl_ma=self._get_cell_value_safe(row_data, "Finaler Mitarbeiter (Wiki>CRM)"), + anzahl_techniker=self._get_cell_value_safe(row_data, "CRM Anzahl Techniker"), + techniker_bucket_ml=self._get_cell_value_safe(row_data, "Geschaetzter Techniker Bucket") + ) + + updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch"] + 1)}{row_num_in_sheet}', 'values': [[fsm_pitch_text]]}) + updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch Timestamp"] + 1)}{row_num_in_sheet}', 'values': [[now_timestamp]]}) + any_processing_done = True + chat_eval_just_ran = True # Signal, dass eine KI-Aktion stattfand + except Exception as e_fsm_pitch: + self.logger.error(f"FEHLER bei FSM-Pitch-Generierung für Zeile {row_num_in_sheet}: {e_fsm_pitch}") + updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch"] + 1)}{row_num_in_sheet}', 'values': [['FEHLER (Generierung)']]} ) @@ -1094,12 +1094,12 @@ class DataProcessor: self.logger.info(f"Re-Evaluierung abgeschlossen. {processed_count_actual} Zeilen verarbeitet.") - def process_fsm_pitch(self, start_sheet_row=None, end_sheet_row=None, limit=None): + def process_fsm_pitch(self, start_sheet_row=None, end_sheet_row=None, limit=None): """ - Generiert FSM-Pitches für alle Zeilen, bei denen der FSM Pitch Timestamp fehlt, - aber die notwendigen Daten vorhanden sind. + Generiert FSM-Pitches für alle Zeilen, bei denen der Pitch oder der Timestamp fehlt. + Nutzt die neue, verbesserte generate_fsm_pitch Funktion. """ - self.logger.info(f"Starte Modus 'fsm_pitch'. Bereich: {start_sheet_row or 'Start'}-{end_sheet_row or 'Ende'}, Limit: {limit or 'Unbegrenzt'}") + self.logger.info(f"Starte Batch-Modus 'fsm_pitch'. Bereich: {start_sheet_row or 'Start'}-{end_sheet_row or 'Ende'}, Limit: {limit or 'Unbegrenzt'}") if not self.sheet_handler.load_data(): self.logger.error("Fehler beim Laden der Daten für FSM-Pitch-Generierung.") @@ -1112,21 +1112,17 @@ class DataProcessor: effective_end = end_sheet_row if end_sheet_row is not None else len(all_data) tasks = [] - # Sammle alle Zeilen, die für die Verarbeitung in Frage kommen for i in range(effective_start - 1, effective_end): if limit is not None and len(tasks) >= limit: - self.logger.info(f"Limit von {limit} zu verarbeitenden Zeilen erreicht. Stoppe das Sammeln von Tasks.") break row_data = all_data[i] - # NEUE PRÜFUNG: Nur Zeilen ohne Timestamp verarbeiten timestamp = self._get_cell_value_safe(row_data, "FSM Pitch Timestamp").strip() + pitch = self._get_cell_value_safe(row_data, "FSM Pitch").strip() - if not timestamp: + if not timestamp or "fehler" in pitch.lower(): company_name = self._get_cell_value_safe(row_data, "CRM Name").strip() - branche = self._get_cell_value_safe(row_data, "Chat Vorschlag Branche").strip() or self._get_cell_value_safe(row_data, "CRM Branche").strip() - - if company_name and branche: + if company_name: tasks.append({'row_num': i + 1, 'data': row_data}) if not tasks: @@ -1146,73 +1142,36 @@ class DataProcessor: self.logger.debug(f"Verarbeite FSM-Pitch für Zeile {row_num}...") - # --- NEUE PRÜFUNG --- - # Extrahiere die Beschreibungen VOR dem API-Call - website_summary = self._get_cell_value_safe(row_data, "Website Zusammenfassung") - wiki_absatz = self._get_cell_value_safe(row_data, "Wiki Absatz") - beschreibung = website_summary if website_summary and website_summary.lower() not in ['k.a.', ''] else wiki_absatz - - # Wenn keine sinnvolle Beschreibung vorhanden ist, überspringe den API-Call - if not beschreibung or beschreibung.lower() in ['k.a.', '']: - self.logger.warning(f"Zeile {row_num}: Überspringe FSM-Pitch-Generierung, da keine Beschreibung vorhanden ist.") - all_sheet_updates.append({ - 'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch"] + 1)}{row_num}', - 'values': [['k.A. (Beschreibung fehlt)']] - }) - # Wichtig: Trotzdem den Timestamp setzen, um diese Zeile nicht erneut zu versuchen - all_sheet_updates.append({ - 'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch Timestamp"] + 1)}{row_num}', - 'values': [[now_timestamp]] - }) - processed_count += 1 - continue # Springe zum nächsten Task in der Schleife - # --- ENDE NEUE PRÜFUNG --- - - try: - # Extrahiere die restlichen Daten für den Pitch - company_name = self._get_cell_value_safe(row_data, "CRM Name") - branche = self._get_cell_value_safe(row_data, "Chat Vorschlag Branche") or self._get_cell_value_safe(row_data, "CRM Branche") - final_ma_val_str = self._get_cell_value_safe(row_data, "Finaler Mitarbeiter (Wiki>CRM)") - crm_techniker_val_str = self._get_cell_value_safe(row_data, "CRM Anzahl Techniker") - - fsm_pitch_text = generate_fsm_argument( - company_name, - branche, - website_summary, # Wir übergeben die bereits ermittelten Werte - wiki_absatz, - final_ma_val_str, - crm_techniker_val_str + # Rufe die neue, verbesserte Pitch-Funktion mit Daten aus dem Sheet auf + fsm_pitch_text = generate_fsm_pitch( + company_name=self._get_cell_value_safe(row_data, "CRM Name"), + company_short_name=self._get_cell_value_safe(row_data, "CRM Kurzform"), + ki_branche=self._get_cell_value_safe(row_data, "Chat Vorschlag Branche"), + website_summary=self._get_cell_value_safe(row_data, "Website Zusammenfassung"), + wiki_absatz=self._get_cell_value_safe(row_data, "Wiki Absatz"), + anzahl_ma=self._get_cell_value_safe(row_data, "Finaler Mitarbeiter (Wiki>CRM)"), + anzahl_techniker=self._get_cell_value_safe(row_data, "CRM Anzahl Techniker"), + techniker_bucket_ml=self._get_cell_value_safe(row_data, "Geschaetzter Techniker Bucket") ) - all_sheet_updates.append({ - 'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch"] + 1)}{row_num}', - 'values': [[fsm_pitch_text]] - }) - + all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch"] + 1)}{row_num}', 'values': [[fsm_pitch_text]]}) except Exception as e: self.logger.error(f"FEHLER bei FSM-Pitch-Generierung für Zeile {row_num}: {e}") - all_sheet_updates.append({ - 'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch"] + 1)}{row_num}', - 'values': [['k.A. (Fehler bei Generierung)']] - }) + all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch"] + 1)}{row_num}', 'values': [['FEHLER (Generierung)']]} ) - # IMMER den Timestamp setzen - all_sheet_updates.append({ - 'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch Timestamp"] + 1)}{row_num}', - 'values': [[now_timestamp]] - }) + # IMMER den Timestamp setzen, auch bei Fehler, um Endlosschleifen zu vermeiden + all_sheet_updates.append({'range': f'{self.sheet_handler._get_col_letter(COLUMN_MAP["FSM Pitch Timestamp"] + 1)}{row_num}', 'values': [[now_timestamp]]}) processed_count += 1 - # NEU: Batch-Update, wenn die Größe erreicht ist oder es der letzte Task ist + # Batch-Update Logik if (idx + 1) % update_batch_size == 0 or (idx + 1) == len(tasks): if all_sheet_updates: - # Die Anzahl der bearbeiteten Zeilen in diesem Batch ist len(all_sheet_updates) / 2 num_rows_in_batch = len(all_sheet_updates) // 2 self.logger.info(f"Sende Batch-Update für {num_rows_in_batch} FSM-Pitches (Verarbeitet bisher: {processed_count}/{len(tasks)})...") self.sheet_handler.batch_update_cells(all_sheet_updates) - all_sheet_updates = [] # Liste für den nächsten Batch leeren - time.sleep(1) # Kurze Pause nach jedem Schreibvorgang + all_sheet_updates = [] + time.sleep(1) self.logger.info(f"FSM-Pitch-Generierung abgeschlossen. {processed_count} Zeilen bearbeitet.")