Skip to content

Commit

Permalink
Add report for deleted Guidebook items
Browse files Browse the repository at this point in the history
We use the tracking table to grab all items that were synced to guidebook but have since been deleted, and send that out in an email. We piggyback on the Guidebook updates email when at-con and check every twelve hours otherwise.

Also turns these emails off by default -- to enable them, you need to define the email address they get sent to.
  • Loading branch information
kitsuta committed Jan 16, 2025
1 parent 83329ca commit 78f6de1
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 7 deletions.
4 changes: 4 additions & 0 deletions uber/configspec.ini
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,10 @@ panels_confirm_deadline = integer(default=0)
# be ready, so we just set this to false whenever it is.
hide_schedule = boolean(default=True)

# Emails about changes to schedule items and other Guidebook items are sent TO this address.
# If the address is not set, these emails are disabled.
guidebook_updates_email = string(default="")

# These are the areas from which we'll show events to associated with panel
# applications on the schedule.
panel_rooms = string_list(default=list())
Expand Down
71 changes: 66 additions & 5 deletions uber/tasks/panels.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,47 @@
import json

from collections import defaultdict
from datetime import timedelta
from dateutil import parser as dateparser
from sqlalchemy import or_

from uber.config import c
from uber.decorators import render
from uber.models import Session
from uber.models import Email, Session, Tracking
from uber.tasks import celery
from uber.tasks.email import send_email
from uber.utils import GuidebookUtils, localized_now


__all__ = ['panels_waitlist_unaccepted_panels', 'sync_guidebook_models', 'check_stale_guidebook_models']
__all__ = ['panels_waitlist_unaccepted_panels', 'sync_guidebook_models',
'check_deleted_guidebook_models', 'check_stale_guidebook_models']


def _get_deleted_models(session, deleted_since=None):
deleted_synced = session.query(Tracking).filter(Tracking.action == c.DELETED,
Tracking.snapshot.contains('"last_synced": {"data": {"guidebook"'))
if deleted_since:
deleted_synced = deleted_synced.filter(Tracking.when > deleted_since)

deleted_models = defaultdict(list)
model_names = {}

for key, label in c.GUIDEBOOK_MODELS:
model_names[key] = label

for tracking_entry in deleted_synced:
snapshot = json.loads(tracking_entry.snapshot)

model = snapshot['_model']
if model == 'GuestGroup':
model += '_band' if snapshot['group_type'] == c.BAND else '_guest'
elif model == 'Group':
model += '_dealer'

model_name = 'Schedule Item' if model == 'Event' else model_names[model]

deleted_models[model_name].append(snapshot['last_synced']['data']['guidebook']['name'])
return deleted_models


@celery.task
Expand All @@ -31,21 +62,51 @@ def sync_guidebook_models(selected_model, sync_time, id_list):
session.commit()


@celery.schedule(timedelta(hours=12))
def check_deleted_guidebook_models():
if not c.PRE_CON or not c.GUIDEBOOK_UPDATES_EMAIL:
return

with Session() as session:
subject = f"Deleted Guidebook Items: {localized_now().strftime("%A %-I:%M %p")}"
last_email = session.query(Email).filter(Email.subject.contains("Deleted Guidebook Items")
).order_by(Email.when.desc()).first()

deleted_models = _get_deleted_models(session, deleted_since=last_email.when) if last_email else _get_deleted_models(session)

if deleted_models:
body = render('emails/guidebook_deletes.txt', {
'deleted_models': deleted_models,
}, encoding=None)
send_email.delay(c.REPORTS_EMAIL, c.GUIDEBOOK_UPDATES_EMAIL,
subject, body, ident="guidebook_deletes"
)


@celery.schedule(timedelta(minutes=15))
def check_stale_guidebook_models():
if not c.AT_THE_CON:
if not c.AT_THE_CON or not c.GUIDEBOOK_UPDATES_EMAIL:
return

with Session() as session:
cl_updates, schedule_updates = GuidebookUtils.get_changed_models(session)
stale_models = [key for key in cl_updates if cl_updates[key]]
if schedule_updates:
stale_models.append('Schedule')
if stale_models:

last_email = session.query(Email).filter(or_(
Email.subject.contains("Guidebook Updates"),
Email.subject.contains("Deleted Guidebook Items"))
).order_by(Email.when.desc()).first()

deleted_models = _get_deleted_models(session, deleted_since=last_email.when) if last_email else _get_deleted_models(session)

if stale_models or deleted_models:
body = render('emails/guidebook_updates.txt', {
'stale_models': stale_models,
'deleted_models': deleted_models,
}, encoding=None)
send_email.delay(c.REPORTS_EMAIL, "gb-ops@magfest.org",
send_email.delay(c.REPORTS_EMAIL, c.GUIDEBOOK_UPDATES_EMAIL,
f"Guidebook Updates: {localized_now().strftime("%A %-I:%M %p")}",
body, ident="guidebook_updates"
)
Expand Down
7 changes: 7 additions & 0 deletions uber/templates/emails/guidebook_deletes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Attention Guidebook admins! The items below have been deleted from the system.

{% for category in deleted_models %}{{ category }}(s):
{% for item in deleted_models[category] %} - {{ item }}
{% endfor %}{% endfor %}

This email will be the only record of these item deletions. Please keep it until you delete all the above items from Guidebook.
11 changes: 9 additions & 2 deletions uber/templates/emails/guidebook_updates.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
Attention Guidebook admins!
The following categories have stale items:

{% if stale_models %}The following categories have been updated in the system:
{% for label in stale_models %}- {{ label }}
{% endfor %}

You can review all pending items here: {{ c.URL_BASE }}/schedule_reports/index
{% endif %}{% if deleted_models %}The following items have been deleted:
{% for category in deleted_models %}{{ category }}(s):
{% for item in deleted_models[category] %} - {{ item }}
{% endfor %}
{% endfor %}

{% endif %}You can review all pending items here: {{ c.URL_BASE }}/schedule_reports/index

0 comments on commit 78f6de1

Please sign in to comment.