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 115503d5..d8ece4a8 100644 --- a/bitbylaw/steps/advoware_cal_sync/calendar_sync_event_step.py +++ b/bitbylaw/steps/advoware_cal_sync/calendar_sync_event_step.py @@ -237,7 +237,6 @@ async def create_advoware_appointment(advoware, data, employee_kuerzel): 'datum': start_dt.strftime('%Y-%m-%dT%H:%M:%S'), 'uhrzeitBis': end_dt.strftime('%H:%M:%S'), 'datumBis': end_dt.strftime('%Y-%m-%dT%H:%M:%S'), - 'sb': employee_kuerzel, 'anwalt': employee_kuerzel, 'vorbereitungsDauer': '00:00:00', 'dauertermin': data['dauertermin'], @@ -254,7 +253,7 @@ async def create_advoware_appointment(advoware, data, employee_kuerzel): logger.error(f"Failed to create Advoware appointment: {e}") raise -async def update_advoware_appointment(advoware, frnr, data): +async def update_advoware_appointment(advoware, frnr, data, employee_kuerzel): """Update Advoware appointment.""" start_dt = data['start'].astimezone(BERLIN_TZ) end_dt = data['end'].astimezone(BERLIN_TZ) @@ -266,6 +265,8 @@ async def update_advoware_appointment(advoware, frnr, data): 'datum': start_dt.strftime('%Y-%m-%dT%H:%M:%S'), 'uhrzeitBis': end_dt.strftime('%H:%M:%S'), 'datumBis': end_dt.strftime('%Y-%m-%dT%H:%M:%S'), + 'anwalt': employee_kuerzel, + 'vorbereitungsDauer': '00:00:00', 'dauertermin': data['dauertermin'], 'turnus': data['turnus'], 'turnusArt': data['turnusArt'] @@ -369,12 +370,12 @@ async def safe_create_advoware_appointment(advoware, data, employee_kuerzel, wri return None return await create_advoware_appointment(advoware, data, employee_kuerzel) -async def safe_update_advoware_appointment(advoware, frnr, data, write_allowed): +async def safe_update_advoware_appointment(advoware, frnr, data, write_allowed, employee_kuerzel): """Safe wrapper for updating Advoware appointments with write permission check.""" if not write_allowed: logger.warning("Cannot update in Advoware, write not allowed") return - await update_advoware_appointment(advoware, frnr, data) + await update_advoware_appointment(advoware, frnr, data, employee_kuerzel) async def safe_delete_advoware_appointment(advoware, frnr, write_allowed): """Safe wrapper for deleting Advoware appointments with write permission check.""" @@ -534,19 +535,36 @@ async def handler(event, context): elif not google_exists: # Missing in Google strategy = row['sync_strategy'] - if strategy == 'source_system_wins' and row['source_system'] == 'google' and row['advoware_write_allowed']: - # Recreate in Advoware - try: - new_frnr = await safe_create_advoware_appointment(advoware, standardize_appointment_data(adv_map[frnr], 'advoware'), employee_kuerzel, row['advoware_write_allowed']) - async with conn.transaction(): - await conn.execute("UPDATE calendar_sync SET advoware_frnr = $1, sync_status = 'synced' WHERE sync_id = $2;", int(new_frnr), row['sync_id']) - logger.info(f"Phase 3: Recreated Advoware appointment {new_frnr} for sync_id {row['sync_id']}") - except Exception as e: - logger.warning(f"Phase 3: Failed to delete Advoware for sync_id {row['sync_id']}: {e}") - async with conn.transaction(): - await conn.execute("UPDATE calendar_sync SET sync_status = 'failed' WHERE sync_id = $1;", row['sync_id']) + if strategy == 'source_system_wins': + if row['source_system'] == 'google': + # Delete in Advoware + if row['advoware_write_allowed']: + try: + await safe_delete_advoware_appointment(advoware, frnr, row['advoware_write_allowed']) + async with conn.transaction(): + await conn.execute("UPDATE calendar_sync SET deleted = TRUE, sync_status = 'synced' WHERE sync_id = $1;", row['sync_id']) + logger.info(f"Phase 3: Propagated delete to Advoware for sync_id {row['sync_id']}") + except Exception as e: + logger.warning(f"Phase 3: Failed to delete Advoware for sync_id {row['sync_id']}: {e}") + async with conn.transaction(): + await conn.execute("UPDATE calendar_sync SET sync_status = 'failed' WHERE sync_id = $1;", row['sync_id']) + else: + logger.warning(f"Phase 3: Cannot delete in Advoware for sync_id {row['sync_id']}, write not allowed") + async with conn.transaction(): + await conn.execute("UPDATE calendar_sync SET sync_status = 'failed' WHERE sync_id = $1;", row['sync_id']) + elif row['source_system'] == 'advoware': + # Recreate in Google + try: + new_event_id = await create_google_event(service, calendar_id, standardize_appointment_data(adv_map[frnr], 'advoware')) + async with conn.transaction(): + await conn.execute("UPDATE calendar_sync SET google_event_id = $1, sync_status = 'synced' WHERE sync_id = $2;", new_event_id, row['sync_id']) + logger.info(f"Phase 3: Recreated Google event {new_event_id} for sync_id {row['sync_id']}") + except Exception as e: + logger.warning(f"Phase 3: Failed to recreate Google for sync_id {row['sync_id']}: {e}") + async with conn.transaction(): + await conn.execute("UPDATE calendar_sync SET sync_status = 'failed' WHERE sync_id = $1;", row['sync_id']) else: - # Propagate delete to Advoware + # last_change_wins or other, propagate delete to Advoware try: await safe_delete_advoware_appointment(advoware, frnr, row['advoware_write_allowed']) async with conn.transaction(): @@ -593,13 +611,13 @@ async def handler(event, context): 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']) + await safe_update_advoware_appointment(advoware, frnr, google_std, row['advoware_write_allowed'], row['employee_kuerzel']) 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']) + await safe_update_advoware_appointment(advoware, frnr, google_std, row['advoware_write_allowed'], row['employee_kuerzel']) 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}") @@ -611,7 +629,7 @@ async def handler(event, context): if adv_ts > google_ts: await update_google_event(service, calendar_id, event_id, adv_std) elif row['advoware_write_allowed']: - await safe_update_advoware_appointment(advoware, frnr, google_std, row['advoware_write_allowed']) + await safe_update_advoware_appointment(advoware, frnr, google_std, row['advoware_write_allowed'], row['employee_kuerzel']) async with conn.transaction(): await conn.execute("UPDATE calendar_sync SET sync_status = 'synced', last_sync = $2 WHERE sync_id = $1;", row['sync_id'], max(adv_ts, google_ts)) logger.info(f"Phase 4: Updated based on last_change_wins for sync_id {row['sync_id']}")