sync_manager.py aktualisiert
This commit is contained in:
@@ -35,9 +35,7 @@ class SyncManager:
|
||||
self.sheet_handler = sheet_handler
|
||||
self.d365_export_path = d365_export_path
|
||||
self.logger = logging.getLogger(__name__)
|
||||
|
||||
# <<< KORREKTUR: Der Name wird erst nach der Verbindung abgerufen.
|
||||
self.target_sheet_name = None
|
||||
self.target_sheet_name = None
|
||||
|
||||
# Definiert, welche D365-Spalten welchen GSheet-Spalten entsprechen.
|
||||
self.d365_to_gsheet_map = {
|
||||
@@ -60,7 +58,7 @@ class SyncManager:
|
||||
"CRM Umsatz", "CRM Anzahl Mitarbeiter"]
|
||||
self.smart_merge_cols = ["CRM Website"]
|
||||
|
||||
def _load_data(self):
|
||||
def _load_data(self):
|
||||
"""Lädt Daten aus der D365-Exportdatei und dem Google Sheet."""
|
||||
self.logger.info(f"Lade Daten aus D365-Export: '{self.d365_export_path}'...")
|
||||
try:
|
||||
@@ -91,22 +89,17 @@ class SyncManager:
|
||||
self.logger.warning("Google Sheet scheint leer zu sein oder enthält keinen Header. Erstelle leeres DataFrame.")
|
||||
self.gsheet_df = pd.DataFrame(columns=COLUMN_ORDER).fillna('')
|
||||
else:
|
||||
# --- ROBUSTE DATENFRAME-ERSTELLUNG START ---
|
||||
# 1. Nimm die korrekte Header-Zeile aus dem Sheet als Spaltennamen
|
||||
actual_header = all_data_with_headers[self.sheet_handler._header_rows - 1]
|
||||
data_rows = all_data_with_headers[self.sheet_handler._header_rows:]
|
||||
|
||||
temp_df = pd.DataFrame(data_rows, columns=actual_header).fillna('')
|
||||
|
||||
# 2. Füge fehlende Spalten hinzu, die in unserer Config definiert sind
|
||||
for col_name in COLUMN_ORDER:
|
||||
if col_name not in temp_df.columns:
|
||||
self.logger.warning(f"Spalte '{col_name}' fehlt im Google Sheet und wird hinzugefügt.")
|
||||
temp_df[col_name] = ''
|
||||
|
||||
# 3. Stelle sicher, dass die Spaltenreihenfolge exakt unserer Config entspricht
|
||||
self.gsheet_df = temp_df[COLUMN_ORDER]
|
||||
# --- ROBUSTE DATENFRAME-ERSTELLUNG ENDE ---
|
||||
|
||||
except Exception as e:
|
||||
self.logger.critical(f"Fehler beim Laden oder Umwandeln der Google Sheet Daten: {e}", exc_info=True)
|
||||
@@ -122,7 +115,6 @@ class SyncManager:
|
||||
if not self._load_data():
|
||||
return
|
||||
|
||||
# <<< KORREKTUR: Sheet-Namen nach erfolgreichem Laden abrufen
|
||||
self.target_sheet_name = self.sheet_handler.get_main_sheet_name()
|
||||
if not self.target_sheet_name:
|
||||
self.logger.critical("Konnte den Namen des Ziel-Sheets nicht ermitteln. Breche ab.")
|
||||
@@ -140,7 +132,6 @@ class SyncManager:
|
||||
updates_to_batch = []
|
||||
rows_to_append = []
|
||||
|
||||
# 1. Neue Accounts verarbeiten
|
||||
if new_ids:
|
||||
new_accounts_df = self.d365_df[self.d365_df['CRM ID'].isin(new_ids)]
|
||||
for _, row in new_accounts_df.iterrows():
|
||||
@@ -151,19 +142,16 @@ class SyncManager:
|
||||
new_row_data[col_idx] = row[d365_col]
|
||||
rows_to_append.append(new_row_data)
|
||||
|
||||
# 2. Gelöschte/Archivierte Accounts verarbeiten
|
||||
if deleted_ids:
|
||||
for crm_id in deleted_ids:
|
||||
row_indices = self.gsheet_df[self.gsheet_df['CRM ID'] == crm_id].index
|
||||
if not row_indices.empty:
|
||||
row_idx = row_indices[0]
|
||||
updates_to_batch.append({
|
||||
# KORREKTUR: Dein Handler erwartet den Range ohne Sheet-Namen
|
||||
"range": f"{COLUMN_MAP['Archiviert']['Titel']}{row_idx + 2}",
|
||||
"values": [["TRUE"]]
|
||||
})
|
||||
|
||||
# 3. Bestehende Accounts intelligent mergen
|
||||
if existing_ids:
|
||||
d365_indexed = self.d365_df.set_index('CRM ID')
|
||||
gsheet_indexed = self.gsheet_df.set_index('CRM ID')
|
||||
@@ -176,14 +164,12 @@ class SyncManager:
|
||||
conflict_messages = []
|
||||
needs_reeval = False
|
||||
|
||||
# Strategie 1: D365 gewinnt immer
|
||||
for gsheet_col in self.d365_wins_cols:
|
||||
d365_col = next((k for k, v in self.d365_to_gsheet_map.items() if v == gsheet_col), None)
|
||||
if d365_col and d365_col in d365_row and str(d365_row[d365_col]) != str(gsheet_row[gsheet_col]):
|
||||
row_updates[gsheet_col] = str(d365_row[d365_col])
|
||||
needs_reeval = True
|
||||
|
||||
# Strategie 2: Smart-Merge
|
||||
for gsheet_col in self.smart_merge_cols:
|
||||
d365_col = next((k for k, v in self.d365_to_gsheet_map.items() if v == gsheet_col), None)
|
||||
d365_val = str(d365_row.get(d365_col, ''))
|
||||
@@ -195,24 +181,20 @@ class SyncManager:
|
||||
elif d365_val and gsheet_val and d365_val != gsheet_val:
|
||||
conflict_messages.append(f"{gsheet_col}_CONFLICT: D365='{d365_val}' | GSHEET='{gsheet_val}'")
|
||||
|
||||
# Updates und Flags
|
||||
if conflict_messages:
|
||||
row_updates["SyncConflict"] = "; ".join(conflict_messages)
|
||||
|
||||
if needs_reeval:
|
||||
row_updates["ReEval Flag"] = "x"
|
||||
|
||||
# Batch-Update-Objekte
|
||||
if row_updates:
|
||||
row_idx = gsheet_indexed.index.get_loc(crm_id)
|
||||
for col_name, value in row_updates.items():
|
||||
updates_to_batch.append({
|
||||
# KORREKTUR: Dein Handler erwartet den Range ohne Sheet-Namen
|
||||
"range": f"{COLUMN_MAP[col_name]['Titel']}{row_idx + 2}",
|
||||
"values": [[value]]
|
||||
})
|
||||
|
||||
# 4. Änderungen ins Google Sheet schreiben
|
||||
if rows_to_append:
|
||||
self.logger.info(f"Füge {len(rows_to_append)} neue Zeilen zum Google Sheet hinzu...")
|
||||
self.sheet_handler.append_rows(sheet_name=self.target_sheet_name, values=rows_to_append)
|
||||
|
||||
Reference in New Issue
Block a user