diff --git a/bitbylaw/steps/advoware_cal_sync/README.md b/bitbylaw/steps/advoware_cal_sync/README.md index 3bca4763..63bafdb5 100644 --- a/bitbylaw/steps/advoware_cal_sync/README.md +++ b/bitbylaw/steps/advoware_cal_sync/README.md @@ -61,7 +61,7 @@ CREATE TABLE calendar_sync_audit ( -- Indizes (angepasst für Soft Deletes) CREATE UNIQUE INDEX idx_calendar_sync_advoware ON calendar_sync (employee_kuerzel, advoware_frnr) WHERE advoware_frnr IS NOT NULL AND deleted = FALSE; -CREATE UNIQUE INDEX idx_calendar_sync_google ON calendar_sync (employee_kuerzel, google_event_id) WHERE google_event_id IS NOT NULL; +CREATE UNIQUE INDEX idx_calendar_sync_google ON calendar_sync (employee_kuerzel, google_event_id) WHERE google_event_id IS NOT NULL AND deleted = FALSE; ``` ## Funktionalität diff --git a/bitbylaw/steps/advoware_cal_sync/calendar_sync_event_step.py b/bitbylaw/steps/advoware_cal_sync/calendar_sync_event_step.py index 861f53d9..115503d5 100644 --- a/bitbylaw/steps/advoware_cal_sync/calendar_sync_event_step.py +++ b/bitbylaw/steps/advoware_cal_sync/calendar_sync_event_step.py @@ -572,22 +572,37 @@ async def handler(event, context): try: if strategy == 'source_system_wins': if row['source_system'] == 'advoware': - # Check if Advoware was modified since last sync + # Check for changes in source (Advoware) or unauthorized changes in target (Google) adv_ts = datetime.datetime.fromisoformat(adv_data['zuletztGeaendertAm']).astimezone(BERLIN_TZ) + google_ts_str = google_data.get('updated', '') + google_ts = datetime.datetime.fromisoformat(google_ts_str.rstrip('Z')).astimezone(BERLIN_TZ) if google_ts_str else None if adv_ts > row['last_sync']: await update_google_event(service, calendar_id, event_id, adv_std) async with conn.transaction(): await conn.execute("UPDATE calendar_sync SET sync_status = 'synced', last_sync = $2 WHERE sync_id = $1;", row['sync_id'], adv_ts) logger.info(f"Phase 4: Updated Google event {event_id} from Advoware frNr {frnr}") + elif google_ts and google_ts > row['last_sync']: + logger.warning(f"Phase 4: Unauthorized change in Google event {event_id}, resetting to Advoware frNr {frnr}") + await update_google_event(service, calendar_id, event_id, adv_std) + async with conn.transaction(): + await conn.execute("UPDATE calendar_sync SET sync_status = 'synced', last_sync = $2 WHERE sync_id = $1;", row['sync_id'], adv_ts) + logger.info(f"Phase 4: Reset Google event {event_id} to Advoware frNr {frnr}") elif row['source_system'] == 'google' and row['advoware_write_allowed']: - # Check if Google was modified since last sync + # Check for changes in source (Google) or unauthorized changes in target (Advoware) google_ts_str = google_data.get('updated', '') google_ts = datetime.datetime.fromisoformat(google_ts_str.rstrip('Z')).astimezone(BERLIN_TZ) if google_ts_str else None + adv_ts = datetime.datetime.fromisoformat(adv_data['zuletztGeaendertAm']).astimezone(BERLIN_TZ) if google_ts and google_ts > row['last_sync']: await safe_update_advoware_appointment(advoware, frnr, google_std, row['advoware_write_allowed']) async with conn.transaction(): await conn.execute("UPDATE calendar_sync SET sync_status = 'synced', last_sync = $2 WHERE sync_id = $1;", row['sync_id'], google_ts) logger.info(f"Phase 4: Updated Advoware frNr {frnr} from Google event {event_id}") + elif adv_ts > row['last_sync']: + logger.warning(f"Phase 4: Unauthorized change in Advoware frNr {frnr}, resetting to Google event {event_id}") + await safe_update_advoware_appointment(advoware, frnr, google_std, row['advoware_write_allowed']) + async with conn.transaction(): + await conn.execute("UPDATE calendar_sync SET sync_status = 'synced', last_sync = $2 WHERE sync_id = $1;", row['sync_id'], google_ts) + logger.info(f"Phase 4: Reset Advoware frNr {frnr} to Google event {event_id}") elif strategy == 'last_change_wins': adv_ts = await get_advoware_timestamp(advoware, frnr) google_ts_str = google_data.get('updated', '')