Add sync strategy documentation and templates for bidirectional sync between EspoCRM and Advoware
- Introduced SYNC_STRATEGY_ARCHIVE.md detailing the sync process, status values, and flow for updating entities from EspoCRM to Advoware and vice versa. - Created SYNC_TEMPLATE.md as a guide for implementing new syncs, including field definitions, mapper examples, sync utilities, event handlers, and cron jobs. - Added README_SYNC.md for the Beteiligte sync event handler, outlining its functionality, event subscriptions, optimizations, error handling, and performance metrics.
This commit is contained in:
@@ -40,7 +40,7 @@ async def handler(event_data, context):
|
||||
|
||||
context.logger.info(f"🔄 Sync-Handler gestartet: {action.upper()} | Entity: {entity_id} | Source: {source}")
|
||||
|
||||
# Redis für Queue-Management
|
||||
# Shared Redis client for distributed locking
|
||||
redis_client = redis.Redis(
|
||||
host=Config.REDIS_HOST,
|
||||
port=int(Config.REDIS_PORT),
|
||||
@@ -51,7 +51,7 @@ async def handler(event_data, context):
|
||||
# APIs initialisieren
|
||||
espocrm = EspoCRMAPI()
|
||||
advoware = AdvowareAPI(context)
|
||||
sync_utils = BeteiligteSync(espocrm, context)
|
||||
sync_utils = BeteiligteSync(espocrm, redis_client, context)
|
||||
mapper = BeteiligteMapper()
|
||||
|
||||
try:
|
||||
@@ -141,11 +141,13 @@ async def handle_create(entity_id, espo_entity, espocrm, advoware, sync_utils, m
|
||||
|
||||
context.logger.info(f"✅ In Advoware erstellt: betNr={new_betnr}")
|
||||
|
||||
# Update EspoCRM mit neuer betNr
|
||||
await sync_utils.release_sync_lock(entity_id, 'clean', error_message=None)
|
||||
await espocrm.update_entity('CBeteiligte', entity_id, {
|
||||
'betnr': new_betnr
|
||||
})
|
||||
# OPTIMIERT: Kombiniere release_lock + betnr update in 1 API call
|
||||
await sync_utils.release_sync_lock(
|
||||
entity_id,
|
||||
'clean',
|
||||
error_message=None,
|
||||
extra_fields={'betnr': new_betnr}
|
||||
)
|
||||
|
||||
context.logger.info(f"✅ CREATE erfolgreich: {entity_id} → betNr {new_betnr}")
|
||||
|
||||
@@ -199,15 +201,8 @@ async def handle_update(entity_id, betnr, espo_entity, espocrm, advoware, sync_u
|
||||
if not espo_entity.get('advowareLastSync'):
|
||||
context.logger.info(f"📤 Initial Sync → EspoCRM STAMMDATEN zu Advoware")
|
||||
|
||||
# WICHTIG: Advoware benötigt vollständiges Objekt für PUT
|
||||
# Mapper liefert nur STAMMDATEN (keine Kontaktdaten - die kommen später über separate Endpoints)
|
||||
advo_updates = mapper.map_cbeteiligte_to_advoware(espo_entity)
|
||||
|
||||
# Merge mit aktuellen Advoware-Daten
|
||||
merged_data = {**advo_entity, **advo_updates}
|
||||
|
||||
context.logger.info(f"📝 Merge: {len(advo_updates)} Stammdaten-Felder → {len(merged_data)} Gesamt-Felder")
|
||||
context.logger.debug(f" Gesynct: {', '.join(advo_updates.keys())}")
|
||||
# OPTIMIERT: Use merge utility (reduces code duplication)
|
||||
merged_data = sync_utils.merge_for_advoware_put(advo_entity, espo_entity, mapper)
|
||||
|
||||
await advoware.api_call(
|
||||
f'api/v1/advonet/Beteiligte/{betnr}',
|
||||
@@ -229,15 +224,8 @@ async def handle_update(entity_id, betnr, espo_entity, espocrm, advoware, sync_u
|
||||
if comparison == 'espocrm_newer':
|
||||
context.logger.info(f"📤 EspoCRM ist neuer → Update Advoware STAMMDATEN")
|
||||
|
||||
# WICHTIG: Advoware benötigt vollständiges Objekt für PUT
|
||||
# Mapper liefert nur STAMMDATEN (keine Kontaktdaten - die kommen über separate Endpoints)
|
||||
advo_updates = mapper.map_cbeteiligte_to_advoware(espo_entity)
|
||||
|
||||
# Merge mit aktuellen Advoware-Daten
|
||||
merged_data = {**advo_entity, **advo_updates}
|
||||
|
||||
context.logger.info(f"📝 Merge: {len(advo_updates)} Stammdaten-Felder → {len(merged_data)} Gesamt-Felder")
|
||||
context.logger.debug(f" Gesynct: {', '.join(advo_updates.keys())}")
|
||||
# OPTIMIERT: Use merge utility
|
||||
merged_data = sync_utils.merge_for_advoware_put(advo_entity, espo_entity, mapper)
|
||||
|
||||
await advoware.api_call(
|
||||
f'api/v1/advonet/Beteiligte/{betnr}',
|
||||
@@ -262,11 +250,8 @@ async def handle_update(entity_id, betnr, espo_entity, espocrm, advoware, sync_u
|
||||
elif comparison == 'conflict':
|
||||
context.logger.warning(f"⚠️ KONFLIKT erkannt → EspoCRM WINS (STAMMDATEN)")
|
||||
|
||||
# Überschreibe Advoware mit EspoCRM (merge mit aktuellen Daten)
|
||||
advo_updates = mapper.map_cbeteiligte_to_advoware(espo_entity)
|
||||
merged_data = {**advo_entity, **advo_updates}
|
||||
|
||||
context.logger.info(f"📝 Merge: {len(advo_updates)} Stammdaten-Felder → {len(merged_data)} Gesamt-Felder")
|
||||
# OPTIMIERT: Use merge utility
|
||||
merged_data = sync_utils.merge_for_advoware_put(advo_entity, espo_entity, mapper)
|
||||
|
||||
await advoware.api_call(
|
||||
f'api/v1/advonet/Beteiligte/{betnr}',
|
||||
|
||||
Reference in New Issue
Block a user