Skip to content
Snippets Groups Projects
Commit 70dfe608 authored by HeJ's avatar HeJ
Browse files

ScheduleSource: allow missing events to be handled specially

Allow an option 'missing_events' to be specified on
ScheduleSource.import_configuration which may have one of the following
values indicating an action on Events which are present on the importing
assembly but not present in the source:

- 'depublish': the local Event will be updated with is_public=False
- 'delete': the local Event will be deleted
parent c8f3a845
Branches
Tags
No related merge requests found
...@@ -181,6 +181,12 @@ class ScheduleSource(models.Model): ...@@ -181,6 +181,12 @@ class ScheduleSource(models.Model):
'source_id': item_source_id, 'source_id': item_source_id,
'local_id': None, 'local_id': None,
}) })
# if we have the item locally but shall skip it, handle it as 'handled' anyway
# so that it is not picked up again as e.g. 'missing_events'
if not new_mapping and mapping.local_id and mapping.local_id in expected_items:
expected_items.remove(mapping.local_id)
return return
if new_mapping: if new_mapping:
...@@ -270,9 +276,14 @@ class ScheduleSource(models.Model): ...@@ -270,9 +276,14 @@ class ScheduleSource(models.Model):
events = {} events = {}
rooms = {} rooms = {}
# derive some flags
missing_events = (self.import_configuration.get('missing_events') if self.import_configuration else None) or 'ignore'
# note down all existing rooms and events so that we can call out the missing ones # note down all existing rooms and events so that we can call out the missing ones
expected_rooms = list(self.assembly.rooms.values_list('id', flat=True)) expected_rooms = list(self.assembly.rooms.values_list('id', flat=True))
expected_events = list(self.assembly.events.values_list('id', flat=True)) expected_events = list(self.mappings.filter(
mapping_type=ScheduleSourceMapping.MappingType.EVENT,
).values_list('local_id', flat=True))
# first, load the rooms (as they're needed for events) # first, load the rooms (as they're needed for events)
for r_id, r in data['rooms'].items(): for r_id, r in data['rooms'].items():
...@@ -331,14 +342,23 @@ class ScheduleSource(models.Model): ...@@ -331,14 +342,23 @@ class ScheduleSource(models.Model):
'local_id': str(room_id), 'local_id': str(room_id),
}) })
# flag the non-loaded rooms as 'missing' # flag the non-loaded events as 'missing'
for event_id in expected_events: for event_id in expected_events:
activity.append({ act = {
'action': 'missing', 'action': 'missing',
'type': 'event', 'type': 'event',
'source_id': None, 'source_id': None,
'local_id': str(event_id), 'local_id': str(event_id),
}) }
# check if we should do something about the missing event
if missing_events == 'depublish':
Event.objects.filter(pk=event_id).update(is_public=False)
elif missing_events == 'delete':
Event.objects.filter(pk=event_id).delete()
act['action'] = 'deleted'
activity.append(act)
return activity return activity
...@@ -543,7 +563,7 @@ class ScheduleSourceImport(models.Model): ...@@ -543,7 +563,7 @@ class ScheduleSourceImport(models.Model):
self.data['_activity'] = activity self.data['_activity'] = activity
if errors: if errors:
# create list of unique erros for summary # create list of unique errors for summary
msgs = list(set([x['message'].split('\n')[0] for x in errors])) msgs = list(set([x['message'].split('\n')[0] for x in errors]))
stats = ', '.join( stats = ', '.join(
......
...@@ -4,6 +4,7 @@ import os ...@@ -4,6 +4,7 @@ import os
from django.test import TestCase, override_settings from django.test import TestCase, override_settings
from ..models import Event
from ..models.assemblies import Assembly from ..models.assemblies import Assembly
from ..models.conference import Conference, ConferenceMember from ..models.conference import Conference, ConferenceMember
from ..models.users import PlatformUser from ..models.users import PlatformUser
...@@ -86,6 +87,8 @@ class ScheduleTests(TestCase): ...@@ -86,6 +87,8 @@ class ScheduleTests(TestCase):
self.assertEqual(1, self.assembly.rooms.count()) self.assertEqual(1, self.assembly.rooms.count())
self.assertEqual(1, self.assembly.events.count()) self.assertEqual(1, self.assembly.events.count())
self.assertIn('_activity', job.data) self.assertIn('_activity', job.data)
job_activity = job.data['_activity']
self.assertEqual(2, len(job_activity))
self.assertTrue(all(a['action'] == 'added' for a in job.data['_activity'])) self.assertTrue(all(a['action'] == 'added' for a in job.data['_activity']))
# check that room and event have been created # check that room and event have been created
...@@ -93,6 +96,7 @@ class ScheduleTests(TestCase): ...@@ -93,6 +96,7 @@ class ScheduleTests(TestCase):
e1 = self.assembly.events.get(slug='minkorrekt') e1 = self.assembly.events.get(slug='minkorrekt')
self.assertIsNotNone(r1) self.assertIsNotNone(r1)
self.assertIsNotNone(e1) self.assertIsNotNone(e1)
self.assertEqual('Methodisch Inkorrekt', e1.name)
# check that mappings exist # check that mappings exist
self.assertEqual(2, src.mappings.count()) self.assertEqual(2, src.mappings.count())
...@@ -107,6 +111,81 @@ class ScheduleTests(TestCase): ...@@ -107,6 +111,81 @@ class ScheduleTests(TestCase):
self.assertEqual(e1.room, r1) self.assertEqual(e1.room, r1)
self.assertEqual(timedelta(minutes=90), e1.schedule_duration) self.assertEqual(timedelta(minutes=90), e1.schedule_duration)
# change the event's name and flag it to be skipped
e1.name = 'Fnord'
e1.save()
e1_m.skip = True
e1_m.save()
# add a new event locally which was not imported
e2 = self.assembly.events.create(conference=self.conference, slug='fnordnewsshow', name='Fnord News Show', room=r1, is_public=True)
# redo the import
job2 = src.imports.create(state=ScheduleSourceImport.State.PREPARED)
job2.do_import()
job2_activity = job2.data.get('_activity')
self.assertIsNotNone(job2_activity)
self.assertEqual(2, len(job2_activity))
# check that the event has not been changed
e1.refresh_from_db()
self.assertEqual('Fnord', e1.name, 'name of skipped event has been changed')
# check that the event was flagged
job2_e1_activity_items = [x for x in job2_activity if x['type'] == 'event' and x['source_id'] == e1_m.source_id]
self.assertEqual(1, len(job2_e1_activity_items))
self.assertEqual('skipped', job2_e1_activity_items[0]['action'])
# fake a previous mapping for the local event (which is not present in the import data)
e2_m = src.mappings.create(mapping_type=ScheduleSourceMapping.MappingType.EVENT, local_id=e2.pk, source_id='foobar')
# redo the import
job3 = src.imports.create(state=ScheduleSourceImport.State.PREPARED)
job3.do_import()
job3_activity = job3.data.get('_activity')
self.assertEqual(3, len(job3_activity))
# check that the local (and fake-mapped) event was marked 'missing'
job3_e2_activity_items = [x for x in job3_activity if x['type'] == 'event' and x['local_id'] == str(e2.id)]
self.assertEqual(1, len(job3_e2_activity_items))
self.assertEqual('missing', job3_e2_activity_items[0]['action'])
# redo the import with missing_event='depublish'
self.assertTrue(e2.is_public)
src.import_configuration = {'missing_events': 'depublish'}
src.save()
job4 = src.imports.create(state=ScheduleSourceImport.State.PREPARED)
job4.do_import()
self.assertEqual(ScheduleSourceImport.State.COMPLETED, job4.state)
job4_activity = job4.data.get('_activity')
# check that the local (and fake-mapped) event was marked 'missing'
job4_e2_activity_items = [x for x in job4_activity if x['type'] == 'event' and x['local_id'] == str(e2.id)]
self.assertEqual(1, len(job4_e2_activity_items))
self.assertEqual('missing', job4_e2_activity_items[0]['action'])
# but now the event should have been de-published
e2.refresh_from_db()
self.assertFalse(e2.is_public)
# redo the import with missing_event='delete'
src.import_configuration = {'missing_events': 'delete'}
src.save()
job5 = src.imports.create(state=ScheduleSourceImport.State.PREPARED)
job5.do_import()
self.assertEqual(ScheduleSourceImport.State.COMPLETED, job5.state)
job5_activity = job5.data.get('_activity')
# check that the local (and fake-mapped) event was marked 'missing'
job5_e2_activity_items = [x for x in job5_activity if x['type'] == 'event' and x['local_id'] == str(e2.id)]
self.assertEqual(1, len(job5_e2_activity_items))
self.assertEqual('deleted', job5_e2_activity_items[0]['action'])
# but now the event should have been de-published
with self.assertRaises(Event.DoesNotExist):
e2.refresh_from_db()
@override_settings(SCHEDULES_SUPPORT_FILE_PROTOCOL=True) @override_settings(SCHEDULES_SUPPORT_FILE_PROTOCOL=True)
def test_xml(self): def test_xml(self):
src = ScheduleSource.objects.create( src = ScheduleSource.objects.create(
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment