diff --git a/eventplanner_gcal/google_sync.py b/eventplanner_gcal/google_sync.py index 7e20ea7..5763773 100644 --- a/eventplanner_gcal/google_sync.py +++ b/eventplanner_gcal/google_sync.py @@ -340,24 +340,40 @@ def sync_from_local_to_google(service=None): all_events = get_all_gcal_events(service) + # Map gcal_id -> django_id for every blechreiz-owned event at Google + gcal_id_to_django_id = {} events_at_google_django_id = set() - events_at_google_google_id = set() for gcal_ev in all_events: try: django_id = int(gcal_ev["extendedProperties"]["private"]["blechreizID"]) events_at_google_django_id.add(django_id) - events_at_google_google_id.add(gcal_ev["id"]) + gcal_id_to_django_id[gcal_ev["id"]] = django_id except (KeyError, ValueError) as e: logger.warning(f"Invalid GCal event structure: {e}") local_events_django_id = set(Event.objects.all().values_list("pk", flat=True)) - local_events_google_id = set( - GCalMapping.objects.all().values_list("gcal_id", flat=True) - ) + + # Repair GCalMapping for events that exist at Google but have no local mapping + # (can happen when a previous batch failed mid-way) + for gcal_id, django_id in gcal_id_to_django_id.items(): + if django_id in local_events_django_id and not GCalMapping.objects.filter(gcal_id=gcal_id).exists(): + try: + event = Event.objects.get(pk=django_id) + GCalMapping.objects.get_or_create(event=event, defaults={"gcal_id": gcal_id}) + logger.info(f"Repaired missing mapping: GCal {gcal_id} <-> Event {django_id}") + except Event.DoesNotExist: + pass events_to_create_django_id = local_events_django_id - events_at_google_django_id - events_to_delete_google_id = events_at_google_google_id - local_events_google_id + + # Only delete Google events whose local Event no longer exists + # (never delete based on missing GCalMapping — that's just a local cache) + events_to_delete_google_id = { + gcal_id + for gcal_id, django_id in gcal_id_to_django_id.items() + if django_id not in local_events_django_id + } batch = service.new_batch_http_request() batch_is_empty = True