feat: Enhance sync conflict detection and resolution logic in BeteiligteSync class
This commit is contained in:
@@ -241,29 +241,38 @@ class BeteiligteSync:
|
|||||||
# PRIMÄR: rowId-basierte Änderungserkennung (zuverlässiger!)
|
# PRIMÄR: rowId-basierte Änderungserkennung (zuverlässiger!)
|
||||||
espo_rowid = espo_entity.get('advowareRowId')
|
espo_rowid = espo_entity.get('advowareRowId')
|
||||||
advo_rowid = advo_entity.get('rowId')
|
advo_rowid = advo_entity.get('rowId')
|
||||||
|
|
||||||
if espo_rowid and advo_rowid:
|
|
||||||
if espo_rowid != advo_rowid:
|
|
||||||
# rowId unterschiedlich → Advoware wurde geändert
|
|
||||||
self._log(f"Advoware rowId geändert: {espo_rowid[:20]}... → {advo_rowid[:20]}...")
|
|
||||||
return 'advoware_newer'
|
|
||||||
else:
|
|
||||||
# rowId gleich → keine Änderung in Advoware
|
|
||||||
# Prüfe ob EspoCRM geändert wurde (via modifiedAt)
|
|
||||||
espo_modified = espo_entity.get('modifiedAt')
|
|
||||||
last_sync = espo_entity.get('advowareLastSync')
|
last_sync = espo_entity.get('advowareLastSync')
|
||||||
|
espo_modified = espo_entity.get('modifiedAt')
|
||||||
|
|
||||||
if espo_modified and last_sync:
|
if espo_rowid and advo_rowid and last_sync:
|
||||||
|
# Prüfe ob Advoware geändert wurde (rowId)
|
||||||
|
advo_changed = (espo_rowid != advo_rowid)
|
||||||
|
|
||||||
|
# Prüfe ob EspoCRM auch geändert wurde (seit letztem Sync)
|
||||||
|
espo_changed = False
|
||||||
|
if espo_modified:
|
||||||
try:
|
try:
|
||||||
espo_ts = self.parse_timestamp(espo_modified)
|
espo_ts = self.parse_timestamp(espo_modified)
|
||||||
sync_ts = self.parse_timestamp(last_sync)
|
sync_ts = self.parse_timestamp(last_sync)
|
||||||
|
if espo_ts and sync_ts:
|
||||||
if espo_ts and sync_ts and espo_ts > sync_ts:
|
espo_changed = (espo_ts > sync_ts)
|
||||||
self._log(f"EspoCRM neuer (rowId gleich, aber modifiedAt > lastSync)")
|
|
||||||
return 'espocrm_newer'
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._log(f"Timestamp-Parse-Fehler: {e}", level='debug')
|
self._log(f"Timestamp-Parse-Fehler: {e}", level='debug')
|
||||||
|
|
||||||
|
# Konfliktlogik: Beide geändert seit letztem Sync?
|
||||||
|
if advo_changed and espo_changed:
|
||||||
|
self._log(f"🚨 KONFLIKT: Beide Seiten geändert seit letztem Sync")
|
||||||
|
return 'conflict'
|
||||||
|
elif advo_changed:
|
||||||
|
self._log(f"Advoware rowId geändert: {espo_rowid[:20]}... → {advo_rowid[:20]}...")
|
||||||
|
return 'advoware_newer'
|
||||||
|
elif espo_changed:
|
||||||
|
self._log(f"EspoCRM neuer (modifiedAt > lastSync)")
|
||||||
|
return 'espocrm_newer'
|
||||||
|
else:
|
||||||
|
# Weder Advoware noch EspoCRM geändert
|
||||||
|
return 'no_change'
|
||||||
|
|
||||||
# Keine Änderungen
|
# Keine Änderungen
|
||||||
self._log("Keine Änderungen (rowId identisch)")
|
self._log("Keine Änderungen (rowId identisch)")
|
||||||
return 'no_change'
|
return 'no_change'
|
||||||
@@ -502,10 +511,6 @@ class BeteiligteSync:
|
|||||||
update_data.update(extra_fields)
|
update_data.update(extra_fields)
|
||||||
|
|
||||||
await self.espocrm.update_entity('CBeteiligte', entity_id, update_data)
|
await self.espocrm.update_entity('CBeteiligte', entity_id, update_data)
|
||||||
'advowareLastSync': now,
|
|
||||||
'syncErrorMessage': f"Konflikt am {now}: {conflict_details}. EspoCRM hat gewonnen.",
|
|
||||||
'syncRetryCount': 0
|
|
||||||
})
|
|
||||||
|
|
||||||
self._log(f"Konflikt gelöst für {entity_id}: EspoCRM wins")
|
self._log(f"Konflikt gelöst für {entity_id}: EspoCRM wins")
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,9 @@ class BeteiligteMapper:
|
|||||||
"""
|
"""
|
||||||
logger.debug(f"Mapping EspoCRM → Advoware STAMMDATEN: {espo_entity.get('id')}")
|
logger.debug(f"Mapping EspoCRM → Advoware STAMMDATEN: {espo_entity.get('id')}")
|
||||||
|
|
||||||
# Bestimme ob Person oder Firma
|
# Bestimme ob Person oder Firma (über firmenname-Feld)
|
||||||
is_firma = bool(espo_entity.get('firmenname'))
|
firmenname = espo_entity.get('firmenname')
|
||||||
|
is_firma = bool(firmenname and firmenname.strip())
|
||||||
rechtsform = espo_entity.get('rechtsform', '')
|
rechtsform = espo_entity.get('rechtsform', '')
|
||||||
|
|
||||||
# Basis-Struktur (nur Stammdaten, keine Kontaktdaten!)
|
# Basis-Struktur (nur Stammdaten, keine Kontaktdaten!)
|
||||||
@@ -41,11 +42,11 @@ class BeteiligteMapper:
|
|||||||
|
|
||||||
# NAME: Person vs. Firma
|
# NAME: Person vs. Firma
|
||||||
if is_firma:
|
if is_firma:
|
||||||
# Firma: name = firmenname
|
# Firma: Lese von firmenname-Feld
|
||||||
advo_data['name'] = espo_entity.get('firmenname', '')
|
advo_data['name'] = firmenname
|
||||||
advo_data['vorname'] = None
|
advo_data['vorname'] = None
|
||||||
else:
|
else:
|
||||||
# Person: name = lastName, vorname = firstName
|
# Natürliche Person: Lese von lastName/firstName
|
||||||
advo_data['name'] = espo_entity.get('lastName', '')
|
advo_data['name'] = espo_entity.get('lastName', '')
|
||||||
advo_data['vorname'] = espo_entity.get('firstName', '')
|
advo_data['vorname'] = espo_entity.get('firstName', '')
|
||||||
|
|
||||||
@@ -100,17 +101,19 @@ class BeteiligteMapper:
|
|||||||
'advowareRowId': advo_entity.get('rowId'), # Änderungserkennung
|
'advowareRowId': advo_entity.get('rowId'), # Änderungserkennung
|
||||||
}
|
}
|
||||||
|
|
||||||
# NAME: Person vs. Firma
|
# NAME: Person vs. Firma (EspoCRM blendet lastName/firstName aus bei Firmen)
|
||||||
if is_person:
|
if is_person:
|
||||||
# Person
|
# Natürliche Person → lastName/firstName verwenden
|
||||||
espo_data['firstName'] = vorname
|
espo_data['firstName'] = vorname
|
||||||
espo_data['lastName'] = advo_entity.get('name', '')
|
espo_data['lastName'] = advo_entity.get('name', '')
|
||||||
espo_data['name'] = f"{vorname} {advo_entity.get('name', '')}".strip()
|
espo_data['name'] = f"{vorname} {advo_entity.get('name', '')}".strip()
|
||||||
espo_data['firmenname'] = None
|
espo_data['firmenname'] = None # Firma-Feld leer lassen
|
||||||
else:
|
else:
|
||||||
# Firma
|
# Firma → firmenname verwenden (EspoCRM zeigt dann nur dieses Feld)
|
||||||
espo_data['firmenname'] = advo_entity.get('name', '')
|
firma_name = advo_entity.get('name', '')
|
||||||
espo_data['name'] = advo_entity.get('name', '')
|
espo_data['firmenname'] = firma_name
|
||||||
|
espo_data['name'] = firma_name
|
||||||
|
# lastName/firstName nicht setzen (EspoCRM blendet sie aus bei Firmen)
|
||||||
espo_data['firstName'] = None
|
espo_data['firstName'] = None
|
||||||
espo_data['lastName'] = None
|
espo_data['lastName'] = None
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user