reservations: Refactor sync_google_calendar to use class
This commit is contained in:
parent
06fd819acf
commit
deb1165afc
@ -1,6 +1,7 @@
|
||||
import logging
|
||||
from datetime import date, datetime
|
||||
from http import HTTPStatus
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from django.conf import settings
|
||||
from django.utils import timezone
|
||||
@ -9,6 +10,9 @@ from google.oauth2 import service_account
|
||||
from googleapiclient.discovery import build
|
||||
from googleapiclient.errors import HttpError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from googleapiclient._apis.calendar.v3 import CalendarResource, Event
|
||||
|
||||
from cmsmanage.django_q2_helper import q_task_group
|
||||
from reservations.models import ExternalReservation, Reservation, Resource
|
||||
|
||||
@ -26,8 +30,21 @@ def parse_google_calendar_datetime(dt) -> date | datetime:
|
||||
raise Exception("Google Calendar event with out a start/end date/dateTime")
|
||||
|
||||
|
||||
class GoogleCalendarSynchronizer:
|
||||
service: "CalendarResource"
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.service = build(
|
||||
"calendar",
|
||||
"v3",
|
||||
credentials=service_account.Credentials.from_service_account_file(
|
||||
settings.GOOGLE_SERVICE_ACCOUNT_FILE,
|
||||
scopes=SCOPES,
|
||||
),
|
||||
)
|
||||
|
||||
def update_calendar_event(
|
||||
service, resource: Resource, existing_event, reservation: Reservation
|
||||
self, resource: Resource, existing_event: "Event", reservation: Reservation
|
||||
):
|
||||
changes = reservation.make_google_calendar_event()
|
||||
# skip update if no changes are needed
|
||||
@ -42,17 +59,16 @@ def update_calendar_event(
|
||||
):
|
||||
logger.debug("Updating event")
|
||||
new_event = existing_event | changes
|
||||
service.events().update(
|
||||
self.service.events().update(
|
||||
calendarId=resource.google_calendar,
|
||||
eventId=reservation.google_calendar_event_id,
|
||||
body=new_event,
|
||||
).execute()
|
||||
|
||||
|
||||
def insert_calendar_event(service, resource: Resource, reservation: Reservation):
|
||||
def insert_calendar_event(self, resource: Resource, reservation: Reservation):
|
||||
new_gcal_event = reservation.make_google_calendar_event()
|
||||
created_event = (
|
||||
service.events()
|
||||
self.service.events()
|
||||
.insert(
|
||||
calendarId=resource.google_calendar,
|
||||
body=new_gcal_event,
|
||||
@ -62,16 +78,15 @@ def insert_calendar_event(service, resource: Resource, reservation: Reservation)
|
||||
reservation.google_calendar_event_id = created_event["id"]
|
||||
reservation.save()
|
||||
|
||||
|
||||
def insert_or_update_calendar_event(
|
||||
service, resource: Resource, reservation: Reservation
|
||||
self, resource: Resource, reservation: Reservation
|
||||
):
|
||||
if not reservation.google_calendar_event_id:
|
||||
logger.info(
|
||||
"Event in database has no Google Calendar event ID: inserting | %s",
|
||||
reservation.google_calendar_event_id,
|
||||
)
|
||||
insert_calendar_event(service, resource, reservation)
|
||||
self.insert_calendar_event(resource, reservation)
|
||||
|
||||
else:
|
||||
# this event was in Google Calendar at some point (possibly for a different
|
||||
@ -83,30 +98,29 @@ def insert_or_update_calendar_event(
|
||||
)
|
||||
try:
|
||||
event = (
|
||||
service.events()
|
||||
self.service.events()
|
||||
.get(
|
||||
calendarId=resource.google_calendar,
|
||||
eventId=reservation.google_calendar_event_id,
|
||||
)
|
||||
.execute()
|
||||
)
|
||||
update_calendar_event(service, resource, event, reservation)
|
||||
self.update_calendar_event(resource, event, reservation)
|
||||
except HttpError as error:
|
||||
if error.status_code == HTTPStatus.NOT_FOUND:
|
||||
logger.info(
|
||||
"Event in database not in Google Calendar: inserting | %s",
|
||||
reservation.google_calendar_event_id,
|
||||
)
|
||||
insert_calendar_event(service, resource, reservation)
|
||||
self.insert_calendar_event(resource, reservation)
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
def sync_resource_from_google_calendar(
|
||||
service, resource: Resource, now: datetime
|
||||
self, resource: Resource, now: datetime
|
||||
) -> set[str]:
|
||||
request = (
|
||||
service.events()
|
||||
self.service.events()
|
||||
.list(
|
||||
calendarId=resource.google_calendar,
|
||||
timeMin=now.isoformat(timespec="seconds"),
|
||||
@ -136,14 +150,14 @@ def sync_resource_from_google_calendar(
|
||||
"Event in Google Calendar found in database: checking for update | %s",
|
||||
event["id"],
|
||||
)
|
||||
update_calendar_event(service, resource, event, reservation)
|
||||
self.update_calendar_event(resource, event, reservation)
|
||||
except Reservation.DoesNotExist:
|
||||
# reservation deleted in database, so remove from Google Calendar
|
||||
logger.info(
|
||||
"Event in Google Calendar not found in database: deleting | %s",
|
||||
event["id"],
|
||||
)
|
||||
service.events().delete(
|
||||
self.service.events().delete(
|
||||
calendarId=resource.google_calendar,
|
||||
eventId=event["id"],
|
||||
sendUpdates="none",
|
||||
@ -167,14 +181,12 @@ def sync_resource_from_google_calendar(
|
||||
|
||||
return {event["id"] for event in events}
|
||||
|
||||
|
||||
def sync_reservation_from_database(service, reservation: Reservation):
|
||||
def sync_reservation_from_database(self, reservation: Reservation):
|
||||
for resource in reservation.resources.all():
|
||||
insert_or_update_calendar_event(service, resource, reservation)
|
||||
|
||||
self.insert_or_update_calendar_event(resource, reservation)
|
||||
|
||||
def sync_resource_from_database(
|
||||
service, resource: Resource, now: datetime, existing_event_ids: set[str]
|
||||
self, resource: Resource, now: datetime, existing_event_ids: set[str]
|
||||
):
|
||||
reservations = (
|
||||
resource.reservation_set.filter(end__gt=now)
|
||||
@ -192,30 +204,21 @@ def sync_resource_from_database(
|
||||
reservation.delete()
|
||||
|
||||
else:
|
||||
insert_or_update_calendar_event(service, resource, reservation)
|
||||
self.insert_or_update_calendar_event(resource, reservation)
|
||||
|
||||
|
||||
def sync_resource(service, resource: Resource, now: datetime):
|
||||
def sync_resource(self, resource: Resource, now: datetime):
|
||||
logger.info(
|
||||
"Checking calendar %s for resource %s", resource.google_calendar, resource
|
||||
)
|
||||
|
||||
existing_event_ids = sync_resource_from_google_calendar(service, resource, now)
|
||||
sync_resource_from_database(service, resource, now, existing_event_ids)
|
||||
existing_event_ids = self.sync_resource_from_google_calendar(resource, now)
|
||||
self.sync_resource_from_database(resource, now, existing_event_ids)
|
||||
|
||||
|
||||
@q_task_group("Sync Reservations with Google Calendar")
|
||||
def sync_reservations_with_google_calendar():
|
||||
service = build(
|
||||
"calendar",
|
||||
"v3",
|
||||
credentials=service_account.Credentials.from_service_account_file(
|
||||
settings.GOOGLE_SERVICE_ACCOUNT_FILE,
|
||||
scopes=SCOPES,
|
||||
),
|
||||
)
|
||||
|
||||
synchronizer = GoogleCalendarSynchronizer()
|
||||
now = timezone.now()
|
||||
|
||||
for resource in Resource.objects.all():
|
||||
sync_resource(service, resource, now)
|
||||
synchronizer.sync_resource(resource, now)
|
||||
|
Loading…
Reference in New Issue
Block a user