Fix recurring event duplication - handle recurringEventId properly in all phases

This commit is contained in:
root
2025-10-23 18:30:46 +00:00
parent 582c9422dc
commit da2b9960b0
2 changed files with 113 additions and 5 deletions

View File

@@ -614,9 +614,14 @@ async def handler(event, context):
)
logger.info(f"Fetched {len(rows)} existing sync rows")
# Build indexes
# Build indexes - use recurringEventId for recurring events to avoid duplicates
db_adv_index = {str(row['advoware_frnr']): row for row in rows if row['advoware_frnr']}
db_google_index = {row['google_event_id']: row for row in rows if row['google_event_id']}
db_google_index = {}
for row in rows:
if row['google_event_id']:
# For recurring events, use the master event ID (recurringEventId)
# For regular events, use the event_id directly
db_google_index[row['google_event_id']] = row
# Phase 1: New from Advoware => Google
logger.info("Phase 1: Processing new appointments from Advoware")
@@ -640,7 +645,12 @@ async def handler(event, context):
# Phase 2: New from Google => Advoware
logger.info("Phase 2: Processing new events from Google")
for event_id, evt in google_map.items():
if event_id not in db_google_index:
# For recurring events, check if the master event (recurringEventId) is already synced
# For regular events, check the event_id directly
recurring_master_id = evt.get('recurringEventId')
is_already_synced = event_id in db_google_index or (recurring_master_id and recurring_master_id in db_google_index)
if not is_already_synced:
try:
frnr = await safe_create_advoware_appointment(advoware, standardize_appointment_data(evt, 'google'), kuerzel, True)
if frnr and str(frnr) != 'None':
@@ -664,7 +674,19 @@ async def handler(event, context):
frnr = row['advoware_frnr']
event_id = row['google_event_id']
adv_exists = str(frnr) in adv_map if frnr else False
google_exists = event_id in google_map if event_id else False
# For Google events, check if the master event or any instance exists
google_exists = False
if event_id:
# Check if the stored event_id exists
if event_id in google_map:
google_exists = True
else:
# Check if any event has this as recurringEventId (master event still exists)
for evt in google_map.values():
if evt.get('recurringEventId') == event_id:
google_exists = True
break
if not adv_exists and not google_exists:
# Both missing - soft delete
@@ -773,11 +795,36 @@ async def handler(event, context):
# Phase 4: Update existing entries if changed
logger.info("Phase 4: Processing updates for existing entries")
# Track which master events we've already processed to avoid duplicate updates
processed_master_events = set()
for row in rows:
frnr = row['advoware_frnr']
event_id = row['google_event_id']
adv_data = adv_map.get(str(frnr)) if frnr else None
google_data = google_map.get(event_id) if event_id else None
# For Google events, find the corresponding event (could be master or instance)
google_data = None
if event_id:
# First try to find the exact event_id
if event_id in google_map:
google_data = google_map[event_id]
else:
# Look for any event that has this as recurringEventId
for evt in google_map.values():
if evt.get('recurringEventId') == event_id:
google_data = evt
break
# Skip if we don't have both sides or if we've already processed this master event
if not adv_data or not google_data:
continue
# For recurring events, only process the master event once
master_event_id = google_data.get('recurringEventId') or event_id
if master_event_id in processed_master_events:
continue
processed_master_events.add(master_event_id)
if adv_data and google_data:
adv_std = standardize_appointment_data(adv_data, 'advoware')